static void ctables_summary_spec_set_uninit (struct ctables_summary_spec_set *);
-struct var_array
+/* A nested sequence of variables, e.g. a > b > c. */
+struct ctables_nest
{
struct variable **vars;
size_t n;
struct ctables_summary_spec_set total_sss;
};
-/* A stack of nestings, e.g. this represents (...) + (...) + ... + (...). */
+/* A stack of nestings, e.g. nest1 + nest2 + ... + nestN. */
struct ctables_stack
{
- struct var_array *vas;
+ struct ctables_nest *nests;
size_t n;
};
}
static void
-var_array_uninit (struct var_array *va)
+ctables_nest_uninit (struct ctables_nest *nest)
{
- if (va)
- free (va->vars);
+ if (nest)
+ free (nest->vars);
}
static void
if (stack)
{
for (size_t i = 0; i < stack->n; i++)
- var_array_uninit (&stack->vas[i]);
- free (stack->vas);
+ ctables_nest_uninit (&stack->nests[i]);
+ free (stack->nests);
}
}
static struct ctables_stack
-nest_fts (struct ctables_stack va0, struct ctables_stack va1)
+nest_fts (struct ctables_stack s0, struct ctables_stack s1)
{
- if (!va0.n)
- return va1;
- else if (!va1.n)
- return va0;
-
- struct ctables_stack stack = { .vas = xnmalloc (va0.n, va1.n * sizeof *stack.vas) };
- for (size_t i = 0; i < va0.n; i++)
- for (size_t j = 0; j < va1.n; j++)
+ if (!s0.n)
+ return s1;
+ else if (!s1.n)
+ return s0;
+
+ struct ctables_stack stack = { .nests = xnmalloc (s0.n, s1.n * sizeof *stack.nests) };
+ for (size_t i = 0; i < s0.n; i++)
+ for (size_t j = 0; j < s1.n; j++)
{
- const struct var_array *a = &va0.vas[i];
- const struct var_array *b = &va1.vas[j];
+ const struct ctables_nest *a = &s0.nests[i];
+ const struct ctables_nest *b = &s1.nests[j];
size_t allocate = a->n + b->n;
struct variable **vars = xnmalloc (allocate, sizeof *vars);
vars[n++] = b->vars[k];
assert (n == allocate);
- const struct var_array *summary_src;
+ const struct ctables_nest *summary_src;
if (!a->cell_sss.var)
summary_src = b;
else if (!b->cell_sss.var)
summary_src = a;
else
NOT_REACHED ();
- stack.vas[stack.n++] = (struct var_array) {
+ stack.nests[stack.n++] = (struct ctables_nest) {
.vars = vars,
.scale_idx = (a->scale_idx != SIZE_MAX ? a->scale_idx
: b->scale_idx != SIZE_MAX ? a->n + b->scale_idx
.total_sss = summary_src->total_sss,
};
}
- ctables_stack_uninit (&va0);
- ctables_stack_uninit (&va1);
+ ctables_stack_uninit (&s0);
+ ctables_stack_uninit (&s1);
return stack;
}
static struct ctables_stack
stack_fts (struct ctables_stack s0, struct ctables_stack s1)
{
- struct ctables_stack stack = { .vas = xnmalloc (s0.n + s1.n, sizeof *stack.vas) };
+ struct ctables_stack stack = { .nests = xnmalloc (s0.n + s1.n, sizeof *stack.nests) };
for (size_t i = 0; i < s0.n; i++)
- stack.vas[stack.n++] = s0.vas[i];
+ stack.nests[stack.n++] = s0.nests[i];
for (size_t i = 0; i < s1.n; i++)
- stack.vas[stack.n++] = s1.vas[i];
+ stack.nests[stack.n++] = s1.nests[i];
assert (stack.n == s0.n + s1.n);
- free (s0.vas);
- free (s1.vas);
+ free (s0.nests);
+ free (s1.nests);
return stack;
}
struct variable **vars = xmalloc (sizeof *vars);
*vars = a->var.var;
- struct var_array *va = xmalloc (sizeof *va);
- *va = (struct var_array) {
+ struct ctables_nest *nest = xmalloc (sizeof *nest);
+ *nest = (struct ctables_nest) {
.vars = vars,
.n = 1,
.scale_idx = a->scale ? 0 : SIZE_MAX,
};
if (a->cell_sss.n || a->scale)
{
- va->cell_sss = a->cell_sss;
- va->total_sss = a->total_sss;
- va->cell_sss.var = a->var.var;
- va->total_sss.var = a->var.var;
+ nest->cell_sss = a->cell_sss;
+ nest->total_sss = a->total_sss;
+ nest->cell_sss.var = a->var.var;
+ nest->total_sss.var = a->var.var;
}
- return (struct ctables_stack) { .vas = va, .n = 1 };
+ return (struct ctables_stack) { .nests = nest, .n = 1 };
case CTAO_STACK:
return stack_fts (enumerate_fts (axis_type, a->subs[0]),
if (a_idx != b_idx)
return a_idx < b_idx ? -1 : 1;
- const struct var_array *va = &aux->t->stacks[aux->a].vas[a_idx];
- for (size_t i = 0; i < va->n; i++)
- if (i != va->scale_idx)
+ const struct ctables_nest *nest = &aux->t->stacks[aux->a].nests[a_idx];
+ for (size_t i = 0; i < nest->n; i++)
+ if (i != nest->scale_idx)
{
- const struct variable *var = va->vars[i];
+ const struct variable *var = nest->vars[i];
const struct ctables_cell_value *a_cv = &a->axes[aux->a].cvs[i];
const struct ctables_cell_value *b_cv = &b->axes[aux->a].cvs[i];
if (a_cv->category != b_cv->category)
for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
{
size_t idx = cell->axes[a].stack_idx;
- const struct var_array *va = &t->stacks[a].vas[idx];
+ const struct ctables_nest *nest = &t->stacks[a].nests[idx];
hash = hash_int (idx, hash);
- for (size_t i = 0; i < va->n_domains[domain]; i++)
+ for (size_t i = 0; i < nest->n_domains[domain]; i++)
{
- size_t v_idx = va->domains[domain][i];
+ size_t v_idx = nest->domains[domain][i];
hash = value_hash (&cell->axes[a].cvs[v_idx].value,
- var_get_width (va->vars[v_idx]), hash);
+ var_get_width (nest->vars[v_idx]), hash);
}
}
if (idx != df->axes[a].stack_idx)
goto not_equal;
- const struct var_array *va = &t->stacks[a].vas[idx];
- for (size_t i = 0; i < va->n_domains[domain]; i++)
+ const struct ctables_nest *nest = &t->stacks[a].nests[idx];
+ for (size_t i = 0; i < nest->n_domains[domain]; i++)
{
- size_t v_idx = va->domains[domain][i];
+ size_t v_idx = nest->domains[domain][i];
if (!value_equal (&df->axes[a].cvs[v_idx].value,
&cell->axes[a].cvs[v_idx].value,
- var_get_width (va->vars[v_idx])))
+ var_get_width (nest->vars[v_idx])))
goto not_equal;
}
}
const struct ctables_category *cats[PIVOT_N_AXES][10],
double weight)
{
- const struct var_array *ss = &t->stacks[t->summary_axis].vas[ix[t->summary_axis]];
+ const struct ctables_nest *ss = &t->stacks[t->summary_axis].nests[ix[t->summary_axis]];
size_t hash = 0;
bool total = false;
for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
{
- const struct var_array *va = &t->stacks[a].vas[ix[a]];
+ const struct ctables_nest *nest = &t->stacks[a].nests[ix[a]];
hash = hash_int (ix[a], hash);
- for (size_t i = 0; i < va->n; i++)
- if (i != va->scale_idx)
+ for (size_t i = 0; i < nest->n; i++)
+ if (i != nest->scale_idx)
{
hash = hash_pointer (cats[a][i], hash);
if (cats[a][i]->type != CCT_TOTAL
&& cats[a][i]->type != CCT_SUBTOTAL
&& cats[a][i]->type != CCT_HSUBTOTAL)
- hash = value_hash (case_data (c, va->vars[i]),
- var_get_width (va->vars[i]), hash);
+ hash = value_hash (case_data (c, nest->vars[i]),
+ var_get_width (nest->vars[i]), hash);
else
total = true;
}
{
for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
{
- const struct var_array *va = &t->stacks[a].vas[ix[a]];
+ const struct ctables_nest *nest = &t->stacks[a].nests[ix[a]];
if (cell->axes[a].stack_idx != ix[a])
goto not_equal;
- for (size_t i = 0; i < va->n; i++)
- if (i != va->scale_idx
+ for (size_t i = 0; i < nest->n; i++)
+ if (i != nest->scale_idx
&& (cats[a][i] != cell->axes[a].cvs[i].category
|| (cats[a][i]->type != CCT_TOTAL
&& cats[a][i]->type != CCT_SUBTOTAL
&& cats[a][i]->type != CCT_HSUBTOTAL
- && !value_equal (case_data (c, va->vars[i]),
+ && !value_equal (case_data (c, nest->vars[i]),
&cell->axes[a].cvs[i].value,
- var_get_width (va->vars[i])))))
+ var_get_width (nest->vars[i])))))
goto not_equal;
}
cell->total = total;
for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
{
- const struct var_array *va = &t->stacks[a].vas[ix[a]];
+ const struct ctables_nest *nest = &t->stacks[a].nests[ix[a]];
cell->axes[a].stack_idx = ix[a];
- cell->axes[a].cvs = (va->n
- ? xnmalloc (va->n, sizeof *cell->axes[a].cvs)
+ cell->axes[a].cvs = (nest->n
+ ? xnmalloc (nest->n, sizeof *cell->axes[a].cvs)
: NULL);
- for (size_t i = 0; i < va->n; i++)
+ for (size_t i = 0; i < nest->n; i++)
{
- if (i != va->scale_idx)
+ if (i != nest->scale_idx)
{
const struct ctables_category *subtotal = cats[a][i]->subtotal;
if (subtotal && subtotal->type == CCT_HSUBTOTAL)
}
cell->axes[a].cvs[i].category = cats[a][i];
- value_clone (&cell->axes[a].cvs[i].value, case_data (c, va->vars[i]),
- var_get_width (va->vars[i]));
+ value_clone (&cell->axes[a].cvs[i].value, case_data (c, nest->vars[i]),
+ var_get_width (nest->vars[i]));
}
}
size_t ix[PIVOT_N_AXES],
const struct ctables_category *cats[PIVOT_N_AXES][10],
double weight,
- enum pivot_axis_type start_a, size_t start_va)
+ enum pivot_axis_type start_axis, size_t start_nest)
{
- for (enum pivot_axis_type a = start_a; a < PIVOT_N_AXES; a++)
+ for (enum pivot_axis_type a = start_axis; a < PIVOT_N_AXES; a++)
{
- const struct var_array *va = &t->stacks[a].vas[ix[a]];
- for (size_t i = start_va; i < va->n; i++)
+ const struct ctables_nest *nest = &t->stacks[a].nests[ix[a]];
+ for (size_t i = start_nest; i < nest->n; i++)
{
- if (i == va->scale_idx)
+ if (i == nest->scale_idx)
continue;
- const struct variable *var = va->vars[i];
+ const struct variable *var = nest->vars[i];
const struct ctables_category *total = ctables_categories_total (
t->categories[var_get_dict_index (var)]);
cats[a][i] = save;
}
}
- start_va = 0;
+ start_nest = 0;
}
}
const struct ctables_category *cats[PIVOT_N_AXES][10];
for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
{
- const struct var_array *va = &t->stacks[a].vas[ix[a]];
- for (size_t i = 0; i < va->n; i++)
+ const struct ctables_nest *nest = &t->stacks[a].nests[ix[a]];
+ for (size_t i = 0; i < nest->n; i++)
{
- if (i == va->scale_idx)
+ if (i == nest->scale_idx)
continue;
- const struct variable *var = va->vars[i];
+ const struct variable *var = nest->vars[i];
const union value *value = case_data (c, var);
if (var_is_numeric (var) && value->f == SYSMIS)
for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
{
- const struct var_array *va = &t->stacks[a].vas[ix[a]];
- for (size_t i = 0; i < va->n; i++)
+ const struct ctables_nest *nest = &t->stacks[a].nests[ix[a]];
+ for (size_t i = 0; i < nest->n; i++)
{
- if (i == va->scale_idx)
+ if (i == nest->scale_idx)
continue;
const struct ctables_category *save = cats[a][i];
for (size_t j = 0; j < t->stacks[a].n; j++)
{
- struct var_array *va = &t->stacks[a].vas[j];
+ struct ctables_nest *nest = &t->stacks[a].nests[j];
for (enum ctables_domain_type dt = 0; dt < N_CTDTS; dt++)
{
- va->domains[dt] = xmalloc (va->n * sizeof *va->domains[dt]);
- va->n_domains[dt] = 0;
+ nest->domains[dt] = xmalloc (nest->n * sizeof *nest->domains[dt]);
+ nest->n_domains[dt] = 0;
- for (size_t k = 0; k < va->n; k++)
+ for (size_t k = 0; k < nest->n; k++)
{
- if (k == va->scale_idx)
+ if (k == nest->scale_idx)
continue;
switch (dt)
: dt == CTDT_ROW ? a == PIVOT_AXIS_COLUMN
: a == PIVOT_AXIS_ROW)
{
- if (k == va->n - 1
- || (va->scale_idx == va->n - 1
- && k == va->n - 2))
+ if (k == nest->n - 1
+ || (nest->scale_idx == nest->n - 1
+ && k == nest->n - 2))
continue;
}
break;
break;
}
- va->domains[dt][va->n_domains[dt]++] = k;
+ nest->domains[dt][nest->n_domains[dt]++] = k;
}
}
}
}
else
{
- struct var_array *va = xmalloc (sizeof *va);
- *va = (struct var_array) { .n = 0 };
- t->stacks[a] = (struct ctables_stack) { .vas = va, .n = 1 };
+ struct ctables_nest *nest = xmalloc (sizeof *nest);
+ *nest = (struct ctables_nest) { .n = 0 };
+ t->stacks[a] = (struct ctables_stack) { .nests = nest, .n = 1 };
}
for (size_t i = 0; i < t->stacks[t->summary_axis].n; i++)
{
- struct var_array *va = &t->stacks[t->summary_axis].vas[i];
- if (!va->cell_sss.n)
+ struct ctables_nest *nest = &t->stacks[t->summary_axis].nests[i];
+ if (!nest->cell_sss.n)
{
- struct ctables_summary_spec_set *sss = &va->cell_sss;
+ struct ctables_summary_spec_set *sss = &nest->cell_sss;
sss->summaries = xmalloc (sizeof *sss->summaries);
sss->n = 1;
.label = ctables_summary_default_label (function, 0),
};
if (!sss->var)
- sss->var = va->vars[0];
+ sss->var = nest->vars[0];
- va->total_sss = va->cell_sss;
+ nest->total_sss = nest->cell_sss;
}
- else if (!va->total_sss.n)
- va->total_sss = va->cell_sss;
+ else if (!nest->total_sss.n)
+ nest->total_sss = nest->cell_sss;
}
}
size_t max_depth = 0;
for (size_t j = 0; j < t->stacks[a].n; j++)
- if (t->stacks[a].vas[j].n > max_depth)
- max_depth = t->stacks[a].vas[j].n;
+ if (t->stacks[a].nests[j].n > max_depth)
+ max_depth = t->stacks[a].nests[j].n;
struct pivot_category **groups = xnmalloc (max_depth, sizeof *groups);
struct pivot_category *top = NULL;
for (size_t j = 0; j < n; j++)
{
struct ctables_cell *cell = sorted[j];
- const struct var_array *va = &t->stacks[a].vas[cell->axes[a].stack_idx];
+ const struct ctables_nest *nest = &t->stacks[a].nests[cell->axes[a].stack_idx];
size_t n_common = 0;
bool new_subtable = false;
struct ctables_cell *prev = sorted[j - 1];
if (prev->axes[a].stack_idx == cell->axes[a].stack_idx)
{
- for (; n_common < va->n; n_common++)
- if (n_common != va->scale_idx
+ for (; n_common < nest->n; n_common++)
+ if (n_common != nest->scale_idx
&& (prev->axes[a].cvs[n_common].category
!= cell->axes[a].cvs[n_common].category
|| !value_equal (&prev->axes[a].cvs[n_common].value,
&cell->axes[a].cvs[n_common].value,
- var_get_type (va->vars[n_common]))))
+ var_get_type (nest->vars[n_common]))))
break;
}
else
if (new_subtable)
{
- enum ctables_vlabel vlabel = ct->vlabels[var_get_dict_index (va->vars[0])];
+ enum ctables_vlabel vlabel = ct->vlabels[var_get_dict_index (nest->vars[0])];
top = d[a]->root;
if (vlabel != CTVL_NONE)
top = pivot_category_create_group__ (
- top, pivot_value_new_variable (va->vars[0]));
+ top, pivot_value_new_variable (nest->vars[0]));
}
- if (n_common == va->n)
+ if (n_common == nest->n)
{
cell->axes[a].leaf = prev_leaf;
continue;
}
- for (size_t k = n_common; k < va->n; k++)
+ for (size_t k = n_common; k < nest->n; k++)
{
struct pivot_category *parent = k > 0 ? groups[k - 1] : top;
struct pivot_value *label
- = (k == va->scale_idx ? NULL
+ = (k == nest->scale_idx ? NULL
: (cell->axes[a].cvs[k].category->type == CCT_TOTAL
|| cell->axes[a].cvs[k].category->type == CCT_SUBTOTAL
|| cell->axes[a].cvs[k].category->type == CCT_HSUBTOTAL)
? pivot_value_new_user_text (cell->axes[a].cvs[k].category->total_label,
SIZE_MAX)
- : pivot_value_new_var_value (va->vars[k],
+ : pivot_value_new_var_value (nest->vars[k],
&cell->axes[a].cvs[k].value));
- if (k == va->n - 1)
+ if (k == nest->n - 1)
{
if (a == t->summary_axis)
{
if (label)
parent = pivot_category_create_group__ (parent, label);
const struct ctables_summary_spec_set *sss
- = cell->total ? &va->total_sss : &va->cell_sss;
+ = cell->total ? &nest->total_sss : &nest->cell_sss;
for (size_t m = 0; m < sss->n; m++)
{
int leaf = pivot_category_create_leaf (
if (label)
parent = pivot_category_create_group__ (parent, label);
- enum ctables_vlabel vlabel = ct->vlabels[var_get_dict_index (va->vars[k + 1])];
+ enum ctables_vlabel vlabel = ct->vlabels[var_get_dict_index (nest->vars[k + 1])];
if (vlabel != CTVL_NONE)
parent = pivot_category_create_group__ (
- parent, pivot_value_new_variable (va->vars[k + 1]));
+ parent, pivot_value_new_variable (nest->vars[k + 1]));
groups[k] = parent;
}
if (cell->hide)
continue;
- const struct var_array *va = &t->stacks[t->summary_axis].vas[cell->axes[t->summary_axis].stack_idx];
- const struct ctables_summary_spec_set *sss = cell->total ? &va->total_sss : &va->cell_sss;
+ const struct ctables_nest *nest = &t->stacks[t->summary_axis].nests[cell->axes[t->summary_axis].stack_idx];
+ const struct ctables_summary_spec_set *sss = cell->total ? &nest->total_sss : &nest->cell_sss;
for (size_t j = 0; j < sss->n; j++)
{
size_t dindexes[3];