X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Fpivot-table.c;h=1e7d2fbb5ac6b72308f54ace365ade5c4a6053f9;hb=53fe23e6cf0f599423080ff2b101df0216ae5480;hp=3e54d776bec128a7c4ea9f92b8e8b452ead93fa1;hpb=6531faae1faddd300ba8ab7e996477ba642e4b6d;p=pspp diff --git a/src/output/pivot-table.c b/src/output/pivot-table.c index 3e54d776be..1e7d2fbb5a 100644 --- a/src/output/pivot-table.c +++ b/src/output/pivot-table.c @@ -24,6 +24,7 @@ #include #include "data/data-out.h" +#include "data/dictionary.h" #include "data/settings.h" #include "data/value.h" #include "data/variable.h" @@ -1443,8 +1444,9 @@ pivot_table_insert_cell (struct pivot_table *table, const size_t *dindexes) } /* Puts VALUE in the cell in TABLE whose indexes are given by the N indexes in - DINDEXES. N must be the number of dimensions in TABLE. Takes ownership of - VALUE. + DINDEXES. The order of the indexes is the same as the order in which the + dimensions were created. N must be the number of dimensions in TABLE. + Takes ownership of VALUE. If VALUE is a numeric value without a specified format, this function checks each of the categories designated by DINDEXES[] and takes the format from @@ -3031,10 +3033,29 @@ pivot_value_ex_destroy (struct pivot_value_ex *ex) /* pivot_splits */ +struct pivot_splits_value + { + struct hmap_node hmap_node; + union value value; + int leaf; + }; + +struct pivot_splits_var + { + struct pivot_dimension *dimension; + int width; + size_t idx; + struct fmt_spec format; + struct hmap values; + }; + struct pivot_splits { - const struct dictionary *dict; - struct hmap splits[MAX_SPLITS]; + struct pivot_splits_var *vars; + size_t n; + char *encoding; + + size_t dindexes[MAX_SPLITS]; }; struct pivot_splits * @@ -3045,13 +3066,162 @@ pivot_splits_create (struct pivot_table *pt, if (dict_get_split_type (dict) != SPLIT_LAYERED) return NULL; - struct pivot_splits *ps = xmalloc (sizeof *ps); - *ps = (struct pivot_splits) { .dict = dict }; - for (size_t i = 0; i < dict_get_n_splits (dict); i++) + size_t n = dict_get_n_splits (dict); + assert (n <= MAX_SPLITS); + + const struct variable *const *vars = dict_get_split_vars (dict); + struct pivot_splits_var *psvars = xnmalloc (n, sizeof *psvars); + for (size_t i = 0; i < n; i++) { - hmap_init (&ps->splits[i]); + const struct variable *var = vars[i]; + struct pivot_splits_var *psvar = &psvars[i]; + struct pivot_dimension *d = pivot_dimension_create__ ( - pt, axis, pivot_value_new_variable (dict_get_split_vars (dict)[i])); + pt, axis, pivot_value_new_variable (var)); + d->root->show_label = true; + + *psvar = (struct pivot_splits_var) { + .width = var_get_width (var), + .idx = var_get_case_index (var), + .format = *var_get_print_format (var), + .values = HMAP_INITIALIZER (psvar->values), + .dimension = d, + }; } + + struct pivot_splits *ps = xmalloc (sizeof *ps); + *ps = (struct pivot_splits) { + .vars = psvars, + .n = n, + .encoding = xstrdup (dict_get_encoding (dict)), + .dindexes = { [0] = SIZE_MAX }, + }; return ps; } + +void +pivot_splits_destroy (struct pivot_splits *ps) +{ + if (!ps) + return; + + for (size_t i = 0; i < ps->n; i++) + { + struct pivot_splits_var *psvar = &ps->vars[i]; + struct pivot_splits_value *psval, *next; + HMAP_FOR_EACH_SAFE (psval, next, struct pivot_splits_value, hmap_node, + &psvar->values) + { + value_destroy (&psval->value, psvar->width); + hmap_delete (&psvar->values, &psval->hmap_node); + free (psval); + } + hmap_destroy (&psvar->values); + } + free (ps->vars); + free (ps->encoding); + free (ps); +} + +static struct pivot_splits_value * +pivot_splits_value_find (struct pivot_splits_var *psvar, + const union value *value) +{ + struct pivot_splits_value *psval; + HMAP_FOR_EACH_WITH_HASH (psval, struct pivot_splits_value, hmap_node, + value_hash (value, psvar->width, 0), &psvar->values) + if (value_equal (&psval->value, value, psvar->width)) + return psval; + return NULL; +} + +void +pivot_splits_new_split (struct pivot_splits *ps, const struct ccase *c) +{ + if (!ps) + return; + + for (size_t i = ps->n - 1; i < ps->n; i--) + { + struct pivot_splits_var *psvar = &ps->vars[i]; + const union value *value = case_data_idx (c, psvar->idx); + struct pivot_splits_value *psval = pivot_splits_value_find (psvar, value); + if (!psval) + { + psval = xmalloc (sizeof *psval); + hmap_insert (&psvar->values, &psval->hmap_node, + value_hash (value, psvar->width, 0)); + value_clone (&psval->value, value, psvar->width); + psval->leaf = pivot_category_create_leaf ( + psvar->dimension->root, + pivot_value_new_value (value, psvar->width, &psvar->format, + ps->encoding)); + } + + ps->dindexes[i] = psval->leaf; + } +} + +size_t +pivot_splits_get_dindexes (const struct pivot_splits *ps, size_t *dindexes) +{ + if (!ps) + return 0; + + assert (ps->dindexes[0] != SIZE_MAX); + for (size_t i = 0; i < ps->n; i++) + dindexes[i] = ps->dindexes[i]; + return ps->n; +} + +void +pivot_splits_put1 (struct pivot_splits *ps, struct pivot_table *table, + size_t idx1, struct pivot_value *value) +{ + size_t dindexes[1 + MAX_SPLITS]; + size_t *p = dindexes; + *p++ = idx1; + p += pivot_splits_get_dindexes (ps, p); + pivot_table_put (table, dindexes, p - dindexes, value); +} + +void +pivot_splits_put2 (struct pivot_splits *ps, struct pivot_table *table, + size_t idx1, size_t idx2, struct pivot_value *value) +{ + size_t dindexes[2 + MAX_SPLITS]; + size_t *p = dindexes; + *p++ = idx1; + *p++ = idx2; + p += pivot_splits_get_dindexes (ps, p); + pivot_table_put (table, dindexes, p - dindexes, value); +} + +void +pivot_splits_put3 (struct pivot_splits *ps, struct pivot_table *table, + size_t idx1, size_t idx2, size_t idx3, + struct pivot_value *value) +{ + size_t dindexes[3 + MAX_SPLITS]; + size_t *p = dindexes; + *p++ = idx1; + *p++ = idx2; + *p++ = idx3; + p += pivot_splits_get_dindexes (ps, p); + pivot_table_put (table, dindexes, p - dindexes, value); +} + +void +pivot_splits_put4 (struct pivot_splits *ps, struct pivot_table *table, + size_t idx1, size_t idx2, size_t idx3, size_t idx4, + struct pivot_value *value) +{ + size_t dindexes[4 + MAX_SPLITS]; + size_t *p = dindexes; + *p++ = idx1; + *p++ = idx2; + *p++ = idx3; + *p++ = idx4; + p += pivot_splits_get_dindexes (ps, p); + pivot_table_put (table, dindexes, p - dindexes, value); +}