+////////////////////////////////////////////////////////////
+// count different (# of times the value is different than the previous)
+
+struct count_diff_scratch{
+ gs_uint32_t count;
+ union{
+ gs_uint32_t ui;
+ gs_int32_t i;
+ gs_uint64_t ul;
+ gs_int64_t l;
+ } r;
+};
+
+////////// HFTA only
+
+// uint32
+void count_diff_HFTA_AGGR_INIT_(gs_sp_t s){
+ count_diff_scratch *scratch = (count_diff_scratch *)s;
+ scratch->count = 0;
+ scratch->r.ul = 0;
+}
+void count_diff_HFTA_AGGR_REINIT_(gs_sp_t s){
+ count_diff_scratch *scratch = (count_diff_scratch *)s;
+ scratch->count = 0;
+}
+void count_diff_HFTA_AGGR_UPDATE_(gs_sp_t s, gs_uint32_t val){
+ count_diff_scratch *scratch = (count_diff_scratch *)s;
+ if(scratch->count==0 || scratch->r.ui != val)
+ scratch->count++;
+ scratch->r.ui = val;
+}
+void count_diff_HFTA_AGGR_OUTPUT_(gs_uint32_t *res, gs_sp_t s){
+ count_diff_scratch *scratch = (count_diff_scratch *)s;
+ *res = scratch->count;
+}
+void count_diff_HFTA_AGGR_DESTROY_(gs_sp_t s){ }
+
+// int32
+void count_diff_HFTA_AGGR_UPDATE_(gs_sp_t s, gs_int32_t val){
+ count_diff_scratch *scratch = (count_diff_scratch *)s;
+ if(scratch->count==0 || scratch->r.i != val)
+ scratch->count++;
+ scratch->r.i = val;
+}
+
+// uint64
+void count_diff_HFTA_AGGR_UPDATE_(gs_sp_t s, gs_uint64_t val){
+ count_diff_scratch *scratch = (count_diff_scratch *)s;
+ if(scratch->count==0 || scratch->r.ul != val)
+ scratch->count++;
+ scratch->r.ul = val;
+}
+
+// int64
+void count_diff_HFTA_AGGR_UPDATE_(gs_sp_t s, gs_int64_t val){
+ count_diff_scratch *scratch = (count_diff_scratch *)s;
+ if(scratch->count==0 || scratch->r.l != val)
+ scratch->count++;
+ scratch->r.l = val;
+}
+
+// vstring
+void count_diff_HFTA_AGGR_UPDATE_(gs_sp_t s, vstring* val){
+ count_diff_scratch *scratch = (count_diff_scratch *)s;
+ gs_uint64_t hashval = hfta_vstr_long_hashfunc(val);
+ if(scratch->count==0 || scratch->r.l != hashval)
+ scratch->count++;
+ scratch->r.l = hashval;
+}
+
+////////// HFTA / LFTA split
+
+struct lfta_count_diff_scratch{
+ gs_uint32_t count;
+ union{
+ gs_uint32_t ui;
+ gs_int32_t i;
+ gs_uint64_t ul;
+ gs_int64_t l;
+ } first;
+ union{
+ gs_uint32_t ui;
+ gs_int32_t i;
+ gs_uint64_t ul;
+ gs_int64_t l;
+ } last;
+};
+
+
+void count_diff_hfta_HFTA_AGGR_INIT_(gs_sp_t s){
+ count_diff_scratch *scratch = (count_diff_scratch *)s;
+ scratch->count = 0;
+ scratch->r.ul = 0;
+}
+void count_diff_hfta_HFTA_AGGR_REINIT_(gs_sp_t s){
+ count_diff_scratch *scratch = (count_diff_scratch *)s;
+ scratch->count = 0;
+ scratch->r.ul = 0;
+}
+void count_diff_hfta_HFTA_AGGR_UPDATE_(gs_sp_t s, vstring *v){
+ lfta_count_diff_scratch *val = (lfta_count_diff_scratch *)v;
+ count_diff_scratch *scratch = (count_diff_scratch *)(v->offset);
+ scratch->count += val->count - 1;
+ if(scratch->r.l != val->first.l)
+ scratch->count++;
+ scratch->r.l = val->last.l;
+}
+void count_diff_hfta_HFTA_AGGR_OUTPUT_(gs_uint32_t *res, gs_sp_t s){
+ count_diff_scratch *scratch = (count_diff_scratch *)s;
+ *res = (scratch->count)+1;
+}
+void count_diff_hfta_HFTA_AGGR_DESTROY_(gs_sp_t scratch){ }
+
+
+