+
+ struct ctables_summary_spec_set merged = { .n = 0 };
+ struct merge_item *items = xnmalloc (2 * stack->n, sizeof *items);
+ size_t n_left = 0;
+ for (size_t j = 0; j < stack->n; j++)
+ {
+ const struct ctables_nest *nest = &stack->nests[j];
+ if (!nest->n)
+ continue;
+
+ for (enum ctables_summary_variant sv = 0; sv < N_CSVS; sv++)
+ {
+ items[n_left] = (struct merge_item) {
+ .tiebreaker = n_left,
+ .set = &nest->specs[sv]
+ };
+ n_left++;
+ }
+ }
+
+ while (n_left > 0)
+ {
+ struct merge_item min = items[0];
+ for (size_t j = 1; j < n_left; j++)
+ if (merge_item_compare_3way (&items[j], &min) < 0)
+ min = items[j];
+
+ /* XXX Add to 'merged' */
+ if (merged.n >= merged.allocated)
+ merged.specs = x2nrealloc (merged.specs, &merged.allocated,
+ sizeof *merged.specs);
+ merged.specs[merged.n++] = min.set->specs[min.ofs];
+
+ for (size_t j = 0; j < n_left; )
+ {
+ if (merge_item_compare_3way (&items[j], &min) == 0)
+ {
+ struct merge_item *item = &items[j];
+ item->set->specs[item->ofs].axis_idx = merged.n - 1;
+ if (++item->ofs >= item->set->n)
+ {
+ items[j] = items[--n_left];
+ continue;
+ }
+ }
+ j++;
+ }
+ }
+
+ for (size_t j = 0; j < merged.n; j++)
+ printf ("%s\n", ctables_summary_function_name (merged.specs[j].function));