}
-static double
+static double UNUSED
ctables_summary_value (union ctables_summary *s,
const struct ctables_summary_spec *ss)
{
const struct ctables_summary_spec *summaries;
size_t n_summaries;
const struct variable *summary_var;
- struct ctables_freq **sorted;
};
static struct ctables_freq *
var, value, weight);
}
+struct ctables_axis_render
+ {
+ size_t ofs;
+ struct variable **vars;
+ size_t n_vars;
+
+ struct ctables_freq **freqs;
+ size_t n_freqs;
+ };
+
static int
-ctables_freq_compare_3way (const void *a_, const void *b_, const void *vars_)
+ctables_freq_compare_3way (const void *a_, const void *b_, const void *ar_)
{
- const struct var_array *vars = vars_;
+ const struct ctables_axis_render *ar = ar_;
struct ctables_freq *const *a = a_;
struct ctables_freq *const *b = b_;
- for (size_t i = 0; i < vars->n; i++)
+ for (size_t i = 0; i < ar->n_vars; i++)
{
- int cmp = value_compare_3way (&(*a)->values[i], &(*b)->values[i],
- var_get_width (vars->vars[i]));
+ int cmp = value_compare_3way (&(*a)->values[i + ar->ofs],
+ &(*b)->values[i + ar->ofs],
+ var_get_width (ar->vars[i]));
if (cmp)
return cmp;
}
struct ctables_table *t = &ct->tables[i];
struct pivot_table *pt = pivot_table_create (N_("Custom Tables"));
- struct pivot_dimension *d = pivot_dimension_create (
- pt, PIVOT_AXIS_ROW, N_("Rows"));
+ pivot_table_set_look (pt, ct->look);
+ struct pivot_dimension *d[PIVOT_N_AXES];
+ for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
+ {
+ static const char *names[] = {
+ [PIVOT_AXIS_ROW] = N_("Rows"),
+ [PIVOT_AXIS_COLUMN] = N_("Columns"),
+ [PIVOT_AXIS_LAYER] = N_("Layers"),
+ };
+ d[a] = (t->axes[a] || a == t->slabels_position
+ ? pivot_dimension_create (pt, a, names[a])
+ : NULL);
+ }
for (size_t j = 0; j < t->n_fts; j++)
{
struct ctables_freqtab *ft = t->fts[j];
- ft->sorted = xnmalloc (ft->data.count, sizeof *ft->sorted);
-
- struct ctables_freq *f;
- size_t n = 0;
- HMAP_FOR_EACH (f, struct ctables_freq, node, &ft->data)
- ft->sorted[n++] = f;
- assert (n == ft->data.count);
- sort (ft->sorted, n, sizeof *ft->sorted,
- ctables_freq_compare_3way, &ft->vars);
-
- struct pivot_category **groups = xnmalloc (ft->vars.n,
- sizeof *groups);
- for (size_t k = 0; k < n; k++)
+
+ struct ctables_axis_render axis_renders[PIVOT_N_AXES];
+
+ for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
{
- struct ctables_freq *prev = k > 0 ? ft->sorted[k - 1] : NULL;
- struct ctables_freq *f = ft->sorted[k];
-
- size_t n_common = 0;
- if (prev)
- for (; n_common + 1 < ft->vars.n; n_common++)
- if (!value_equal (&prev->values[n_common],
- &f->values[n_common],
- var_get_type (ft->vars.vars[n_common])))
+ size_t ofs = 0;
+ struct variable **vars = NULL;
+ size_t n = 0;
+ for (size_t k = 0; k < ft->vars.n; k++)
+ if (ft->vars.axes[k] == a)
+ {
+ ofs = k;
+ vars = &ft->vars.vars[k];
+ for (n = 1; k + n < ft->vars.n; n++)
+ if (ft->vars.axes[k + n] != a)
+ break;
break;
+ }
- for (size_t m = n_common; m < ft->vars.n; m++)
- {
- struct pivot_category *parent = m > 0 ? groups[m - 1] : d->root;
- const struct variable *var = ft->vars.vars[m];
- enum ctables_vlabel vlabel = ct->vlabels[var_get_dict_index (var)];
+ struct ctables_axis_render *ar = &axis_renders[a];
+ *ar = (struct ctables_axis_render) {
+ .ofs = ofs,
+ .vars = vars,
+ .n_vars = n
+ };
+ printf ("axis %s: %zu variables\n", pivot_axis_type_to_string (a), n);
+ if (!n)
+ continue;
- if (vlabel != CTVL_NONE)
- parent = pivot_category_create_group__ (
- parent, pivot_value_new_variable (ft->vars.vars[m]));
+ ar->freqs = xnmalloc (ft->data.count, sizeof *ar->freqs);
- if (m + 1 < ft->vars.n)
- parent = pivot_category_create_group__ (
- parent,
- pivot_value_new_var_value (ft->vars.vars[m], &f->values[m]));
- groups[m] = parent;
+ struct ctables_freq *f;
+ size_t n_freqs = 0;
+ HMAP_FOR_EACH (f, struct ctables_freq, node, &ft->data)
+ ar->freqs[n_freqs++] = f;
+ assert (n_freqs == ft->data.count);
+ ar->n_freqs = sort_unique (ar->freqs, n_freqs, sizeof *ar->freqs,
+ ctables_freq_compare_3way, ar);
+ }
- if (m == ft->vars.n - 1)
+ for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
+ {
+ struct ctables_axis_render *ar = &axis_renders[a];
+ if (!ar->n_vars && a != t->slabels_position)
+ continue;
+
+ struct pivot_category **groups = xnmalloc (ar->n_vars,
+ sizeof *groups);
+ for (size_t k = 0; k < ar->n_freqs; k++)
+ {
+ struct ctables_freq *prev = k > 0 ? ar->freqs[k - 1] : NULL;
+ struct ctables_freq *f = ar->freqs[k];
+
+ size_t n_common = 0;
+ if (prev)
+ for (; n_common + 1 < ar->n_vars; n_common++)
+ if (!value_equal (&prev->values[ar->ofs + n_common],
+ &f->values[ar->ofs + n_common],
+ var_get_type (ar->vars[n_common])))
+ break;
+
+ for (size_t m = n_common; m < ar->n_vars; m++)
{
- struct pivot_category *c = pivot_category_create_group__ (
- parent,
- pivot_value_new_var_value (ft->vars.vars[ft->vars.n - 1],
- &f->values[ft->vars.n - 1]));
- for (size_t p = 0; p < ft->n_summaries; p++)
+ struct pivot_category *parent = m > 0 ? groups[m - 1] : d[a]->root;
+ const struct variable *var = ar->vars[m];
+ enum ctables_vlabel vlabel = ct->vlabels[var_get_dict_index (var)];
+
+ if (vlabel != CTVL_NONE)
+ parent = pivot_category_create_group__ (
+ parent, pivot_value_new_variable (ar->vars[m]));
+
+ if (m + 1 < ar->n_vars)
+ parent = pivot_category_create_group__ (
+ parent,
+ pivot_value_new_var_value (ar->vars[m], &f->values[m]));
+ groups[m] = parent;
+
+ if (m == ar->n_vars - 1)
{
- double value = ctables_summary_value (
- &f->summaries[p], &ft->summaries[p]);
- int leaf = pivot_category_create_leaf (
- c, pivot_value_new_text (ft->summaries[p].label));
- pivot_table_put1 (pt, leaf, pivot_value_new_number (value));
+ pivot_category_create_leaf (
+ parent,
+ pivot_value_new_var_value (ar->vars[ar->n_vars - 1],
+ &f->values[ar->ofs + ar->n_vars - 1]));
+#if 0
+ for (size_t p = 0; p < ft->n_summaries; p++)
+ {
+ if (a == t->slabels_position)
+ pivot_category_create_leaf (
+ c, pivot_value_new_text (ft->summaries[p].label));
+ //pivot_table_put1 (pt, leaf, pivot_value_new_number (value));
+ }
+#endif
}
}
}
+ free (groups);
}
- free (groups);
}
pivot_table_submit (pt);
}
free (f);
}
hmap_destroy (&ft->data);
- free (ft->sorted);
var_array_uninit (&ft->vars);
free (ft);
}
.vlabels = vlabels,
.hide_threshold = 5,
};
+ ct->look->omit_empty = false;
if (!lex_force_match (lexer, T_SLASH))
goto error;