From d8b3292a8c12564dbc67e59f24d626dcfbf2e274 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sat, 13 Aug 2022 13:00:48 -0700 Subject: [PATCH] simplify function specifications in CTABLES --- doc/pspp-figures/ctables22.sps | 2 +- src/language/stats/ctables.c | 1194 +++++++++++-------------------- src/language/stats/ctables.inc | 145 +--- src/libpspp/str.c | 15 + src/libpspp/str.h | 1 + tests/language/stats/ctables.at | 18 +- 6 files changed, 463 insertions(+), 912 deletions(-) diff --git a/doc/pspp-figures/ctables22.sps b/doc/pspp-figures/ctables22.sps index 396fbd3939..205814c3d7 100644 --- a/doc/pspp-figures/ctables22.sps +++ b/doc/pspp-figures/ctables22.sps @@ -1,5 +1,5 @@ GET FILE='nhtsa.sav'. CTABLES /VLABELS VARIABLES=ALL DISPLAY=NAME - /TABLE qn61 > qn57 BY qnd7a > qn86 + qn64b BY qns3a[TABLE.ID, LAYER.ID, SUBTABLE.ID] + /TABLE qn61 > qn57 BY qnd7a > qn86 + qn64b BY qns3a[TABLEID, LAYERID, SUBTABLEID] /SLABELS POSITION=ROW. diff --git a/src/language/stats/ctables.c b/src/language/stats/ctables.c index fd296a0021..1abbf8a667 100644 --- a/src/language/stats/ctables.c +++ b/src/language/stats/ctables.c @@ -63,47 +63,106 @@ enum ctables_vlabel CTVL_BOTH = SETTINGS_VALUE_SHOW_BOTH, }; -/* XXX: - - unweighted summaries (U*) - - lower confidence limits (*.LCL) - - upper confidence limits (*.UCL) - - standard error (*.SE) - */ +enum ctables_function_type + { + /* A function that operates on data in a single cell. The function does + not have an unweighted version. */ + CTFT_CELL, + + /* A function that operates on data in a single cell. The function has an + unweighted version. */ + CTFT_UCELL, + + /* A function that operates on an area of cells. The function has an + unweighted version. */ + CTFT_AREA, + }; + +enum ctables_format + { + CTF_COUNT, + CTF_PERCENT, + CTF_GENERAL + }; + +enum ctables_function_availability + { + CTFA_ALL, /* Any variables. */ + CTFA_SCALE, /* Only scale variables, totals, and subtotals. */ + //CTFA_MRSETS, /* Only multiple-response sets */ + }; enum ctables_summary_function { -#define S(ENUM, NAME, LABEL, FORMAT, AVAILABILITY) ENUM, +#define S(ENUM, NAME, TYPE, FORMAT, AVAILABILITY) ENUM, #include "ctables.inc" #undef S }; enum { -#define S(ENUM, NAME, LABEL, FORMAT, AVAILABILITY) +1 +#define S(ENUM, NAME, TYPE, FORMAT, AVAILABILITY) +1 N_CTSF_FUNCTIONS = #include "ctables.inc" #undef S }; +struct ctables_function_info + { + struct substring basename; + enum ctables_function_type type; + enum ctables_format format; + enum ctables_function_availability availability; + + bool may_be_unweighted; + bool is_area; + }; +static const struct ctables_function_info ctables_function_info[N_CTSF_FUNCTIONS] = { +#define S(ENUM, NAME, TYPE, FORMAT, AVAILABILITY) \ + [ENUM] = { \ + .basename = SS_LITERAL_INITIALIZER (NAME), \ + .type = TYPE, \ + .format = FORMAT, \ + .availability = AVAILABILITY, \ + .may_be_unweighted = (TYPE) == CTFT_UCELL || (TYPE) == CTFT_AREA, \ + .is_area = (TYPE) == CTFT_AREA \ + }, +#include "ctables.inc" +#undef S +}; + static bool ctables_summary_function_is_count (enum ctables_summary_function); -enum ctables_domain_type +enum ctables_area_type { /* Within a section, where stacked variables divide one section from - another. */ - CTDT_TABLE, /* All layers of a whole section. */ - CTDT_LAYER, /* One layer within a section. */ - CTDT_LAYERROW, /* Row in one layer within a section. */ - CTDT_LAYERCOL, /* Column in one layer within a section. */ + another. + + Keep CTAT_LAYER after CTAT_LAYERROW and CTAT_LAYERCOL so that + parse_ctables_summary_function() parses correctly. */ + CTAT_TABLE, /* All layers of a whole section. */ + CTAT_LAYERROW, /* Row in one layer within a section. */ + CTAT_LAYERCOL, /* Column in one layer within a section. */ + CTAT_LAYER, /* One layer within a section. */ /* Within a subtable, where a subtable pairs an innermost row variable with an innermost column variable within a single layer. */ - CTDT_SUBTABLE, /* Whole subtable. */ - CTDT_ROW, /* Row within a subtable. */ - CTDT_COL, /* Column within a subtable. */ -#define N_CTDTS 7 + CTAT_SUBTABLE, /* Whole subtable. */ + CTAT_ROW, /* Row within a subtable. */ + CTAT_COL, /* Column within a subtable. */ +#define N_CTATS 7 }; -struct ctables_domain +static const char *ctables_area_type_name[N_CTATS] = { + [CTAT_TABLE] = "TABLE", + [CTAT_LAYER] = "LAYER", + [CTAT_LAYERROW] = "LAYERROW", + [CTAT_LAYERCOL] = "LAYERCOL", + [CTAT_SUBTABLE] = "SUBTABLE", + [CTAT_ROW] = "ROW", + [CTAT_COL] = "COL", +}; + +struct ctables_area { struct hmap_node node; @@ -141,9 +200,9 @@ struct ctables_cell all the axes (except the scalar variable, if any). */ struct hmap_node node; - /* The domains that contain this cell. */ - uint32_t omit_domains; - struct ctables_domain *domains[N_CTDTS]; + /* The areas that contain this cell. */ + uint32_t omit_areas; + struct ctables_area *areas[N_CTATS]; bool hide; @@ -314,8 +373,8 @@ struct ctables_nest struct variable **vars; size_t n; size_t scale_idx; - size_t *domains[N_CTDTS]; - size_t n_domains[N_CTDTS]; + size_t *areas[N_CTATS]; + size_t n_areas[N_CTATS]; size_t group_head; struct ctables_summary_spec_set specs[N_CSVS]; @@ -352,7 +411,7 @@ struct ctables_section /* Data. */ struct hmap *occurrences[PIVOT_N_AXES]; /* "struct ctables_occurrence"s. */ struct hmap cells; /* Contains "struct ctables_cell"s. */ - struct hmap domains[N_CTDTS]; /* Contains "struct ctables_domain"s. */ + struct hmap areas[N_CTATS]; /* Contains "struct ctables_area"s. */ }; static void ctables_section_uninit (struct ctables_section *); @@ -482,6 +541,8 @@ struct ctables_category /* CCT_FUNCTION. */ enum ctables_summary_function sort_function; + bool weighted; + enum ctables_area_type area; struct variable *sort_var; double percentile; }; @@ -672,23 +733,11 @@ struct ctables_axis static void ctables_axis_destroy (struct ctables_axis *); -enum ctables_format - { - CTF_COUNT, - CTF_PERCENT, - CTF_GENERAL - }; - -enum ctables_function_availability - { - CTFA_ALL, /* Any variables. */ - CTFA_SCALE, /* Only scale variables, totals, and subtotals. */ - //CTFA_MRSETS, /* Only multiple-response sets */ - }; - struct ctables_summary_spec { enum ctables_summary_function function; + bool weighted; + enum ctables_area_type area; double percentile; /* CTSF_PTILE only. */ char *label; @@ -777,7 +826,7 @@ static enum ctables_function_availability ctables_function_availability (enum ctables_summary_function f) { static enum ctables_function_availability availability[] = { -#define S(ENUM, NAME, LABEL, FORMAT, AVAILABILITY) [ENUM] = AVAILABILITY, +#define S(ENUM, NAME, TYPE, FORMAT, AVAILABILITY) [ENUM] = AVAILABILITY, #include "ctables.inc" #undef S }; @@ -788,44 +837,55 @@ ctables_function_availability (enum ctables_summary_function f) static bool ctables_summary_function_is_count (enum ctables_summary_function f) { - return f == CTSF_COUNT || f == CTSF_ECOUNT || f == CTSF_UCOUNT; + return f == CTSF_COUNT || f == CTSF_ECOUNT; } static bool parse_ctables_summary_function (struct lexer *lexer, - enum ctables_summary_function *f) + enum ctables_summary_function *function, + bool *weighted, + enum ctables_area_type *area) { - struct pair - { - enum ctables_summary_function function; - struct substring name; - }; - static struct pair names[] = { -#define S(ENUM, NAME, LABEL, FORMAT, AVAILABILITY) \ - { ENUM, SS_LITERAL_INITIALIZER (NAME) }, -#include "ctables.inc" - /* The .COUNT suffix may be omitted. */ - S(CTSF_ROWPCT_COUNT, "ROWPCT", _, _, _) - S(CTSF_COLPCT_COUNT, "COLPCT", _, _, _) - S(CTSF_TABLEPCT_COUNT, "TABLEPCT", _, _, _) - S(CTSF_SUBTABLEPCT_COUNT, "SUBTABLEPCT", _, _, _) - S(CTSF_LAYERPCT_COUNT, "LAYERPCT", _, _, _) - S(CTSF_LAYERROWPCT_COUNT, "LAYERROWPCT", _, _, _) - S(CTSF_LAYERCOLPCT_COUNT, "LAYERCOLPCT", _, _, _) -#undef S - }; - if (!lex_force_id (lexer)) return false; - for (size_t i = 0; i < sizeof names / sizeof *names; i++) - if (ss_equals_case (names[i].name, lex_tokss (lexer))) + struct substring name = lex_tokss (lexer); + *weighted = !(ss_match_byte (&name, 'U') || ss_match_byte (&name, 'u')); + + bool has_area = false; + *area = 0; + for (enum ctables_area_type at = 0; at < N_CTATS; at++) + if (ss_match_string_case (&name, ss_cstr (ctables_area_type_name[at]))) { - *f = names[i].function; - lex_get (lexer); - return true; + has_area = true; + *area = at; + + if (ss_equals_case (name, ss_cstr ("PCT"))) + { + /* Special case where .COUNT suffix is omitted. */ + *function = CTSF_areaPCT_COUNT; + lex_get (lexer); + return true; + } + break; } + for (int f = 0; f < N_CTSF_FUNCTIONS; f++) + { + const struct ctables_function_info *cfi = &ctables_function_info[f]; + if (ss_equals_case (cfi->basename, name)) + { + *function = f; + if (!*weighted && !cfi->may_be_unweighted) + break; + if (has_area != cfi->is_area) + break; + + lex_get (lexer); + return true; + } + } + lex_error (lexer, _("Expecting summary function name.")); return false; } @@ -881,7 +941,7 @@ ctables_summary_default_format (enum ctables_summary_function function, const struct variable *var) { static const enum ctables_format default_formats[] = { -#define S(ENUM, NAME, LABEL, FORMAT, AVAILABILITY) [ENUM] = FORMAT, +#define S(ENUM, NAME, TYPE, FORMAT, AVAILABILITY) [ENUM] = FORMAT, #include "ctables.inc" #undef S }; @@ -901,21 +961,120 @@ ctables_summary_default_format (enum ctables_summary_function function, } } +static const char * +ctables_summary_label__ (const struct ctables_summary_spec *spec) +{ + bool w = spec->weighted; + enum ctables_area_type a = spec->area; + switch (spec->function) + { + case CTSF_COUNT: + return w ? N_("Count") : N_("Unweighted Count"); + + case CTSF_ECOUNT: + return N_("Adjusted Count"); + + case CTSF_areaPCT_COUNT: + switch (a) + { + case CTAT_TABLE: return w ? N_("Table %") : N_("Unweighted Table %"); + case CTAT_LAYER: return w ? N_("Layer %") : N_("Unweighted Layer %"); + case CTAT_LAYERROW: return w ? N_("Layer Row %") : N_("Unweighted Layer Row %"); + case CTAT_LAYERCOL: return w ? N_("Layer Column %") : N_("Unweighted Layer Column %"); + case CTAT_SUBTABLE: return w ? N_("Subtable %") : N_("Unweighted Subtable %"); + case CTAT_ROW: return w ? N_("Row %") : N_("Unweighted Row %"); + case CTAT_COL: return w ? N_("Column %") : N_("Unweighted Column %"); + } + NOT_REACHED (); + + case CTSF_areaPCT_VALIDN: + switch (a) + { + case CTAT_TABLE: return w ? N_("Table Valid N %") : N_("Unweighted Table Valid N %"); + case CTAT_LAYER: return w ? N_("Layer Valid N %") : N_("Unweighted Layer Valid N %"); + case CTAT_LAYERROW: return w ? N_("Layer Row Valid N %") : N_("Unweighted Layer Row Valid N %"); + case CTAT_LAYERCOL: return w ? N_("Layer Column Valid N %") : N_("Unweighted Layer Column Valid N %"); + case CTAT_SUBTABLE: return w ? N_("Subtable Valid N %") : N_("Unweighted Subtable Valid N %"); + case CTAT_ROW: return w ? N_("Row Valid N %") : N_("Unweighted Row Valid N %"); + case CTAT_COL: return w ? N_("Column Valid N %") : N_("Unweighted Column Valid N %"); + } + NOT_REACHED (); + + case CTSF_areaPCT_TOTALN: + switch (a) + { + case CTAT_TABLE: return w ? N_("Table Total N %") : N_("Unweighted Table Total N %"); + case CTAT_LAYER: return w ? N_("Layer Total N %") : N_("Unweighted Layer Total N %"); + case CTAT_LAYERROW: return w ? N_("Layer Row Total N %") : N_("Unweighted Layer Row Total N %"); + case CTAT_LAYERCOL: return w ? N_("Layer Column Total N %") : N_("Unweighted Layer Column Total N %"); + case CTAT_SUBTABLE: return w ? N_("Subtable Total N %") : N_("Unweighted Subtable Total N %"); + case CTAT_ROW: return w ? N_("Row Total N %") : N_("Unweighted Row Total N %"); + case CTAT_COL: return w ? N_("Column Total N %") : N_("Unweighted Column Total N %"); + } + NOT_REACHED (); + + case CTSF_MAXIMUM: return N_("Maximum"); + case CTSF_MEAN: return w ? N_("Mean") : N_("Unweighted Mean"); + case CTSF_MEDIAN: return N_("Median"); + case CTSF_MINIMUM: return N_("Minimum"); + case CTSF_MISSING: return N_("Missing"); + case CTSF_MODE: return N_("Mode"); + case CTSF_PTILE: NOT_REACHED (); + case CTSF_RANGE: return N_("Range"); + case CTSF_SEMEAN: return N_("Std Error of Mean"); + case CTSF_STDDEV: return N_("Std Deviation"); + case CTSF_SUM: return N_("Sum"); + case CTSF_TOTALN: return N_("Total N"); + case CTSF_ETOTALN: return N_("Adjusted Total N"); + case CTSF_VALIDN: return N_("Valid N"); + case CTSF_EVALIDN: return N_("Adjusted Valid N"); + case CTSF_VARIANCE: return N_("Variance"); + case CTSF_areaPCT_SUM: + switch (a) + { + case CTAT_TABLE: return w ? N_("Table Sum %") : N_("Unweighted Table Sum %"); + case CTAT_LAYER: return w ? N_("Layer Sum %") : N_("Unweighted Layer Sum %"); + case CTAT_LAYERROW: return w ? N_("Layer Row Sum %") : N_("Unweighted Layer Row Sum %"); + case CTAT_LAYERCOL: return w ? N_("Layer Column Sum %") : N_("Unweighted Layer Column Sum %"); + case CTAT_SUBTABLE: return w ? N_("Subtable Sum %") : N_("Unweighted Subtable Sum %"); + case CTAT_ROW: return w ? N_("Row Sum %") : N_("Unweighted Row Sum %"); + case CTAT_COL: return w ? N_("Column Sum %") : N_("Unweighted Column Sum %"); + } + NOT_REACHED (); + + case CTSF_areaID: + switch (a) + { + /* Don't bother translating these: they are for developers only. */ + case CTAT_TABLE: return "Table ID"; + case CTAT_LAYER: return "Layer ID"; + case CTAT_LAYERROW: return "Layer Row ID"; + case CTAT_LAYERCOL: return "Layer Column ID"; + case CTAT_SUBTABLE: return "Subtable ID"; + case CTAT_ROW: return "Row ID"; + case CTAT_COL: return "Column ID"; + } + NOT_REACHED (); + } + + NOT_REACHED (); +} + static struct pivot_value * ctables_summary_label (const struct ctables_summary_spec *spec, double cilevel) { if (!spec->label) { - static const char *default_labels[] = { -#define S(ENUM, NAME, LABEL, FORMAT, AVAILABILITY) [ENUM] = LABEL, -#include "ctables.inc" -#undef S - }; - - return (spec->function == CTSF_PTILE - ? pivot_value_new_text_format (N_("Percentile %.2f"), - spec->percentile) - : pivot_value_new_text (default_labels[spec->function])); + if (spec->function == CTSF_PTILE) + { + double p = spec->percentile; + char *s = (spec->weighted + ? xasprintf (_("Percentile %.2f"), p) + : xasprintf (_("Unweighted Percentile %.2f"), p)); + return pivot_value_new_user_text_nocopy (s); + } + else + return pivot_value_new_text (ctables_summary_label__ (spec)); } else { @@ -930,7 +1089,7 @@ ctables_summary_label (const struct ctables_summary_spec *spec, double cilevel) ss_advance (&in, chunk); if (!in.length) return pivot_value_new_user_text_nocopy (ds_steal_cstr (&out)); - + ss_advance (&in, target.length); ds_put_format (&out, "%g", cilevel); } @@ -938,26 +1097,32 @@ ctables_summary_label (const struct ctables_summary_spec *spec, double cilevel) } static const char * -ctables_summary_function_name (enum ctables_summary_function function) +ctables_summary_function_name (enum ctables_summary_function function, + bool weighted, + enum ctables_area_type area, + char *buffer, size_t bufsize) { - static const char *names[] = { -#define S(ENUM, NAME, LABEL, FORMAT, AVAILABILITY) [ENUM] = NAME, -#include "ctables.inc" -#undef S - }; - return names[function]; + const struct ctables_function_info *cfi = &ctables_function_info[function]; + snprintf (buffer, bufsize, "%s%s%s", + weighted ? "" : "U", + cfi->is_area ? ctables_area_type_name[area] : "", + cfi->basename.string); + return buffer; } static bool add_summary_spec (struct ctables_axis *axis, - enum ctables_summary_function function, double percentile, + enum ctables_summary_function function, bool weighted, + enum ctables_area_type area, double percentile, const char *label, const struct fmt_spec *format, bool is_ctables_format, const struct msg_location *loc, enum ctables_summary_variant sv) { if (axis->op == CTAO_VAR) { - const char *function_name = ctables_summary_function_name (function); + char function_name[128]; + ctables_summary_function_name (function, weighted, area, + function_name, sizeof function_name); const char *var_name = var_get_name (axis->var); switch (ctables_function_availability (function)) { @@ -994,6 +1159,8 @@ add_summary_spec (struct ctables_axis *axis, struct ctables_summary_spec *dst = &set->specs[set->n++]; *dst = (struct ctables_summary_spec) { .function = function, + .weighted = weighted, + .area = area, .percentile = percentile, .label = xstrdup_if_nonnull (label), .format = (format ? *format @@ -1005,8 +1172,9 @@ add_summary_spec (struct ctables_axis *axis, else { for (size_t i = 0; i < 2; i++) - if (!add_summary_spec (axis->subs[i], function, percentile, label, - format, is_ctables_format, loc, sv)) + if (!add_summary_spec (axis->subs[i], function, weighted, area, + percentile, label, format, is_ctables_format, + loc, sv)) return false; return true; } @@ -1122,7 +1290,10 @@ ctables_axis_parse_postfix (struct ctables_axis_parse_ctx *ctx) /* Parse function. */ enum ctables_summary_function function; - if (!parse_ctables_summary_function (ctx->lexer, &function)) + bool weighted; + enum ctables_area_type area; + if (!parse_ctables_summary_function (ctx->lexer, &function, &weighted, + &area)) goto error; /* Parse percentile. */ @@ -1163,8 +1334,8 @@ ctables_axis_parse_postfix (struct ctables_axis_parse_ctx *ctx) struct msg_location *loc = lex_ofs_location (ctx->lexer, start_ofs, lex_ofs (ctx->lexer) - 1); - add_summary_spec (sub, function, percentile, label, formatp, - is_ctables_format, loc, sv); + add_summary_spec (sub, function, weighted, area, percentile, label, + formatp, is_ctables_format, loc, sv); free (label); msg_location_destroy (loc); @@ -1912,7 +2083,8 @@ ctables_table_parse_categories (struct lexer *lexer, struct dictionary *dict, else { cat.type = CCT_FUNCTION; - if (!parse_ctables_summary_function (lexer, &cat.sort_function)) + if (!parse_ctables_summary_function (lexer, &cat.sort_function, + &cat.weighted, &cat.area)) goto error; if (lex_match (lexer, T_LPAREN)) @@ -2174,8 +2346,8 @@ ctables_nest_uninit (struct ctables_nest *nest) free (nest->vars); for (enum ctables_summary_variant sv = 0; sv < N_CSVS; sv++) ctables_summary_spec_set_uninit (&nest->specs[sv]); - for (enum ctables_domain_type dt = 0; dt < N_CTDTS; dt++) - free (nest->domains[dt]); + for (enum ctables_area_type at = 0; at < N_CTATS; at++) + free (nest->areas[at]); } static void @@ -2336,67 +2508,18 @@ ctables_summary_init (union ctables_summary *s, { case CTSF_COUNT: case CTSF_ECOUNT: - case CTSF_ROWPCT_COUNT: - case CTSF_COLPCT_COUNT: - case CTSF_TABLEPCT_COUNT: - case CTSF_SUBTABLEPCT_COUNT: - case CTSF_LAYERPCT_COUNT: - case CTSF_LAYERROWPCT_COUNT: - case CTSF_LAYERCOLPCT_COUNT: - case CTSF_ROWPCT_VALIDN: - case CTSF_COLPCT_VALIDN: - case CTSF_TABLEPCT_VALIDN: - case CTSF_SUBTABLEPCT_VALIDN: - case CTSF_LAYERPCT_VALIDN: - case CTSF_LAYERROWPCT_VALIDN: - case CTSF_LAYERCOLPCT_VALIDN: - case CTSF_ROWPCT_TOTALN: - case CTSF_COLPCT_TOTALN: - case CTSF_TABLEPCT_TOTALN: - case CTSF_SUBTABLEPCT_TOTALN: - case CTSF_LAYERPCT_TOTALN: - case CTSF_LAYERROWPCT_TOTALN: - case CTSF_LAYERCOLPCT_TOTALN: + case CTSF_areaPCT_COUNT: + case CTSF_areaPCT_VALIDN: + case CTSF_areaPCT_TOTALN: case CTSF_MISSING: - case CSTF_TOTALN: + case CTSF_TOTALN: case CTSF_ETOTALN: case CTSF_VALIDN: case CTSF_EVALIDN: - case CTSF_UCOUNT: - case CTSF_UROWPCT_COUNT: - case CTSF_UCOLPCT_COUNT: - case CTSF_UTABLEPCT_COUNT: - case CTSF_USUBTABLEPCT_COUNT: - case CTSF_ULAYERPCT_COUNT: - case CTSF_ULAYERROWPCT_COUNT: - case CTSF_ULAYERCOLPCT_COUNT: - case CTSF_UROWPCT_VALIDN: - case CTSF_UCOLPCT_VALIDN: - case CTSF_UTABLEPCT_VALIDN: - case CTSF_USUBTABLEPCT_VALIDN: - case CTSF_ULAYERPCT_VALIDN: - case CTSF_ULAYERROWPCT_VALIDN: - case CTSF_ULAYERCOLPCT_VALIDN: - case CTSF_UROWPCT_TOTALN: - case CTSF_UCOLPCT_TOTALN: - case CTSF_UTABLEPCT_TOTALN: - case CTSF_USUBTABLEPCT_TOTALN: - case CTSF_ULAYERPCT_TOTALN: - case CTSF_ULAYERROWPCT_TOTALN: - case CTSF_ULAYERCOLPCT_TOTALN: - case CTSF_UMISSING: - case CSTF_UTOTALN: - case CTSF_UVALIDN: s->count = 0; break; - case CTSF_ROW_ID: - case CTSF_COL_ID: - case CTSF_TABLE_ID: - case CTSF_SUBTABLE_ID: - case CTSF_LAYER_ID: - case CTSF_LAYERROW_ID: - case CTSF_LAYERCOL_ID: + case CTSF_areaID: break; case CTSF_MAXIMUM: @@ -2410,34 +2533,13 @@ ctables_summary_init (union ctables_summary *s, case CTSF_STDDEV: case CTSF_SUM: case CTSF_VARIANCE: - case CTSF_ROWPCT_SUM: - case CTSF_COLPCT_SUM: - case CTSF_TABLEPCT_SUM: - case CTSF_SUBTABLEPCT_SUM: - case CTSF_LAYERPCT_SUM: - case CTSF_LAYERROWPCT_SUM: - case CTSF_LAYERCOLPCT_SUM: - case CTSF_UMEAN: - case CTSF_USEMEAN: - case CTSF_USTDDEV: - case CTSF_USUM: - case CTSF_UVARIANCE: - case CTSF_UROWPCT_SUM: - case CTSF_UCOLPCT_SUM: - case CTSF_UTABLEPCT_SUM: - case CTSF_USUBTABLEPCT_SUM: - case CTSF_ULAYERPCT_SUM: - case CTSF_ULAYERROWPCT_SUM: - case CTSF_ULAYERCOLPCT_SUM: + case CTSF_areaPCT_SUM: s->moments = moments1_create (MOMENT_VARIANCE); break; case CTSF_MEDIAN: case CTSF_MODE: case CTSF_PTILE: - case CTSF_UMEDIAN: - case CTSF_UMODE: - case CTSF_UPTILE: { struct caseproto *proto = caseproto_create (); proto = caseproto_add_width (proto, 0); @@ -2464,66 +2566,17 @@ ctables_summary_uninit (union ctables_summary *s, { case CTSF_COUNT: case CTSF_ECOUNT: - case CTSF_ROWPCT_COUNT: - case CTSF_COLPCT_COUNT: - case CTSF_TABLEPCT_COUNT: - case CTSF_SUBTABLEPCT_COUNT: - case CTSF_LAYERPCT_COUNT: - case CTSF_LAYERROWPCT_COUNT: - case CTSF_LAYERCOLPCT_COUNT: - case CTSF_ROWPCT_VALIDN: - case CTSF_COLPCT_VALIDN: - case CTSF_TABLEPCT_VALIDN: - case CTSF_SUBTABLEPCT_VALIDN: - case CTSF_LAYERPCT_VALIDN: - case CTSF_LAYERROWPCT_VALIDN: - case CTSF_LAYERCOLPCT_VALIDN: - case CTSF_ROWPCT_TOTALN: - case CTSF_COLPCT_TOTALN: - case CTSF_TABLEPCT_TOTALN: - case CTSF_SUBTABLEPCT_TOTALN: - case CTSF_LAYERPCT_TOTALN: - case CTSF_LAYERROWPCT_TOTALN: - case CTSF_LAYERCOLPCT_TOTALN: + case CTSF_areaPCT_COUNT: + case CTSF_areaPCT_VALIDN: + case CTSF_areaPCT_TOTALN: case CTSF_MISSING: - case CSTF_TOTALN: + case CTSF_TOTALN: case CTSF_ETOTALN: case CTSF_VALIDN: case CTSF_EVALIDN: - case CTSF_UCOUNT: - case CTSF_UROWPCT_COUNT: - case CTSF_UCOLPCT_COUNT: - case CTSF_UTABLEPCT_COUNT: - case CTSF_USUBTABLEPCT_COUNT: - case CTSF_ULAYERPCT_COUNT: - case CTSF_ULAYERROWPCT_COUNT: - case CTSF_ULAYERCOLPCT_COUNT: - case CTSF_UROWPCT_VALIDN: - case CTSF_UCOLPCT_VALIDN: - case CTSF_UTABLEPCT_VALIDN: - case CTSF_USUBTABLEPCT_VALIDN: - case CTSF_ULAYERPCT_VALIDN: - case CTSF_ULAYERROWPCT_VALIDN: - case CTSF_ULAYERCOLPCT_VALIDN: - case CTSF_UROWPCT_TOTALN: - case CTSF_UCOLPCT_TOTALN: - case CTSF_UTABLEPCT_TOTALN: - case CTSF_USUBTABLEPCT_TOTALN: - case CTSF_ULAYERPCT_TOTALN: - case CTSF_ULAYERROWPCT_TOTALN: - case CTSF_ULAYERCOLPCT_TOTALN: - case CTSF_UMISSING: - case CSTF_UTOTALN: - case CTSF_UVALIDN: break; - case CTSF_ROW_ID: - case CTSF_COL_ID: - case CTSF_TABLE_ID: - case CTSF_SUBTABLE_ID: - case CTSF_LAYER_ID: - case CTSF_LAYERROW_ID: - case CTSF_LAYERCOL_ID: + case CTSF_areaID: break; case CTSF_MAXIMUM: @@ -2536,34 +2589,13 @@ ctables_summary_uninit (union ctables_summary *s, case CTSF_STDDEV: case CTSF_SUM: case CTSF_VARIANCE: - case CTSF_ROWPCT_SUM: - case CTSF_COLPCT_SUM: - case CTSF_TABLEPCT_SUM: - case CTSF_SUBTABLEPCT_SUM: - case CTSF_LAYERPCT_SUM: - case CTSF_LAYERROWPCT_SUM: - case CTSF_LAYERCOLPCT_SUM: - case CTSF_UMEAN: - case CTSF_USEMEAN: - case CTSF_USTDDEV: - case CTSF_USUM: - case CTSF_UVARIANCE: - case CTSF_UROWPCT_SUM: - case CTSF_UCOLPCT_SUM: - case CTSF_UTABLEPCT_SUM: - case CTSF_USUBTABLEPCT_SUM: - case CTSF_ULAYERPCT_SUM: - case CTSF_ULAYERROWPCT_SUM: - case CTSF_ULAYERCOLPCT_SUM: + case CTSF_areaPCT_SUM: moments1_destroy (s->moments); break; case CTSF_MEDIAN: case CTSF_MODE: case CTSF_PTILE: - case CTSF_UMEDIAN: - case CTSF_UMODE: - case CTSF_UPTILE: casewriter_destroy (s->writer); break; } @@ -2597,101 +2629,33 @@ ctables_summary_add (union ctables_summary *s, */ switch (ss->function) { - case CSTF_TOTALN: - case CTSF_ROWPCT_TOTALN: - case CTSF_COLPCT_TOTALN: - case CTSF_TABLEPCT_TOTALN: - case CTSF_SUBTABLEPCT_TOTALN: - case CTSF_LAYERPCT_TOTALN: - case CTSF_LAYERROWPCT_TOTALN: - case CTSF_LAYERCOLPCT_TOTALN: - s->count += d_weight; - break; - - case CSTF_UTOTALN: - case CTSF_UROWPCT_TOTALN: - case CTSF_UCOLPCT_TOTALN: - case CTSF_UTABLEPCT_TOTALN: - case CTSF_USUBTABLEPCT_TOTALN: - case CTSF_ULAYERPCT_TOTALN: - case CTSF_ULAYERROWPCT_TOTALN: - case CTSF_ULAYERCOLPCT_TOTALN: - s->count += 1.0; + case CTSF_TOTALN: + case CTSF_areaPCT_TOTALN: + s->count += ss->weighted ? d_weight : 1.0; break; case CTSF_COUNT: - case CTSF_ROWPCT_COUNT: - case CTSF_COLPCT_COUNT: - case CTSF_TABLEPCT_COUNT: - case CTSF_SUBTABLEPCT_COUNT: - case CTSF_LAYERPCT_COUNT: - case CTSF_LAYERROWPCT_COUNT: - case CTSF_LAYERCOLPCT_COUNT: + case CTSF_areaPCT_COUNT: if (is_scale || !excluded_missing) - s->count += d_weight; - break; - - case CTSF_UCOUNT: - case CTSF_UROWPCT_COUNT: - case CTSF_UCOLPCT_COUNT: - case CTSF_UTABLEPCT_COUNT: - case CTSF_USUBTABLEPCT_COUNT: - case CTSF_ULAYERPCT_COUNT: - case CTSF_ULAYERROWPCT_COUNT: - case CTSF_ULAYERCOLPCT_COUNT: - if (is_scale || !excluded_missing) - s->count += 1.0; + s->count += ss->weighted ? d_weight : 1.0; break; case CTSF_VALIDN: - case CTSF_ROWPCT_VALIDN: - case CTSF_COLPCT_VALIDN: - case CTSF_TABLEPCT_VALIDN: - case CTSF_SUBTABLEPCT_VALIDN: - case CTSF_LAYERPCT_VALIDN: - case CTSF_LAYERROWPCT_VALIDN: - case CTSF_LAYERCOLPCT_VALIDN: - if (is_scale - ? !is_scale_missing - : !is_missing) - s->count += d_weight; - break; - - case CTSF_UVALIDN: - case CTSF_UROWPCT_VALIDN: - case CTSF_UCOLPCT_VALIDN: - case CTSF_UTABLEPCT_VALIDN: - case CTSF_USUBTABLEPCT_VALIDN: - case CTSF_ULAYERPCT_VALIDN: - case CTSF_ULAYERROWPCT_VALIDN: - case CTSF_ULAYERCOLPCT_VALIDN: + case CTSF_areaPCT_VALIDN: if (is_scale ? !is_scale_missing : !is_missing) - s->count += 1.0; + s->count += ss->weighted ? d_weight : 1.0; break; - case CTSF_ROW_ID: - case CTSF_COL_ID: - case CTSF_TABLE_ID: - case CTSF_SUBTABLE_ID: - case CTSF_LAYER_ID: - case CTSF_LAYERROW_ID: - case CTSF_LAYERCOL_ID: + case CTSF_areaID: break; case CTSF_MISSING: if (is_scale ? is_scale_missing : is_missing) - s->count += d_weight; - break; - - case CTSF_UMISSING: - if (is_scale - ? is_scale_missing - : is_missing) - s->count += 1.0; + s->count += ss->weighted ? d_weight : 1.0; break; case CTSF_ECOUNT: @@ -2728,278 +2692,28 @@ ctables_summary_add (union ctables_summary *s, case CTSF_STDDEV: case CTSF_SUM: case CTSF_VARIANCE: - case CTSF_ROWPCT_SUM: - case CTSF_COLPCT_SUM: - case CTSF_TABLEPCT_SUM: - case CTSF_SUBTABLEPCT_SUM: - case CTSF_LAYERPCT_SUM: - case CTSF_LAYERROWPCT_SUM: - case CTSF_LAYERCOLPCT_SUM: - if (!is_scale_missing) - moments1_add (s->moments, value->f, e_weight); - break; - - case CTSF_UMEAN: - case CTSF_USEMEAN: - case CTSF_USTDDEV: - case CTSF_USUM: - case CTSF_UVARIANCE: - case CTSF_UROWPCT_SUM: - case CTSF_UCOLPCT_SUM: - case CTSF_UTABLEPCT_SUM: - case CTSF_USUBTABLEPCT_SUM: - case CTSF_ULAYERPCT_SUM: - case CTSF_ULAYERROWPCT_SUM: - case CTSF_ULAYERCOLPCT_SUM: + case CTSF_areaPCT_SUM: if (!is_scale_missing) - moments1_add (s->moments, value->f, 1.0); + moments1_add (s->moments, value->f, ss->weighted ? e_weight : 1.0); break; - case CTSF_UMEDIAN: - case CTSF_UMODE: - case CTSF_UPTILE: - d_weight = e_weight = 1.0; - /* Fall through. */ case CTSF_MEDIAN: case CTSF_MODE: case CTSF_PTILE: if (!is_scale_missing) { - s->ovalid += e_weight; + double w = ss->weighted ? e_weight : 1.0; + s->ovalid += w; struct ccase *c = case_create (casewriter_get_proto (s->writer)); *case_num_rw_idx (c, 0) = value->f; - *case_num_rw_idx (c, 1) = e_weight; + *case_num_rw_idx (c, 1) = w; casewriter_write (s->writer, c); } break; } } -static enum ctables_domain_type -ctables_function_domain (enum ctables_summary_function function) -{ - switch (function) - { - case CTSF_COUNT: - case CTSF_ECOUNT: - case CTSF_MISSING: - case CSTF_TOTALN: - case CTSF_ETOTALN: - case CTSF_VALIDN: - case CTSF_EVALIDN: - case CTSF_MAXIMUM: - case CTSF_MINIMUM: - case CTSF_RANGE: - case CTSF_MEAN: - case CTSF_SEMEAN: - case CTSF_STDDEV: - case CTSF_SUM: - case CTSF_VARIANCE: - case CTSF_MEDIAN: - case CTSF_PTILE: - case CTSF_MODE: - case CTSF_UCOUNT: - case CTSF_UMISSING: - case CSTF_UTOTALN: - case CTSF_UVALIDN: - case CTSF_UMEAN: - case CTSF_USEMEAN: - case CTSF_USTDDEV: - case CTSF_USUM: - case CTSF_UVARIANCE: - case CTSF_UMEDIAN: - case CTSF_UPTILE: - case CTSF_UMODE: - NOT_REACHED (); - - case CTSF_COLPCT_COUNT: - case CTSF_COLPCT_SUM: - case CTSF_COLPCT_TOTALN: - case CTSF_COLPCT_VALIDN: - case CTSF_UCOLPCT_COUNT: - case CTSF_UCOLPCT_SUM: - case CTSF_UCOLPCT_TOTALN: - case CTSF_UCOLPCT_VALIDN: - case CTSF_COL_ID: - return CTDT_COL; - - case CTSF_LAYERCOLPCT_COUNT: - case CTSF_LAYERCOLPCT_SUM: - case CTSF_LAYERCOLPCT_TOTALN: - case CTSF_LAYERCOLPCT_VALIDN: - case CTSF_ULAYERCOLPCT_COUNT: - case CTSF_ULAYERCOLPCT_SUM: - case CTSF_ULAYERCOLPCT_TOTALN: - case CTSF_ULAYERCOLPCT_VALIDN: - case CTSF_LAYERCOL_ID: - return CTDT_LAYERCOL; - - case CTSF_LAYERPCT_COUNT: - case CTSF_LAYERPCT_SUM: - case CTSF_LAYERPCT_TOTALN: - case CTSF_LAYERPCT_VALIDN: - case CTSF_ULAYERPCT_COUNT: - case CTSF_ULAYERPCT_SUM: - case CTSF_ULAYERPCT_TOTALN: - case CTSF_ULAYERPCT_VALIDN: - case CTSF_LAYER_ID: - return CTDT_LAYER; - - case CTSF_LAYERROWPCT_COUNT: - case CTSF_LAYERROWPCT_SUM: - case CTSF_LAYERROWPCT_TOTALN: - case CTSF_LAYERROWPCT_VALIDN: - case CTSF_ULAYERROWPCT_COUNT: - case CTSF_ULAYERROWPCT_SUM: - case CTSF_ULAYERROWPCT_TOTALN: - case CTSF_ULAYERROWPCT_VALIDN: - case CTSF_LAYERROW_ID: - return CTDT_LAYERROW; - - case CTSF_ROWPCT_COUNT: - case CTSF_ROWPCT_SUM: - case CTSF_ROWPCT_TOTALN: - case CTSF_ROWPCT_VALIDN: - case CTSF_UROWPCT_COUNT: - case CTSF_UROWPCT_SUM: - case CTSF_UROWPCT_TOTALN: - case CTSF_UROWPCT_VALIDN: - case CTSF_ROW_ID: - return CTDT_ROW; - - case CTSF_SUBTABLEPCT_COUNT: - case CTSF_SUBTABLEPCT_SUM: - case CTSF_SUBTABLEPCT_TOTALN: - case CTSF_SUBTABLEPCT_VALIDN: - case CTSF_USUBTABLEPCT_COUNT: - case CTSF_USUBTABLEPCT_SUM: - case CTSF_USUBTABLEPCT_TOTALN: - case CTSF_USUBTABLEPCT_VALIDN: - case CTSF_SUBTABLE_ID: - return CTDT_SUBTABLE; - - case CTSF_TABLEPCT_COUNT: - case CTSF_TABLEPCT_SUM: - case CTSF_TABLEPCT_TOTALN: - case CTSF_TABLEPCT_VALIDN: - case CTSF_UTABLEPCT_COUNT: - case CTSF_UTABLEPCT_SUM: - case CTSF_UTABLEPCT_TOTALN: - case CTSF_UTABLEPCT_VALIDN: - case CTSF_TABLE_ID: - return CTDT_TABLE; - } - - NOT_REACHED (); -} - -static enum ctables_domain_type -ctables_function_is_pctsum (enum ctables_summary_function function) -{ - switch (function) - { - case CTSF_COUNT: - case CTSF_ECOUNT: - case CTSF_MISSING: - case CSTF_TOTALN: - case CTSF_ETOTALN: - case CTSF_VALIDN: - case CTSF_EVALIDN: - case CTSF_MAXIMUM: - case CTSF_MINIMUM: - case CTSF_RANGE: - case CTSF_MEAN: - case CTSF_SEMEAN: - case CTSF_STDDEV: - case CTSF_SUM: - case CTSF_VARIANCE: - case CTSF_MEDIAN: - case CTSF_PTILE: - case CTSF_MODE: - case CTSF_UCOUNT: - case CTSF_UMISSING: - case CSTF_UTOTALN: - case CTSF_UVALIDN: - case CTSF_UMEAN: - case CTSF_USEMEAN: - case CTSF_USTDDEV: - case CTSF_USUM: - case CTSF_UVARIANCE: - case CTSF_UMEDIAN: - case CTSF_UPTILE: - case CTSF_UMODE: - case CTSF_COLPCT_COUNT: - case CTSF_COLPCT_TOTALN: - case CTSF_COLPCT_VALIDN: - case CTSF_UCOLPCT_COUNT: - case CTSF_UCOLPCT_TOTALN: - case CTSF_UCOLPCT_VALIDN: - case CTSF_LAYERCOLPCT_COUNT: - case CTSF_LAYERCOLPCT_TOTALN: - case CTSF_LAYERCOLPCT_VALIDN: - case CTSF_ULAYERCOLPCT_COUNT: - case CTSF_ULAYERCOLPCT_TOTALN: - case CTSF_ULAYERCOLPCT_VALIDN: - case CTSF_LAYERPCT_COUNT: - case CTSF_LAYERPCT_TOTALN: - case CTSF_LAYERPCT_VALIDN: - case CTSF_ULAYERPCT_COUNT: - case CTSF_ULAYERPCT_TOTALN: - case CTSF_ULAYERPCT_VALIDN: - case CTSF_LAYERROWPCT_COUNT: - case CTSF_LAYERROWPCT_TOTALN: - case CTSF_LAYERROWPCT_VALIDN: - case CTSF_ULAYERROWPCT_COUNT: - case CTSF_ULAYERROWPCT_TOTALN: - case CTSF_ULAYERROWPCT_VALIDN: - case CTSF_ROWPCT_COUNT: - case CTSF_ROWPCT_TOTALN: - case CTSF_ROWPCT_VALIDN: - case CTSF_UROWPCT_COUNT: - case CTSF_UROWPCT_TOTALN: - case CTSF_UROWPCT_VALIDN: - case CTSF_SUBTABLEPCT_COUNT: - case CTSF_SUBTABLEPCT_TOTALN: - case CTSF_SUBTABLEPCT_VALIDN: - case CTSF_USUBTABLEPCT_COUNT: - case CTSF_USUBTABLEPCT_TOTALN: - case CTSF_USUBTABLEPCT_VALIDN: - case CTSF_TABLEPCT_COUNT: - case CTSF_TABLEPCT_TOTALN: - case CTSF_TABLEPCT_VALIDN: - case CTSF_UTABLEPCT_COUNT: - case CTSF_UTABLEPCT_TOTALN: - case CTSF_UTABLEPCT_VALIDN: - case CTSF_ROW_ID: - case CTSF_COL_ID: - case CTSF_TABLE_ID: - case CTSF_SUBTABLE_ID: - case CTSF_LAYER_ID: - case CTSF_LAYERROW_ID: - case CTSF_LAYERCOL_ID: - return false; - - case CTSF_COLPCT_SUM: - case CTSF_UCOLPCT_SUM: - case CTSF_LAYERCOLPCT_SUM: - case CTSF_ULAYERCOLPCT_SUM: - case CTSF_LAYERPCT_SUM: - case CTSF_ULAYERPCT_SUM: - case CTSF_LAYERROWPCT_SUM: - case CTSF_ULAYERROWPCT_SUM: - case CTSF_ROWPCT_SUM: - case CTSF_UROWPCT_SUM: - case CTSF_SUBTABLEPCT_SUM: - case CTSF_USUBTABLEPCT_SUM: - case CTSF_TABLEPCT_SUM: - case CTSF_UTABLEPCT_SUM: - return true; - } - - NOT_REACHED (); -} - static double ctables_summary_value (const struct ctables_cell *cell, union ctables_summary *s, @@ -3009,109 +2723,36 @@ ctables_summary_value (const struct ctables_cell *cell, { case CTSF_COUNT: case CTSF_ECOUNT: - case CTSF_UCOUNT: return s->count; - case CTSF_ROW_ID: - case CTSF_COL_ID: - case CTSF_TABLE_ID: - case CTSF_SUBTABLE_ID: - case CTSF_LAYER_ID: - case CTSF_LAYERROW_ID: - case CTSF_LAYERCOL_ID: - return cell->domains[ctables_function_domain (ss->function)]->sequence; - - case CTSF_ROWPCT_COUNT: - case CTSF_COLPCT_COUNT: - case CTSF_TABLEPCT_COUNT: - case CTSF_SUBTABLEPCT_COUNT: - case CTSF_LAYERPCT_COUNT: - case CTSF_LAYERROWPCT_COUNT: - case CTSF_LAYERCOLPCT_COUNT: - { - enum ctables_domain_type d = ctables_function_domain (ss->function); - return (cell->domains[d]->e_count - ? s->count / cell->domains[d]->e_count * 100 - : SYSMIS); - } - - case CTSF_UROWPCT_COUNT: - case CTSF_UCOLPCT_COUNT: - case CTSF_UTABLEPCT_COUNT: - case CTSF_USUBTABLEPCT_COUNT: - case CTSF_ULAYERPCT_COUNT: - case CTSF_ULAYERROWPCT_COUNT: - case CTSF_ULAYERCOLPCT_COUNT: - { - enum ctables_domain_type d = ctables_function_domain (ss->function); - return (cell->domains[d]->u_count - ? s->count / cell->domains[d]->u_count * 100 - : SYSMIS); - } - - case CTSF_ROWPCT_VALIDN: - case CTSF_COLPCT_VALIDN: - case CTSF_TABLEPCT_VALIDN: - case CTSF_SUBTABLEPCT_VALIDN: - case CTSF_LAYERPCT_VALIDN: - case CTSF_LAYERROWPCT_VALIDN: - case CTSF_LAYERCOLPCT_VALIDN: - { - enum ctables_domain_type d = ctables_function_domain (ss->function); - return (cell->domains[d]->e_valid - ? s->count / cell->domains[d]->e_valid * 100 - : SYSMIS); - } + case CTSF_areaID: + return cell->areas[ss->area]->sequence; - case CTSF_UROWPCT_VALIDN: - case CTSF_UCOLPCT_VALIDN: - case CTSF_UTABLEPCT_VALIDN: - case CTSF_USUBTABLEPCT_VALIDN: - case CTSF_ULAYERPCT_VALIDN: - case CTSF_ULAYERROWPCT_VALIDN: - case CTSF_ULAYERCOLPCT_VALIDN: + case CTSF_areaPCT_COUNT: { - enum ctables_domain_type d = ctables_function_domain (ss->function); - return (cell->domains[d]->u_valid - ? s->count / cell->domains[d]->u_valid * 100 - : SYSMIS); + const struct ctables_area *a = cell->areas[ss->area]; + double a_count = ss->weighted ? a->e_count : a->u_count; + return a_count ? s->count / a_count * 100 : SYSMIS; } - case CTSF_ROWPCT_TOTALN: - case CTSF_COLPCT_TOTALN: - case CTSF_TABLEPCT_TOTALN: - case CTSF_SUBTABLEPCT_TOTALN: - case CTSF_LAYERPCT_TOTALN: - case CTSF_LAYERROWPCT_TOTALN: - case CTSF_LAYERCOLPCT_TOTALN: + case CTSF_areaPCT_VALIDN: { - enum ctables_domain_type d = ctables_function_domain (ss->function); - return (cell->domains[d]->e_total - ? s->count / cell->domains[d]->e_total * 100 - : SYSMIS); + const struct ctables_area *a = cell->areas[ss->area]; + double a_valid = ss->weighted ? a->e_valid : a->u_valid; + return a_valid ? s->count / a_valid * 100 : SYSMIS; } - case CTSF_UROWPCT_TOTALN: - case CTSF_UCOLPCT_TOTALN: - case CTSF_UTABLEPCT_TOTALN: - case CTSF_USUBTABLEPCT_TOTALN: - case CTSF_ULAYERPCT_TOTALN: - case CTSF_ULAYERROWPCT_TOTALN: - case CTSF_ULAYERCOLPCT_TOTALN: + case CTSF_areaPCT_TOTALN: { - enum ctables_domain_type d = ctables_function_domain (ss->function); - return (cell->domains[d]->u_total - ? s->count / cell->domains[d]->u_total * 100 - : SYSMIS); + const struct ctables_area *a = cell->areas[ss->area]; + double a_total = ss->weighted ? a->e_total : a->u_total; + return a_total ? s->count / a_total * 100 : SYSMIS; } case CTSF_MISSING: - case CTSF_UMISSING: - case CSTF_TOTALN: + case CTSF_TOTALN: case CTSF_ETOTALN: - case CSTF_UTOTALN: case CTSF_VALIDN: - case CTSF_UVALIDN: case CTSF_EVALIDN: return s->count; @@ -3125,7 +2766,6 @@ ctables_summary_value (const struct ctables_cell *cell, return s->max != SYSMIS && s->min != SYSMIS ? s->max - s->min : SYSMIS; case CTSF_MEAN: - case CTSF_UMEAN: { double mean; moments1_calculate (s->moments, NULL, &mean, NULL, NULL, NULL); @@ -3133,7 +2773,6 @@ ctables_summary_value (const struct ctables_cell *cell, } case CTSF_SEMEAN: - case CTSF_USEMEAN: { double weight, variance; moments1_calculate (s->moments, &weight, NULL, &variance, NULL, NULL); @@ -3141,7 +2780,6 @@ ctables_summary_value (const struct ctables_cell *cell, } case CTSF_STDDEV: - case CTSF_USTDDEV: { double variance; moments1_calculate (s->moments, NULL, NULL, &variance, NULL, NULL); @@ -3149,7 +2787,6 @@ ctables_summary_value (const struct ctables_cell *cell, } case CTSF_SUM: - case CTSF_USUM: { double weight, mean; moments1_calculate (s->moments, &weight, &mean, NULL, NULL, NULL); @@ -3157,52 +2794,27 @@ ctables_summary_value (const struct ctables_cell *cell, } case CTSF_VARIANCE: - case CTSF_UVARIANCE: { double variance; moments1_calculate (s->moments, NULL, NULL, &variance, NULL, NULL); return variance; } - case CTSF_ROWPCT_SUM: - case CTSF_COLPCT_SUM: - case CTSF_TABLEPCT_SUM: - case CTSF_SUBTABLEPCT_SUM: - case CTSF_LAYERPCT_SUM: - case CTSF_LAYERROWPCT_SUM: - case CTSF_LAYERCOLPCT_SUM: - { - double weight, mean; - moments1_calculate (s->moments, &weight, &mean, NULL, NULL, NULL); - if (weight == SYSMIS || mean == SYSMIS) - return SYSMIS; - enum ctables_domain_type d = ctables_function_domain (ss->function); - double num = weight * mean; - double denom = cell->domains[d]->sums[ss->sum_var_idx].e_sum; - return denom != 0 ? num / denom * 100 : SYSMIS; - } - case CTSF_UROWPCT_SUM: - case CTSF_UCOLPCT_SUM: - case CTSF_UTABLEPCT_SUM: - case CTSF_USUBTABLEPCT_SUM: - case CTSF_ULAYERPCT_SUM: - case CTSF_ULAYERROWPCT_SUM: - case CTSF_ULAYERCOLPCT_SUM: + case CTSF_areaPCT_SUM: { double weight, mean; moments1_calculate (s->moments, &weight, &mean, NULL, NULL, NULL); if (weight == SYSMIS || mean == SYSMIS) return SYSMIS; - enum ctables_domain_type d = ctables_function_domain (ss->function); - double num = weight * mean; - double denom = cell->domains[d]->sums[ss->sum_var_idx].u_sum; - return denom != 0 ? num / denom * 100 : SYSMIS; + + const struct ctables_area *a = cell->areas[ss->area]; + const struct ctables_sum *sum = &a->sums[ss->sum_var_idx]; + double denom = ss->weighted ? sum->e_sum : sum->u_sum; + return denom != 0 ? weight * mean / denom * 100 : SYSMIS; } case CTSF_MEDIAN: case CTSF_PTILE: - case CTSF_UMEDIAN: - case CTSF_UPTILE: if (s->writer) { struct casereader *reader = casewriter_make_reader (s->writer); @@ -3218,7 +2830,6 @@ ctables_summary_value (const struct ctables_cell *cell, return s->ovalue; case CTSF_MODE: - case CTSF_UMODE: if (s->writer) { struct casereader *reader = casewriter_make_reader (s->writer); @@ -3359,17 +2970,17 @@ ctables_cell_compare_leaf_3way (const void *a_, const void *b_, Fill the table entry using the indexes from before. */ -static struct ctables_domain * -ctables_domain_insert (struct ctables_section *s, struct ctables_cell *cell, - enum ctables_domain_type domain) +static struct ctables_area * +ctables_area_insert (struct ctables_section *s, struct ctables_cell *cell, + enum ctables_area_type area) { size_t hash = 0; for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++) { const struct ctables_nest *nest = s->nests[a]; - for (size_t i = 0; i < nest->n_domains[domain]; i++) + for (size_t i = 0; i < nest->n_areas[area]; i++) { - size_t v_idx = nest->domains[domain][i]; + size_t v_idx = nest->areas[area][i]; struct ctables_cell_value *cv = &cell->axes[a].cvs[v_idx]; hash = hash_pointer (cv->category, hash); if (cv->category->type != CCT_TOTAL @@ -3380,16 +2991,16 @@ ctables_domain_insert (struct ctables_section *s, struct ctables_cell *cell, } } - struct ctables_domain *d; - HMAP_FOR_EACH_WITH_HASH (d, struct ctables_domain, node, hash, &s->domains[domain]) + struct ctables_area *a; + HMAP_FOR_EACH_WITH_HASH (a, struct ctables_area, node, hash, &s->areas[area]) { - const struct ctables_cell *df = d->example; + const struct ctables_cell *df = a->example; for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++) { const struct ctables_nest *nest = s->nests[a]; - for (size_t i = 0; i < nest->n_domains[domain]; i++) + for (size_t i = 0; i < nest->n_areas[area]; i++) { - size_t v_idx = nest->domains[domain][i]; + size_t v_idx = nest->areas[area][i]; struct ctables_cell_value *cv1 = &df->axes[a].cvs[v_idx]; struct ctables_cell_value *cv2 = &cell->axes[a].cvs[v_idx]; if (cv1->category != cv2->category @@ -3401,7 +3012,7 @@ ctables_domain_insert (struct ctables_section *s, struct ctables_cell *cell, goto not_equal; } } - return d; + return a; not_equal: ; } @@ -3410,10 +3021,10 @@ ctables_domain_insert (struct ctables_section *s, struct ctables_cell *cell, ? xzalloc (s->table->n_sum_vars * sizeof *sums) : NULL); - d = xmalloc (sizeof *d); - *d = (struct ctables_domain) { .example = cell, .sums = sums }; - hmap_insert (&s->domains[domain], &d->node, hash); - return d; + a = xmalloc (sizeof *a); + *a = (struct ctables_area) { .example = cell, .sums = sums }; + hmap_insert (&s->areas[area], &a->node, hash); + return a; } static struct substring @@ -3558,7 +3169,7 @@ ctables_cell_insert__ (struct ctables_section *s, const struct ccase *c, cell = xmalloc (sizeof *cell); cell->hide = false; cell->sv = sv; - cell->omit_domains = 0; + cell->omit_areas = 0; cell->postcompute = false; //struct string name = DS_EMPTY_INITIALIZER; for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++) @@ -3587,22 +3198,22 @@ ctables_cell_insert__ (struct ctables_section *s, const struct ccase *c, switch (a) { case PIVOT_AXIS_COLUMN: - cell->omit_domains |= ((1u << CTDT_TABLE) | - (1u << CTDT_LAYER) | - (1u << CTDT_LAYERCOL) | - (1u << CTDT_SUBTABLE) | - (1u << CTDT_COL)); + cell->omit_areas |= ((1u << CTAT_TABLE) | + (1u << CTAT_LAYER) | + (1u << CTAT_LAYERCOL) | + (1u << CTAT_SUBTABLE) | + (1u << CTAT_COL)); break; case PIVOT_AXIS_ROW: - cell->omit_domains |= ((1u << CTDT_TABLE) | - (1u << CTDT_LAYER) | - (1u << CTDT_LAYERROW) | - (1u << CTDT_SUBTABLE) | - (1u << CTDT_ROW)); + cell->omit_areas |= ((1u << CTAT_TABLE) | + (1u << CTAT_LAYER) | + (1u << CTAT_LAYERROW) | + (1u << CTAT_SUBTABLE) | + (1u << CTAT_ROW)); break; case PIVOT_AXIS_LAYER: - cell->omit_domains |= ((1u << CTDT_TABLE) | - (1u << CTDT_LAYER)); + cell->omit_areas |= ((1u << CTAT_TABLE) | + (1u << CTAT_LAYER)); break; } } @@ -3640,8 +3251,8 @@ ctables_cell_insert__ (struct ctables_section *s, const struct ccase *c, cell->summaries = xmalloc (specs->n * sizeof *cell->summaries); for (size_t i = 0; i < specs->n; i++) ctables_summary_init (&cell->summaries[i], &specs->specs[i]); - for (enum ctables_domain_type dt = 0; dt < N_CTDTS; dt++) - cell->domains[dt] = ctables_domain_insert (s, cell, dt); + for (enum ctables_area_type at = 0; at < N_CTATS; at++) + cell->areas[at] = ctables_area_insert (s, cell, at); hmap_insert (&s->cells, &cell->node, hash); return cell; } @@ -3683,24 +3294,24 @@ ctables_cell_add__ (struct ctables_section *s, const struct ccase *c, specs->var, case_data (c, specs->var), specs->is_scale, scale_missing, is_missing, excluded_missing, d_weight, e_weight); - for (enum ctables_domain_type dt = 0; dt < N_CTDTS; dt++) - if (!(cell->omit_domains && (1u << dt))) + for (enum ctables_area_type at = 0; at < N_CTATS; at++) + if (!(cell->omit_areas && (1u << at))) { - struct ctables_domain *d = cell->domains[dt]; - d->d_total += d_weight; - d->e_total += e_weight; - d->u_total += 1.0; + struct ctables_area *a = cell->areas[at]; + a->d_total += d_weight; + a->e_total += e_weight; + a->u_total += 1.0; if (!excluded_missing) { - d->d_count += d_weight; - d->e_count += e_weight; - d->u_count += 1.0; + a->d_count += d_weight; + a->e_count += e_weight; + a->u_count += 1.0; } if (!is_missing) { - d->d_valid += d_weight; - d->e_valid += e_weight; - d->u_count += 1.0; + a->d_valid += d_weight; + a->e_valid += e_weight; + a->u_count += 1.0; for (size_t i = 0; i < s->table->n_sum_vars; i++) { @@ -3709,7 +3320,7 @@ ctables_cell_add__ (struct ctables_section *s, const struct ccase *c, double addend = case_num (c, var); if (!var_is_num_missing (var, addend)) { - struct ctables_sum *sum = &d->sums[i]; + struct ctables_sum *sum = &a->sums[i]; sum->e_sum += addend * e_weight; sum->u_sum += addend; } @@ -3886,6 +3497,10 @@ merge_item_compare_3way (const struct merge_item *a, const struct merge_item *b) const struct ctables_summary_spec *bs = &b->set->specs[b->ofs]; if (as->function != bs->function) return as->function > bs->function ? 1 : -1; + else if (as->weighted != bs->weighted) + return as->weighted > bs->weighted ? 1 : -1; + else if (as->area != bs->area) + return as->area > bs->area ? 1 : -1; else if (as->percentile != bs->percentile) return as->percentile < bs->percentile ? 1 : -1; @@ -4089,8 +3704,8 @@ ctables_table_add_section (struct ctables_table *t, enum pivot_axis_type a, for (size_t i = 0; i < nest->n; i++) hmap_init (&s->occurrences[a][i]); } - for (size_t i = 0; i < N_CTDTS; i++) - hmap_init (&s->domains[i]); + for (size_t i = 0; i < N_CTATS; i++) + hmap_init (&s->areas[i]); } } @@ -4380,6 +3995,8 @@ ctables_cell_calculate_postcompute (const struct ctables_section *s, { const struct ctables_summary_spec *ss2 = &pc->specs->specs[i]; if (ss->function == ss2->function + && ss->weighted == ss2->weighted + && ss->area == ss2->area && ss->percentile == ss2->percentile) { *format = ss2->format; @@ -4562,16 +4179,16 @@ ctables_table_output (struct ctables *ct, struct ctables_table *t) #if 0 if (a == PIVOT_AXIS_ROW) { - size_t ids[N_CTDTS]; + size_t ids[N_CTATS]; memset (ids, 0, sizeof ids); for (size_t j = 0; j < n_sorted; j++) { struct ctables_cell *cell = sorted[j]; - for (enum ctables_domain_type dt = 0; dt < N_CTDTS; dt++) + for (enum ctables_area_type at = 0; at < N_CTATS; at++) { - struct ctables_domain *domain = cell->domains[dt]; - if (!domain->sequence) - domain->sequence = ++ids[dt]; + struct ctables_area *area = cell->areas[at]; + if (!area->sequence) + area->sequence = ++ids[at]; } } } @@ -4580,7 +4197,7 @@ ctables_table_output (struct ctables *ct, struct ctables_table *t) #if 0 for (size_t j = 0; j < n_sorted; j++) { - printf ("%s (%s): %f/%f = %.1f%%\n", sorted[j]->name, sorted[j]->contributes_to_domains ? "y" : "n", sorted[j]->summaries[0].count, sorted[j]->domains[CTDT_COL]->e_count, sorted[j]->summaries[0].count / sorted[j]->domains[CTDT_COL]->e_count * 100.0); + printf ("%s (%s): %f/%f = %.1f%%\n", sorted[j]->name, sorted[j]->contributes_to_areas ? "y" : "n", sorted[j]->summaries[0].count, sorted[j]->areas[CTAT_COL]->e_count, sorted[j]->summaries[0].count / sorted[j]->areas[CTAT_COL]->e_count * 100.0); } printf ("\n"); #endif @@ -4757,16 +4374,16 @@ ctables_table_output (struct ctables *ct, struct ctables_table *t) assert (n_sorted <= n_total_cells); sort (sorted, n_sorted, sizeof *sorted, ctables_cell_compare_leaf_3way, NULL); - size_t ids[N_CTDTS]; + size_t ids[N_CTATS]; memset (ids, 0, sizeof ids); for (size_t j = 0; j < n_sorted; j++) { struct ctables_cell *cell = sorted[j]; - for (enum ctables_domain_type dt = 0; dt < N_CTDTS; dt++) + for (enum ctables_area_type at = 0; at < N_CTATS; at++) { - struct ctables_domain *domain = cell->domains[dt]; - if (!domain->sequence) - domain->sequence = ++ids[dt]; + struct ctables_area *area = cell->areas[at]; + if (!area->sequence) + area->sequence = ++ids[at]; } } @@ -4972,7 +4589,7 @@ enumerate_sum_vars (const struct ctables_axis *a, for (size_t j = 0; j < a->specs[i].n; j++) { struct ctables_summary_spec *spec = &a->specs[i].specs[j]; - if (ctables_function_is_pctsum (spec->function)) + if (spec->function == CTSF_areaPCT_SUM) spec->sum_var_idx = add_sum_var (a->var, sum_vars, n, allocated); } break; @@ -4996,31 +4613,31 @@ ctables_prepare_table (struct ctables_table *t) for (size_t j = 0; j < t->stacks[a].n; j++) { struct ctables_nest *nest = &t->stacks[a].nests[j]; - for (enum ctables_domain_type dt = 0; dt < N_CTDTS; dt++) + for (enum ctables_area_type at = 0; at < N_CTATS; at++) { - nest->domains[dt] = xmalloc (nest->n * sizeof *nest->domains[dt]); - nest->n_domains[dt] = 0; + nest->areas[at] = xmalloc (nest->n * sizeof *nest->areas[at]); + nest->n_areas[at] = 0; for (size_t k = 0; k < nest->n; k++) { if (k == nest->scale_idx) continue; - switch (dt) + switch (at) { - case CTDT_TABLE: + case CTAT_TABLE: continue; - case CTDT_LAYER: + case CTAT_LAYER: if (a != PIVOT_AXIS_LAYER) continue; break; - case CTDT_SUBTABLE: - case CTDT_ROW: - case CTDT_COL: - if (dt == CTDT_SUBTABLE ? a != PIVOT_AXIS_LAYER - : dt == CTDT_ROW ? a == PIVOT_AXIS_COLUMN + case CTAT_SUBTABLE: + case CTAT_ROW: + case CTAT_COL: + if (at == CTAT_SUBTABLE ? a != PIVOT_AXIS_LAYER + : at == CTAT_ROW ? a == PIVOT_AXIS_COLUMN : a == PIVOT_AXIS_ROW) { if (k == nest->n - 1 @@ -5030,18 +4647,18 @@ ctables_prepare_table (struct ctables_table *t) } break; - case CTDT_LAYERROW: + case CTAT_LAYERROW: if (a == PIVOT_AXIS_COLUMN) continue; break; - case CTDT_LAYERCOL: + case CTAT_LAYERCOL: if (a == PIVOT_AXIS_ROW) continue; break; } - nest->domains[dt][nest->n_domains[dt]++] = k; + nest->areas[at][nest->n_areas[at]++] = k; } } } @@ -5072,6 +4689,7 @@ ctables_prepare_table (struct ctables_table *t) *specs->specs = (struct ctables_summary_spec) { .function = function, + .weighted = true, .format = ctables_summary_default_format (function, specs->var), }; if (!specs->var) @@ -5440,17 +5058,17 @@ ctables_section_clear (struct ctables_section *s) } hmap_shrink (&s->cells); - for (enum ctables_domain_type dt = 0; dt < N_CTDTS; dt++) + for (enum ctables_area_type at = 0; at < N_CTATS; at++) { - struct ctables_domain *domain, *next_domain; - HMAP_FOR_EACH_SAFE (domain, next_domain, struct ctables_domain, node, - &s->domains[dt]) + struct ctables_area *area, *next_area; + HMAP_FOR_EACH_SAFE (area, next_area, struct ctables_area, node, + &s->areas[at]) { - free (domain->sums); - hmap_delete (&s->domains[dt], &domain->node); - free (domain); + free (area->sums); + hmap_delete (&s->areas[at], &area->node); + free (area); } - hmap_shrink (&s->domains[dt]); + hmap_shrink (&s->areas[at]); } } @@ -5468,8 +5086,8 @@ ctables_section_uninit (struct ctables_section *s) } hmap_destroy (&s->cells); - for (size_t i = 0; i < N_CTDTS; i++) - hmap_destroy (&s->domains[i]); + for (size_t i = 0; i < N_CTATS; i++) + hmap_destroy (&s->areas[i]); } static void @@ -6046,7 +5664,9 @@ ctables_parse_pproperties_format (struct lexer *lexer, { /* Parse function. */ enum ctables_summary_function function; - if (!parse_ctables_summary_function (lexer, &function)) + bool weighted; + enum ctables_area_type area; + if (!parse_ctables_summary_function (lexer, &function, &weighted, &area)) goto error; /* Parse percentile. */ @@ -6070,6 +5690,8 @@ ctables_parse_pproperties_format (struct lexer *lexer, sizeof *sss->specs); sss->specs[sss->n++] = (struct ctables_summary_spec) { .function = function, + .weighted = weighted, + .area = area, .percentile = percentile, .format = format, .is_ctables_format = is_ctables_format, diff --git a/src/language/stats/ctables.inc b/src/language/stats/ctables.inc index e039cfd3ce..1a418fe03d 100644 --- a/src/language/stats/ctables.inc +++ b/src/language/stats/ctables.inc @@ -1,129 +1,30 @@ /* -*- c -*- */ /* Summary functions for all variables. */ -S(CTSF_COUNT, "COUNT", N_("Count"), CTF_COUNT, CTFA_ALL) -S(CTSF_ECOUNT, "ECOUNT", N_("Adjusted Count"), CTF_COUNT, CTFA_ALL) -S(CTSF_ROWPCT_COUNT, "ROWPCT.COUNT", N_("Row %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_COLPCT_COUNT, "COLPCT.COUNT", N_("Column %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_TABLEPCT_COUNT, "TABLEPCT.COUNT", N_("Table %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_SUBTABLEPCT_COUNT, "SUBTABLEPCT.COUNT", N_("Subtable %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_LAYERPCT_COUNT, "LAYERPCT.COUNT", N_("Layer %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_LAYERROWPCT_COUNT, "LAYERROWPCT.COUNT", N_("Layer Row %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_LAYERCOLPCT_COUNT, "LAYERCOLPCT.COUNT", N_("Layer Column %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_ROWPCT_VALIDN, "ROWPCT.VALIDN", N_("Row Valid N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_COLPCT_VALIDN, "COLPCT.VALIDN", N_("Column Valid N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_TABLEPCT_VALIDN, "TABLEPCT.VALIDN", N_("Table Valid N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_SUBTABLEPCT_VALIDN, "SUBTABLEPCT.VALIDN", N_("Subtable Valid N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_LAYERPCT_VALIDN, "LAYERPCT.VALIDN", N_("Layer Valid N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_LAYERROWPCT_VALIDN, "LAYERROWPCT.VALIDN", N_("Layer Row Valid N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_LAYERCOLPCT_VALIDN, "LAYERCOLPCT.VALIDN", N_("Layer Column Valid N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_ROWPCT_TOTALN, "ROWPCT.TOTALN", N_("Row Total N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_COLPCT_TOTALN, "COLPCT.TOTALN", N_("Column Total N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_TABLEPCT_TOTALN, "TABLEPCT.TOTALN", N_("Table Total N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_SUBTABLEPCT_TOTALN, "SUBTABLEPCT.TOTALN", N_("Subtable Total N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_LAYERPCT_TOTALN, "LAYERPCT.TOTALN", N_("Layer Total N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_LAYERROWPCT_TOTALN, "LAYERROWPCT.TOTALN", N_("Layer Row Total N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_LAYERCOLPCT_TOTALN, "LAYERCOLPCT.TOTALN", N_("Layer Column Total N %"), CTF_PERCENT, CTFA_ALL) - -/* All variables (unweighted.) */ -S(CTSF_UCOUNT, "UCOUNT", N_("Unweighted Count"), CTF_COUNT, CTFA_ALL) -S(CTSF_UROWPCT_COUNT, "UROWPCT.COUNT", N_("Unweighted Row %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_UCOLPCT_COUNT, "UCOLPCT.COUNT", N_("Unweighted Column %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_UTABLEPCT_COUNT, "UTABLEPCT.COUNT", N_("Unweighted Table %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_USUBTABLEPCT_COUNT, "USUBTABLEPCT.COUNT", N_("Unweighted Subtable %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_ULAYERPCT_COUNT, "ULAYERPCT.COUNT", N_("Unweighted Layer %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_ULAYERROWPCT_COUNT, "ULAYERROWPCT.COUNT", N_("Unweighted Layer Row %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_ULAYERCOLPCT_COUNT, "ULAYERCOLPCT.COUNT", N_("Unweighted Layer Column %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_UROWPCT_VALIDN, "UROWPCT.VALIDN", N_("Unweighted Row Valid N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_UCOLPCT_VALIDN, "UCOLPCT.VALIDN", N_("Unweighted Column Valid N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_UTABLEPCT_VALIDN, "UTABLEPCT.VALIDN", N_("Unweighted Table Valid N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_USUBTABLEPCT_VALIDN, "USUBTABLEPCT.VALIDN", N_("Unweighted Subtable Valid N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_ULAYERPCT_VALIDN, "ULAYERPCT.VALIDN", N_("Unweighted Layer Valid N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_ULAYERROWPCT_VALIDN, "ULAYERROWPCT.VALIDN", N_("Unweighted Layer Row Valid N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_ULAYERCOLPCT_VALIDN, "ULAYERCOLPCT.VALIDN", N_("Unweighted Layer Column Valid N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_UROWPCT_TOTALN, "UROWPCT.TOTALN", N_("Unweighted Row Total N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_UCOLPCT_TOTALN, "UCOLPCT.TOTALN", N_("Unweighted Column Total N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_UTABLEPCT_TOTALN, "UTABLEPCT.TOTALN", N_("Unweighted Table Total N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_USUBTABLEPCT_TOTALN, "USUBTABLEPCT.TOTALN", N_("Unweighted Subtable Total N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_ULAYERPCT_TOTALN, "ULAYERPCT.TOTALN", N_("Unweighted Layer Total N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_ULAYERROWPCT_TOTALN, "ULAYERROWPCT.TOTALN", N_("Unweighted Layer Row Total N %"), CTF_PERCENT, CTFA_ALL) -S(CTSF_ULAYERCOLPCT_TOTALN, "ULAYERCOLPCT.TOTALN", N_("Unweighted Layer Column Total N %"), CTF_PERCENT, CTFA_ALL) +S(CTSF_COUNT, "COUNT", CTFT_UCELL, CTF_COUNT, CTFA_ALL) +S(CTSF_ECOUNT, "ECOUNT", CTFT_CELL, CTF_COUNT, CTFA_ALL) +S(CTSF_areaPCT_COUNT, "PCT.COUNT", CTFT_AREA, CTF_PERCENT, CTFA_ALL) +S(CTSF_areaPCT_VALIDN, "PCT.VALIDN", CTFT_AREA, CTF_PERCENT, CTFA_ALL) +S(CTSF_areaPCT_TOTALN, "PCT.TOTALN", CTFT_AREA, CTF_PERCENT, CTFA_ALL) /* Scale variables, totals, and subtotals. */ -S(CTSF_MAXIMUM, "MAXIMUM", N_("Maximum"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_MEAN, "MEAN", N_("Mean"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_MEDIAN, "MEDIAN", N_("Median"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_MINIMUM, "MINIMUM", N_("Minimum"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_MISSING, "MISSING", N_("Missing"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_MODE, "MODE", N_("Mode"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_PTILE, "PTILE", N_("Percentile"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_RANGE, "RANGE", N_("Range"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_SEMEAN, "SEMEAN", N_("Std Error of Mean"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_STDDEV, "STDDEV", N_("Std Deviation"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_SUM, "SUM", N_("Sum"), CTF_GENERAL, CTFA_SCALE) -S(CSTF_TOTALN, "TOTALN", N_("Total N"), CTF_COUNT, CTFA_SCALE) -S(CTSF_ETOTALN, "ETOTALN", N_("Adjusted Total N"), CTF_COUNT, CTFA_SCALE) -S(CTSF_VALIDN, "VALIDN", N_("Valid N"), CTF_COUNT, CTFA_SCALE) -S(CTSF_EVALIDN, "EVALIDN", N_("Adjusted Valid N"), CTF_COUNT, CTFA_SCALE) -S(CTSF_VARIANCE, "VARIANCE", N_("Variance"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_ROWPCT_SUM, "ROWPCT.SUM", N_("Row Sum %"), CTF_PERCENT, CTFA_SCALE) -S(CTSF_COLPCT_SUM, "COLPCT.SUM", N_("Column Sum %"), CTF_PERCENT, CTFA_SCALE) -S(CTSF_TABLEPCT_SUM, "TABLEPCT.SUM", N_("Table Sum %"), CTF_PERCENT, CTFA_SCALE) -S(CTSF_SUBTABLEPCT_SUM, "SUBTABLEPCT.SUM", N_("Subtable Sum %"), CTF_PERCENT, CTFA_SCALE) -S(CTSF_LAYERPCT_SUM, "LAYERPCT.SUM", N_("Layer Sum %"), CTF_PERCENT, CTFA_SCALE) -S(CTSF_LAYERROWPCT_SUM, "LAYERROWPCT.SUM", N_("Layer Row Sum %"), CTF_PERCENT, CTFA_SCALE) -S(CTSF_LAYERCOLPCT_SUM, "LAYERCOLPCT.SUM", N_("Layer Column Sum %"), CTF_PERCENT, CTFA_SCALE) - -/* Scale variables, totals, and subtotals (unweighted). */ -S(CTSF_UMEAN, "UMEAN", N_("Unweighted Mean"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_UMEDIAN, "UMEDIAN", N_("Unweighted Median"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_UMISSING, "UMISSING", N_("Unweighted Missing"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_UMODE, "UMODE", N_("Unweighted Mode"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_UPTILE, "UPTILE", N_("Unweighted Percentile"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_USEMEAN, "USEMEAN", N_("Unweighted Std Error of Mean"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_USTDDEV, "USTDDEV", N_("Unweighted Std Deviation"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_USUM, "USUM", N_("Unweighted Sum"), CTF_GENERAL, CTFA_SCALE) -S(CSTF_UTOTALN, "UTOTALN", N_("Unweighted Total N"), CTF_COUNT, CTFA_SCALE) -S(CTSF_UVALIDN, "UVALIDN", N_("Unweighted Valid N"), CTF_COUNT, CTFA_SCALE) -S(CTSF_UVARIANCE, "UVARIANCE", N_("Unweighted Variance"), CTF_GENERAL, CTFA_SCALE) -S(CTSF_UROWPCT_SUM, "UROWPCT.SUM", N_("Unweighted Row Sum %"), CTF_PERCENT, CTFA_SCALE) -S(CTSF_UCOLPCT_SUM, "UCOLPCT.SUM", N_("Unweighted Column Sum %"), CTF_PERCENT, CTFA_SCALE) -S(CTSF_UTABLEPCT_SUM, "UTABLEPCT.SUM", N_("Unweighted Table Sum %"), CTF_PERCENT, CTFA_SCALE) -S(CTSF_USUBTABLEPCT_SUM, "USUBTABLEPCT.SUM", N_("Unweighted Subtable Sum %"), CTF_PERCENT, CTFA_SCALE) -S(CTSF_ULAYERPCT_SUM, "ULAYERPCT.SUM", N_("Unweighted Layer Sum %"), CTF_PERCENT, CTFA_SCALE) -S(CTSF_ULAYERROWPCT_SUM, "ULAYERROWPCT.SUM", N_("Unweighted Layer Row Sum %"), CTF_PERCENT, CTFA_SCALE) -S(CTSF_ULAYERCOLPCT_SUM, "ULAYERCOLPCT.SUM", N_("Unweighted Layer Column Sum %"), CTF_PERCENT, CTFA_SCALE) +S(CTSF_MAXIMUM, "MAXIMUM", CTFT_CELL, CTF_GENERAL, CTFA_SCALE) +S(CTSF_MEAN, "MEAN", CTFT_UCELL, CTF_GENERAL, CTFA_SCALE) +S(CTSF_MEDIAN, "MEDIAN", CTFT_UCELL, CTF_GENERAL, CTFA_SCALE) +S(CTSF_MINIMUM, "MINIMUM", CTFT_CELL, CTF_GENERAL, CTFA_SCALE) +S(CTSF_MISSING, "MISSING", CTFT_UCELL, CTF_GENERAL, CTFA_SCALE) +S(CTSF_MODE, "MODE", CTFT_UCELL, CTF_GENERAL, CTFA_SCALE) +S(CTSF_PTILE, "PTILE", CTFT_UCELL, CTF_GENERAL, CTFA_SCALE) +S(CTSF_RANGE, "RANGE", CTFT_CELL, CTF_GENERAL, CTFA_SCALE) +S(CTSF_SEMEAN, "SEMEAN", CTFT_UCELL, CTF_GENERAL, CTFA_SCALE) +S(CTSF_STDDEV, "STDDEV", CTFT_UCELL, CTF_GENERAL, CTFA_SCALE) +S(CTSF_SUM, "SUM", CTFT_UCELL, CTF_GENERAL, CTFA_SCALE) +S(CTSF_TOTALN, "TOTALN", CTFT_UCELL, CTF_COUNT, CTFA_SCALE) +S(CTSF_ETOTALN, "ETOTALN", CTFT_CELL, CTF_COUNT, CTFA_SCALE) +S(CTSF_VALIDN, "VALIDN", CTFT_UCELL, CTF_COUNT, CTFA_SCALE) +S(CTSF_EVALIDN, "EVALIDN", CTFT_CELL, CTF_COUNT, CTFA_SCALE) +S(CTSF_VARIANCE, "VARIANCE", CTFT_UCELL, CTF_GENERAL, CTFA_SCALE) +S(CTSF_areaPCT_SUM, "PCT.SUM", CTFT_AREA, CTF_PERCENT, CTFA_SCALE) /* Debugging and troubleshooting. */ -S(CTSF_ROW_ID, "ROW.ID", N_("Row ID"), CTF_COUNT, CTFA_ALL) -S(CTSF_COL_ID, "COL.ID", N_("Column ID"), CTF_COUNT, CTFA_ALL) -S(CTSF_TABLE_ID, "TABLE.ID", N_("Table ID"), CTF_COUNT, CTFA_ALL) -S(CTSF_SUBTABLE_ID, "SUBTABLE.ID", N_("Subtable ID"), CTF_COUNT, CTFA_ALL) -S(CTSF_LAYER_ID, "LAYER.ID", N_("Layer ID"), CTF_COUNT, CTFA_ALL) -S(CTSF_LAYERROW_ID, "LAYERROW.ID", N_("Layer Row ID"), CTF_COUNT, CTFA_ALL) -S(CTSF_LAYERCOL_ID, "LAYERCOL.ID", N_("Layer Column ID"), CTF_COUNT, CTFA_ALL) - -#if 0 /* Multiple response sets not yet implemented. */ -S(CTSF_RESPONSES, "RESPONSES", N_("Responses"), CTF_COUNT, CTFA_MRSETS) -S(CTSF_ROWPCT_RESPONSES, "ROWPCT.RESPONSES", N_("Row Responses %"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_COLPCT_RESPONSES, "COLPCT.RESPONSES", N_("Column Responses %"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_TABLEPCT_RESPONSES, "TABLEPCT.RESPONSES", N_("Table Responses %"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_SUBTABLEPCT_RESPONSES, "SUBTABLEPCT.RESPONSES", N_("Subtable Responses %"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_LAYERPCT_RESPONSES, "LAYERPCT.RESPONSES", N_("Layer Responses %"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_LAYERROWPCT_RESPONSES, "LAYERROWPCT.RESPONSES", N_("Layer Row Responses %"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_LAYERCOLPCT_RESPONSES, "LAYERCOLPCT.RESPONSES", N_("Layer Column Responses %"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_ROWPCT_RESPONSES_COUNT, "ROWPCT.RESPONSES.COUNT", N_("Row Responses % (Base: Count)"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_COLPCT_RESPONSES_COUNT, "COLPCT.RESPONSES.COUNT", N_("Column Responses % (Base: Count)"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_TABLEPCT_RESPONSES_COUNT, "TABLEPCT.RESPONSES.COUNT", N_("Table Responses % (Base: Count)"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_SUBTABLEPCT_RESPONSES_COUNT, "SUBTABLEPCT.RESPONSES.COUNT", N_("Subtable Responses % (Base: Count)"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_LAYERPCT_RESPONSES_COUNT, "LAYERPCT.RESPONSES.COUNT", N_("Layer Responses % (Base: Count)"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_LAYERROWPCT_RESPONSES_COUNT, "LAYERROWPCT.RESPONSES.COUNT", N_("Layer Row Responses % (Base: Count)"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_LAYERCOLPCT_RESPONSES_COUNT, "LAYERCOLPCT.RESPONSES.COUNT", N_("Layer Column Responses % (Base: Count)"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_ROWPCT_COUNT_RESPONSES, "ROWPCT.COUNT.RESPONSES", N_("Row Count % (Base: Responses)"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_COLPCT_COUNT_RESPONSES, "COLPCT.COUNT.RESPONSES", N_("Column Count % (Base: Responses)"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_TABLEPCT_COUNT_RESPONSES, "TABLEPCT.COUNT.RESPONSES", N_("Table Count % (Base: Responses)"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_SUBTABLEPCT_COUNT_RESPONSES, "SUBTABLEPCT.COUNT.RESPONSES", N_("Subtable Count % (Base: Responses)"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_LAYERPCT_COUNT_RESPONSES, "LAYERPCT.COUNT.RESPONSES", N_("Layer Count % (Base: Responses)"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_LAYERROWPCT_COUNT_RESPONSES, "LAYERROWPCT.COUNT.RESPONSES", N_("Layer Row Count % (Base: Responses)"), CTF_PERCENT, CTFA_MRSETS) -S(CTSF_LAYERCOLPCT_COUNT_RESPONSES, "LAYERCOLPCT.RESPONSES.COUNT", N_("Layer Column Count % (Base: Responses)"), CTF_PERCENT, CTFA_MRSETS) -#endif +S(CTSF_areaID, "ID", CTFT_AREA, CTF_COUNT, CTFA_ALL) diff --git a/src/libpspp/str.c b/src/libpspp/str.c index 811674225c..45187ef12b 100644 --- a/src/libpspp/str.c +++ b/src/libpspp/str.c @@ -615,6 +615,21 @@ ss_match_string (struct substring *ss, const struct substring target) return false; } +/* If SS begins with TARGET, except possibly for case differences, removes it + and returns true. Otherwise, returns false without changing SS. */ +bool +ss_match_string_case (struct substring *ss, const struct substring target) +{ + size_t length = ss_length (target); + if (ss_equals_case (ss_head (*ss, length), target)) + { + ss_advance (ss, length); + return true; + } + else + return false; +} + /* Removes the first byte from SS and returns it. If SS is empty, returns EOF without modifying SS. */ int diff --git a/src/libpspp/str.h b/src/libpspp/str.h index 91de05f395..86ffddca32 100644 --- a/src/libpspp/str.h +++ b/src/libpspp/str.h @@ -118,6 +118,7 @@ void ss_advance (struct substring *, size_t); bool ss_match_byte (struct substring *, char); int ss_match_byte_in (struct substring *, struct substring); bool ss_match_string (struct substring *, const struct substring); +bool ss_match_string_case (struct substring *, const struct substring); int ss_get_byte (struct substring *); size_t ss_get_bytes (struct substring *, size_t n, struct substring *); bool ss_get_until (struct substring *, char delimiter, struct substring *); diff --git a/tests/language/stats/ctables.at b/tests/language/stats/ctables.at index 62efd1b056..fd1000b853 100644 --- a/tests/language/stats/ctables.at +++ b/tests/language/stats/ctables.at @@ -2051,6 +2051,18 @@ Female ]) AT_CLEANUP +AT_SETUP([CTABLES CLABELS]) +AT_CHECK([ln $top_srcdir/examples/nhtsa.sav . || cp $top_srcdir/examples/nhtsa.sav .]) +AT_DATA([ctables.sps], +[[GET 'nhtsa.sav'. +CTABLES /TABLE qns3a > (qn26 + qn27 + qn28 + qn29) [COLPCT]. +CTABLES /TABLE qns3a > (qn26 + qn27 + qn28 + qn29) [COLPCT] /CLABELS ROWLABELS=OPPOSITE. +CTABLES /TABLE qns3a > (qn26 + qn27 + qn28 + qn29) [COLPCT] /CLABELS ROWLABELS=LAYER. +]]) +AT_CHECK([pspp ctables.sps --table-look="$builddir"/all-layers.stt -O box=unicode], [0], [dnl +]) +AT_CLEANUP + AT_SETUP([CTABLES missing values]) AT_DATA([ctables.sps], [[DATA LIST LIST NOTABLE/x y. @@ -3026,11 +3038,11 @@ AT_DATA([ctables.sps], [[GET 'nhtsa.sav'. CTABLES /VLABELS VARIABLES=ALL DISPLAY=NAME - /TABLE qn61 > qn57 BY qnd7a > qn86 + qn64b BY qns3a[TABLE.ID, LAYER.ID, SUBTABLE.ID] + /TABLE qn61 > qn57 BY qnd7a > qn86 + qn64b BY qns3a[TABLEID, LAYERID, SUBTABLEID] /SLABELS POSITION=ROW - /TABLE qn61 > qn57 BY qnd7a > qn86 + qn64b BY qns3a[ROW.ID, LAYERROW.ID] + /TABLE qn61 > qn57 BY qnd7a > qn86 + qn64b BY qns3a[ROWID, LAYERROWID] /SLABELS POSITION=ROW - /TABLE qn61 > qn57 BY qnd7a > qn86 + qn64b BY qns3a[COL.ID, LAYERCOL.ID] + /TABLE qn61 > qn57 BY qnd7a > qn86 + qn64b BY qns3a[COLID, LAYERCOLID] /SLABELS POSITION=ROW. ]]) AT_CHECK([pspp ctables.sps --table-look="$builddir"/all-layers.stt -O box=unicode -O width=80], [0], [dnl -- 2.30.2