X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fstats%2Fcrosstabs.q;h=b71524a11a41175d132ea56978d6a1e4d7ff9400;hb=c6fe58a22249f4f486b42f35fd8bd537c91e8e6e;hp=405460de4a4b1c5a637fe9e7eea409b30e6da514;hpb=42489b63e0b4bec2e20c2f55c9791234f7b41764;p=pspp-builds.git diff --git a/src/language/stats/crosstabs.q b/src/language/stats/crosstabs.q index 405460de..b71524a1 100644 --- a/src/language/stats/crosstabs.q +++ b/src/language/stats/crosstabs.q @@ -1,21 +1,18 @@ -/* PSPP - computes sample statistics. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. - Written by Ben Pfaff . +/* PSPP - a program for statistical analysis. + Copyright (C) 1997-9, 2000, 2006, 2009 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 the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with this program. If not, see . */ /* FIXME: @@ -37,7 +34,11 @@ #include #include +#include +#include +#include #include +#include #include #include #include @@ -45,13 +46,10 @@ #include #include #include -#include #include #include #include #include -#include -#include #include #include #include @@ -59,6 +57,10 @@ #include #include +#include "minmax.h" +#include "xalloc.h" +#include "xmalloca.h" + #include "gettext.h" #define _(msgid) gettext (msgid) #define N_(msgid) msgid @@ -113,7 +115,7 @@ struct crosstab int nvar; /* Number of variables. */ double missing; /* Missing cases count. */ int ofs; /* Integer mode: Offset into sorted_tab[]. */ - struct variable *vars[2]; /* At least two variables; sorted by + const struct variable *vars[2]; /* At least two variables; sorted by larger indices first. */ }; @@ -126,11 +128,9 @@ struct var_range }; static inline struct var_range * -get_var_range (struct variable *v) +get_var_range (const struct variable *v) { - assert (v != NULL); - assert (v->aux != NULL); - return v->aux; + return var_get_aux (v); } /* Indexes into crosstab.v. */ @@ -146,7 +146,7 @@ static int n_sorted_tab; /* Number of entries in sorted_tab. */ static struct table_entry **sorted_tab; /* Sorted table. */ /* Variables specifies on VARIABLES. */ -static struct variable **variables; +static const struct variable **variables; static size_t variables_cnt; /* TABLES. */ @@ -166,7 +166,7 @@ static int num_cells; /* Number of cells requested. */ static int cells[8]; /* Cells requested. */ /* WRITE. */ -static int write; /* One of WR_* that specifies the WRITE style. */ +static int write_style; /* One of WR_* that specifies the WRITE style. */ /* Command parsing info. */ static struct cmd_crosstabs cmd; @@ -175,11 +175,12 @@ static struct cmd_crosstabs cmd; static struct pool *pl_tc; /* For table cells. */ static struct pool *pl_col; /* For column data. */ -static int internal_cmd_crosstabs (void); -static void precalc (const struct ccase *, void *); -static bool calc_general (const struct ccase *, void *); -static bool calc_integer (const struct ccase *, void *); -static void postcalc (void *); +static int internal_cmd_crosstabs (struct lexer *lexer, struct dataset *ds); +static void precalc (struct casereader *, const struct dataset *); +static void calc_general (const struct ccase *, const struct dataset *); +static void calc_integer (const struct ccase *, const struct dataset *); +static void postcalc (const struct dataset *); + static void submit (struct tab_table *); static void format_short (char *s, const struct fmt_spec *fp, @@ -187,23 +188,30 @@ static void format_short (char *s, const struct fmt_spec *fp, /* Parse and execute CROSSTABS, then clean up. */ int -cmd_crosstabs (void) +cmd_crosstabs (struct lexer *lexer, struct dataset *ds) { - int result = internal_cmd_crosstabs (); + int result = internal_cmd_crosstabs (lexer, ds); + int i; free (variables); pool_destroy (pl_tc); pool_destroy (pl_col); - + + for (i = 0; i < nxtab; i++) + free (xtab[i]); + free (xtab); + return result; } /* Parses and executes the CROSSTABS procedure. */ static int -internal_cmd_crosstabs (void) +internal_cmd_crosstabs (struct lexer *lexer, struct dataset *ds) { - int i; + struct casegrouper *grouper; + struct casereader *input, *group; bool ok; + int i; variables = NULL; variables_cnt = 0; @@ -212,7 +220,7 @@ internal_cmd_crosstabs (void) pl_tc = pool_create (); pl_col = pool_create (); - if (!parse_crosstabs (&cmd, NULL)) + if (!parse_crosstabs (lexer, ds, &cmd, NULL)) return CMD_FAILURE; mode = variables ? INTEGER : GENERAL; @@ -222,7 +230,7 @@ internal_cmd_crosstabs (void) { cmd.a_cells[CRS_CL_COUNT] = 1; } - else + else { int count = 0; @@ -263,7 +271,7 @@ internal_cmd_crosstabs (void) for (i = 0; i < CRS_ST_count; i++) cmd.a_statistics[i] = 1; } - + /* MISSING. */ if (cmd.miss == CRS_REPORT && mode == GENERAL) { @@ -287,70 +295,90 @@ internal_cmd_crosstabs (void) + cmd.a_write[CRS_WR_CELLS] == 0)) cmd.a_write[CRS_WR_CELLS] = 1; if (cmd.a_write[CRS_WR_CELLS]) - write = CRS_WR_CELLS; + write_style = CRS_WR_CELLS; else if (cmd.a_write[CRS_WR_ALL]) - write = CRS_WR_ALL; + write_style = CRS_WR_ALL; else - write = CRS_WR_NONE; + write_style = CRS_WR_NONE; - ok = procedure_with_splits (current_dataset, precalc, - mode == GENERAL ? calc_general : calc_integer, - postcalc, NULL); + input = casereader_create_filter_weight (proc_open (ds), dataset_dict (ds), + NULL, NULL); + grouper = casegrouper_create_splits (input, dataset_dict (ds)); + while (casegrouper_get_next_group (grouper, &group)) + { + struct ccase *c; + + precalc (group, ds); + + for (; (c = casereader_read (group)) != NULL; case_unref (c)) + { + if (mode == GENERAL) + calc_general (c, ds); + else + calc_integer (c, ds); + } + casereader_destroy (group); + + postcalc (ds); + } + ok = casegrouper_destroy (grouper); + ok = proc_commit (ds) && ok; return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE; } /* Parses the TABLES subcommand. */ static int -crs_custom_tables (struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED) +crs_custom_tables (struct lexer *lexer, struct dataset *ds, struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED) { - struct var_set *var_set; + struct const_var_set *var_set; int n_by; - struct variable ***by = NULL; + const struct variable ***by = NULL; size_t *by_nvar = NULL; size_t nx = 1; int success = 0; /* Ensure that this is a TABLES subcommand. */ - if (!lex_match_id ("TABLES") - && (token != T_ID || dict_lookup_var (dataset_dict (current_dataset), tokid) == NULL) - && token != T_ALL) + if (!lex_match_id (lexer, "TABLES") + && (lex_token (lexer) != T_ID || + dict_lookup_var (dataset_dict (ds), lex_tokid (lexer)) == NULL) + && lex_token (lexer) != T_ALL) return 2; - lex_match ('='); + lex_match (lexer, '='); if (variables != NULL) - var_set = var_set_create_from_array (variables, variables_cnt); + var_set = const_var_set_create_from_array (variables, variables_cnt); else - var_set = var_set_create_from_dict (dataset_dict (current_dataset)); + var_set = const_var_set_create_from_dict (dataset_dict (ds)); assert (var_set != NULL); - + for (n_by = 0; ;) { by = xnrealloc (by, n_by + 1, sizeof *by); by_nvar = xnrealloc (by_nvar, n_by + 1, sizeof *by_nvar); - if (!parse_var_set_vars (var_set, &by[n_by], &by_nvar[n_by], + 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])) + if (xalloc_oversized (nx, by_nvar[n_by])) { - msg (SE, _("Too many crosstabulation variables or dimensions.")); + msg (SE, _("Too many cross-tabulation variables or dimensions.")); goto done; } nx *= by_nvar[n_by]; n_by++; - if (!lex_match (T_BY)) + if (!lex_match (lexer, T_BY)) { if (n_by < 2) { - lex_error (_("expecting BY")); + lex_error (lexer, _("expecting BY")); goto done; } - else + else break; } } - + { int *by_iter = xcalloc (n_by, sizeof *by_iter); int i; @@ -370,7 +398,7 @@ crs_custom_tables (struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED) for (i = 0; i < n_by; i++) x->vars[i] = by[i][by_iter[i]]; } - + { int i; @@ -399,14 +427,14 @@ crs_custom_tables (struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED) free (by_nvar); } - var_set_destroy (var_set); + const_var_set_destroy (var_set); return success; } /* Parses the VARIABLES subcommand. */ static int -crs_custom_variables (struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED) +crs_custom_variables (struct lexer *lexer, struct dataset *ds, struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED) { if (nxtab) { @@ -414,53 +442,54 @@ crs_custom_variables (struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED) return 0; } - lex_match ('='); - + lex_match (lexer, '='); + for (;;) { size_t orig_nv = variables_cnt; size_t i; long min, max; - - if (!parse_variables (dataset_dict (current_dataset), &variables, &variables_cnt, + + if (!parse_variables_const (lexer, dataset_dict (ds), + &variables, &variables_cnt, (PV_APPEND | PV_NUMERIC | PV_NO_DUPLICATE | PV_NO_SCRATCH))) return 0; - if (token != '(') + if (lex_token (lexer) != '(') { - lex_error ("expecting `('"); + lex_error (lexer, "expecting `('"); goto lossage; } - lex_get (); + lex_get (lexer); - if (!lex_force_int ()) + if (!lex_force_int (lexer)) goto lossage; - min = lex_integer (); - lex_get (); + min = lex_integer (lexer); + lex_get (lexer); - lex_match (','); + lex_match (lexer, ','); - if (!lex_force_int ()) + if (!lex_force_int (lexer)) goto lossage; - max = lex_integer (); + max = lex_integer (lexer); if (max < min) { msg (SE, _("Maximum value (%ld) less than minimum value (%ld)."), max, min); goto lossage; } - lex_get (); + lex_get (lexer); - if (token != ')') + if (lex_token (lexer) != ')') { - lex_error ("expecting `)'"); + lex_error (lexer, "expecting `)'"); goto lossage; } - lex_get (); - - for (i = orig_nv; i < variables_cnt; i++) + lex_get (lexer); + + for (i = orig_nv; i < variables_cnt; i++) { struct var_range *vr = xmalloc (sizeof *vr); vr->min = min; @@ -468,11 +497,11 @@ crs_custom_variables (struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED) vr->count = max - min + 1; var_attach_aux (variables[i], vr, var_dtor_free); } - - if (token == '/') + + if (lex_token (lexer) == '/') break; } - + return 1; lossage: @@ -483,20 +512,28 @@ crs_custom_variables (struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED) /* Data file processing. */ -static int compare_table_entry (const void *, const void *, void *); -static unsigned hash_table_entry (const void *, void *); +static int compare_table_entry (const void *, const void *, const void *); +static unsigned hash_table_entry (const void *, const void *); /* Set up the crosstabulation tables for processing. */ -static void -precalc (const struct ccase *first, void *aux UNUSED) +static void +precalc (struct casereader *input, const struct dataset *ds) { - output_split_file_values (first); + struct ccase *c; + + c = casereader_peek (input, 0); + if (c != NULL) + { + output_split_file_values (ds, c); + case_unref (c); + } + if (mode == GENERAL) { gen_tab = hsh_create (512, compare_table_entry, hash_table_entry, NULL, NULL); } - else + else { int i; @@ -512,14 +549,14 @@ precalc (const struct ccase *first, void *aux UNUSED) x->ofs = n_sorted_tab; - for (j = 2; j < x->nvar; j++) + for (j = 2; j < x->nvar; j++) count *= get_var_range (x->vars[j - 2])->count; - + sorted_tab = xnrealloc (sorted_tab, n_sorted_tab + count, sizeof *sorted_tab); - v = local_alloc (sizeof *v * x->nvar); - for (j = 2; j < x->nvar; j++) - v[j] = get_var_range (x->vars[j])->min; + v = xmalloca (sizeof *v * x->nvar); + for (j = 2; j < x->nvar; j++) + v[j] = get_var_range (x->vars[j])->min; for (j = 0; j < count; j++) { struct table_entry *te; @@ -528,30 +565,30 @@ precalc (const struct ccase *first, void *aux UNUSED) te = sorted_tab[n_sorted_tab++] = xmalloc (sizeof *te + sizeof (union value) * (x->nvar - 1)); te->table = i; - + { int row_cnt = get_var_range (x->vars[0])->count; int col_cnt = get_var_range (x->vars[1])->count; const int mat_size = row_cnt * col_cnt; int m; - + te->u.data = xnmalloc (mat_size, sizeof *te->u.data); for (m = 0; m < mat_size; m++) te->u.data[m] = 0.; } - + for (k = 2; k < x->nvar; k++) te->values[k].f = v[k]; - for (k = 2; k < x->nvar; k++) + for (k = 2; k < x->nvar; k++) { struct var_range *vr = get_var_range (x->vars[k]); if (++v[k] >= vr->max) v[k] = vr->min; else - break; + break; } } - local_free (v); + freea (v); } sorted_tab = xnrealloc (sorted_tab, @@ -562,13 +599,16 @@ precalc (const struct ccase *first, void *aux UNUSED) } /* Form crosstabulations for general mode. */ -static bool -calc_general (const struct ccase *c, void *aux UNUSED) +static void +calc_general (const struct ccase *c, const struct dataset *ds) { - bool bad_warn = true; + /* Missing values to exclude. */ + enum mv_class exclude = (cmd.miss == CRS_TABLE ? MV_ANY + : cmd.miss == CRS_INCLUDE ? MV_SYSTEM + : MV_NEVER); /* Case weight. */ - double weight = dict_get_case_weight (dataset_dict (current_dataset), c, &bad_warn); + double weight = dict_get_case_weight (dataset_dict (ds), c, NULL); /* Flattened current table index. */ int t; @@ -578,7 +618,7 @@ calc_general (const struct ccase *c, void *aux UNUSED) struct crosstab *x = xtab[t]; const size_t entry_size = (sizeof (struct table_entry) + sizeof (union value) * (x->nvar - 1)); - struct table_entry *te = local_alloc (entry_size); + struct table_entry *te = xmalloca (entry_size); /* Construct table entry for the current record and table. */ te->table = t; @@ -588,26 +628,25 @@ calc_general (const struct ccase *c, void *aux UNUSED) assert (x != NULL); for (j = 0; j < x->nvar; j++) { - const union value *v = case_data (c, x->vars[j]->fv); - const struct missing_values *mv = &x->vars[j]->miss; - if ((cmd.miss == CRS_TABLE && mv_is_value_missing (mv, v)) - || (cmd.miss == CRS_INCLUDE - && mv_is_value_system_missing (mv, v))) + const union value *v = case_data (c, x->vars[j]); + if (var_is_value_missing (x->vars[j], v, exclude)) { x->missing += weight; goto next_crosstab; } - - if (x->vars[j]->type == NUMERIC) - te->values[j].f = case_num (c, x->vars[j]->fv); + + if (var_is_numeric (x->vars[j])) + te->values[j].f = case_num (c, x->vars[j]); else { - memcpy (te->values[j].s, case_str (c, x->vars[j]->fv), - x->vars[j]->width); - + size_t n = var_get_width (x->vars[j]); + if (n > MAX_SHORT_STRING) + n = MAX_SHORT_STRING; + memcpy (te->values[j].s, case_str (c, x->vars[j]), n); + /* Necessary in order to simplify comparisons. */ - memset (&te->values[j].s[x->vars[j]->width], 0, - sizeof (union value) - x->vars[j]->width); + memset (&te->values[j].s[var_get_width (x->vars[j])], 0, + sizeof (union value) - n); } } } @@ -619,10 +658,10 @@ calc_general (const struct ccase *c, void *aux UNUSED) if (*tepp == NULL) { struct table_entry *tep = pool_alloc (pl_tc, entry_size); - + te->u.freq = weight; memcpy (tep, te, entry_size); - + *tepp = tep; } else @@ -630,74 +669,70 @@ calc_general (const struct ccase *c, void *aux UNUSED) } next_crosstab: - local_free (te); + freea (te); } - - return true; } -static bool -calc_integer (const struct ccase *c, void *aux UNUSED) +static void +calc_integer (const struct ccase *c, const struct dataset *ds) { bool bad_warn = true; /* Case weight. */ - double weight = dict_get_case_weight (dataset_dict (current_dataset), c, &bad_warn); - + double weight = dict_get_case_weight (dataset_dict (ds), c, &bad_warn); + /* Flattened current table index. */ int t; - + for (t = 0; t < nxtab; t++) { struct crosstab *x = xtab[t]; int i, fact, ofs; - + fact = i = 1; ofs = x->ofs; for (i = 0; i < x->nvar; i++) { - struct variable *const v = x->vars[i]; + const struct variable *const v = x->vars[i]; struct var_range *vr = get_var_range (v); - double value = case_num (c, v->fv); - + double value = case_num (c, v); + /* Note that the first test also rules out SYSMIS. */ if ((value < vr->min || value >= vr->max) || (cmd.miss == CRS_TABLE - && mv_is_num_user_missing (&v->miss, value))) + && var_is_num_missing (v, value, MV_USER))) { x->missing += weight; goto next_crosstab; } - + if (i > 1) { ofs += fact * ((int) value - vr->min); fact *= vr->count; } } - + { - struct variable *row_var = x->vars[ROW_VAR]; - const int row = case_num (c, row_var->fv) - get_var_range (row_var)->min; + const struct variable *row_var = x->vars[ROW_VAR]; + const int row = case_num (c, row_var) - get_var_range (row_var)->min; - struct variable *col_var = x->vars[COL_VAR]; - const int col = case_num (c, col_var->fv) - get_var_range (col_var)->min; + const struct variable *col_var = x->vars[COL_VAR]; + const int col = case_num (c, col_var) - get_var_range (col_var)->min; const int col_dim = get_var_range (col_var)->count; sorted_tab[ofs]->u.data[col + row * col_dim] += weight; } - + next_crosstab: ; } - - return true; } /* Compare the table_entry's at A and B and return a strcmp()-type result. */ -static int -compare_table_entry (const void *a_, const void *b_, void *foo UNUSED) +static int +compare_table_entry (const void *a_, const void *b_, const void *aux UNUSED) { const struct table_entry *a = a_; const struct table_entry *b = b_; @@ -706,13 +741,13 @@ compare_table_entry (const void *a_, const void *b_, void *foo UNUSED) return 1; else if (a->table < b->table) return -1; - + { const struct crosstab *x = xtab[a->table]; int i; for (i = x->nvar - 1; i >= 0; i--) - if (x->vars[i]->type == NUMERIC) + if (var_is_numeric (x->vars[i])) { const double diffnum = a->values[i].f - b->values[i].f; if (diffnum < 0) @@ -720,24 +755,21 @@ compare_table_entry (const void *a_, const void *b_, void *foo UNUSED) else if (diffnum > 0) return 1; } - else - { - assert (x->vars[i]->type == ALPHA); - { - const int diffstr = strncmp (a->values[i].s, b->values[i].s, - x->vars[i]->width); - if (diffstr) - return diffstr; - } - } + else + { + const int diffstr = strncmp (a->values[i].s, b->values[i].s, + var_get_width (x->vars[i])); + if (diffstr) + return diffstr; + } } - + return 0; } /* Calculate a hash value from table_entry A. */ static unsigned -hash_table_entry (const void *a_, void *foo UNUSED) +hash_table_entry (const void *a_, const void *aux UNUSED) { const struct table_entry *a = a_; unsigned long hash; @@ -745,8 +777,8 @@ hash_table_entry (const void *a_, void *foo UNUSED) hash = a->table; for (i = 0; i < xtab[a->table]->nvar; i++) - hash ^= hsh_hash_bytes (&a->values[i], sizeof a->values[i]); - + hash = hash_bytes (&a->values[i], sizeof a->values[i], hash); + return hash; } @@ -758,21 +790,22 @@ static void enum_var_values (struct table_entry **entries, int entry_cnt, int var_idx, union value **values, int *value_cnt); static void output_pivot_table (struct table_entry **, struct table_entry **, + const struct dictionary *, double **, double **, double **, int *, int *, int *); -static void make_summary_table (void); +static void make_summary_table (const struct dictionary *); static void -postcalc (void *aux UNUSED) +postcalc (const struct dataset *ds) { if (mode == GENERAL) { n_sorted_tab = hsh_count (gen_tab); sorted_tab = (struct table_entry **) hsh_sort (gen_tab); } - - make_summary_table (); - + + make_summary_table (dataset_dict (ds)); + /* Identify all the individual crosstabulation tables, and deal with them. */ { @@ -787,28 +820,41 @@ postcalc (void *aux UNUSED) pe = find_pivot_extent (pb, &pc, cmd.pivot == CRS_PIVOT); if (pe == NULL) break; - - output_pivot_table (pb, pe, &mat, &row_tot, &col_tot, + + output_pivot_table (pb, pe, dataset_dict (ds), + &mat, &row_tot, &col_tot, &maxrows, &maxcols, &maxcells); - + pb = pe; } free (mat); free (row_tot); free (col_tot); } - + hsh_destroy (gen_tab); + if (mode == INTEGER) + { + int i; + for (i = 0; i < n_sorted_tab; i++) + { + free (sorted_tab[i]->u.data); + free (sorted_tab[i]); + } + free (sorted_tab); + } } -static void insert_summary (struct tab_table *, int tab_index, double valid); +static void insert_summary (struct tab_table *, int tab_index, + const struct dictionary *, + double valid); /* Output a table summarizing the cases processed. */ static void -make_summary_table (void) +make_summary_table (const struct dictionary *dict) { struct tab_table *summary; - + struct table_entry **pb = sorted_tab, **pe; int pc = n_sorted_tab; int cur_tab = 0; @@ -834,17 +880,17 @@ make_summary_table (void) } } tab_offset (summary, 0, 3); - + for (;;) { double valid; - + pe = find_pivot_extent (pb, &pc, cmd.pivot == CRS_PIVOT); if (pe == NULL) break; while (cur_tab < (*pb)->table) - insert_summary (summary, cur_tab++, 0.); + insert_summary (summary, cur_tab++, dict, 0.); if (mode == GENERAL) for (valid = 0.; pb < pe; pb++) @@ -855,23 +901,23 @@ make_summary_table (void) const int n_cols = get_var_range (x->vars[COL_VAR])->count; const int n_rows = get_var_range (x->vars[ROW_VAR])->count; const int count = n_cols * n_rows; - + for (valid = 0.; pb < pe; pb++) { const double *data = (*pb)->u.data; int i; - + for (i = 0; i < count; i++) valid += *data++; } } - insert_summary (summary, cur_tab++, valid); + insert_summary (summary, cur_tab++, dict, valid); pb = pe; } - + while (cur_tab < nxtab) - insert_summary (summary, cur_tab++, 0.); + insert_summary (summary, cur_tab++, dict, 0.); submit (summary); } @@ -879,15 +925,20 @@ make_summary_table (void) /* Inserts a line into T describing the crosstabulation at index TAB_INDEX, which has VALID valid observations. */ static void -insert_summary (struct tab_table *t, int tab_index, double valid) +insert_summary (struct tab_table *t, int tab_index, + const struct dictionary *dict, + double valid) { struct crosstab *x = xtab[tab_index]; + const struct variable *wv = dict_get_weight (dict); + const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0; + tab_hline (t, TAL_1, 0, 6, 0); - + /* Crosstabulation name. */ { - char *buf = local_alloc (128 * x->nvar); + char *buf = xmalloca (128 * x->nvar); char *cp = buf; int i; @@ -896,14 +947,13 @@ insert_summary (struct tab_table *t, int tab_index, double valid) if (i > 0) cp = stpcpy (cp, " * "); - cp = stpcpy (cp, - x->vars[i]->label ? x->vars[i]->label : x->vars[i]->name); + cp = stpcpy (cp, var_to_string (x->vars[i])); } tab_text (t, 0, 0, TAB_LEFT, buf); - local_free (buf); + freea (buf); } - + /* Counts and percentages. */ { double n[3]; @@ -916,12 +966,12 @@ insert_summary (struct tab_table *t, int tab_index, double valid) for (i = 0; i < 3; i++) { - tab_float (t, i * 2 + 1, 0, TAB_RIGHT, n[i], 8, 0); + tab_double (t, i * 2 + 1, 0, TAB_RIGHT, n[i], wfmt); tab_text (t, i * 2 + 2, 0, TAB_RIGHT | TAT_PRINTF, "%.1f%%", n[i] / n[2] * 100.); } } - + tab_next_row (t); } @@ -944,13 +994,13 @@ static int n_cols; /* Row values, number of rows. */ static union value *rows; static int n_rows; - + /* Number of statistically interesting columns/rows (columns/rows with data in them). */ static int ns_cols, ns_rows; /* Crosstabulation. */ -static struct crosstab *x; +static const struct crosstab *x; /* Number of variables from the crosstabulation to consider. This is either x->nvar, if pivoting is on, or 2, if pivoting is off. */ @@ -965,11 +1015,11 @@ static double W; /* Grand total. */ static void display_dimensions (struct tab_table *, int first_difference, struct table_entry *); static void display_crosstabulation (void); -static void display_chisq (void); -static void display_symmetric (void); -static void display_risk (void); +static void display_chisq (const struct dictionary *); +static void display_symmetric (const struct dictionary *); +static void display_risk (const struct dictionary *); static void display_directional (void); -static void crosstabs_dim (struct tab_table *, struct outp_driver *); +static void crosstabs_dim (struct tab_table *, struct outp_driver *, void *); static void table_value_missing (struct tab_table *table, int c, int r, unsigned char opt, const union value *v, const struct variable *var); @@ -980,6 +1030,7 @@ static void delete_missing (void); hold *MAXROWS entries. */ static void output_pivot_table (struct table_entry **pb, struct table_entry **pe, + const struct dictionary *dict, double **matp, double **row_totp, double **col_totp, int *maxrows, int *maxcols, int *maxcells) { @@ -1004,21 +1055,19 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe, /* First header line. */ tab_joint_text (table, nvar - 1, 0, (nvar - 1) + (n_cols - 1), 0, - TAB_CENTER | TAT_TITLE, x->vars[COL_VAR]->name); - + TAB_CENTER | TAT_TITLE, var_get_name (x->vars[COL_VAR])); + tab_hline (table, TAL_1, nvar - 1, nvar + n_cols - 2, 1); - + /* Second header line. */ { int i; for (i = 2; i < nvar; i++) tab_joint_text (table, nvar - i - 1, 0, nvar - i - 1, 1, - TAB_RIGHT | TAT_TITLE, - (x->vars[i]->label - ? x->vars[i]->label : x->vars[i]->name)); + TAB_RIGHT | TAT_TITLE, var_to_string (x->vars[i])); tab_text (table, nvar - 2, 1, TAB_RIGHT | TAT_TITLE, - x->vars[ROW_VAR]->name); + var_get_name (x->vars[ROW_VAR])); for (i = 0; i < n_cols; i++) table_value_missing (table, nvar + i - 1, 1, TAB_RIGHT, &cols[i], x->vars[COL_VAR]); @@ -1030,21 +1079,22 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe, /* Title. */ { - char *title = local_alloc (x->nvar * 64 + 128); + char *title = xmalloca (x->nvar * 64 + 128); char *cp = title; int i; - + if (cmd.pivot == CRS_PIVOT) for (i = 0; i < nvar; i++) { if (i) cp = stpcpy (cp, " by "); - cp = stpcpy (cp, x->vars[i]->name); + cp = stpcpy (cp, var_get_name (x->vars[i])); } else { cp = spprintf (cp, "%s by %s for", - x->vars[0]->name, x->vars[1]->name); + var_get_name (x->vars[0]), + var_get_name (x->vars[1])); for (i = 2; i < nvar; i++) { char buf[64], *bufp; @@ -1052,9 +1102,10 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe, if (i > 2) *cp++ = ','; *cp++ = ' '; - cp = stpcpy (cp, x->vars[i]->name); + cp = stpcpy (cp, var_get_name (x->vars[i])); *cp++ = '='; - format_short (buf, &x->vars[i]->print, &(*pb)->values[i]); + format_short (buf, var_get_print_format (x->vars[i]), + &(*pb)->values[i]); for (bufp = buf; isspace ((unsigned char) *bufp); bufp++) ; cp = stpcpy (cp, bufp); @@ -1069,8 +1120,8 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe, int value; const char *name; }; - - static const struct tuple cell_names[] = + + static const struct tuple cell_names[] = { {CRS_CL_COUNT, N_("count")}, {CRS_CL_ROW, N_("row %")}, @@ -1094,14 +1145,14 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe, strcpy (cp, "]."); tab_title (table, "%s", title); - local_free (title); + freea (title); } - + tab_offset (table, 0, 2); } else table = NULL; - + /* Chi-square table initialization. */ if (cmd.a_statistics[CRS_ST_CHISQ]) { @@ -1110,7 +1161,7 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe, tab_headers (chisq, 1 + (nvar - 2), 0, 1, 0); tab_title (chisq, _("Chi-square tests.")); - + tab_offset (chisq, nvar - 2, 0); tab_text (chisq, 0, 0, TAB_LEFT | TAT_TITLE, _("Statistic")); tab_text (chisq, 1, 0, TAB_RIGHT | TAT_TITLE, _("Value")); @@ -1126,7 +1177,7 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe, } else chisq = NULL; - + /* Symmetric measures. */ if (cmd.a_statistics[CRS_ST_PHI] || cmd.a_statistics[CRS_ST_CC] || cmd.a_statistics[CRS_ST_BTAU] || cmd.a_statistics[CRS_ST_CTAU] @@ -1214,11 +1265,11 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe, col_tot = *col_totp; *maxcols = n_cols; } - + /* Allocate table space for the matrix. */ if (table && tab_row (table) + (n_rows + 1) * num_cells > tab_nr (table)) tab_realloc (table, -1, - max (tab_nr (table) + (n_rows + 1) * num_cells, + MAX (tab_nr (table) + (n_rows + 1) * num_cells, tab_nr (table) * (pe - pb) / (te - tb))); if (mode == GENERAL) @@ -1229,7 +1280,7 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe, *matp = xnrealloc (*matp, n_cols * n_rows, sizeof **matp); *maxcells = n_cols * n_rows; } - + mat = *matp; /* Build the matrix and calculate column totals. */ @@ -1296,7 +1347,7 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe, { int r, c; double *tp = col_tot; - + assert (mode == INTEGER); mat = (*tb)->u.data; ns_cols = n_cols; @@ -1306,16 +1357,16 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe, { double cum = 0.; double *cp = &mat[c]; - + for (r = 0; r < n_rows; r++) cum += cp[r * n_cols]; *tp++ = cum; } } - + { double *cp; - + for (ns_cols = 0, cp = col_tot; cp < &col_tot[n_cols]; cp++) ns_cols += *cp != 0.; } @@ -1325,7 +1376,7 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe, double *mp = mat; double *rp = row_tot; int r, c; - + for (ns_rows = 0, r = n_rows; r--; ) { double cum = 0.; @@ -1351,13 +1402,13 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe, cum += *tp++; W = cum; } - + /* Find the first variable that differs from the last subtable, then display the values of the dimensioning variables for each table that needs it. */ { int first_difference = nvar - 1; - + if (tb != pb) for (; ; first_difference--) { @@ -1368,7 +1419,7 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe, break; } cmp = *tb; - + if (table) display_dimensions (table, first_difference, *tb); if (chisq) @@ -1386,20 +1437,20 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe, if (cmd.miss == CRS_REPORT) delete_missing (); if (chisq) - display_chisq (); + display_chisq (dict); if (sym) - display_symmetric (); + display_symmetric (dict); if (risk) - display_risk (); + display_risk (dict); if (direct) display_directional (); - + tb = te; free (rows); } submit (table); - + if (chisq) { if (!chisq_fisher) @@ -1423,7 +1474,7 @@ delete_missing (void) int r; for (r = 0; r < n_rows; r++) - if (mv_is_num_user_missing (&x->vars[ROW_VAR]->miss, rows[r].f)) + if (var_is_num_missing (x->vars[ROW_VAR], rows[r].f, MV_USER)) { int c; @@ -1432,12 +1483,12 @@ delete_missing (void) ns_rows--; } } - + { int c; for (c = 0; c < n_cols; c++) - if (mv_is_num_user_missing (&x->vars[COL_VAR]->miss, cols[c].f)) + if (var_is_num_missing (x->vars[COL_VAR], cols[c].f, MV_USER)) { int r; @@ -1453,10 +1504,10 @@ static void submit (struct tab_table *t) { int i; - + if (t == NULL) return; - + tab_resize (t, -1, 0); if (tab_nr (t) == tab_t (t)) { @@ -1467,24 +1518,24 @@ submit (struct tab_table *t) if (t != table) for (i = 2; i < nvar; i++) tab_text (t, nvar - i - 1, 0, TAB_RIGHT | TAT_TITLE, - x->vars[i]->label ? x->vars[i]->label : x->vars[i]->name); + var_to_string (x->vars[i])); tab_box (t, TAL_2, TAL_2, -1, -1, 0, 0, tab_nc (t) - 1, tab_nr (t) - 1); tab_box (t, -1, -1, -1, TAL_1, tab_l (t), tab_t (t) - 1, tab_nc (t) - 1, tab_nr (t) - 1); tab_box (t, -1, -1, -1, TAL_GAP, 0, tab_t (t), tab_l (t) - 1, tab_nr (t) - 1); tab_vline (t, TAL_2, tab_l (t), 0, tab_nr (t) - 1); - tab_dim (t, crosstabs_dim); + tab_dim (t, crosstabs_dim, NULL); tab_submit (t); } /* Sets the widths of all the columns and heights of all the rows in table T for driver D. */ static void -crosstabs_dim (struct tab_table *t, struct outp_driver *d) +crosstabs_dim (struct tab_table *t, struct outp_driver *d, void *aux UNUSED) { int i; - + /* Width of a numerical column. */ int c = outp_string_width (d, "0.000000", OUTP_PROPORTIONAL); if (cmd.miss == CRS_REPORT) @@ -1500,7 +1551,7 @@ crosstabs_dim (struct tab_table *t, struct outp_driver *d) for (i = 0; i <= t->nc; i++) w -= t->wrv[i]; w /= t->l; - + if (w < d->prop_em_width * 8) w = d->prop_em_width * 8; @@ -1595,7 +1646,7 @@ find_pivot_extent_integer (struct table_entry **tp, int *cnt, int pivot) break; if (pivot) continue; - + if (memcmp (&(*tp)->values[2], &fp->values[2], sizeof (union value) * (x->nvar - 2))) break; @@ -1608,7 +1659,7 @@ find_pivot_extent_integer (struct table_entry **tp, int *cnt, int pivot) result. WIDTH_ points to an int which is either 0 for a numeric value or a string width for a string value. */ static int -compare_value (const void *a_, const void *b_, void *width_) +compare_value (const void *a_, const void *b_, const void *width_) { const union value *a = a_; const union value *b = b_; @@ -1627,15 +1678,15 @@ compare_value (const void *a_, const void *b_, void *width_) malloc()'darray stored in *VALUES, with the number of values stored in *VALUE_CNT. */ -static void +static void enum_var_values (struct table_entry **entries, int entry_cnt, int var_idx, union value **values, int *value_cnt) { - struct variable *v = xtab[(*entries)->table]->vars[var_idx]; + const struct variable *v = xtab[(*entries)->table]->vars[var_idx]; if (mode == GENERAL) { - int width = v->width; + int width = MIN (var_get_width (v), MAX_SHORT_STRING); int i; *values = xnmalloc (entry_cnt, sizeof **values); @@ -1648,7 +1699,7 @@ enum_var_values (struct table_entry **entries, int entry_cnt, int var_idx, { struct var_range *vr = get_var_range (v); int i; - + assert (mode == INTEGER); *values = xnmalloc (vr->count, sizeof **values); for (i = 0; i < vr->count; i++) @@ -1665,18 +1716,19 @@ table_value_missing (struct tab_table *table, int c, int r, unsigned char opt, const union value *v, const struct variable *var) { struct substring s; + const struct fmt_spec *print = var_get_print_format (var); - const char *label = val_labs_find (var->val_labs, *v); - if (label) + const char *label = var_lookup_value_label (var, v); + if (label) { tab_text (table, c, r, TAB_LEFT, label); return; } - s.string = tab_alloc (table, var->print.w); - format_short (s.string, &var->print, v); + s.string = tab_alloc (table, print->w); + format_short (s.string, print, v); s.length = strlen (s.string); - if (cmd.miss == CRS_REPORT && mv_is_num_user_missing (&var->miss, v->f)) + if (cmd.miss == CRS_REPORT && var_is_num_missing (var, v->f, MV_USER)) s.string[s.length++] = 'M'; while (s.length && *s.string == ' ') { @@ -1712,11 +1764,11 @@ format_cell_entry (struct tab_table *table, int c, int r, double value, const struct fmt_spec f = {FMT_F, 10, 1}; union value v; struct substring s; - + s.length = 10; s.string = tab_alloc (table, 16); v.f = value; - data_out (s.string, &f, &v); + data_out (&v, &f, s.string); while (*s.string == ' ') { s.length--; @@ -1736,14 +1788,14 @@ display_crosstabulation (void) { { int r; - + for (r = 0; r < n_rows; r++) table_value_missing (table, nvar - 2, r * num_cells, TAB_RIGHT, &rows[r], x->vars[ROW_VAR]); } tab_text (table, nvar - 2, n_rows * num_cells, TAB_LEFT, _("Total")); - + /* Put in the actual cells. */ { double *mp = mat; @@ -1759,9 +1811,9 @@ display_crosstabulation (void) bool mark_missing = false; double expected_value = row_tot[r] * col_tot[c] / W; if (cmd.miss == CRS_REPORT - && (mv_is_num_user_missing (&x->vars[COL_VAR]->miss, cols[c].f) - || mv_is_num_user_missing (&x->vars[ROW_VAR]->miss, - rows[r].f))) + && (var_is_num_missing (x->vars[COL_VAR], cols[c].f, MV_USER) + || var_is_num_missing (x->vars[ROW_VAR], rows[r].f, + MV_USER))) mark_missing = true; for (i = 0; i < num_cells; i++) { @@ -1819,17 +1871,17 @@ display_crosstabulation (void) int r, i; tab_offset (table, -1, tab_row (table) - num_cells * n_rows); - for (r = 0; r < n_rows; r++) + for (r = 0; r < n_rows; r++) { - char suffix = 0; bool mark_missing = false; if (cmd.miss == CRS_REPORT - && mv_is_num_user_missing (&x->vars[ROW_VAR]->miss, rows[r].f)) + && var_is_num_missing (x->vars[ROW_VAR], rows[r].f, MV_USER)) mark_missing = true; for (i = 0; i < num_cells; i++) { + char suffix = 0; double v; switch (cells[i]) @@ -1838,7 +1890,7 @@ display_crosstabulation (void) v = row_tot[r]; break; case CRS_CL_ROW: - v = 100.; + v = 100.0; suffix = '%'; break; case CRS_CL_COLUMN: @@ -1861,7 +1913,7 @@ display_crosstabulation (void) format_cell_entry (table, n_cols, 0, v, suffix, mark_missing); tab_next_row (table); - } + } } } @@ -1876,22 +1928,21 @@ display_crosstabulation (void) { double ct = c < n_cols ? col_tot[c] : W; bool mark_missing = false; - char suffix = 0; int i; - - if (cmd.miss == CRS_REPORT && c < n_cols - && mv_is_num_user_missing (&x->vars[COL_VAR]->miss, cols[c].f)) + + if (cmd.miss == CRS_REPORT && c < n_cols + && var_is_num_missing (x->vars[COL_VAR], cols[c].f, MV_USER)) mark_missing = true; for (i = 0; i < num_cells; i++) { + char suffix = 0; double v; switch (cells[i]) { case CRS_CL_COUNT: v = ct; - suffix = '%'; break; case CRS_CL_ROW: v = ct / W * 100.; @@ -1914,14 +1965,14 @@ display_crosstabulation (void) NOT_REACHED (); } - format_cell_entry (table, c, i, v, suffix, mark_missing); + format_cell_entry (table, c, i, v, suffix, mark_missing); } last_row = i; } tab_offset (table, -1, tab_row (table) + last_row); } - + tab_offset (table, 0, -1); } @@ -1930,9 +1981,12 @@ static void calc_chisq (double[N_CHISQ], int[N_CHISQ], double *, double *); /* Display chi-square statistics. */ static void -display_chisq (void) +display_chisq (const struct dictionary *dict) { - static const char *chisq_stats[N_CHISQ] = + const struct variable *wv = dict_get_weight (dict); + const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0; + + static const char *chisq_stats[N_CHISQ] = { N_("Pearson Chi-Square"), N_("Likelihood Ratio"), @@ -1946,39 +2000,39 @@ display_chisq (void) int s = 0; int i; - + calc_chisq (chisq_v, df, &fisher1, &fisher2); tab_offset (chisq, nvar - 2, -1); - + for (i = 0; i < N_CHISQ; i++) { if ((i != 2 && chisq_v[i] == SYSMIS) || (i == 2 && fisher1 == SYSMIS)) continue; s = 1; - + tab_text (chisq, 0, 0, TAB_LEFT, gettext (chisq_stats[i])); if (i != 2) { - tab_float (chisq, 1, 0, TAB_RIGHT, chisq_v[i], 8, 3); - tab_float (chisq, 2, 0, TAB_RIGHT, df[i], 8, 0); - tab_float (chisq, 3, 0, TAB_RIGHT, - gsl_cdf_chisq_Q (chisq_v[i], df[i]), 8, 3); + tab_double (chisq, 1, 0, TAB_RIGHT, chisq_v[i], NULL); + tab_double (chisq, 2, 0, TAB_RIGHT, df[i], wfmt); + tab_double (chisq, 3, 0, TAB_RIGHT, + gsl_cdf_chisq_Q (chisq_v[i], df[i]), NULL); } else { chisq_fisher = 1; - tab_float (chisq, 4, 0, TAB_RIGHT, fisher2, 8, 3); - tab_float (chisq, 5, 0, TAB_RIGHT, fisher1, 8, 3); + tab_double (chisq, 4, 0, TAB_RIGHT, fisher2, NULL); + tab_double (chisq, 5, 0, TAB_RIGHT, fisher1, NULL); } tab_next_row (chisq); } tab_text (chisq, 0, 0, TAB_LEFT, _("N of Valid Cases")); - tab_float (chisq, 1, 0, TAB_RIGHT, W, 8, 0); + tab_double (chisq, 1, 0, TAB_RIGHT, W, wfmt); tab_next_row (chisq); - + tab_offset (chisq, 0, -1); } @@ -1987,9 +2041,12 @@ static int calc_symmetric (double[N_SYMMETRIC], double[N_SYMMETRIC], /* Display symmetric measures. */ static void -display_symmetric (void) +display_symmetric (const struct dictionary *dict) { - static const char *categories[] = + const struct variable *wv = dict_get_weight (dict); + const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0; + + static const char *categories[] = { N_("Nominal by Nominal"), N_("Ordinal by Ordinal"), @@ -2023,7 +2080,7 @@ display_symmetric (void) return; tab_offset (sym, nvar - 2, -1); - + for (i = 0; i < N_SYMMETRIC; i++) { if (sym_v[i] == SYSMIS) @@ -2034,21 +2091,21 @@ display_symmetric (void) last_cat = stats_categories[i]; tab_text (sym, 0, 0, TAB_LEFT, gettext (categories[last_cat])); } - + tab_text (sym, 1, 0, TAB_LEFT, gettext (stats[i])); - tab_float (sym, 2, 0, TAB_RIGHT, sym_v[i], 8, 3); + tab_double (sym, 2, 0, TAB_RIGHT, sym_v[i], NULL); if (sym_ase[i] != SYSMIS) - tab_float (sym, 3, 0, TAB_RIGHT, sym_ase[i], 8, 3); + tab_double (sym, 3, 0, TAB_RIGHT, sym_ase[i], NULL); if (sym_t[i] != SYSMIS) - tab_float (sym, 4, 0, TAB_RIGHT, sym_t[i], 8, 3); - /*tab_float (sym, 5, 0, TAB_RIGHT, normal_sig (sym_v[i]), 8, 3);*/ + tab_double (sym, 4, 0, TAB_RIGHT, sym_t[i], NULL); + /*tab_double (sym, 5, 0, TAB_RIGHT, normal_sig (sym_v[i]), NULL);*/ tab_next_row (sym); } tab_text (sym, 0, 0, TAB_LEFT, _("N of Valid Cases")); - tab_float (sym, 2, 0, TAB_RIGHT, W, 8, 0); + tab_double (sym, 2, 0, TAB_RIGHT, W, wfmt); tab_next_row (sym); - + tab_offset (sym, 0, -1); } @@ -2056,18 +2113,21 @@ static int calc_risk (double[], double[], double[], union value *); /* Display risk estimate. */ static void -display_risk (void) +display_risk (const struct dictionary *dict) { + const struct variable *wv = dict_get_weight (dict); + const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0; + char buf[256]; double risk_v[3], lower[3], upper[3]; union value c[2]; int i; - + if (!calc_risk (risk_v, upper, lower, c)) return; - + tab_offset (risk, nvar - 2, -1); - + for (i = 0; i < 3; i++) { if (risk_v[i] == SYSMIS) @@ -2076,38 +2136,38 @@ display_risk (void) switch (i) { case 0: - if (x->vars[COL_VAR]->type == NUMERIC) + if (var_is_numeric (x->vars[COL_VAR])) sprintf (buf, _("Odds Ratio for %s (%g / %g)"), - x->vars[COL_VAR]->name, c[0].f, c[1].f); + var_get_name (x->vars[COL_VAR]), c[0].f, c[1].f); else sprintf (buf, _("Odds Ratio for %s (%.*s / %.*s)"), - x->vars[COL_VAR]->name, - x->vars[COL_VAR]->width, c[0].s, - x->vars[COL_VAR]->width, c[1].s); + var_get_name (x->vars[COL_VAR]), + var_get_width (x->vars[COL_VAR]), c[0].s, + var_get_width (x->vars[COL_VAR]), c[1].s); break; case 1: case 2: - if (x->vars[ROW_VAR]->type == NUMERIC) + if (var_is_numeric (x->vars[ROW_VAR])) sprintf (buf, _("For cohort %s = %g"), - x->vars[ROW_VAR]->name, rows[i - 1].f); + var_get_name (x->vars[ROW_VAR]), rows[i - 1].f); else sprintf (buf, _("For cohort %s = %.*s"), - x->vars[ROW_VAR]->name, - x->vars[ROW_VAR]->width, rows[i - 1].s); + var_get_name (x->vars[ROW_VAR]), + var_get_width (x->vars[ROW_VAR]), rows[i - 1].s); break; } - + tab_text (risk, 0, 0, TAB_LEFT, buf); - tab_float (risk, 1, 0, TAB_RIGHT, risk_v[i], 8, 3); - tab_float (risk, 2, 0, TAB_RIGHT, lower[i], 8, 3); - tab_float (risk, 3, 0, TAB_RIGHT, upper[i], 8, 3); + tab_double (risk, 1, 0, TAB_RIGHT, risk_v[i], NULL); + tab_double (risk, 2, 0, TAB_RIGHT, lower[i], NULL); + tab_double (risk, 3, 0, TAB_RIGHT, upper[i], NULL); tab_next_row (risk); } tab_text (risk, 0, 0, TAB_LEFT, _("N of Valid Cases")); - tab_float (risk, 1, 0, TAB_RIGHT, W, 8, 0); + tab_double (risk, 1, 0, TAB_RIGHT, W, wfmt); tab_next_row (risk); - + tab_offset (risk, 0, -1); } @@ -2118,7 +2178,7 @@ static int calc_directional (double[N_DIRECTIONAL], double[N_DIRECTIONAL], static void display_directional (void) { - static const char *categories[] = + static const char *categories[] = { N_("Nominal by Nominal"), N_("Ordinal by Ordinal"), @@ -2134,7 +2194,7 @@ display_directional (void) N_("Eta"), }; - static const char *types[] = + static const char *types[] = { N_("Symmetric"), N_("%s Dependent"), @@ -2145,18 +2205,18 @@ display_directional (void) { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, }; - - static const int stats_stats[N_DIRECTIONAL] = + + static const int stats_stats[N_DIRECTIONAL] = { 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, }; - static const int stats_types[N_DIRECTIONAL] = + static const int stats_types[N_DIRECTIONAL] = { 0, 1, 2, 1, 2, 0, 1, 2, 0, 1, 2, 1, 2, }; - static const int *stats_lookup[] = + static const int *stats_lookup[] = { stats_categories, stats_stats, @@ -2174,23 +2234,23 @@ display_directional (void) { -1, -1, -1, }; - + double direct_v[N_DIRECTIONAL]; double direct_ase[N_DIRECTIONAL]; double direct_t[N_DIRECTIONAL]; - + int i; if (!calc_directional (direct_v, direct_ase, direct_t)) return; tab_offset (direct, nvar - 2, -1); - + for (i = 0; i < N_DIRECTIONAL; i++) { if (direct_v[i] == SYSMIS) continue; - + { int j; @@ -2199,31 +2259,31 @@ display_directional (void) { if (j < 2) tab_hline (direct, TAL_1, j, 6, 0); - + for (; j < 3; j++) { - char *string; + const char *string; int k = last[j] = stats_lookup[j][i]; if (k == 0) string = NULL; else if (k == 1) - string = x->vars[0]->name; + string = var_get_name (x->vars[0]); else - string = x->vars[1]->name; - + string = var_get_name (x->vars[1]); + tab_text (direct, j, 0, TAB_LEFT | TAT_PRINTF, gettext (stats_names[j][k]), string); } } } - - tab_float (direct, 3, 0, TAB_RIGHT, direct_v[i], 8, 3); + + tab_double (direct, 3, 0, TAB_RIGHT, direct_v[i], NULL); if (direct_ase[i] != SYSMIS) - tab_float (direct, 4, 0, TAB_RIGHT, direct_ase[i], 8, 3); + tab_double (direct, 4, 0, TAB_RIGHT, direct_ase[i], NULL); if (direct_t[i] != SYSMIS) - tab_float (direct, 5, 0, TAB_RIGHT, direct_t[i], 8, 3); - /*tab_float (direct, 6, 0, TAB_RIGHT, normal_sig (direct_v[i]), 8, 3);*/ + tab_double (direct, 5, 0, TAB_RIGHT, direct_t[i], NULL); + /*tab_double (direct, 6, 0, TAB_RIGHT, normal_sig (direct_v[i]), NULL);*/ tab_next_row (direct); } @@ -2239,7 +2299,7 @@ gamma_int (double x) { double r = 1; int i; - + for (i = 2; i < x; i++) r *= i; return r; @@ -2272,10 +2332,10 @@ static void calc_fisher (int a, int b, int c, int d, double *fisher1, double *fisher2) { int x; - - if (min (c, d) < min (a, b)) + + if (MIN (c, d) < MIN (a, b)) swap (&a, &c), swap (&b, &d); - if (min (b, d) < min (a, c)) + if (MIN (b, d) < MIN (a, c)) swap (&a, &b), swap (&c, &d); if (b * c < a * d) { @@ -2321,7 +2381,7 @@ calc_chisq (double chisq[N_CHISQ], int df[N_CHISQ], const double expected = row_tot[r] * col_tot[c] / W; const double freq = mat[n_cols * r + c]; const double residual = freq - expected; - + chisq[0] += residual * residual / expected; if (freq) chisq[1] += freq * log (expected / freq); @@ -2339,7 +2399,7 @@ calc_chisq (double chisq[N_CHISQ], int df[N_CHISQ], if (ns_cols == 2 && ns_rows == 2) { double f11, f12, f21, f22; - + { int nz_cols[2]; int i, j; @@ -2380,11 +2440,11 @@ calc_chisq (double chisq[N_CHISQ], int df[N_CHISQ], } /* Calculate Mantel-Haenszel. */ - if (x->vars[ROW_VAR]->type == NUMERIC && x->vars[COL_VAR]->type == NUMERIC) + if (var_is_numeric (x->vars[ROW_VAR]) && var_is_numeric (x->vars[COL_VAR])) { double r, ase_0, ase_1; calc_r ((double *) rows, (double *) cols, &r, &ase_0, &ase_1); - + chisq[4] = (W - 1.) * r * r; df[4] = 1; } @@ -2416,7 +2476,7 @@ calc_r (double *X, double *Y, double *r, double *ase_0, double *ase_1) for (sum_Xr = sum_X2r = 0., i = 0; i < n_rows; i++) { sum_Xr += X[i] * row_tot[i]; - sum_X2r += X[i] * X[i] * row_tot[i]; + sum_X2r += pow2 (X[i]) * row_tot[i]; } Xbar = sum_Xr / W; @@ -2428,15 +2488,15 @@ calc_r (double *X, double *Y, double *r, double *ase_0, double *ase_1) Ybar = sum_Yc / W; S = sum_XYf - sum_Xr * sum_Yc / W; - SX = sum_X2r - sum_Xr * sum_Xr / W; - SY = sum_Y2c - sum_Yc * sum_Yc / W; + SX = sum_X2r - pow2 (sum_Xr) / W; + SY = sum_Y2c - pow2 (sum_Yc) / W; T = sqrt (SX * SY); *r = S / T; - *ase_0 = sqrt ((sum_X2Y2f - (sum_XYf * sum_XYf) / W) / (sum_X2r * sum_Y2c)); - + *ase_0 = sqrt ((sum_X2Y2f - pow2 (sum_XYf) / W) / (sum_X2r * sum_Y2c)); + { double s, c, y, t; - + for (s = c = 0., i = 0; i < n_rows; i++) for (j = 0; j < n_cols; j++) { @@ -2467,15 +2527,15 @@ static int calc_symmetric (double v[N_SYMMETRIC], double ase[N_SYMMETRIC], double t[N_SYMMETRIC]) { - int q = min (ns_rows, ns_cols); - + int q = MIN (ns_rows, ns_cols); + if (q <= 1) return 0; - + { int i; - if (v) + if (v) for (i = 0; i < N_SYMMETRIC; i++) v[i] = ase[i] = t[i] = SYSMIS; } @@ -2487,14 +2547,14 @@ calc_symmetric (double v[N_SYMMETRIC], double ase[N_SYMMETRIC], { int r, c; - + for (r = 0; r < n_rows; r++) for (c = 0; c < n_cols; c++) { const double expected = row_tot[r] * col_tot[c] / W; const double freq = mat[n_cols * r + c]; const double residual = freq - expected; - + Xp += residual * residual / expected; } } @@ -2507,7 +2567,7 @@ calc_symmetric (double v[N_SYMMETRIC], double ase[N_SYMMETRIC], if (cmd.a_statistics[CRS_ST_CC]) v[2] = sqrt (Xp / (Xp + W)); } - + if (cmd.a_statistics[CRS_ST_BTAU] || cmd.a_statistics[CRS_ST_CTAU] || cmd.a_statistics[CRS_ST_GAMMA] || cmd.a_statistics[CRS_ST_D]) { @@ -2516,17 +2576,17 @@ calc_symmetric (double v[N_SYMMETRIC], double ase[N_SYMMETRIC], double P, Q; double btau_cum, ctau_cum, gamma_cum, d_yx_cum, d_xy_cum; double btau_var; - + { int r, c; - + Dr = Dc = W * W; for (r = 0; r < n_rows; r++) - Dr -= row_tot[r] * row_tot[r]; + Dr -= pow2 (row_tot[r]); for (c = 0; c < n_cols; c++) - Dc -= col_tot[c] * col_tot[c]; + Dc -= pow2 (col_tot[c]); } - + { int r, c; @@ -2534,12 +2594,12 @@ calc_symmetric (double v[N_SYMMETRIC], double ase[N_SYMMETRIC], for (c = 0; c < n_cols; c++) { double ct = 0.; - + for (r = 0; r < n_rows; r++) cum[c + r * n_cols] = ct += mat[c + r * n_cols]; } } - + /* P and Q. */ { int i, j; @@ -2562,14 +2622,14 @@ calc_symmetric (double v[N_SYMMETRIC], double ase[N_SYMMETRIC], double fij = mat[j + i * n_cols]; P += fij * Cij; Q += fij * Dij; - + if (++j == n_cols) break; assert (j < n_cols); Cij -= col_tot[j] - cum[j + i * n_cols]; Dij += col_tot[j - 1] - cum[j - 1 + i * n_cols]; - + if (i > 0) { Cij += cum[j - 1 + (i - 1) * n_cols]; @@ -2615,7 +2675,7 @@ calc_symmetric (double v[N_SYMMETRIC], double ase[N_SYMMETRIC], + col_tot[j] * Dr)); btau_cum += fij * temp * temp; } - + { const double temp = Cij - Dij; ctau_cum += fij * temp * temp; @@ -2634,14 +2694,14 @@ calc_symmetric (double v[N_SYMMETRIC], double ase[N_SYMMETRIC], d_xy_cum += fij * pow2 (Dc * (Dij - Cij) - (Q - P) * (W - col_tot[j])); } - + if (++j == n_cols) break; assert (j < n_cols); Cij -= col_tot[j] - cum[j + i * n_cols]; Dij += col_tot[j - 1] - cum[j - 1 + i * n_cols]; - + if (i > 0) { Cij += cum[j - 1 + (i - 1) * n_cols]; @@ -2697,13 +2757,13 @@ calc_symmetric (double v[N_SYMMETRIC], double ase[N_SYMMETRIC], /* Spearman correlation, Pearson's r. */ if (cmd.a_statistics[CRS_ST_CORR]) { - double *R = local_alloc (sizeof *R * n_rows); - double *C = local_alloc (sizeof *C * n_cols); - + double *R = xmalloca (sizeof *R * n_rows); + double *C = xmalloca (sizeof *C * n_cols); + { double y, t, c = 0., s = 0.; int i = 0; - + for (;;) { R[i] = s + (row_tot[i] + 1.) / 2.; @@ -2716,11 +2776,11 @@ calc_symmetric (double v[N_SYMMETRIC], double ase[N_SYMMETRIC], assert (i < n_rows); } } - + { double y, t, c = 0., s = 0.; int j = 0; - + for (;;) { C[j] = s + (col_tot[j] + 1.) / 2; @@ -2733,12 +2793,12 @@ calc_symmetric (double v[N_SYMMETRIC], double ase[N_SYMMETRIC], assert (j < n_cols); } } - + calc_r (R, C, &v[6], &t[6], &ase[6]); t[6] = v[6] / t[6]; - local_free (R); - local_free (C); + freea (R); + freea (C); calc_r ((double *) rows, (double *) cols, &v[7], &t[7], &ase[7]); t[7] = v[7] / t[7]; @@ -2749,18 +2809,18 @@ calc_symmetric (double v[N_SYMMETRIC], double ase[N_SYMMETRIC], { 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 < ns_rows; i++, j++) { double prod, sum; - + while (col_tot[j] == 0.) j++; - + prod = row_tot[i] * col_tot[j]; sum = row_tot[i] + col_tot[j]; - + sum_fii += mat[j + i * n_cols]; sum_rici += prod; sum_fiiri_ci += mat[j + i * n_cols] * sum; @@ -2772,7 +2832,7 @@ calc_symmetric (double v[N_SYMMETRIC], double ase[N_SYMMETRIC], double sum = row_tot[i] + col_tot[j]; sum_fijri_ci2 += mat[j + i * n_cols] * sum * sum; } - + v[8] = (W * sum_fii - sum_rici) / (W * W - sum_rici); ase[8] = sqrt ((W * W * sum_rici @@ -2807,14 +2867,14 @@ calc_risk (double *value, double *upper, double *lower, union value *c) { int i; - + for (i = 0; i < 3; i++) value[i] = upper[i] = lower[i] = SYSMIS; } - + if (ns_rows != 2 || ns_cols != 2) return 0; - + { int nz_cols[2]; int i, j; @@ -2848,7 +2908,7 @@ calc_risk (double *value, double *upper, double *lower, union value *c) + (f22 / (f21 * (f21 + f22)))); lower[1] = value[1] * exp (-1.960 * v); upper[1] = value[1] * exp (1.960 * v); - + value[2] = (f12 * (f21 + f22)) / (f22 * (f11 + f12)); v = sqrt ((f11 / (f12 * (f11 + f12))) + (f21 / (f22 * (f21 + f22)))); @@ -2894,7 +2954,7 @@ calc_directional (double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL], max = mat[j + i * n_cols]; index = j; } - + sum_fim += fim[i] = max; fim_index[i] = index; } @@ -2911,7 +2971,7 @@ calc_directional (double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL], max = mat[j + i * n_cols]; index = i; } - + sum_fmj += fmj[j] = max; fmj_index[j] = index; } @@ -2953,14 +3013,14 @@ calc_directional (double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL], - deltaj + v[0] * deltaj)); } - + ase[2] = sqrt (accum - W * v[0]) / (W - cm); } /* ASE0 for Y given X. */ { double accum; - + for (accum = 0., i = 0; i < n_rows; i++) if (cm_index != fim_index[i]) accum += (mat[i * n_cols + fim_index[i]] @@ -2981,14 +3041,14 @@ calc_directional (double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL], - deltaj + v[0] * deltaj)); } - + ase[1] = sqrt (accum - W * v[0]) / (W - rm); } /* ASE0 for X given Y. */ { double accum; - + for (accum = 0., j = 0; j < n_cols; j++) if (rm_index != fmj_index[j]) accum += (mat[j + n_cols * fmj_index[j]] @@ -3019,7 +3079,7 @@ calc_directional (double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL], free (fim_index); free (fmj); free (fmj_index); - + { double sum_fij2_ri, sum_fij2_ci; double sum_ri2, sum_cj2; @@ -3033,10 +3093,10 @@ calc_directional (double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL], } for (sum_ri2 = 0., i = 0; i < n_rows; i++) - sum_ri2 += row_tot[i] * row_tot[i]; + sum_ri2 += pow2 (row_tot[i]); for (sum_cj2 = 0., j = 0; j < n_cols; j++) - sum_cj2 += col_tot[j] * col_tot[j]; + sum_cj2 += pow2 (col_tot[j]); v[3] = (W * sum_fij2_ci - sum_ri2) / (W * W - sum_ri2); v[4] = (W * sum_fij2_ri - sum_cj2) / (W * W - sum_cj2); @@ -3052,7 +3112,7 @@ calc_directional (double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL], for (UX = 0., i = 0; i < n_rows; i++) if (row_tot[i] > 0.) UX -= row_tot[i] / W * log (row_tot[i] / W); - + for (UY = 0., j = 0; j < n_cols; j++) if (col_tot[j] > 0.) UY -= col_tot[j] / W * log (col_tot[j] / W); @@ -3064,7 +3124,7 @@ calc_directional (double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL], if (entry <= 0.) continue; - + P += entry * pow2 (log (col_tot[j] * row_tot[i] / (W * entry))); UXY -= entry / W * log (entry / W); } @@ -3076,7 +3136,7 @@ calc_directional (double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL], if (entry <= 0.) continue; - + ase1_yx += entry * pow2 (UY * log (entry / row_tot[i]) + (UX - UXY) * log (col_tot[j] / W)); ase1_xy += entry * pow2 (UX * log (entry / col_tot[j]) @@ -3085,16 +3145,16 @@ calc_directional (double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL], * log (row_tot[i] * col_tot[j] / (W * W))) - (UX + UY) * log (entry / W)); } - + v[5] = 2. * ((UX + UY - UXY) / (UX + UY)); ase[5] = (2. / (W * pow2 (UX + UY))) * sqrt (ase1_sym); t[5] = v[5] / ((2. / (W * (UX + UY))) * sqrt (P - pow2 (UX + UY - UXY) / W)); - + v[6] = (UX + UY - UXY) / UX; ase[6] = sqrt (ase1_xy) / (W * UX * UX); t[6] = v[6] / (sqrt (P - W * pow2 (UX + UY - UXY)) / (W * UX)); - + v[7] = (UX + UY - UXY) / UY; ase[7] = sqrt (ase1_yx) / (W * UY * UY); t[7] = v[7] / (sqrt (P - W * pow2 (UX + UY - UXY)) / (W * UY)); @@ -3104,7 +3164,7 @@ calc_directional (double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL], if (cmd.a_statistics[CRS_ST_D]) { int i; - + if (!sym) calc_symmetric (NULL, NULL, NULL); for (i = 0; i < 3; i++) @@ -3122,21 +3182,21 @@ calc_directional (double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL], double sum_Xr, sum_X2r; double SX, SXW; int i, j; - + for (sum_Xr = sum_X2r = 0., i = 0; i < n_rows; i++) { sum_Xr += rows[i].f * row_tot[i]; - sum_X2r += rows[i].f * rows[i].f * row_tot[i]; + sum_X2r += pow2 (rows[i].f) * row_tot[i]; } - SX = sum_X2r - sum_Xr * sum_Xr / W; - + SX = sum_X2r - pow2 (sum_Xr) / W; + for (SXW = 0., j = 0; j < n_cols; j++) { double cum; for (cum = 0., i = 0; i < n_rows; i++) { - SXW += rows[i].f * rows[i].f * mat[j + i * n_cols]; + SXW += pow2 (rows[i].f) * mat[j + i * n_cols]; cum += rows[i].f * mat[j + i * n_cols]; } @@ -3153,7 +3213,7 @@ calc_directional (double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL], for (sum_Yc = sum_Y2c = 0., i = 0; i < n_cols; i++) { sum_Yc += cols[i].f * col_tot[i]; - sum_Y2c += cols[i].f * cols[i].f * col_tot[i]; + sum_Y2c += pow2 (cols[i].f) * col_tot[i]; } SY = sum_Y2c - sum_Yc * sum_Yc / W; @@ -3163,10 +3223,10 @@ calc_directional (double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL], for (cum = 0., j = 0; j < n_cols; j++) { - SYW += cols[j].f * cols[j].f * mat[j + i * n_cols]; + SYW += pow2 (cols[j].f) * mat[j + i * n_cols]; cum += cols[j].f * mat[j + i * n_cols]; } - + SYW -= cum * cum / row_tot[i]; } v[12] = sqrt (1. - SYW / SY); @@ -3184,27 +3244,27 @@ format_short (char *s, const struct fmt_spec *fp, const union value *v) struct fmt_spec fmt_subst; /* Limit to short string width. */ - if (formats[fp->type].cat & FCAT_STRING) + if (fmt_is_string (fp->type)) { fmt_subst = *fp; assert (fmt_subst.type == FMT_A || fmt_subst.type == FMT_AHEX); if (fmt_subst.type == FMT_A) - fmt_subst.w = min (8, fmt_subst.w); + fmt_subst.w = MIN (8, fmt_subst.w); else - fmt_subst.w = min (16, fmt_subst.w); + fmt_subst.w = MIN (16, fmt_subst.w); fp = &fmt_subst; } /* Format. */ - data_out (s, fp, v); - + data_out (v, fp, s); + /* Null terminate. */ s[fp->w] = '\0'; } -/* +/* Local Variables: mode: c End: