sort the frequency tables
authorBen Pfaff <blp@cs.stanford.edu>
Thu, 30 Dec 2021 19:37:09 +0000 (11:37 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 1 Jan 2022 19:17:32 +0000 (11:17 -0800)
src/language/stats/ctables.c

index 563abdf7f1d99951db13b7522e1d65d9cb0f7b50..268a44692e8f1ca1256441263594734daa734bff 100644 (file)
@@ -25,6 +25,7 @@
 #include "language/lexer/lexer.h"
 #include "language/lexer/variable-parser.h"
 #include "language/stats/freq.h"
+#include "libpspp/array.h"
 #include "libpspp/assertion.h"
 #include "libpspp/hmap.h"
 #include "libpspp/message.h"
@@ -1354,8 +1355,27 @@ struct ctables_freqtab
   {
     struct var_array vars;
     struct hmap data;           /* Contains "struct freq"s. */
+    struct freq **sorted;
   };
 
+static int
+compare_freq_3way (const void *a_, const void *b_, const void *vars_)
+{
+  const struct var_array *vars = vars_;
+  struct freq *const *a = a_;
+  struct freq *const *b = b_;
+
+  for (size_t i = 0; i < vars->n; i++)
+    {
+      int cmp = value_compare_3way (&(*a)->values[i], &(*b)->values[i],
+                                    var_get_width (vars->vars[i]));
+      if (cmp)
+        return cmp;
+    }
+  
+  return 0;
+}
+
 static bool
 ctables_execute (struct dataset *ds, struct ctables *ct)
 {
@@ -1448,6 +1468,19 @@ ctables_execute (struct dataset *ds, struct ctables *ct)
     }
   casereader_destroy (input);
 
+  for (size_t i = 0; i < n_fts; i++)
+    {
+      struct ctables_freqtab *ft = fts[i];
+      ft->sorted = xnmalloc (ft->data.count, sizeof *ft->sorted);
+
+      struct freq *f;
+      size_t n = 0;
+      HMAP_FOR_EACH (f, struct freq, node, &ft->data)
+        ft->sorted[n++] = f;
+      sort (ft->sorted, ft->data.count, sizeof *ft->sorted,
+            compare_freq_3way, &ft->vars);
+    }
+
   for (size_t i = 0; i < n_fts; i++)
     {
       struct ctables_freqtab *ft = fts[i];
@@ -1463,6 +1496,7 @@ ctables_execute (struct dataset *ds, struct ctables *ct)
           free (f);
         }
       hmap_destroy (&ft->data);
+      free (ft->sorted);
       var_array_uninit (&ft->vars);
       free (ft);
     }