*^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,
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. */
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)
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;
{
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)
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);
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);
}
/* 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
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))
}
}
- 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);
}