X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fstats%2Fcrosstabs.q;h=6e87c0260b856173bb4debbcd07dbabbd6036f7f;hb=c84078d8498785e9a52945cc63fb663cd48027af;hp=2edf248b2b0660ac82152d048995d7860758a5e7;hpb=389df78f3bf8c730238f4ed5e5ae09d14c7bff5d;p=pspp diff --git a/src/language/stats/crosstabs.q b/src/language/stats/crosstabs.q index 2edf248b2b..6e87c0260b 100644 --- a/src/language/stats/crosstabs.q +++ b/src/language/stats/crosstabs.q @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014, 2016 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -74,6 +74,8 @@ *^tables=custom; +variables=custom; missing=miss:!table/include/report; + count=roundwhat:asis/case/!cell, + roundhow:!round/truncate; +write[wr_]=none,cells,all; +format=val:!avalue/dvalue, indx:!noindex/index, @@ -182,6 +184,11 @@ struct crosstabs_proc unsigned int cells; /* Bit k is 1 if cell k is requested. */ int a_cells[CRS_CL_count]; /* 0...n_cells-1 are the requested cells. */ + /* Rounding of cells. */ + bool round_case_weights; /* Round case weights? */ + bool round_cells; /* If !round_case_weights, round cells? */ + bool round_down; /* Round down? (otherwise to nearest) */ + /* STATISTICS. */ unsigned int statistics; /* Bit k is 1 if statistic k is requested. */ @@ -200,6 +207,12 @@ static void tabulate_integer_case (struct pivot_table *, const struct ccase *, static void postcalc (struct crosstabs_proc *); static void submit (struct pivot_table *, struct tab_table *); +static double +round_weight (const struct crosstabs_proc *proc, double weight) +{ + return proc->round_down ? floor (weight) : floor (weight + 0.5); +} + /* Parses and executes the CROSSTABS procedure. */ int cmd_crosstabs (struct lexer *lexer, struct dataset *ds) @@ -236,6 +249,10 @@ cmd_crosstabs (struct lexer *lexer, struct dataset *ds) proc.descending = cmd.val == CRS_DVALUE; + proc.round_case_weights = cmd.sbc_count && cmd.roundwhat == CRS_CASE; + proc.round_cells = cmd.sbc_count && cmd.roundwhat == CRS_CELL; + proc.round_down = cmd.roundhow == CRS_TRUNCATE; + /* CELLS. */ if (!cmd.sbc_cells) proc.cells = 1u << CRS_CL_COUNT; @@ -316,6 +333,12 @@ cmd_crosstabs (struct lexer *lexer, struct dataset *ds) { double weight = dict_get_case_weight (dataset_dict (ds), c, &proc.bad_warn); + if (cmd.roundwhat == CRS_CASE) + { + weight = round_weight (&proc, weight); + if (weight == 0.) + continue; + } if (should_tabulate_case (pt, c, proc.exclude)) { if (proc.mode == GENERAL) @@ -404,14 +427,11 @@ crs_custom_tables (struct lexer *lexer, struct dataset *ds, } nx *= by_nvar[n_by]; n_by++; - + if (!lex_match (lexer, T_BY)) { if (n_by < 2) - { - lex_force_match (lexer, T_BY); - goto done; - } + goto done; else break; } @@ -517,7 +537,7 @@ crs_custom_variables (struct lexer *lexer, struct dataset *ds, vr->var = var; vr->min = min; - vr->max = max + 1.; + vr->max = max; vr->count = max - min + 1; hmap_insert (&proc->var_ranges, &vr->hmap_node, hash_pointer (var, 0)); @@ -570,7 +590,7 @@ should_tabulate_case (const struct pivot_table *pt, const struct ccase *c, if (range != NULL) { double num = case_num (c, var); - if (num < range->min || num > range->max) + if (num < range->min || num >= range->max + 1.) return false; } } @@ -680,17 +700,36 @@ static bool find_crosstab (struct pivot_table *, size_t *row0p, size_t *row1p); static void postcalc (struct crosstabs_proc *proc) { - struct pivot_table *pt; + + /* Round hash table entries, if requested + + If this causes any of the cell counts to fall to zero, delete those + cells. */ + if (proc->round_cells) + for (struct pivot_table *pt = proc->pivots; + pt < &proc->pivots[proc->n_pivots]; pt++) + { + struct freq *e, *next; + HMAP_FOR_EACH_SAFE (e, next, struct freq, node, &pt->data) + { + e->count = round_weight (proc, e->count); + if (e->count == 0.0) + { + hmap_delete (&pt->data, &e->node); + free (e); + } + } + } /* Convert hash tables into sorted arrays of entries. */ - for (pt = &proc->pivots[0]; pt < &proc->pivots[proc->n_pivots]; pt++) + for (struct pivot_table *pt = proc->pivots; + pt < &proc->pivots[proc->n_pivots]; pt++) { struct freq *e; - size_t i; pt->n_entries = hmap_count (&pt->data); pt->entries = xnmalloc (pt->n_entries, sizeof *pt->entries); - i = 0; + size_t i = 0; HMAP_FOR_EACH (e, struct freq, node, &pt->data) pt->entries[i++] = e; hmap_destroy (&pt->data); @@ -704,7 +743,8 @@ postcalc (struct crosstabs_proc *proc) make_summary_table (proc); /* Output each pivot table. */ - for (pt = &proc->pivots[0]; pt < &proc->pivots[proc->n_pivots]; pt++) + for (struct pivot_table *pt = proc->pivots; + pt < &proc->pivots[proc->n_pivots]; pt++) { if (proc->pivot || pt->n_vars == 2) output_pivot_table (proc, pt); @@ -724,10 +764,9 @@ postcalc (struct crosstabs_proc *proc) } /* Free output and prepare for next split file. */ - for (pt = &proc->pivots[0]; pt < &proc->pivots[proc->n_pivots]; pt++) + for (struct pivot_table *pt = proc->pivots; + pt < &proc->pivots[proc->n_pivots]; pt++) { - size_t i; - pt->missing = 0.0; /* Free the members that were allocated in this function(and the values @@ -737,7 +776,7 @@ postcalc (struct crosstabs_proc *proc) lower level (in output_pivot_table), or both allocated and destroyed at a higher level (in crs_custom_tables and free_proc, respectively). */ - for (i = 0; i < pt->n_vars; i++) + for (size_t i = 0; i < pt->n_vars; i++) { int width = var_get_width (pt->vars[i]); if (value_needs_init (width)) @@ -749,7 +788,7 @@ postcalc (struct crosstabs_proc *proc) } } - for (i = 0; i < pt->n_entries; i++) + for (size_t i = 0; i < pt->n_entries; i++) free (pt->entries[i]); free (pt->entries); }