From 3b7a1d755ef39bb2fb78e94cba2d33a443bec624 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 10 Nov 2022 22:13:32 -0800 Subject: [PATCH] CROSSTABS: Improve error messages and coding style. --- src/language/stats/crosstabs.c | 804 ++++++++++++++---------------- tests/language/stats/crosstabs.at | 90 ++++ 2 files changed, 456 insertions(+), 438 deletions(-) diff --git a/src/language/stats/crosstabs.c b/src/language/stats/crosstabs.c index 2205544d90..7211d38d53 100644 --- a/src/language/stats/crosstabs.c +++ b/src/language/stats/crosstabs.c @@ -155,11 +155,11 @@ struct crosstabulation double missing; /* Weight of missing cases. */ /* Variables (2 or more). */ - int n_vars; + size_t n_vars; struct xtab_var *vars; /* Constants (0 or more). */ - int n_consts; + size_t n_consts; struct xtab_var *const_vars; size_t *const_indexes; @@ -170,7 +170,7 @@ struct crosstabulation /* Number of statistically interesting columns/rows (columns/rows with data in them). */ - int ns_cols, ns_rows; + size_t ns_cols, ns_rows; /* Matrix contents. */ double *mat; /* Matrix proper. */ @@ -209,10 +209,10 @@ struct crosstabs_proc /* TABLES. */ struct crosstabulation *pivots; - int n_pivots; + size_t n_pivots; /* CELLS. */ - int n_cells; /* Number of cells requested. */ + size_t n_cells; /* Number of cells requested. */ unsigned int cells; /* Bit k is 1 if cell k is requested. */ int a_cells[CRS_N_CELLS]; /* 0...n_cells-1 are the requested cells. */ @@ -250,13 +250,13 @@ round_weight (const struct crosstabs_proc *proc, double weight) } #define FOR_EACH_POPULATED_COLUMN(C, XT) \ - for (int C = next_populated_column (0, XT); \ + for (size_t C = next_populated_column (0, XT); \ C < (XT)->vars[COL_VAR].n_values; \ C = next_populated_column (C + 1, XT)) -static int -next_populated_column (int c, const struct crosstabulation *xt) +static size_t +next_populated_column (size_t c, const struct crosstabulation *xt) { - int n_columns = xt->vars[COL_VAR].n_values; + size_t n_columns = xt->vars[COL_VAR].n_values; for (; c < n_columns; c++) if (xt->col_tot[c]) break; @@ -264,12 +264,12 @@ next_populated_column (int c, const struct crosstabulation *xt) } #define FOR_EACH_POPULATED_ROW(R, XT) \ - for (int R = next_populated_row (0, XT); R < (XT)->vars[ROW_VAR].n_values; \ + for (size_t R = next_populated_row (0, XT); R < (XT)->vars[ROW_VAR].n_values; \ R = next_populated_row (R + 1, XT)) -static int -next_populated_row (int r, const struct crosstabulation *xt) +static size_t +next_populated_row (size_t r, const struct crosstabulation *xt) { - int n_rows = xt->vars[ROW_VAR].n_values; + size_t n_rows = xt->vars[ROW_VAR].n_values; for (; r < n_rows; r++) if (xt->row_tot[r]) break; @@ -330,7 +330,7 @@ cmd_crosstabs (struct lexer *lexer, struct dataset *ds) proc.exclude = 0; else { - lex_error (lexer, NULL); + lex_error_expecting (lexer, "TABLE", "INCLUDE", "REPORT"); goto exit; } } @@ -365,7 +365,8 @@ cmd_crosstabs (struct lexer *lexer, struct dataset *ds) proc.round_down = true; else { - lex_error (lexer, NULL); + lex_error_expecting (lexer, "ASIS", "CASE", "CELL", + "ROUND", "TRUNCATE"); goto exit; } lex_match (lexer, T_COMMA); @@ -386,7 +387,8 @@ cmd_crosstabs (struct lexer *lexer, struct dataset *ds) show_tables = false; else { - lex_error (lexer, NULL); + lex_error_expecting (lexer, "AVALUE", "DVALUE", + "TABLES", "NOTABLES"); goto exit; } lex_match (lexer, T_COMMA); @@ -415,7 +417,15 @@ cmd_crosstabs (struct lexer *lexer, struct dataset *ds) } CRS_CELLS #undef C - lex_error (lexer, NULL); + + static const char *cells[] = + { +#define C(KEYWORD, STRING, RC) #KEYWORD, + CRS_CELLS +#undef C + }; + lex_error_expecting_array (lexer, cells, + sizeof cells / sizeof *cells); goto exit; } if (!proc.cells) @@ -444,7 +454,14 @@ cmd_crosstabs (struct lexer *lexer, struct dataset *ds) } CRS_STATISTICS #undef S - lex_error (lexer, NULL); + static const char *stats[] = + { +#define S(KEYWORD) #KEYWORD, + CRS_STATISTICS +#undef S + }; + lex_error_expecting_array (lexer, stats, + sizeof stats / sizeof *stats); goto exit; } if (!proc.statistics) @@ -470,7 +487,7 @@ cmd_crosstabs (struct lexer *lexer, struct dataset *ds) /* Cells. */ if (!show_tables) proc.cells = 0; - for (int i = 0; i < CRS_N_CELLS; i++) + for (size_t i = 0; i < CRS_N_CELLS; i++) if (proc.cells & (1u << i)) proc.a_cells[proc.n_cells++] = i; assert (proc.n_cells < CRS_N_CELLS); @@ -478,9 +495,9 @@ cmd_crosstabs (struct lexer *lexer, struct dataset *ds) /* Missing values. */ if (proc.mode == GENERAL && !proc.exclude) { - lex_ofs_error (lexer, exclude_ofs, exclude_ofs, - _("Missing mode %s not allowed in general mode. " - "Assuming %s."), "REPORT", "MISSING=TABLE"); + lex_ofs_msg (lexer, SW, exclude_ofs, exclude_ofs, + _("Missing mode %s not allowed in general mode. " + "Assuming %s."), "REPORT", "MISSING=TABLE"); proc.exclude = MV_ANY; } @@ -491,10 +508,8 @@ cmd_crosstabs (struct lexer *lexer, struct dataset *ds) struct casereader *group; while (casegrouper_get_next_group (grouper, &group)) { - struct ccase *c; - /* Output SPLIT FILE variables. */ - c = casereader_peek (group, 0); + struct ccase *c = casereader_peek (group, 0); if (c != NULL) { output_split_file_values (ds, c); @@ -537,7 +552,7 @@ cmd_crosstabs (struct lexer *lexer, struct dataset *ds) bool ok = casegrouper_destroy (grouper); ok = proc_commit (ds) && ok; - result = ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE; + result = ok ? CMD_SUCCESS : CMD_FAILURE; exit: free (proc.variables); @@ -576,7 +591,8 @@ parse_crosstabs_tables (struct lexer *lexer, struct dataset *ds, dict_lookup_var (dataset_dict (ds), lex_tokcstr (lexer)) == NULL) && lex_token (lexer) != T_ALL) { - lex_error (lexer, NULL); + lex_error (lexer, _("Syntax error expecting subcommand name or " + "variable name.")); return false; } lex_match (lexer, T_EQUALS); @@ -588,39 +604,37 @@ parse_crosstabs_tables (struct lexer *lexer, struct dataset *ds, : const_var_set_create_from_dict (dataset_dict (ds))); size_t nx = 1; - int n_by = 0; + size_t n_by = 0; int vars_start = lex_ofs (lexer); - for (;;) + do { by = xnrealloc (by, n_by + 1, sizeof *by); by_nvar = xnrealloc (by_nvar, n_by + 1, sizeof *by_nvar); if (!parse_const_var_set_vars (lexer, var_set, &by[n_by], &by_nvar[n_by], PV_NO_DUPLICATE | PV_NO_SCRATCH)) goto done; - if (xalloc_oversized (nx, by_nvar[n_by])) + size_t n = by_nvar[n_by++]; + if (xalloc_oversized (nx, n)) { lex_ofs_error ( - lexer, vars_start, lex_ofs (lexer), + lexer, vars_start, lex_ofs (lexer) - 1, _("Too many cross-tabulation variables or dimensions.")); goto done; } - nx *= by_nvar[n_by]; - n_by++; - - if (!lex_match (lexer, T_BY)) - { - if (n_by < 2) - goto done; - else - break; - } + nx *= n; + } + while (lex_match (lexer, T_BY)); + if (n_by < 2) + { + bool unused UNUSED = lex_force_match (lexer, T_BY); + goto done; } int vars_end = lex_ofs (lexer) - 1; - int *by_iter = XCALLOC (n_by, int); + size_t *by_iter = XCALLOC (n_by, size_t); proc->pivots = xnrealloc (proc->pivots, proc->n_pivots + nx, sizeof *proc->pivots); - for (int i = 0; i < nx; i++) + for (size_t i = 0; i < nx; i++) { struct crosstabulation *xt = &proc->pivots[proc->n_pivots++]; @@ -637,7 +651,7 @@ parse_crosstabs_tables (struct lexer *lexer, struct dataset *ds, .end_ofs = vars_end, }; - for (int j = 0; j < n_by; j++) + for (size_t j = 0; j < n_by; j++) xt->vars[j].var = by[j][by_iter[j]]; for (int j = n_by - 1; j >= 0; j--) @@ -652,7 +666,7 @@ parse_crosstabs_tables (struct lexer *lexer, struct dataset *ds, done: /* All return paths lead here. */ - for (int i = 0; i < n_by; i++) + for (size_t i = 0; i < n_by; i++) free (by[i]); free (by); free (by_nvar); @@ -708,11 +722,12 @@ parse_crosstabs_variables (struct lexer *lexer, struct dataset *ds, { const struct variable *var = proc->variables[i]; struct var_range *vr = xmalloc (sizeof *vr); - - vr->var = var; - vr->min = min; - vr->max = max; - vr->count = max - min + 1; + *vr = (struct var_range) { + .var = var, + .min = min, + .max = max, + .count = max - min + 1, + }; hmap_insert (&proc->var_ranges, &vr->hmap_node, hash_pointer (var, 0)); } @@ -753,8 +768,7 @@ static bool should_tabulate_case (const struct crosstabulation *xt, const struct ccase *c, enum mv_class exclude) { - int j; - for (j = 0; j < xt->n_vars; j++) + for (size_t j = 0; j < xt->n_vars; j++) { const struct variable *var = xt->vars[j].var; const struct var_range *range = get_var_range (xt->proc, var); @@ -776,20 +790,17 @@ static void tabulate_integer_case (struct crosstabulation *xt, const struct ccase *c, double weight) { - struct freq *te; - size_t hash; - int j; - - hash = 0; - for (j = 0; j < xt->n_vars; j++) + size_t hash = 0; + for (size_t j = 0; j < xt->n_vars; j++) { /* Throw away fractional parts of values. */ hash = hash_int (case_num (c, xt->vars[j].var), hash); } + struct freq *te; HMAP_FOR_EACH_WITH_HASH (te, struct freq, node, hash, &xt->data) { - for (j = 0; j < xt->n_vars; j++) + for (size_t j = 0; j < xt->n_vars; j++) if ((int) case_num (c, xt->vars[j].var) != (int) te->values[j].f) goto no_match; @@ -803,7 +814,7 @@ tabulate_integer_case (struct crosstabulation *xt, const struct ccase *c, /* No existing entry. Create a new one. */ te = xmalloc (table_entry_size (xt->n_vars)); te->count = weight; - for (j = 0; j < xt->n_vars; j++) + for (size_t j = 0; j < xt->n_vars; j++) te->values[j].f = (int) case_num (c, xt->vars[j].var); hmap_insert (&xt->data, &te->node, hash); } @@ -812,20 +823,17 @@ static void tabulate_general_case (struct crosstabulation *xt, const struct ccase *c, double weight) { - struct freq *te; - size_t hash; - int j; - - hash = 0; - for (j = 0; j < xt->n_vars; j++) + size_t hash = 0; + for (size_t j = 0; j < xt->n_vars; j++) { const struct variable *var = xt->vars[j].var; hash = value_hash (case_data (c, var), var_get_width (var), hash); } + struct freq *te; HMAP_FOR_EACH_WITH_HASH (te, struct freq, node, hash, &xt->data) { - for (j = 0; j < xt->n_vars; j++) + for (size_t j = 0; j < xt->n_vars; j++) { const struct variable *var = xt->vars[j].var; if (!value_equal (case_data (c, var), &te->values[j], @@ -843,7 +851,7 @@ tabulate_general_case (struct crosstabulation *xt, const struct ccase *c, /* No existing entry. Create a new one. */ te = xmalloc (table_entry_size (xt->n_vars)); te->count = weight; - for (j = 0; j < xt->n_vars; j++) + for (size_t j = 0; j < xt->n_vars; j++) { const struct variable *var = xt->vars[j].var; value_clone (&te->values[j], case_data (c, var), var_get_width (var)); @@ -902,19 +910,19 @@ postcalc (struct crosstabs_proc *proc, struct lexer *lexer) for (struct crosstabulation *xt = proc->pivots; xt < &proc->pivots[proc->n_pivots]; xt++) { - struct freq *e; - xt->n_entries = hmap_count (&xt->data); xt->entries = xnmalloc (xt->n_entries, sizeof *xt->entries); + size_t i = 0; + struct freq *e; HMAP_FOR_EACH (e, struct freq, node, &xt->data) xt->entries[i++] = e; + hmap_destroy (&xt->data); sort (xt->entries, xt->n_entries, sizeof *xt->entries, proc->descending ? compare_table_entry_3way_inv : compare_table_entry_3way, xt); - } make_summary_table (proc); @@ -954,12 +962,8 @@ postcalc (struct crosstabs_proc *proc, struct lexer *lexer) { int width = var_get_width (xt->vars[i].var); if (value_needs_init (width)) - { - size_t j; - - for (j = 0; j < xt->n_entries; j++) - value_destroy (&xt->entries[j]->values[i], width); - } + for (size_t j = 0; j < xt->n_entries; j++) + value_destroy (&xt->entries[j]->values[i], width); } for (size_t i = 0; i < xt->n_entries; i++) @@ -1018,9 +1022,7 @@ compare_table_entry_vars_3way (const struct freq *a, const struct crosstabulation *xt, int idx0, int idx1) { - int i; - - for (i = idx1 - 1; i >= idx0; i--) + for (int i = idx1 - 1; i >= idx0; i--) { int cmp = compare_table_entry_var_3way (a, b, xt, i); if (cmp != 0) @@ -1039,9 +1041,8 @@ compare_table_entry_3way (const void *ap_, const void *bp_, const void *xt_) const struct freq *a = *ap; const struct freq *b = *bp; const struct crosstabulation *xt = xt_; - int cmp; - cmp = compare_table_entry_vars_3way (a, b, xt, 2, xt->n_vars); + int cmp = compare_table_entry_vars_3way (a, b, xt, 2, xt->n_vars); if (cmp != 0) return cmp; @@ -1147,10 +1148,9 @@ output_crosstabulation (struct crosstabs_proc *proc, struct crosstabulation *xt, if (xt->vars[COL_VAR].n_values == 0) { struct string vars; - int i; ds_init_cstr (&vars, var_to_string (xt->vars[0].var)); - for (i = 1; i < xt->n_vars; i++) + for (size_t i = 1; i < xt->n_vars; i++) ds_put_format (&vars, " × %s", var_to_string (xt->vars[i].var)); /* TRANSLATORS: The %s here describes a crosstabulation. It takes the @@ -1258,13 +1258,11 @@ build_matrix (struct crosstabulation *x) const int row_var_width = var_get_width (x->vars[ROW_VAR].var); size_t n_rows = x->vars[ROW_VAR].n_values; size_t n_cols = x->vars[COL_VAR].n_values; - int col, row; - double *mp; - struct freq **p; - mp = x->mat; - col = row = 0; - for (p = x->entries; p < &x->entries[x->n_entries]; p++) + double *mp = x->mat; + size_t col = 0; + size_t row = 0; + for (struct freq **p = x->entries; p < &x->entries[x->n_entries]; p++) { const struct freq *te = *p; @@ -1575,23 +1573,22 @@ delete_missing (struct crosstabulation *xt) { size_t n_rows = xt->vars[ROW_VAR].n_values; size_t n_cols = xt->vars[COL_VAR].n_values; - int r, c; - for (r = 0; r < n_rows; r++) + for (size_t r = 0; r < n_rows; r++) if (var_is_num_missing (xt->vars[ROW_VAR].var, xt->vars[ROW_VAR].values[r].f) == MV_USER) { - for (c = 0; c < n_cols; c++) + for (size_t c = 0; c < n_cols; c++) xt->mat[c + r * n_cols] = 0.; xt->ns_rows--; } - for (c = 0; c < n_cols; c++) + for (size_t c = 0; c < n_cols; c++) if (var_is_num_missing (xt->vars[COL_VAR].var, xt->vars[COL_VAR].values[c].f) == MV_USER) { - for (r = 0; r < n_rows; r++) + for (size_t r = 0; r < n_rows; r++) xt->mat[c + r * n_cols] = 0.; xt->ns_cols--; } @@ -1601,11 +1598,10 @@ static bool find_crosstab (struct crosstabulation *xt, size_t *row0p, size_t *row1p) { size_t row0 = *row1p; - size_t row1; - if (row0 >= xt->n_entries) return false; + size_t row1; for (row1 = row0 + 1; row1 < xt->n_entries; row1++) { struct freq *a = xt->entries[row0]; @@ -1660,17 +1656,16 @@ enum_var_values (const struct crosstabulation *xt, int var_idx, else { int width = var_get_width (xv->var); - struct hmapx_node *node; - const union value *iter; - struct hmapx set; + struct hmapx set = HMAPX_INITIALIZER (set); - hmapx_init (&set); for (size_t i = 0; i < xt->n_entries; i++) { const struct freq *te = xt->entries[i]; const union value *value = &te->values[var_idx]; size_t hash = value_hash (value, width, 0); + const union value *iter; + struct hmapx_node *node; HMAPX_FOR_EACH_WITH_HASH (iter, node, hash, &set) if (value_equal (iter, value, width)) goto next_entry; @@ -1683,6 +1678,8 @@ enum_var_values (const struct crosstabulation *xt, int var_idx, xv->n_values = hmapx_count (&set); xv->values = xnmalloc (xv->n_values, sizeof *xv->values); size_t i = 0; + const union value *iter; + struct hmapx_node *node; HMAPX_FOR_EACH (iter, node, &set) xv->values[i++] = *iter; hmapx_destroy (&set); @@ -1811,7 +1808,7 @@ display_crosstabulation (struct crosstabs_proc *proc, }; for (size_t i = 0; i < proc->n_cells; i++) { - int cell = proc->a_cells[i]; + size_t cell = proc->a_cells[i]; double entry = entries[cell]; if (entry != SYSMIS) { @@ -1845,7 +1842,7 @@ display_chisq (struct crosstabulation *xt, struct pivot_table *chisq) assert (xt->n_vars == 2); for (size_t i = 0; i < xt->n_consts; i++) indexes[i + 2] = xt->const_indexes[i]; - for (int i = 0; i < N_CHISQ; i++) + for (size_t i = 0; i < N_CHISQ; i++) { indexes[0] = i; @@ -1879,10 +1876,10 @@ display_chisq (struct crosstabulation *xt, struct pivot_table *chisq) free (indexes); } -static int calc_symmetric (struct crosstabs_proc *, struct crosstabulation *, - double[N_SYMMETRIC], double[N_SYMMETRIC], - double[N_SYMMETRIC], - double[3], double[3], double[3]); +static bool calc_symmetric (struct crosstabs_proc *, struct crosstabulation *, + double[N_SYMMETRIC], double[N_SYMMETRIC], + double[N_SYMMETRIC], + double[3], double[3], double[3]); /* Display symmetric measures. */ static void @@ -1901,7 +1898,7 @@ display_symmetric (struct crosstabs_proc *proc, struct crosstabulation *xt, for (size_t i = 0; i < xt->n_consts; i++) indexes[i + 2] = xt->const_indexes[i]; - for (int i = 0; i < N_SYMMETRIC; i++) + for (size_t i = 0; i < N_SYMMETRIC; i++) { if (sym_v[i] == SYSMIS) continue; @@ -1947,7 +1944,7 @@ display_risk (struct crosstabulation *xt, struct pivot_table *risk, for (size_t i = 0; i < xt->n_consts; i++) indexes[i + 2] = xt->const_indexes[i]; - for (int i = 0; i < 3; i++) + for (size_t i = 0; i < 3; i++) { const struct variable *cv = xt->vars[COL_VAR].var; const struct variable *rv = xt->vars[ROW_VAR].var; @@ -1994,9 +1991,9 @@ display_risk (struct crosstabulation *xt, struct pivot_table *risk, free (indexes); } -static int calc_directional (struct crosstabs_proc *, struct crosstabulation *, - double[N_DIRECTIONAL], double[N_DIRECTIONAL], - double[N_DIRECTIONAL], double[N_DIRECTIONAL]); +static void calc_directional (struct crosstabs_proc *, struct crosstabulation *, + double[N_DIRECTIONAL], double[N_DIRECTIONAL], + double[N_DIRECTIONAL], double[N_DIRECTIONAL]); /* Display directional measures. */ static void @@ -2007,15 +2004,14 @@ display_directional (struct crosstabs_proc *proc, double direct_ase[N_DIRECTIONAL]; double direct_t[N_DIRECTIONAL]; double sig[N_DIRECTIONAL]; - if (!calc_directional (proc, xt, direct_v, direct_ase, direct_t, sig)) - return; + calc_directional (proc, xt, direct_v, direct_ase, direct_t, sig); size_t *indexes = xnmalloc (direct->n_dimensions, sizeof *indexes); assert (xt->n_vars == 2); for (size_t i = 0; i < xt->n_consts; i++) indexes[i + 2] = xt->const_indexes[i]; - for (int i = 0; i < N_DIRECTIONAL; i++) + for (size_t i = 0; i < N_DIRECTIONAL; i++) { if (direct_v[i] == SYSMIS) continue; @@ -2045,11 +2041,8 @@ static double log_gamma_int (double xt) { double r = 0; - int i; - - for (i = 2; i < xt; i++) + for (int i = 2; i < xt; i++) r += log(i); - return r; } @@ -2079,9 +2072,6 @@ swap (int *a, int *b) static void calc_fisher (int a, int b, int c, int d, double *fisher1, double *fisher2) { - int xt; - double pn1; - if (MIN (c, d) < MIN (a, b)) swap (&a, &c), swap (&b, &d); if (MIN (b, d) < MIN (a, c)) @@ -2094,16 +2084,13 @@ calc_fisher (int a, int b, int c, int d, double *fisher1, double *fisher2) swap (&a, &c), swap (&b, &d); } - pn1 = Pr (a, b, c, d); + double pn1 = Pr (a, b, c, d); *fisher1 = pn1; - for (xt = 1; xt <= a; xt++) - { - *fisher1 += Pr (a - xt, b + xt, c + xt, d - xt); - } + for (int xt = 1; xt <= a; xt++) + *fisher1 += Pr (a - xt, b + xt, c + xt, d - xt); *fisher2 = *fisher1; - - for (xt = 1; xt <= b; xt++) + for (int xt = 1; xt <= b; xt++) { double p = Pr (a + xt, b - xt, c - xt, d + xt); if (p < pn1) @@ -2155,39 +2142,33 @@ calc_chisq (struct crosstabulation *xt, /* Calculate Yates and Fisher exact test. */ if (xt->ns_cols == 2 && xt->ns_rows == 2) { - double f11, f12, f21, f22; - - { - int nz_cols[2]; + int nz_cols[2]; - int j = 0; - FOR_EACH_POPULATED_COLUMN (c, xt) - { - nz_cols[j++] = c; - if (j == 2) - break; - } - assert (j == 2); + size_t j = 0; + FOR_EACH_POPULATED_COLUMN (c, xt) + { + nz_cols[j++] = c; + if (j == 2) + break; + } + assert (j == 2); - f11 = xt->mat[nz_cols[0]]; - f12 = xt->mat[nz_cols[1]]; - f21 = xt->mat[nz_cols[0] + n_cols]; - f22 = xt->mat[nz_cols[1] + n_cols]; - } + double f11 = xt->mat[nz_cols[0]]; + double f12 = xt->mat[nz_cols[1]]; + double f21 = xt->mat[nz_cols[0] + n_cols]; + double f22 = xt->mat[nz_cols[1] + n_cols]; /* Yates. */ - { - const double xt_ = fabs (f11 * f22 - f12 * f21) - 0.5 * xt->total; + const double xt_ = fabs (f11 * f22 - f12 * f21) - 0.5 * xt->total; - if (xt_ > 0.) - chisq[3] = (xt->total * pow2 (xt_) - / (f11 + f12) / (f21 + f22) - / (f11 + f21) / (f12 + f22)); - else - chisq[3] = 0.; + if (xt_ > 0.) + chisq[3] = (xt->total * pow2 (xt_) + / (f11 + f12) / (f21 + f22) + / (f11 + f21) / (f12 + f22)); + else + chisq[3] = 0.; - df[3] = 1.; - } + df[3] = 1.; /* Fisher. */ calc_fisher (f11 + .5, f12 + .5, f21 + .5, f22 + .5, fisher1, fisher2); @@ -2216,70 +2197,63 @@ calc_r (struct crosstabulation *xt, { size_t n_rows = xt->vars[ROW_VAR].n_values; size_t n_cols = xt->vars[COL_VAR].n_values; - double SX, SY, S, T; - double Xbar, Ybar; - double sum_XYf, sum_X2Y2f; - double sum_Xr, sum_X2r; - double sum_Yc, sum_Y2c; - int i, j; - - for (sum_X2Y2f = sum_XYf = 0., i = 0; i < n_rows; i++) - for (j = 0; j < n_cols; j++) + + double sum_XYf = 0; + for (size_t i = 0; i < n_rows; i++) + for (size_t j = 0; j < n_cols; j++) { double fij = xt->mat[j + i * n_cols]; double product = XT[i] * Y[j]; double temp = fij * product; sum_XYf += temp; - sum_X2Y2f += temp * product; } - for (sum_Xr = sum_X2r = 0., i = 0; i < n_rows; i++) + double sum_Xr = 0; + double sum_X2r = 0; + for (size_t i = 0; i < n_rows; i++) { sum_Xr += XT[i] * xt->row_tot[i]; sum_X2r += pow2 (XT[i]) * xt->row_tot[i]; } - Xbar = sum_Xr / xt->total; + double Xbar = sum_Xr / xt->total; - for (sum_Yc = sum_Y2c = 0., i = 0; i < n_cols; i++) + double sum_Yc = 0; + double sum_Y2c = 0; + for (size_t i = 0; i < n_cols; i++) { sum_Yc += Y[i] * xt->col_tot[i]; sum_Y2c += Y[i] * Y[i] * xt->col_tot[i]; } - Ybar = sum_Yc / xt->total; + double Ybar = sum_Yc / xt->total; - S = sum_XYf - sum_Xr * sum_Yc / xt->total; - SX = sum_X2r - pow2 (sum_Xr) / xt->total; - SY = sum_Y2c - pow2 (sum_Yc) / xt->total; - T = sqrt (SX * SY); + double S = sum_XYf - sum_Xr * sum_Yc / xt->total; + double SX = sum_X2r - pow2 (sum_Xr) / xt->total; + double SY = sum_Y2c - pow2 (sum_Yc) / xt->total; + double T = sqrt (SX * SY); *r = S / T; *t = *r / sqrt (1 - pow2 (*r)) * sqrt (xt->total - 2); - { - double s, c, y, t; - - for (s = c = 0., i = 0; i < n_rows; i++) - for (j = 0; j < n_cols; j++) - { - double Xresid, Yresid; - double temp; - - Xresid = XT[i] - Xbar; - Yresid = Y[j] - Ybar; - temp = (T * Xresid * Yresid - - ((S / (2. * T)) - * (Xresid * Xresid * SY + Yresid * Yresid * SX))); - y = xt->mat[j + i * n_cols] * temp * temp - c; - t = s + y; - c = (t - s) - y; - s = t; - } - *error = sqrt (s) / (T * T); - } + double s = 0; + double c = 0; + for (size_t i = 0; i < n_rows; i++) + for (size_t j = 0; j < n_cols; j++) + { + double Xresid = XT[i] - Xbar; + double Yresid = Y[j] - Ybar; + double temp = (T * Xresid * Yresid + - ((S / (2. * T)) + * (Xresid * Xresid * SY + Yresid * Yresid * SX))); + double y = xt->mat[j + i * n_cols] * temp * temp - c; + double t = s + y; + c = (t - s) - y; + s = t; + } + *error = sqrt (s) / (T * T); } /* Calculate symmetric statistics and their asymptotic standard - errors. Returns 0 if none could be calculated. */ -static int + errors. Returns false if none could be calculated. */ +static bool calc_symmetric (struct crosstabs_proc *proc, struct crosstabulation *xt, double v[N_SYMMETRIC], double ase[N_SYMMETRIC], double t[N_SYMMETRIC], @@ -2288,13 +2262,12 @@ calc_symmetric (struct crosstabs_proc *proc, struct crosstabulation *xt, { size_t n_rows = xt->vars[ROW_VAR].n_values; size_t n_cols = xt->vars[COL_VAR].n_values; - int q, i; - q = MIN (xt->ns_rows, xt->ns_cols); + size_t q = MIN (xt->ns_rows, xt->ns_cols); if (q <= 1) - return 0; + return false; - for (i = 0; i < N_SYMMETRIC; i++) + for (size_t i = 0; i < N_SYMMETRIC; i++) v[i] = ase[i] = t[i] = SYSMIS; /* Phi, Cramer's V, contingency coefficient. */ @@ -2324,66 +2297,56 @@ calc_symmetric (struct crosstabs_proc *proc, struct crosstabulation *xt, if (proc->statistics & (CRS_ST_BTAU | CRS_ST_CTAU | CRS_ST_GAMMA | CRS_ST_D)) { - double *cum; - double Dr, Dc; - double P, Q; - double btau_cum, ctau_cum, gamma_cum, d_yx_cum, d_xy_cum; - double btau_var; - int r, c; - - Dr = Dc = pow2 (xt->total); - for (r = 0; r < n_rows; r++) + double Dr = pow2 (xt->total); + for (size_t r = 0; r < n_rows; r++) Dr -= pow2 (xt->row_tot[r]); - for (c = 0; c < n_cols; c++) + + double Dc = pow2 (xt->total); + for (size_t c = 0; c < n_cols; c++) Dc -= pow2 (xt->col_tot[c]); - cum = xnmalloc (n_cols * n_rows, sizeof *cum); - for (c = 0; c < n_cols; c++) + double *cum = xnmalloc (n_cols * n_rows, sizeof *cum); + for (size_t c = 0; c < n_cols; c++) { double ct = 0.; - for (r = 0; r < n_rows; r++) + for (size_t r = 0; r < n_rows; r++) cum[c + r * n_cols] = ct += xt->mat[c + r * n_cols]; } /* P and Q. */ - { - int i, j; - double Cij, Dij; + double P = 0; + double Q = 0; + for (size_t i = 0; i < n_rows; i++) + { + double Cij = 0; + for (size_t j = 1; j < n_cols; j++) + Cij += xt->col_tot[j] - cum[j + i * n_cols]; - P = Q = 0.; - for (i = 0; i < n_rows; i++) - { - Cij = Dij = 0.; + double Dij = 0; + if (i > 0) + for (size_t j = 1; j < n_cols; j++) + Dij += cum[j + (i - 1) * n_cols]; - for (j = 1; j < n_cols; j++) - Cij += xt->col_tot[j] - cum[j + i * n_cols]; + for (size_t j = 0;;) + { + double fij = xt->mat[j + i * n_cols]; + P += fij * Cij; + Q += fij * Dij; - if (i > 0) - for (j = 1; j < n_cols; j++) - Dij += cum[j + (i - 1) * n_cols]; + if (++j >= n_cols) + break; - for (j = 0;;) - { - double fij = xt->mat[j + i * n_cols]; - P += fij * Cij; - Q += fij * Dij; - - if (++j == n_cols) - break; - assert (j < n_cols); - - Cij -= xt->col_tot[j] - cum[j + i * n_cols]; - Dij += xt->col_tot[j - 1] - cum[j - 1 + i * n_cols]; - - if (i > 0) - { - Cij += cum[j - 1 + (i - 1) * n_cols]; - Dij -= cum[j + (i - 1) * n_cols]; - } - } - } - } + Cij -= xt->col_tot[j] - cum[j + i * n_cols]; + Dij += xt->col_tot[j - 1] - cum[j - 1 + i * n_cols]; + + if (i > 0) + { + Cij += cum[j - 1 + (i - 1) * n_cols]; + Dij -= cum[j + (i - 1) * n_cols]; + } + } + } if (proc->statistics & CRS_ST_BTAU) v[3] = (P - Q) / sqrt (Dr * Dc); @@ -2394,74 +2357,62 @@ calc_symmetric (struct crosstabs_proc *proc, struct crosstabulation *xt, /* ASE for tau-b, tau-c, gamma. Calculations could be eliminated here, at expense of memory. */ - { - int i, j; - double Cij, Dij; + double btau_cum = 0; + double ctau_cum = 0; + double gamma_cum = 0; + double d_yx_cum = 0; + double d_xy_cum = 0; + for (size_t i = 0; i < n_rows; i++) + { + double Cij = 0; + for (size_t j = 1; j < n_cols; j++) + Cij += xt->col_tot[j] - cum[j + i * n_cols]; - btau_cum = ctau_cum = gamma_cum = d_yx_cum = d_xy_cum = 0.; - for (i = 0; i < n_rows; i++) - { - Cij = Dij = 0.; + double Dij = 0; + if (i > 0) + for (size_t j = 1; j < n_cols; j++) + Dij += cum[j + (i - 1) * n_cols]; - for (j = 1; j < n_cols; j++) - Cij += xt->col_tot[j] - cum[j + i * n_cols]; + for (size_t j = 0;;) + { + double fij = xt->mat[j + i * n_cols]; - if (i > 0) - for (j = 1; j < n_cols; j++) - Dij += cum[j + (i - 1) * n_cols]; + if (proc->statistics & CRS_ST_BTAU) + btau_cum += fij * pow2 (2. * sqrt (Dr * Dc) * (Cij - Dij) + + v[3] * (xt->row_tot[i] * Dc + + xt->col_tot[j] * Dr)); + ctau_cum += fij * pow2 (Cij - Dij); - for (j = 0;;) - { - double fij = xt->mat[j + i * n_cols]; - - if (proc->statistics & CRS_ST_BTAU) - { - const double temp = (2. * sqrt (Dr * Dc) * (Cij - Dij) - + v[3] * (xt->row_tot[i] * Dc - + xt->col_tot[j] * Dr)); - btau_cum += fij * temp * temp; - } - - { - const double temp = Cij - Dij; - ctau_cum += fij * temp * temp; - } - - if (proc->statistics & CRS_ST_GAMMA) - { - const double temp = Q * Cij - P * Dij; - gamma_cum += fij * temp * temp; - } - - if (proc->statistics & CRS_ST_D) - { - d_yx_cum += fij * pow2 (Dr * (Cij - Dij) - - (P - Q) * (xt->total - xt->row_tot[i])); - d_xy_cum += fij * pow2 (Dc * (Dij - Cij) - - (Q - P) * (xt->total - xt->col_tot[j])); - } - - if (++j == n_cols) - break; - assert (j < n_cols); - - Cij -= xt->col_tot[j] - cum[j + i * n_cols]; - Dij += xt->col_tot[j - 1] - cum[j - 1 + i * n_cols]; - - if (i > 0) - { - Cij += cum[j - 1 + (i - 1) * n_cols]; - Dij -= cum[j + (i - 1) * n_cols]; - } - } - } - } + if (proc->statistics & CRS_ST_GAMMA) + gamma_cum += fij * pow2 (Q * Cij - P * Dij); + + if (proc->statistics & CRS_ST_D) + { + d_yx_cum += fij * pow2 (Dr * (Cij - Dij) + - (P - Q) * (xt->total - xt->row_tot[i])); + d_xy_cum += fij * pow2 (Dc * (Dij - Cij) + - (Q - P) * (xt->total - xt->col_tot[j])); + } + + if (++j >= n_cols) + break; + + Cij -= xt->col_tot[j] - cum[j + i * n_cols]; + Dij += xt->col_tot[j - 1] - cum[j - 1 + i * n_cols]; + + if (i > 0) + { + Cij += cum[j - 1 + (i - 1) * n_cols]; + Dij -= cum[j + (i - 1) * n_cols]; + } + } + } - btau_var = ((btau_cum - - (xt->total * pow2 (xt->total * (P - Q) / sqrt (Dr * Dc) * (Dr + Dc)))) - / pow2 (Dr * Dc)); if (proc->statistics & CRS_ST_BTAU) { + double btau_var = ((btau_cum + - (xt->total * pow2 (xt->total * (P - Q) / sqrt (Dr * Dc) * (Dr + Dc)))) + / pow2 (Dr * Dc)); ase[3] = sqrt (btau_var); t[3] = v[3] / (2 * sqrt ((ctau_cum - (P - Q) * (P - Q) / xt->total) / (Dr * Dc))); @@ -2504,41 +2455,27 @@ calc_symmetric (struct crosstabs_proc *proc, struct crosstabulation *xt, if (proc->statistics & CRS_ST_CORR) { double *R = xmalloc (sizeof *R * n_rows); - double *C = xmalloc (sizeof *C * n_cols); - - { - double y, t, c = 0., s = 0.; - int i = 0; - - for (;;) - { - R[i] = s + (xt->row_tot[i] + 1.) / 2.; - y = xt->row_tot[i] - c; - t = s + y; - c = (t - s) - y; - s = t; - if (++i == n_rows) - break; - assert (i < n_rows); - } - } - - { - double y, t, c = 0., s = 0.; - int j = 0; + double c = 0; + double s = 0; + for (size_t i = 0; i < n_rows; i++) + { + R[i] = s + (xt->row_tot[i] + 1.) / 2.; + double y = xt->row_tot[i] - c; + double t = s + y; + c = (t - s) - y; + s = t; + } - for (;;) - { - C[j] = s + (xt->col_tot[j] + 1.) / 2; - y = xt->col_tot[j] - c; - t = s + y; - c = (t - s) - y; - s = t; - if (++j == n_cols) - break; - assert (j < n_cols); - } - } + double *C = xmalloc (sizeof *C * n_cols); + c = s = 0; + for (size_t j = 0; j < n_cols; j++) + { + C[j] = s + (xt->col_tot[j] + 1.) / 2; + double y = xt->col_tot[j] - c; + double t = s + y; + c = (t - s) - y; + s = t; + } calc_r (xt, R, C, &v[6], &t[6], &ase[6]); @@ -2553,28 +2490,27 @@ calc_symmetric (struct crosstabs_proc *proc, struct crosstabulation *xt, /* Cohen's kappa. */ if (proc->statistics & CRS_ST_KAPPA && xt->ns_rows == xt->ns_cols) { - double ase_under_h0; - double sum_fii, sum_rici, sum_fiiri_ci, sum_fijri_ci2, sum_riciri_ci; - int i, j; - - for (sum_fii = sum_rici = sum_fiiri_ci = sum_riciri_ci = 0., i = j = 0; - i < xt->ns_rows; i++, j++) + double sum_fii = 0; + double sum_rici = 0; + double sum_fiiri_ci = 0; + double sum_riciri_ci = 0; + for (size_t i = 0, j = 0; i < xt->ns_rows; i++, j++) { - double prod, sum; - while (xt->col_tot[j] == 0.) j++; - prod = xt->row_tot[i] * xt->col_tot[j]; - sum = xt->row_tot[i] + xt->col_tot[j]; + double prod = xt->row_tot[i] * xt->col_tot[j]; + double sum = xt->row_tot[i] + xt->col_tot[j]; sum_fii += xt->mat[j + i * n_cols]; sum_rici += prod; sum_fiiri_ci += xt->mat[j + i * n_cols] * sum; sum_riciri_ci += prod * sum; } - for (sum_fijri_ci2 = 0., i = 0; i < xt->ns_rows; i++) - for (j = 0; j < xt->ns_cols; j++) + + double sum_fijri_ci2 = 0; + for (size_t i = 0; i < xt->ns_rows; i++) + for (size_t j = 0; j < xt->ns_cols; j++) { double sum = xt->row_tot[i] + xt->col_tot[j]; sum_fijri_ci2 += xt->mat[j + i * n_cols] * sum * sum; @@ -2582,10 +2518,10 @@ calc_symmetric (struct crosstabs_proc *proc, struct crosstabulation *xt, v[8] = (xt->total * sum_fii - sum_rici) / (pow2 (xt->total) - sum_rici); - ase_under_h0 = sqrt ((pow2 (xt->total) * sum_rici - + sum_rici * sum_rici - - xt->total * sum_riciri_ci) - / (xt->total * (pow2 (xt->total) - sum_rici) * (pow2 (xt->total) - sum_rici))); + double ase_under_h0 = sqrt ((pow2 (xt->total) * sum_rici + + sum_rici * sum_rici + - xt->total * sum_riciri_ci) + / (xt->total * (pow2 (xt->total) - sum_rici) * (pow2 (xt->total) - sum_rici))); ase[8] = sqrt (xt->total * (((sum_fii * (xt->total - sum_fii)) / pow2 (pow2 (xt->total) - sum_rici)) @@ -2601,7 +2537,7 @@ calc_symmetric (struct crosstabs_proc *proc, struct crosstabulation *xt, t[8] = v[8] / ase_under_h0; } - return 1; + return true; } /* Calculate risk estimate. */ @@ -2611,42 +2547,38 @@ calc_risk (struct crosstabulation *xt, double *n_valid) { size_t n_cols = xt->vars[COL_VAR].n_values; - double f11, f12, f21, f22; - double v; - for (int i = 0; i < 3; i++) + for (size_t i = 0; i < 3; i++) value[i] = upper[i] = lower[i] = SYSMIS; if (xt->ns_rows != 2 || xt->ns_cols != 2) return false; - { - /* Find populated columns. */ - int nz_cols[2]; - int n = 0; - FOR_EACH_POPULATED_COLUMN (c, xt) - nz_cols[n++] = c; - assert (n == 2); - - /* Find populated rows. */ - int nz_rows[2]; - n = 0; - FOR_EACH_POPULATED_ROW (r, xt) - nz_rows[n++] = r; - assert (n == 2); - - f11 = xt->mat[nz_cols[0] + n_cols * nz_rows[0]]; - f12 = xt->mat[nz_cols[1] + n_cols * nz_rows[0]]; - f21 = xt->mat[nz_cols[0] + n_cols * nz_rows[1]]; - f22 = xt->mat[nz_cols[1] + n_cols * nz_rows[1]]; - *n_valid = f11 + f12 + f21 + f22; - - c[0] = xt->vars[COL_VAR].values[nz_cols[0]]; - c[1] = xt->vars[COL_VAR].values[nz_cols[1]]; - } + /* Find populated columns. */ + size_t nz_cols[2]; + size_t n = 0; + FOR_EACH_POPULATED_COLUMN (c, xt) + nz_cols[n++] = c; + assert (n == 2); + + /* Find populated rows. */ + size_t nz_rows[2]; + n = 0; + FOR_EACH_POPULATED_ROW (r, xt) + nz_rows[n++] = r; + assert (n == 2); + + double f11 = xt->mat[nz_cols[0] + n_cols * nz_rows[0]]; + double f12 = xt->mat[nz_cols[1] + n_cols * nz_rows[0]]; + double f21 = xt->mat[nz_cols[0] + n_cols * nz_rows[1]]; + double f22 = xt->mat[nz_cols[1] + n_cols * nz_rows[1]]; + *n_valid = f11 + f12 + f21 + f22; + + c[0] = xt->vars[COL_VAR].values[nz_cols[0]]; + c[1] = xt->vars[COL_VAR].values[nz_cols[1]]; value[0] = (f11 * f22) / (f12 * f21); - v = sqrt (1. / f11 + 1. / f12 + 1. / f21 + 1. / f22); + double v = sqrt (1. / f11 + 1. / f12 + 1. / f21 + 1. / f22); lower[0] = value[0] * exp (-1.960 * v); upper[0] = value[0] * exp (1.960 * v); @@ -2666,14 +2598,14 @@ calc_risk (struct crosstabulation *xt, } /* Calculate directional measures. */ -static int +static void calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL], double t[N_DIRECTIONAL], double sig[N_DIRECTIONAL]) { size_t n_rows = xt->vars[ROW_VAR].n_values; size_t n_cols = xt->vars[COL_VAR].n_values; - for (int i = 0; i < N_DIRECTIONAL; i++) + for (size_t i = 0; i < N_DIRECTIONAL; i++) v[i] = ase[i] = t[i] = sig[i] = SYSMIS; /* Lambda. */ @@ -2681,14 +2613,14 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, { /* Find maximum for each row and their sum. */ double *fim = xnmalloc (n_rows, sizeof *fim); - int *fim_index = xnmalloc (n_rows, sizeof *fim_index); + size_t *fim_index = xnmalloc (n_rows, sizeof *fim_index); double sum_fim = 0.0; - for (int i = 0; i < n_rows; i++) + for (size_t i = 0; i < n_rows; i++) { double max = xt->mat[i * n_cols]; - int index = 0; + size_t index = 0; - for (int j = 1; j < n_cols; j++) + for (size_t j = 1; j < n_cols; j++) if (xt->mat[j + i * n_cols] > max) { max = xt->mat[j + i * n_cols]; @@ -2702,14 +2634,14 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, /* Find maximum for each column. */ double *fmj = xnmalloc (n_cols, sizeof *fmj); - int *fmj_index = xnmalloc (n_cols, sizeof *fmj_index); + size_t *fmj_index = xnmalloc (n_cols, sizeof *fmj_index); double sum_fmj = 0.0; - for (int j = 0; j < n_cols; j++) + for (size_t j = 0; j < n_cols; j++) { double max = xt->mat[j]; - int index = 0; + size_t index = 0; - for (int i = 1; i < n_rows; i++) + for (size_t i = 1; i < n_rows; i++) if (xt->mat[j + i * n_cols] > max) { max = xt->mat[j + i * n_cols]; @@ -2723,8 +2655,8 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, /* Find maximum row total. */ double rm = xt->row_tot[0]; - int rm_index = 0; - for (int i = 1; i < n_rows; i++) + size_t rm_index = 0; + for (size_t i = 1; i < n_rows; i++) if (xt->row_tot[i] > rm) { rm = xt->row_tot[i]; @@ -2733,8 +2665,8 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, /* Find maximum column total. */ double cm = xt->col_tot[0]; - int cm_index = 0; - for (int j = 1; j < n_cols; j++) + size_t cm_index = 0; + for (size_t j = 1; j < n_cols; j++) if (xt->col_tot[j] > cm) { cm = xt->col_tot[j]; @@ -2748,7 +2680,7 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, /* ASE1 for Y given XT. */ { double accum = 0.0; - for (int i = 0; i < n_rows; i++) + for (size_t i = 0; i < n_rows; i++) if (cm_index == fim_index[i]) accum += fim[i]; ase[2] = sqrt ((xt->total - sum_fim) * (sum_fim + cm - 2. * accum) @@ -2758,7 +2690,7 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, /* ASE0 for Y given XT. */ { double accum = 0.0; - for (int i = 0; i < n_rows; i++) + for (size_t i = 0; i < n_rows; i++) if (cm_index != fim_index[i]) accum += (xt->mat[i * n_cols + fim_index[i]] + xt->mat[i * n_cols + cm_index]); @@ -2768,7 +2700,7 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, /* ASE1 for XT given Y. */ { double accum = 0.0; - for (int j = 0; j < n_cols; j++) + for (size_t j = 0; j < n_cols; j++) if (rm_index == fmj_index[j]) accum += fmj[j]; ase[1] = sqrt ((xt->total - sum_fmj) * (sum_fmj + rm - 2. * accum) @@ -2778,7 +2710,7 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, /* ASE0 for XT given Y. */ { double accum = 0.0; - for (int j = 0; j < n_cols; j++) + for (size_t j = 0; j < n_cols; j++) if (rm_index != fmj_index[j]) accum += (xt->mat[j + n_cols * fmj_index[j]] + xt->mat[j + n_cols * rm_index]); @@ -2789,8 +2721,8 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, { double accum0 = 0.0; double accum1 = 0.0; - for (int i = 0; i < n_rows; i++) - for (int j = 0; j < n_cols; j++) + for (size_t i = 0; i < n_rows; i++) + for (size_t j = 0; j < n_cols; j++) { int temp0 = (fmj_index[j] == i) + (fim_index[i] == j); int temp1 = (i == rm_index) + (j == cm_index); @@ -2803,7 +2735,7 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, / (2. * xt->total - rm - cm)); } - for (int i = 0; i < 3; i++) + for (size_t i = 0; i < 3; i++) sig[i] = 2 * gsl_cdf_ugaussian_Q (t[i]); free (fim); @@ -2812,28 +2744,26 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, free (fmj_index); /* Tau. */ - { - double sum_fij2_ri = 0.0; - double sum_fij2_ci = 0.0; - FOR_EACH_POPULATED_ROW (i, xt) - FOR_EACH_POPULATED_COLUMN (j, xt) - { - double temp = pow2 (xt->mat[j + i * n_cols]); - sum_fij2_ri += temp / xt->row_tot[i]; - sum_fij2_ci += temp / xt->col_tot[j]; - } + double sum_fij2_ri = 0.0; + double sum_fij2_ci = 0.0; + FOR_EACH_POPULATED_ROW (i, xt) + FOR_EACH_POPULATED_COLUMN (j, xt) + { + double temp = pow2 (xt->mat[j + i * n_cols]); + sum_fij2_ri += temp / xt->row_tot[i]; + sum_fij2_ci += temp / xt->col_tot[j]; + } - double sum_ri2 = 0.0; - for (int i = 0; i < n_rows; i++) - sum_ri2 += pow2 (xt->row_tot[i]); + double sum_ri2 = 0.0; + for (size_t i = 0; i < n_rows; i++) + sum_ri2 += pow2 (xt->row_tot[i]); - double sum_cj2 = 0.0; - for (int j = 0; j < n_cols; j++) - sum_cj2 += pow2 (xt->col_tot[j]); + double sum_cj2 = 0.0; + for (size_t j = 0; j < n_cols; j++) + sum_cj2 += pow2 (xt->col_tot[j]); - v[3] = (xt->total * sum_fij2_ci - sum_ri2) / (pow2 (xt->total) - sum_ri2); - v[4] = (xt->total * sum_fij2_ri - sum_cj2) / (pow2 (xt->total) - sum_cj2); - } + v[3] = (xt->total * sum_fij2_ci - sum_ri2) / (pow2 (xt->total) - sum_ri2); + v[4] = (xt->total * sum_fij2_ri - sum_cj2) / (pow2 (xt->total) - sum_cj2); } if (proc->statistics & CRS_ST_UC) @@ -2848,8 +2778,8 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, double UXY = 0.0; double P = 0.0; - for (int i = 0; i < n_rows; i++) - for (int j = 0; j < n_cols; j++) + for (size_t i = 0; i < n_rows; i++) + for (size_t j = 0; j < n_cols; j++) { double entry = xt->mat[j + i * n_cols]; @@ -2863,8 +2793,8 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, double ase1_yx = 0.0; double ase1_xy = 0.0; double ase1_sym = 0.0; - for (int i = 0; i < n_rows; i++) - for (int j = 0; j < n_cols; j++) + for (size_t i = 0; i < n_rows; i++) + for (size_t j = 0; j < n_cols; j++) { double entry = xt->mat[j + i * n_cols]; @@ -2906,7 +2836,7 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, if (calc_symmetric (proc, xt, v_dummy, ase_dummy, t_dummy, somers_d_v, somers_d_ase, somers_d_t)) { - for (int i = 0; i < 3; i++) + for (size_t i = 0; i < 3; i++) { v[8 + i] = somers_d_v[i]; ase[8 + i] = somers_d_ase[i]; @@ -2922,7 +2852,7 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, /* X dependent. */ double sum_Xr = 0.0; double sum_X2r = 0.0; - for (int i = 0; i < n_rows; i++) + for (size_t i = 0; i < n_rows; i++) { sum_Xr += xt->vars[ROW_VAR].values[i].f * xt->row_tot[i]; sum_X2r += pow2 (xt->vars[ROW_VAR].values[i].f) * xt->row_tot[i]; @@ -2934,7 +2864,7 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, { double cum = 0.0; - for (int i = 0; i < n_rows; i++) + for (size_t i = 0; i < n_rows; i++) { SXW += (pow2 (xt->vars[ROW_VAR].values[i].f) * xt->mat[j + i * n_cols]); @@ -2949,7 +2879,7 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, /* Y dependent. */ double sum_Yc = 0.0; double sum_Y2c = 0.0; - for (int i = 0; i < n_cols; i++) + for (size_t i = 0; i < n_cols; i++) { sum_Yc += xt->vars[COL_VAR].values[i].f * xt->col_tot[i]; sum_Y2c += pow2 (xt->vars[COL_VAR].values[i].f) * xt->col_tot[i]; @@ -2960,7 +2890,7 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, FOR_EACH_POPULATED_ROW (i, xt) { double cum = 0.0; - for (int j = 0; j < n_cols; j++) + for (size_t j = 0; j < n_cols; j++) { SYW += (pow2 (xt->vars[COL_VAR].values[j].f) * xt->mat[j + i * n_cols]); @@ -2972,6 +2902,4 @@ calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt, } v[12] = sqrt (1. - SYW / SY); } - - return 1; } diff --git a/tests/language/stats/crosstabs.at b/tests/language/stats/crosstabs.at index 53a7335de9..a26379e88a 100644 --- a/tests/language/stats/crosstabs.at +++ b/tests/language/stats/crosstabs.at @@ -1939,3 +1939,93 @@ AT_CHECK([test -e xxx-2.png], [0], [ignore]) AT_CHECK([diff xxx-1.png xxx-2.png], [0], [ignore]) AT_CLEANUP + +AT_SETUP([CROSSTABS syntax errors]) +AT_DATA([crosstabs.sps], [dnl +DATA LIST LIST NOTABLE/x y v1 to v100. +CROSSTABS TABLES=x BY y/VARIABLES **. +CROSSTABS VARIABLES=**. +CROSSTABS VARIABLES=x **. +CROSSTABS VARIABLES=x (**). +CROSSTABS VARIABLES=x (1,**). +CROSSTABS VARIABLES=x (1,5**). +CROSSTABS MISSING=**. +CROSSTABS COUNT=**. +CROSSTABS FORMAT=**. +CROSSTABS CELLS=**. +CROSSTABS STATISTICS=**. +CROSSTABS **. +CROSSTABS + v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 + BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 + BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 + BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 + BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 + BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100. +CROSSTABS BARCHART. +CROSSTABS x BY y/MISSING=REPORT. +]) +AT_CHECK([pspp -O format=csv crosstabs.sps], [1], [dnl +"crosstabs.sps:2.25-2.33: error: CROSSTABS: VARIABLES must be specified before TABLES. + 2 | CROSSTABS TABLES=x BY y/VARIABLES **. + | ^~~~~~~~~" + +"crosstabs.sps:3.21-3.22: error: CROSSTABS: Syntax error expecting variable name. + 3 | CROSSTABS VARIABLES=**. + | ^~" + +"crosstabs.sps:4.23-4.24: error: CROSSTABS: Syntax error expecting `('. + 4 | CROSSTABS VARIABLES=x **. + | ^~" + +"crosstabs.sps:5.24-5.25: error: CROSSTABS: Syntax error expecting integer. + 5 | CROSSTABS VARIABLES=x (**). + | ^~" + +"crosstabs.sps:6.26-6.27: error: CROSSTABS: Syntax error expecting positive integer. + 6 | CROSSTABS VARIABLES=x (1,**). + | ^~" + +"crosstabs.sps:7.27-7.28: error: CROSSTABS: Syntax error expecting `)'. + 7 | CROSSTABS VARIABLES=x (1,5**). + | ^~" + +"crosstabs.sps:8.19-8.20: error: CROSSTABS: Syntax error expecting TABLE, INCLUDE, or REPORT. + 8 | CROSSTABS MISSING=**. + | ^~" + +"crosstabs.sps:9.17-9.18: error: CROSSTABS: Syntax error expecting ASIS, CASE, CELL, ROUND, or TRUNCATE. + 9 | CROSSTABS COUNT=**. + | ^~" + +"crosstabs.sps:10.18-10.19: error: CROSSTABS: Syntax error expecting AVALUE, DVALUE, TABLES, or NOTABLES. + 10 | CROSSTABS FORMAT=**. + | ^~" + +"crosstabs.sps:11.17-11.18: error: CROSSTABS: Syntax error expecting COUNT, EXPECTED, ROW, COLUMN, TOTAL, RESIDUAL, SRESIDUAL, or ASRESIDUAL. + 11 | CROSSTABS CELLS=**. + | ^~" + +"crosstabs.sps:12.22-12.23: error: CROSSTABS: Syntax error expecting one of the following: CHISQ, PHI, CC, LAMBDA, UC, BTAU, CTAU, RISK, GAMMA, D, KAPPA, ETA, CORR. + 12 | CROSSTABS STATISTICS=**. + | ^~" + +"crosstabs.sps:13.11-13.12: error: CROSSTABS: Syntax error expecting subcommand name or variable name. + 13 | CROSSTABS **. + | ^~" + +"crosstabs.sps:15.8-16.59: error: CROSSTABS: Too many cross-tabulation variables or dimensions. + 15 | v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 16 | BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 BY v1 to v100 + | -----------------------------------------------------------" + +crosstabs.sps:21: error: CROSSTABS: At least one crosstabulation must be requested (using the TABLES subcommand). + +"crosstabs.sps:22.26-22.31: warning: CROSSTABS: Missing mode REPORT not allowed in general mode. Assuming MISSING=TABLE. + 22 | CROSSTABS x BY y/MISSING=REPORT. + | ^~~~~~" + +error: CROSSTABS: At end of input: Syntax error expecting `BEGIN DATA'. +]) +AT_CLEANUP \ No newline at end of file -- 2.30.2