X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fstats%2Fmeans.c;h=4ebd60d83ab496239d21ef1a556e44ebeefd75c4;hb=4783127cc513fa1bd3aa05f560c4030fa334d669;hp=37fa8873aeba7b81804ce5d682205bbccfa404e8;hpb=67d88181d071a1c2ad3e0cd11b0646cef6e0c021;p=pspp diff --git a/src/language/stats/means.c b/src/language/stats/means.c index 37fa8873ae..4ebd60d83a 100644 --- a/src/language/stats/means.c +++ b/src/language/stats/means.c @@ -27,6 +27,10 @@ #include "libpspp/hmap.h" #include "libpspp/bt.h" #include "libpspp/hash-functions.h" +#include "libpspp/misc.h" +#include "libpspp/pool.h" + +#include "language/command.h" #include "count-one-bits.h" #include "count-leading-zeros.h" @@ -116,7 +120,7 @@ destroy_workspace (const struct mtable *mt, struct workspace *ws) struct instance *inst; struct instance *next; HMAP_FOR_EACH_SAFE (inst, next, struct instance, hmap_node, - &instances->map) + &instances->map) { int width = var_get_width (inst->var); value_destroy (&inst->value, width); @@ -185,15 +189,17 @@ means_destroy_cells (const struct means *means, struct cell *cell, struct cell *sub_cell; struct cell *next; HMAP_FOR_EACH_SAFE (sub_cell, next, struct cell, hmap_node, - &container->map) - { - means_destroy_cells (means, sub_cell, table); - } + &container->map) + { + means_destroy_cells (means, sub_cell, table); + } } destroy_cell (means, table, cell); } +#if 0 + static void dump_cell (const struct cell *cell, const struct mtable *mt, int level) { @@ -254,6 +260,8 @@ dump_tree (const struct cell *cell, const struct mtable *table, } } +#endif + /* Generate a hash based on the values of the N variables in the array VARS which are taken from the case C. */ static unsigned int @@ -292,7 +300,7 @@ generate_cell (const struct means *means, const struct workspace *ws) { int n_vars = count_one_bits (not_wild); - struct cell *cell = xzalloc ((sizeof *cell)); + struct cell *cell = XZALLOC (struct cell); cell->values = xcalloc (n_vars, sizeof *cell->values); cell->vars = xcalloc (n_vars, sizeof *cell->vars); cell->not_wild = not_wild; @@ -529,7 +537,7 @@ populate_table (const struct means *means, const struct mtable *mt, const struct cell *cell, struct pivot_table *pt) { - size_t *indexes = xcalloc (pt->n_dimensions, sizeof *indexes); + size_t *indexes = XCALLOC (pt->n_dimensions, size_t); for (int v = 0; v < mt->n_dep_vars; ++v) { for (int s = 0; s < means->n_statistics; ++s) @@ -563,8 +571,14 @@ populate_table (const struct means *means, const struct mtable *mt, } int idx = s + v * means->n_statistics; - pivot_table_put (pt, indexes, pt->n_dimensions, - pivot_value_new_number (sg (cell->stat[idx]))); + struct pivot_value *pv + = pivot_value_new_number (sg (cell->stat[idx])); + if (NULL == cell_spec[stat].rc) + { + const struct variable *dv = mt->dep_vars[v]; + pv->numeric.format = * var_get_print_format (dv); + } + pivot_table_put (pt, indexes, pt->n_dimensions, pv); } } free (indexes); @@ -674,7 +688,7 @@ populate_case_processing_summary (struct pivot_category *pc, } /* Create the "Case Processing Summary" table. */ -void +static void means_case_processing_summary (const struct mtable *mt) { struct pivot_table *pt = pivot_table_create (N_("Case Processing Summary")); @@ -737,7 +751,6 @@ means_shipout_single (const struct mtable *mt, const struct means *means, const struct workspace *ws) { struct pivot_table *pt = pivot_table_create (N_("Report")); - pt->omit_empty = true; struct pivot_dimension *dim_cells = pivot_dimension_create (pt, PIVOT_AXIS_COLUMN, N_("Statistics")); @@ -765,22 +778,20 @@ means_shipout_multivar (const struct mtable *mt, const struct means *means, ds_init_empty (&dss); for (int dv = 0; dv < mt->n_dep_vars; ++dv) { - ds_put_cstr (&dss, var_get_name (mt->dep_vars[dv])); - if (mt->n_layers > 0) + if (dv > 0) ds_put_cstr (&dss, " * "); + ds_put_cstr (&dss, var_get_name (mt->dep_vars[dv])); } for (int l = 0; l < mt->n_layers; ++l) { + ds_put_cstr (&dss, " * "); const struct layer *layer = mt->layers[l]; const struct variable *var = layer->factor_vars[ws->control_idx[l]]; ds_put_cstr (&dss, var_get_name (var)); - if (l < mt->n_layers - 1) - ds_put_cstr (&dss, " * "); } struct pivot_table *pt = pivot_table_create (ds_cstr (&dss)); - pt->omit_empty = true; ds_destroy (&dss); struct pivot_dimension *dim_cells = @@ -811,7 +822,7 @@ means_shipout_multivar (const struct mtable *mt, const struct means *means, pivot_table_submit (pt); } -void +static void means_shipout (const struct mtable *mt, const struct means *means) { for (int cmb = 0; cmb < mt->n_combinations; ++cmb) @@ -857,7 +868,7 @@ control_var_missing (const struct means *means, const struct variable *var = layer->factor_vars[ws->control_idx[l]]; const union value *vv = case_data (c, var); - miss = var_is_value_missing (var, vv, means->ctrl_exclude); + miss = (var_is_value_missing (var, vv) & means->ctrl_exclude) != 0; if (miss) break; } @@ -919,7 +930,7 @@ service_cell_map (const struct means *means, const struct mtable *mt, { const struct variable *dep_var = mt->dep_vars[v]; const union value *vv = case_data (c, dep_var); - if (var_is_value_missing (dep_var, vv, means->dep_exclude)) + if (var_is_value_missing (dep_var, vv) & means->dep_exclude) continue; for (int stat = 0; stat < means->n_statistics; ++stat) @@ -928,7 +939,7 @@ service_cell_map (const struct means *means, const struct mtable *mt, NULL); stat_update *su = cell_spec[means->statistics[stat]].su; su (cell->stat[stat + v * means->n_statistics], weight, - case_data (c, dep_var)->f); + case_num (c, dep_var)); } } } @@ -955,21 +966,12 @@ prepare_means (struct means *cmd) { struct mtable *mt = cmd->table + t; - mt->n_combinations = 1; - for (int l = 0; l < mt->n_layers; ++l) - mt->n_combinations *= mt->layers[l]->n_factor_vars; - - mt->ws = xzalloc (mt->n_combinations * sizeof (*mt->ws)); - mt->summ = xzalloc (mt->n_combinations * mt->n_dep_vars - * sizeof (*mt->summ)); for (int i = 0; i < mt->n_combinations; ++i) { struct workspace *ws = mt->ws + i; ws->root_cell = NULL; - ws->control_idx = xzalloc (mt->n_layers - * sizeof *ws->control_idx); - ws->instances = xzalloc (mt->n_layers - * sizeof *ws->instances); + ws->control_idx = xcalloc (mt->n_layers, sizeof *ws->control_idx); + ws->instances = xcalloc (mt->n_layers, sizeof *ws->instances); int cmb = i; for (int l = mt->n_layers - 1; l >= 0; --l) { @@ -1045,7 +1047,7 @@ update_summaries (const struct means *means, struct mtable *mt, const struct variable *var = mt->dep_vars[dv]; const union value *vv = case_data (c, var); /* First check if the dependent variable is missing. */ - if (var_is_value_missing (var, vv, means->dep_exclude)) + if (var_is_value_missing (var, vv) & means->dep_exclude) summ->n_missing += weight; /* If the dep var is not missing, then check each control variable. */ @@ -1056,7 +1058,7 @@ update_summaries (const struct means *means, struct mtable *mt, const struct variable *var = layer->factor_vars[ws->control_idx[l]]; const union value *vv = case_data (c, var); - if (var_is_value_missing (var, vv, means->ctrl_exclude)) + if (var_is_value_missing (var, vv) & means->ctrl_exclude) { summ->n_missing += weight; break; @@ -1100,29 +1102,95 @@ run_means (struct means *cmd, struct casereader *input, post_means (cmd); } +struct lexer; -/* Release all resources allocated by this routine. - This does not include those allocated by the parser, - which exclusively use MEANS->pool. */ -void -destroy_means (struct means *means) +int +cmd_means (struct lexer *lexer, struct dataset *ds) { - for (int t = 0; t < means->n_tables; ++t) + struct means means; + means.pool = pool_create (); + + means.ctrl_exclude = MV_ANY; + means.dep_exclude = MV_ANY; + means.table = NULL; + means.n_tables = 0; + + means.dict = dataset_dict (ds); + + means.n_statistics = 3; + means.statistics = pool_calloc (means.pool, 3, sizeof *means.statistics); + means.statistics[0] = MEANS_MEAN; + means.statistics[1] = MEANS_N; + means.statistics[2] = MEANS_STDDEV; + + if (! means_parse (lexer, &means)) + goto error; + + /* Calculate some constant data for each table. */ + for (int t = 0; t < means.n_tables; ++t) { - const struct mtable *table = means->table + t; - for (int i = 0; i < table->n_combinations; ++i) - { - struct workspace *ws = table->ws + i; - if (ws->root_cell == NULL) - continue; - means_destroy_cells (means, ws->root_cell, table); - } - for (int i = 0; i < table->n_combinations; ++i) - { - struct workspace *ws = table->ws + i; - destroy_workspace (table, ws); - } - free (table->ws); - free (table->summ); + struct mtable *mt = means.table + t; + mt->n_combinations = 1; + for (int l = 0; l < mt->n_layers; ++l) + mt->n_combinations *= mt->layers[l]->n_factor_vars; } + + { + struct casegrouper *grouper; + struct casereader *group; + bool ok; + + grouper = casegrouper_create_splits (proc_open (ds), means.dict); + while (casegrouper_get_next_group (grouper, &group)) + { + /* Allocate the workspaces. */ + for (int t = 0; t < means.n_tables; ++t) + { + struct mtable *mt = means.table + t; + mt->summ = xcalloc (mt->n_combinations * mt->n_dep_vars, + sizeof (*mt->summ)); + mt->ws = xcalloc (mt->n_combinations, sizeof (*mt->ws)); + } + run_means (&means, group, ds); + for (int t = 0; t < means.n_tables; ++t) + { + const struct mtable *mt = means.table + t; + + means_case_processing_summary (mt); + means_shipout (mt, &means); + + for (int i = 0; i < mt->n_combinations; ++i) + { + struct workspace *ws = mt->ws + i; + if (ws->root_cell == NULL) + continue; + + means_destroy_cells (&means, ws->root_cell, mt); + } + } + + /* Destroy the workspaces. */ + for (int t = 0; t < means.n_tables; ++t) + { + struct mtable *mt = means.table + t; + free (mt->summ); + for (int i = 0; i < mt->n_combinations; ++i) + { + struct workspace *ws = mt->ws + i; + destroy_workspace (mt, ws); + } + free (mt->ws); + } + } + ok = casegrouper_destroy (grouper); + ok = proc_commit (ds) && ok; + } + + pool_destroy (means.pool); + return CMD_SUCCESS; + + error: + + pool_destroy (means.pool); + return CMD_FAILURE; }