struct
{
- size_t nest_idx;
struct ctables_cell_value
{
const struct ctables_category *category;
int leaf;
};
+struct ctables_section
+ {
+ struct ctables_table *table;
+ struct ctables_nest *nests[PIVOT_N_AXES];
+ struct hmap cells; /* Contains "struct ctable_cell"s. */
+ struct hmap domains[N_CTDTS]; /* Contains "struct ctable_domain"s. */
+ };
+
struct ctables_table
{
struct ctables_axis *axes[PIVOT_N_AXES];
struct ctables_stack stacks[PIVOT_N_AXES];
+ struct ctables_section *sections;
+ size_t n_sections;
enum pivot_axis_type summary_axis;
struct ctables_summary_spec_set summary_specs;
- struct hmap cells;
- struct hmap domains[N_CTDTS];
const struct variable *clabels_example;
struct hmap clabels_values_map;
struct ctables_cell_sort_aux
{
- const struct ctables_table *t;
+ const struct ctables_nest *nest;
enum pivot_axis_type a;
};
const struct ctables_cell *a = *ap;
const struct ctables_cell *b = *bp;
- size_t a_idx = a->axes[aux->a].nest_idx;
- size_t b_idx = b->axes[aux->a].nest_idx;
- if (a_idx != b_idx)
- return a_idx < b_idx ? -1 : 1;
-
- const struct ctables_nest *nest = &aux->t->stacks[aux->a].nests[a_idx];
+ const struct ctables_nest *nest = aux->nest;
for (size_t i = 0; i < nest->n; i++)
if (i != nest->scale_idx)
{
*/
static struct ctables_domain *
-ctables_domain_insert (struct ctables_table *t, struct ctables_cell *cell,
+ctables_domain_insert (struct ctables_section *s, struct ctables_cell *cell,
enum ctables_domain_type domain)
{
size_t hash = 0;
for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
{
- size_t idx = cell->axes[a].nest_idx;
- const struct ctables_nest *nest = &t->stacks[a].nests[idx];
- hash = hash_int (idx, hash);
+ const struct ctables_nest *nest = s->nests[a];
for (size_t i = 0; i < nest->n_domains[domain]; i++)
{
size_t v_idx = nest->domains[domain][i];
}
struct ctables_domain *d;
- HMAP_FOR_EACH_WITH_HASH (d, struct ctables_domain, node, hash, &t->domains[domain])
+ HMAP_FOR_EACH_WITH_HASH (d, struct ctables_domain, node, hash, &s->domains[domain])
{
const struct ctables_cell *df = d->example;
for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
{
- size_t idx = cell->axes[a].nest_idx;
- if (idx != df->axes[a].nest_idx)
- goto not_equal;
-
- const struct ctables_nest *nest = &t->stacks[a].nests[idx];
+ const struct ctables_nest *nest = s->nests[a];
for (size_t i = 0; i < nest->n_domains[domain]; i++)
{
size_t v_idx = nest->domains[domain][i];
d = xmalloc (sizeof *d);
*d = (struct ctables_domain) { .example = cell };
- hmap_insert (&t->domains[domain], &d->node, hash);
+ hmap_insert (&s->domains[domain], &d->node, hash);
return d;
}
}
static struct ctables_cell *
-ctables_cell_insert__ (struct ctables_table *t, const struct ccase *c,
- size_t ix[PIVOT_N_AXES],
+ctables_cell_insert__ (struct ctables_section *s, const struct ccase *c,
const struct ctables_category *cats[PIVOT_N_AXES][10])
{
- const struct ctables_nest *ss = &t->stacks[t->summary_axis].nests[ix[t->summary_axis]];
+ const struct ctables_nest *ss = s->nests[s->table->summary_axis];
size_t hash = 0;
enum ctables_summary_variant sv = CSV_CELL;
for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
{
- const struct ctables_nest *nest = &t->stacks[a].nests[ix[a]];
- hash = hash_int (ix[a], hash);
+ const struct ctables_nest *nest = s->nests[a];
for (size_t i = 0; i < nest->n; i++)
if (i != nest->scale_idx)
{
}
struct ctables_cell *cell;
- HMAP_FOR_EACH_WITH_HASH (cell, struct ctables_cell, node, hash, &t->cells)
+ HMAP_FOR_EACH_WITH_HASH (cell, struct ctables_cell, node, hash, &s->cells)
{
for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
{
- const struct ctables_nest *nest = &t->stacks[a].nests[ix[a]];
- if (cell->axes[a].nest_idx != ix[a])
- goto not_equal;
+ const struct ctables_nest *nest = s->nests[a];
for (size_t i = 0; i < nest->n; i++)
if (i != nest->scale_idx
&& (cats[a][i] != cell->axes[a].cvs[i].category
cell->contributes_to_domains = true;
for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
{
- const struct ctables_nest *nest = &t->stacks[a].nests[ix[a]];
- cell->axes[a].nest_idx = ix[a];
+ const struct ctables_nest *nest = s->nests[a];
cell->axes[a].cvs = (nest->n
? xnmalloc (nest->n, sizeof *cell->axes[a].cvs)
: NULL);
for (size_t i = 0; i < specs->n; i++)
ctables_summary_init (&cell->summaries[i], &specs->specs[i]);
for (enum ctables_domain_type dt = 0; dt < N_CTDTS; dt++)
- cell->domains[dt] = ctables_domain_insert (t, cell, dt);
- hmap_insert (&t->cells, &cell->node, hash);
+ cell->domains[dt] = ctables_domain_insert (s, cell, dt);
+ hmap_insert (&s->cells, &cell->node, hash);
return cell;
}
static void
-ctables_cell_add__ (struct ctables_table *t, const struct ccase *c,
- size_t ix[PIVOT_N_AXES],
+ctables_cell_add__ (struct ctables_section *s, const struct ccase *c,
const struct ctables_category *cats[PIVOT_N_AXES][10],
double d_weight, double e_weight)
{
- struct ctables_cell *cell = ctables_cell_insert__ (t, c, ix, cats);
- const struct ctables_nest *ss = &t->stacks[t->summary_axis].nests[ix[t->summary_axis]];
+ struct ctables_cell *cell = ctables_cell_insert__ (s, c, cats);
+ const struct ctables_nest *ss = s->nests[s->table->summary_axis];
const struct ctables_summary_spec_set *specs = &ss->specs[cell->sv];
for (size_t i = 0; i < specs->n; i++)
}
static void
-recurse_totals (struct ctables_table *t, const struct ccase *c,
- size_t ix[PIVOT_N_AXES],
+recurse_totals (struct ctables_section *s, const struct ccase *c,
const struct ctables_category *cats[PIVOT_N_AXES][10],
double d_weight, double e_weight,
enum pivot_axis_type start_axis, size_t start_nest)
{
for (enum pivot_axis_type a = start_axis; a < PIVOT_N_AXES; a++)
{
- const struct ctables_nest *nest = &t->stacks[a].nests[ix[a]];
+ const struct ctables_nest *nest = s->nests[a];
for (size_t i = start_nest; i < nest->n; i++)
{
if (i == nest->scale_idx)
const struct variable *var = nest->vars[i];
const struct ctables_category *total = ctables_categories_total (
- t->categories[var_get_dict_index (var)]);
+ s->table->categories[var_get_dict_index (var)]);
if (total)
{
const struct ctables_category *save = cats[a][i];
cats[a][i] = total;
- ctables_cell_add__ (t, c, ix, cats, d_weight, e_weight);
- recurse_totals (t, c, ix, cats, d_weight, e_weight, a, i + 1);
+ ctables_cell_add__ (s, c, cats, d_weight, e_weight);
+ recurse_totals (s, c, cats, d_weight, e_weight, a, i + 1);
cats[a][i] = save;
}
}
}
static void
-recurse_subtotals (struct ctables_table *t, const struct ccase *c,
- size_t ix[PIVOT_N_AXES],
+recurse_subtotals (struct ctables_section *s, const struct ccase *c,
const struct ctables_category *cats[PIVOT_N_AXES][10],
double d_weight, double e_weight,
enum pivot_axis_type start_axis, size_t start_nest)
{
for (enum pivot_axis_type a = start_axis; a < PIVOT_N_AXES; a++)
{
- const struct ctables_nest *nest = &t->stacks[a].nests[ix[a]];
+ const struct ctables_nest *nest = s->nests[a];
for (size_t i = start_nest; i < nest->n; i++)
{
if (i == nest->scale_idx)
if (save->subtotal)
{
cats[a][i] = save->subtotal;
- ctables_cell_add__ (t, c, ix, cats, d_weight, e_weight);
- recurse_subtotals (t, c, ix, cats, d_weight, e_weight, a, i + 1);
+ ctables_cell_add__ (s, c, cats, d_weight, e_weight);
+ recurse_subtotals (s, c, cats, d_weight, e_weight, a, i + 1);
cats[a][i] = save;
}
}
}
static void
-ctables_cell_insert (struct ctables_table *t,
+ctables_cell_insert (struct ctables_section *s,
const struct ccase *c,
- size_t ix[PIVOT_N_AXES],
double d_weight, double e_weight)
{
const struct ctables_category *cats[PIVOT_N_AXES][10];
for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
{
- const struct ctables_nest *nest = &t->stacks[a].nests[ix[a]];
+ const struct ctables_nest *nest = s->nests[a];
for (size_t i = 0; i < nest->n; i++)
{
if (i == nest->scale_idx)
return;
cats[a][i] = ctables_categories_match (
- t->categories[var_get_dict_index (var)], value, var);
+ s->table->categories[var_get_dict_index (var)], value, var);
if (!cats[a][i])
return;
}
}
- ctables_cell_add__ (t, c, ix, cats, d_weight, e_weight);
+ ctables_cell_add__ (s, c, cats, d_weight, e_weight);
- recurse_totals (t, c, ix, cats, d_weight, e_weight, 0, 0);
- recurse_subtotals (t, c, ix, cats, d_weight, e_weight, 0, 0);
+ recurse_totals (s, c, cats, d_weight, e_weight, 0, 0);
+ recurse_subtotals (s, c, cats, d_weight, e_weight, 0, 0);
}
struct merge_item
value_hash (value, width, 0));
}
+static void
+ctables_table_add_section (struct ctables_table *t, enum pivot_axis_type a,
+ size_t ix[PIVOT_N_AXES])
+{
+ if (a < PIVOT_N_AXES)
+ {
+ size_t limit = MAX (t->stacks[a].n, 1);
+ for (ix[a] = 0; ix[a] < limit; ix[a]++)
+ ctables_table_add_section (t, a + 1, ix);
+ }
+ else
+ {
+ struct ctables_section *s = &t->sections[t->n_sections++];
+ *s = (struct ctables_section) {
+ .table = t,
+ .cells = HMAP_INITIALIZER (s->cells),
+ };
+ for (a = 0; a < PIVOT_N_AXES; a++)
+ s->nests[a] = t->stacks[a].n ? &t->stacks[a].nests[ix[a]] : NULL;
+ for (size_t i = 0; i < N_CTDTS; i++)
+ hmap_init (&s->domains[i]);
+ }
+}
+
static void
ctables_table_output (struct ctables *ct, struct ctables_table *t)
{
assert (t->axes[a]);
- struct ctables_cell **sorted = xnmalloc (t->cells.count, sizeof *sorted);
- size_t n_sorted = 0;
+ for (size_t i = 0; i < t->stacks[a].n; i++)
+ {
+ struct ctables_nest *nest = &t->stacks[a].nests[i];
+ struct ctables_section **sections = xnmalloc (t->n_sections,
+ sizeof *sections);
+ size_t n_sections = 0;
- struct ctables_cell *cell;
- HMAP_FOR_EACH (cell, struct ctables_cell, node, &t->cells)
- if (!cell->hide)
- sorted[n_sorted++] = cell;
- assert (n_sorted <= t->cells.count);
-
- struct ctables_cell_sort_aux aux = { .t = t, .a = a };
- sort (sorted, n_sorted, sizeof *sorted, ctables_cell_compare_3way, &aux);
-
- size_t max_depth = 0;
- for (size_t j = 0; j < t->stacks[a].n; j++)
- if (t->stacks[a].nests[j].n > max_depth)
- max_depth = t->stacks[a].nests[j].n;
-
- /* Pivot categories:
-
- - variable label for nest->vars[0], if vlabel != CTVL_NONE
- - category for nest->vars[0], if nest->scale_idx != 0
- - variable label for nest->vars[1], if vlabel != CTVL_NONE
- - category for nest->vars[1], if nest->scale_idx != 1
- ...
- - variable label for nest->vars[n - 1], if vlabel != CTVL_NONE
- - category for nest->vars[n - 1], if t->label_axis[a] == a && nest->scale_idx != n - 1.
- - summary function, if 'a == t->slabels_axis && a ==
- t->summary_axis'.
-
- Additional dimensions:
-
- - If 'a == t->slabels_axis && a != t->summary_axis', add a summary
- dimension.
- - If 't->label_axis[b] == a' for some 'b != a', add a category
- dimension to 'a'.
- */
-
- struct ctables_level
- {
- enum ctables_level_type
+ size_t n_total_cells = 0;
+ size_t max_depth = 0;
+ for (size_t j = 0; j < t->n_sections; j++)
+ if (t->sections[j].nests[a] == nest)
+ {
+ struct ctables_section *s = &t->sections[j];
+ sections[n_sections++] = s;
+ n_total_cells += s->cells.count;
+
+ size_t depth = s->nests[a]->n;
+ max_depth = MAX (depth, max_depth);
+ }
+
+ struct ctables_cell **sorted = xnmalloc (n_total_cells,
+ sizeof *sorted);
+ size_t n_sorted = 0;
+
+ for (size_t j = 0; j < n_sections; j++)
{
- CTL_VAR, /* Variable label for nest->vars[var_idx]. */
- CTL_CATEGORY, /* Category for nest->vars[var_idx]. */
- CTL_SUMMARY, /* Summary functions. */
- }
- type;
+ struct ctables_section *s = sections[j];
- size_t var_idx;
- };
- struct ctables_level *levels = xnmalloc (1 + 2 * max_depth, sizeof *levels);
- size_t n_levels = 0;
+ struct ctables_cell *cell;
+ HMAP_FOR_EACH (cell, struct ctables_cell, node, &s->cells)
+ if (!cell->hide)
+ sorted[n_sorted++] = cell;
+ assert (n_sorted <= n_total_cells);
+ }
- struct pivot_category **groups = xnmalloc (1 + 2 * max_depth, sizeof *groups);
- int prev_leaf = 0;
- for (size_t j = 0; j < n_sorted; j++)
- {
- struct ctables_cell *cell = sorted[j];
- struct ctables_cell *prev = j > 0 ? sorted[j - 1] : NULL;
- const struct ctables_nest *nest = &t->stacks[a].nests[cell->axes[a].nest_idx];
+ struct ctables_cell_sort_aux aux = { .nest = nest, .a = a };
+ sort (sorted, n_sorted, sizeof *sorted, ctables_cell_compare_3way, &aux);
- bool new_subtable = !prev || prev->axes[a].nest_idx != cell->axes[a].nest_idx;
- if (new_subtable)
+ struct ctables_level
{
- n_levels = 0;
- for (size_t k = 0; k < nest->n; k++)
+ enum ctables_level_type
{
- enum ctables_vlabel vlabel = ct->vlabels[var_get_dict_index (nest->vars[k])];
- if (vlabel != CTVL_NONE)
- {
- levels[n_levels++] = (struct ctables_level) {
- .type = CTL_VAR,
- .var_idx = k,
- };
- }
+ CTL_VAR, /* Variable label for nest->vars[var_idx]. */
+ CTL_CATEGORY, /* Category for nest->vars[var_idx]. */
+ CTL_SUMMARY, /* Summary functions. */
+ }
+ type;
- if (nest->scale_idx != k
- && (k != nest->n - 1 || t->label_axis[a] == a))
- {
- levels[n_levels++] = (struct ctables_level) {
- .type = CTL_CATEGORY,
- .var_idx = k,
- };
- }
+ size_t var_idx;
+ };
+ struct ctables_level *levels = xnmalloc (1 + 2 * max_depth, sizeof *levels);
+ size_t n_levels = 0;
+ for (size_t k = 0; k < nest->n; k++)
+ {
+ enum ctables_vlabel vlabel = ct->vlabels[var_get_dict_index (nest->vars[k])];
+ if (vlabel != CTVL_NONE)
+ {
+ levels[n_levels++] = (struct ctables_level) {
+ .type = CTL_VAR,
+ .var_idx = k,
+ };
}
- if (!summary_dimension && a == t->slabels_axis)
+ if (nest->scale_idx != k
+ && (k != nest->n - 1 || t->label_axis[a] == a))
{
levels[n_levels++] = (struct ctables_level) {
- .type = CTL_SUMMARY,
- .var_idx = SIZE_MAX,
+ .type = CTL_CATEGORY,
+ .var_idx = k,
};
}
}
- size_t n_common = 0;
- if (!new_subtable)
+ if (!summary_dimension && a == t->slabels_axis)
{
- for (; n_common < n_levels; n_common++)
- {
- const struct ctables_level *level = &levels[n_common];
- if (level->type == CTL_CATEGORY)
- {
- size_t var_idx = level->var_idx;
- const struct ctables_category *c = cell->axes[a].cvs[var_idx].category;
- if (prev->axes[a].cvs[var_idx].category != c)
- break;
- else if (c->type != CCT_SUBTOTAL
- && c->type != CCT_HSUBTOTAL
- && c->type != CCT_TOTAL
- && !value_equal (&prev->axes[a].cvs[var_idx].value,
- &cell->axes[a].cvs[var_idx].value,
- var_get_type (nest->vars[var_idx])))
- break;
- }
- }
+ levels[n_levels++] = (struct ctables_level) {
+ .type = CTL_SUMMARY,
+ .var_idx = SIZE_MAX,
+ };
}
- for (size_t k = n_common; k < n_levels; k++)
+ /* Pivot categories:
+
+ - variable label for nest->vars[0], if vlabel != CTVL_NONE
+ - category for nest->vars[0], if nest->scale_idx != 0
+ - variable label for nest->vars[1], if vlabel != CTVL_NONE
+ - category for nest->vars[1], if nest->scale_idx != 1
+ ...
+ - variable label for nest->vars[n - 1], if vlabel != CTVL_NONE
+ - category for nest->vars[n - 1], if t->label_axis[a] == a && nest->scale_idx != n - 1.
+ - summary function, if 'a == t->slabels_axis && a ==
+ t->summary_axis'.
+
+ Additional dimensions:
+
+ - If 'a == t->slabels_axis && a != t->summary_axis', add a summary
+ dimension.
+ - If 't->label_axis[b] == a' for some 'b != a', add a category
+ dimension to 'a'.
+ */
+
+
+ struct pivot_category **groups = xnmalloc (1 + 2 * max_depth, sizeof *groups);
+ int prev_leaf = 0;
+ for (size_t j = 0; j < n_sorted; j++)
{
- const struct ctables_level *level = &levels[k];
- struct pivot_category *parent = k ? groups[k - 1] : d[a]->root;
- if (level->type == CTL_SUMMARY)
- {
- assert (k == n_levels - 1);
+ struct ctables_cell *cell = sorted[j];
+ struct ctables_cell *prev = j > 0 ? sorted[j - 1] : NULL;
- const struct ctables_summary_spec_set *specs = &t->summary_specs;
- for (size_t m = 0; m < specs->n; m++)
+ size_t n_common = 0;
+ if (j > 0)
+ {
+ for (; n_common < n_levels; n_common++)
{
- int leaf = pivot_category_create_leaf (
- parent, pivot_value_new_text (specs->specs[m].label));
- if (!m)
- prev_leaf = leaf;
+ const struct ctables_level *level = &levels[n_common];
+ if (level->type == CTL_CATEGORY)
+ {
+ size_t var_idx = level->var_idx;
+ const struct ctables_category *c = cell->axes[a].cvs[var_idx].category;
+ if (prev->axes[a].cvs[var_idx].category != c)
+ break;
+ else if (c->type != CCT_SUBTOTAL
+ && c->type != CCT_HSUBTOTAL
+ && c->type != CCT_TOTAL
+ && !value_equal (&prev->axes[a].cvs[var_idx].value,
+ &cell->axes[a].cvs[var_idx].value,
+ var_get_type (nest->vars[var_idx])))
+ break;
+ }
}
}
- else
+
+ for (size_t k = n_common; k < n_levels; k++)
{
- const struct variable *var = nest->vars[level->var_idx];
- struct pivot_value *label;
- if (level->type == CTL_VAR)
- label = pivot_value_new_variable (var);
- else if (level->type == CTL_CATEGORY)
+ const struct ctables_level *level = &levels[k];
+ struct pivot_category *parent = k ? groups[k - 1] : d[a]->root;
+ if (level->type == CTL_SUMMARY)
{
- const struct ctables_cell_value *cv = &cell->axes[a].cvs[level->var_idx];
- label = ctables_category_create_label (cv->category,
- var, &cv->value);
+ assert (k == n_levels - 1);
+
+ const struct ctables_summary_spec_set *specs = &t->summary_specs;
+ for (size_t m = 0; m < specs->n; m++)
+ {
+ int leaf = pivot_category_create_leaf (
+ parent, pivot_value_new_text (specs->specs[m].label));
+ if (!m)
+ prev_leaf = leaf;
+ }
}
else
- NOT_REACHED ();
+ {
+ const struct variable *var = nest->vars[level->var_idx];
+ struct pivot_value *label;
+ if (level->type == CTL_VAR)
+ label = pivot_value_new_variable (var);
+ else if (level->type == CTL_CATEGORY)
+ {
+ const struct ctables_cell_value *cv = &cell->axes[a].cvs[level->var_idx];
+ label = ctables_category_create_label (cv->category,
+ var, &cv->value);
+ }
+ else
+ NOT_REACHED ();
- if (k == n_levels - 1)
- prev_leaf = pivot_category_create_leaf (parent, label);
- else
- groups[k] = pivot_category_create_group__ (parent, label);
+ if (k == n_levels - 1)
+ prev_leaf = pivot_category_create_leaf (parent, label);
+ else
+ groups[k] = pivot_category_create_group__ (parent, label);
+ }
}
- }
- cell->axes[a].leaf = prev_leaf;
+ cell->axes[a].leaf = prev_leaf;
+ }
+ free (sorted);
+ free (groups);
}
- free (sorted);
- free (groups);
}
- struct ctables_cell *cell;
- HMAP_FOR_EACH (cell, struct ctables_cell, node, &t->cells)
+ for (size_t i = 0; i < t->n_sections; i++)
{
- if (cell->hide)
- continue;
+ struct ctables_section *s = &t->sections[i];
- const struct ctables_nest *specs_nest = &t->stacks[t->summary_axis].nests[cell->axes[t->summary_axis].nest_idx];
- const struct ctables_summary_spec_set *specs = &specs_nest->specs[cell->sv];
- for (size_t j = 0; j < specs->n; j++)
+ struct ctables_cell *cell;
+ HMAP_FOR_EACH (cell, struct ctables_cell, node, &s->cells)
{
- size_t dindexes[5];
- size_t n_dindexes = 0;
-
- if (summary_dimension)
- dindexes[n_dindexes++] = specs->specs[j].axis_idx;
+ if (cell->hide)
+ continue;
- if (categories_dimension)
+ const struct ctables_nest *specs_nest = s->nests[t->summary_axis];
+ const struct ctables_summary_spec_set *specs = &specs_nest->specs[cell->sv];
+ for (size_t j = 0; j < specs->n; j++)
{
- const struct ctables_nest *clabels_nest = &t->stacks[t->clabels_from_axis].nests[cell->axes[t->clabels_from_axis].nest_idx];
- const struct variable *var = clabels_nest->vars[clabels_nest->n - 1];
- const union value *value = &cell->axes[t->clabels_from_axis].cvs[clabels_nest->n - 1].value;
- const struct ctables_value *ctv = ctables_value_find (t, value, var_get_width (var));
- assert (ctv != NULL);
- dindexes[n_dindexes++] = ctv->leaf;
- }
+ size_t dindexes[5];
+ size_t n_dindexes = 0;
- for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
- if (d[a])
- {
- int leaf = cell->axes[a].leaf;
- if (a == t->summary_axis && !summary_dimension)
- leaf += j;
- dindexes[n_dindexes++] = leaf;
- }
+ if (summary_dimension)
+ dindexes[n_dindexes++] = specs->specs[j].axis_idx;
+
+ if (categories_dimension)
+ {
+ const struct ctables_nest *clabels_nest = s->nests[t->clabels_from_axis];
+ const struct variable *var = clabels_nest->vars[clabels_nest->n - 1];
+ const union value *value = &cell->axes[t->clabels_from_axis].cvs[clabels_nest->n - 1].value;
+ const struct ctables_value *ctv = ctables_value_find (t, value, var_get_width (var));
+ assert (ctv != NULL);
+ dindexes[n_dindexes++] = ctv->leaf;
+ }
+
+ for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
+ if (d[a])
+ {
+ int leaf = cell->axes[a].leaf;
+ if (a == t->summary_axis && !summary_dimension)
+ leaf += j;
+ dindexes[n_dindexes++] = leaf;
+ }
- double d = ctables_summary_value (cell, &cell->summaries[j], &specs->specs[j]);
- struct pivot_value *value = pivot_value_new_number (d);
- value->numeric.format = specs->specs[j].format;
- pivot_table_put (pt, dindexes, n_dindexes, value);
+ double d = ctables_summary_value (cell, &cell->summaries[j], &specs->specs[j]);
+ struct pivot_value *value = pivot_value_new_number (d);
+ value->numeric.format = specs->specs[j].format;
+ pivot_table_put (pt, dindexes, n_dindexes, value);
+ }
}
}
static bool
ctables_execute (struct dataset *ds, struct ctables *ct)
{
+ for (size_t i = 0; i < ct->n_tables; i++)
+ {
+ struct ctables_table *t = ct->tables[i];
+ t->sections = xnmalloc (MAX (1, t->stacks[PIVOT_AXIS_ROW].n) *
+ MAX (1, t->stacks[PIVOT_AXIS_COLUMN].n) *
+ MAX (1, t->stacks[PIVOT_AXIS_LAYER].n),
+ sizeof *t->sections);
+ size_t ix[PIVOT_N_AXES];
+ ctables_table_add_section (t, 0, ix);
+ }
+
struct casereader *input = proc_open (ds);
bool warn_on_invalid = true;
for (struct ccase *c = casereader_read (input); c;
{
struct ctables_table *t = ct->tables[i];
- for (size_t ir = 0; ir < t->stacks[PIVOT_AXIS_ROW].n; ir++)
- for (size_t ic = 0; ic < t->stacks[PIVOT_AXIS_COLUMN].n; ic++)
- for (size_t il = 0; il < t->stacks[PIVOT_AXIS_LAYER].n; il++)
- {
- size_t ix[PIVOT_N_AXES] = {
- [PIVOT_AXIS_ROW] = ir,
- [PIVOT_AXIS_COLUMN] = ic,
- [PIVOT_AXIS_LAYER] = il,
- };
-
- ctables_cell_insert (t, c, ix, d_weight, e_weight);
- }
+ for (size_t j = 0; j < t->n_sections; j++)
+ ctables_cell_insert (&t->sections[j], c, d_weight, e_weight);
for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
if (t->label_axis[a] != a)
struct ctables_table *t = xmalloc (sizeof *t);
*t = (struct ctables_table) {
- .cells = HMAP_INITIALIZER (t->cells),
.slabels_axis = PIVOT_AXIS_COLUMN,
.slabels_visible = true,
.clabels_values_map = HMAP_INITIALIZER (t->clabels_values_map),
.n_categories = n_vars,
.cilevel = 95,
};
- for (enum ctables_domain_type dt = 0; dt < N_CTDTS; dt++)
- hmap_init (&t->domains[dt]);
ct->tables[ct->n_tables++] = t;
lex_match (lexer, T_EQUALS);