From: Ben Pfaff Date: Mon, 4 Jul 2022 19:50:28 +0000 (-0700) Subject: PPROPERTIES FORMAT X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp;a=commitdiff_plain;h=2ec7a9fa319816227df1684cd32206fcec77d55c PPROPERTIES FORMAT --- diff --git a/src/language/stats/ctables.c b/src/language/stats/ctables.c index ee35fd6bd3..a29361cc3c 100644 --- a/src/language/stats/ctables.c +++ b/src/language/stats/ctables.c @@ -733,7 +733,7 @@ ctables_summary_spec_clone (struct ctables_summary_spec *dst, const struct ctables_summary_spec *src) { *dst = *src; - dst->label = xstrdup (src->label); + dst->label = xstrdup_if_nonnull (src->label); } static void @@ -3546,6 +3546,7 @@ struct ctables_pcexpr_evaluate_ctx const struct ctables_categories *cats; enum pivot_axis_type pc_a; size_t pc_a_idx; + size_t summary_idx; }; static double ctables_pcexpr_evaluate ( @@ -3626,8 +3627,8 @@ found: ; const struct ctables_table *t = s->table; const struct ctables_nest *specs_nest = s->nests[t->summary_axis]; const struct ctables_summary_spec_set *specs = &specs_nest->specs[tc->sv]; - size_t j = 0 /* XXX */; - return ctables_summary_value (tc, &tc->summaries[j], &specs->specs[j]); + return ctables_summary_value (tc, &tc->summaries[ctx->summary_idx], + &specs->specs[ctx->summary_idx]); } static double @@ -3697,27 +3698,61 @@ ctables_pcexpr_evaluate (const struct ctables_pcexpr_evaluate_ctx *ctx, NOT_REACHED (); } +/* XXX what if there is a postcompute in more than one dimension?? */ +static const struct ctables_postcompute * +ctables_cell_postcompute (const struct ctables_section *s, + const struct ctables_cell *cell, + enum pivot_axis_type *pc_a_p, + size_t *pc_a_idx_p) +{ + assert (cell->postcompute); + for (enum pivot_axis_type pc_a = 0; ; pc_a++) + { + assert (pc_a < PIVOT_N_AXES); + for (size_t pc_a_idx = 0; pc_a_idx < s->nests[pc_a]->n; pc_a_idx++) + { + const struct ctables_cell_value *cv = &cell->axes[pc_a].cvs[pc_a_idx]; + if (cv->category->type == CCT_POSTCOMPUTE) + { + if (pc_a_p) + *pc_a_p = pc_a; + if (pc_a_idx_p) + *pc_a_idx_p = pc_a_idx; + return cv->category->pc; + } + } + } + + NOT_REACHED (); +} + static double ctables_cell_calculate_postcompute (const struct ctables_section *s, - const struct ctables_cell *cell) + const struct ctables_cell *cell, + const struct ctables_summary_spec *ss, + struct fmt_spec *format, + bool *is_ctables_format, + size_t summary_idx) { enum pivot_axis_type pc_a; size_t pc_a_idx; - const struct ctables_postcompute *pc; - for (pc_a = 0; ; pc_a++) + const struct ctables_postcompute *pc = ctables_cell_postcompute ( + s, cell, &pc_a, &pc_a_idx); + + if (pc->specs) { - assert (pc_a < PIVOT_N_AXES); - for (pc_a_idx = 0; pc_a_idx < s->nests[pc_a]->n; pc_a_idx++) + for (size_t i = 0; i < pc->specs->n; i++) { - const struct ctables_cell_value *cv = &cell->axes[pc_a].cvs[pc_a_idx]; - if (cv->category->type == CCT_POSTCOMPUTE) + const struct ctables_summary_spec *ss2 = &pc->specs->specs[i]; + if (ss->function == ss2->function + && ss->percentile == ss2->percentile) { - pc = cv->category->pc; - goto found; + *format = ss2->format; + *is_ctables_format = ss2->is_ctables_format; + break; } } } -found: ; const struct variable *var = s->nests[pc_a]->vars[pc_a_idx]; const struct ctables_categories *cats = s->table->categories[ @@ -3728,6 +3763,7 @@ found: ; .cats = cats, .pc_a = pc_a, .pc_a_idx = pc_a_idx, + .summary_idx = summary_idx, }; return ctables_pcexpr_evaluate (&ctx, pc->expr); } @@ -4034,15 +4070,18 @@ ctables_table_output (struct ctables *ct, struct ctables_table *t) const struct ctables_summary_spec *ss = &specs->specs[j]; + struct fmt_spec format = specs->specs[j].format; + bool is_ctables_format = ss->is_ctables_format; double d = (cell->postcompute - ? ctables_cell_calculate_postcompute (s, cell) - : ctables_summary_value (cell, &cell->summaries[j], ss)); + ? ctables_cell_calculate_postcompute ( + s, cell, ss, &format, &is_ctables_format, j) + : ctables_summary_value (cell, &cell->summaries[j], + ss)); + struct pivot_value *value; if (ct->hide_threshold != 0 && d < ct->hide_threshold - && (cell->postcompute - ? false /* XXX */ - : ctables_summary_function_is_count (ss->function))) + && ctables_summary_function_is_count (ss->function)) { value = pivot_value_new_user_text_nocopy ( xasprintf ("<%d", ct->hide_threshold)); @@ -4051,18 +4090,17 @@ ctables_table_output (struct ctables *ct, struct ctables_table *t) value = pivot_value_new_user_text (ct->zero, SIZE_MAX); else if (d == SYSMIS && ct->missing) value = pivot_value_new_user_text (ct->missing, SIZE_MAX); - else if (specs->specs[j].is_ctables_format) + else if (is_ctables_format) { char *s = data_out_stretchy (&(union value) { .f = d }, - "UTF-8", - &specs->specs[j].format, + "UTF-8", &format, &ct->ctables_formats, NULL); value = pivot_value_new_user_text_nocopy (s); } else { value = pivot_value_new_number (d); - value->numeric.format = specs->specs[j].format; + value->numeric.format = format; } pivot_table_put (pt, dindexes, n_dindexes, value); } @@ -5038,9 +5076,8 @@ ctables_parse_pproperties_format (struct lexer *lexer, /* Parse format. */ struct fmt_spec format; - if (!parse_format_specifier (lexer, &format) - || !fmt_check_output (&format) - || !fmt_check_type_compat (&format, VAL_NUMERIC)) + bool is_ctables_format; + if (!parse_ctables_format_specifier (lexer, &format, &is_ctables_format)) goto error; if (sss->n >= sss->allocated) @@ -5050,6 +5087,7 @@ ctables_parse_pproperties_format (struct lexer *lexer, .function = function, .percentile = percentile, .format = format, + .is_ctables_format = is_ctables_format, }; } return true; diff --git a/tests/language/stats/ctables.at b/tests/language/stats/ctables.at index 1d787428d3..124b73938f 100644 --- a/tests/language/stats/ctables.at +++ b/tests/language/stats/ctables.at @@ -14,11 +14,9 @@ dnl * .SE suffixes. dnl - CATEGORIES: dnl * Data-dependent sorting. dnl - PCOMPUTE: -dnl * multi-dimensional +dnl * multi-dimensional (multiple CCT_POSTCOMPUTE in one cell dnl * MISSING, OTHERNM dnl * strings -dnl - PPROPERTIES: -dnl * summary statistics and formats? dnl dnl Features not yet tested: dnl - Parsing (positive and negative) @@ -28,6 +26,7 @@ dnl - test CLABELS ROWLABELS=LAYER. dnl - Test VLABELS. dnl - Test WEIGHT and adjustment weights. dnl - Test PCOMPUTE and PPROPERTIES. +dnl * PCOMPUTE for more than one kind of summary (e.g. [COUNT, ROWPCT]). dnl - EMPTY=INCLUDE For string ranges. dnl - Summary functions: dnl * Separate summary functions for totals and subtotals. @@ -858,31 +857,31 @@ AT_DATA([ctables.sps], CTABLES /PCOMPUTE &x=EXPR([3] + [4]) /PCOMPUTE &y=EXPR([4] + [5]) - /PPROPERTIES &x LABEL='3+4' HIDESOURCECATS=YES + /PPROPERTIES &x LABEL='3+4' HIDESOURCECATS=YES FORMAT=COUNT F8.2 /PPROPERTIES &y LABEL='4+5' /TABLE=qn105ba BY qns1 /CATEGORIES VARIABLES=qns1 [1, 2, SUBTOTAL, 3, 4, 5, &x, &y, SUBTOTAL] ]]) AT_CHECK([pspp ctables.sps -O box=unicode -O width=120], [0], [dnl Custom Tables -╭─────────────────────────────────────────────────────────┬────────────────────────────────────────────────────────────╮ -│ │ S1. Including yourself, how many members of this household │ -│ │ are age 16 or older? │ -│ ├───────┬───────┬─────────┬───────┬────────┬──────┬──────────┤ -│ │ 1 │ 2 │ Subtotal│ 5 │ 3+4 │ 4+5 │ Subtotal │ -│ ├───────┼───────┼─────────┼───────┼────────┼──────┼──────────┤ -│ │ Count │ Count │ Count │ Count │ Count │ Count│ Count │ -├─────────────────────────────────────────────────────────┼───────┼───────┼─────────┼───────┼────────┼──────┼──────────┤ -│105b. How likely is it that drivers who have Almost │ 147│ 246│ 393│ 11│ 81│ 30│ 92│ -│had too much to drink to drive safely will A. certain │ │ │ │ │ │ │ │ -│Get stopped by the police? Very likely│ 384│ 552│ 936│ 14│ 171│ 65│ 185│ -│ Somewhat │ 590│ 1249│ 1839│ 20│ 265│ 92│ 285│ -│ likely │ │ │ │ │ │ │ │ -│ Somewhat │ 278│ 647│ 925│ 6│ 116│ 38│ 122│ -│ unlikely │ │ │ │ │ │ │ │ -│ Very │ 141│ 290│ 431│ 4│ 59│ 22│ 63│ -│ unlikely │ │ │ │ │ │ │ │ -╰─────────────────────────────────────────────────────────┴───────┴───────┴─────────┴───────┴────────┴──────┴──────────╯ +╭────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────╮ +│ │ S1. Including yourself, how many members of this household │ +│ │ are age 16 or older? │ +│ ├───────┬───────┬──────────┬───────┬────────┬──────┬──────────┤ +│ │ 1 │ 2 │ Subtotal │ 5 │ 3+4 │ 4+5 │ Subtotal │ +│ ├───────┼───────┼──────────┼───────┼────────┼──────┼──────────┤ +│ │ Count │ Count │ Count │ Count │ Count │ Count│ Count │ +├────────────────────────────────────────────────────────┼───────┼───────┼──────────┼───────┼────────┼──────┼──────────┤ +│105b. How likely is it that drivers who have Almost │ 147│ 246│ 393│ 11│ 81.00│ 30│ 92│ +│had too much to drink to drive safely will certain │ │ │ │ │ │ │ │ +│A. Get stopped by the police? Very likely│ 384│ 552│ 936│ 14│ 171.00│ 65│ 185│ +│ Somewhat │ 590│ 1249│ 1839│ 20│ 265.00│ 92│ 285│ +│ likely │ │ │ │ │ │ │ │ +│ Somewhat │ 278│ 647│ 925│ 6│ 116.00│ 38│ 122│ +│ unlikely │ │ │ │ │ │ │ │ +│ Very │ 141│ 290│ 431│ 4│ 59.00│ 22│ 63│ +│ unlikely │ │ │ │ │ │ │ │ +╰────────────────────────────────────────────────────────┴───────┴───────┴──────────┴───────┴────────┴──────┴──────────╯ ]) AT_CLEANUP