From e4c6d9fad9dfac0e7fae4323e1c2aaa3642acf94 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 4 Aug 2022 17:40:51 -0700 Subject: [PATCH] test NEGPAREN & friends --- src/language/stats/ctables.c | 39 ++++++++++++++++++++++++++++----- tests/language/stats/ctables.at | 19 +++++++++++++++- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/language/stats/ctables.c b/src/language/stats/ctables.c index 64c399bcbc..461007c555 100644 --- a/src/language/stats/ctables.c +++ b/src/language/stats/ctables.c @@ -4358,6 +4358,37 @@ ctables_cell_calculate_postcompute (const struct ctables_section *s, return ctables_pcexpr_evaluate (&ctx, pc->expr); } +static char * +ctables_format (double d, const struct fmt_spec *format, + const struct fmt_settings *settings) +{ + const union value v = { .f = d }; + char *s = data_out_stretchy (&v, "UTF-8", format, settings, NULL); + + /* The custom-currency specifications for NEQUAL, PAREN, and PCTPAREN don't + produce the results we want for negative numbers, putting the negative + sign in the wrong spot, before the prefix instead of after it. We can't, + in fact, produce the desired results using a custom-currency + specification. Instead, we postprocess the output, moving the negative + sign into place: + + NEQUAL: "-N=3" => "N=-3" + PAREN: "-(3)" => "(-3)" + PCTPAREN: "-(3%)" => "(-3%)" + + This transformation doesn't affect NEGPAREN. */ + char *minus_src = strchr (s, '-'); + if (minus_src && (minus_src == s || minus_src[-1] != 'E')) + { + char *n_equals = strstr (s, "N="); + char *lparen = strchr (s, '('); + char *minus_dst = n_equals ? n_equals + 1 : lparen; + if (minus_dst) + move_element (s, minus_dst - s + 1, 1, minus_src - s, minus_dst - s); + } + return s; +} + static void ctables_table_output (struct ctables *ct, struct ctables_table *t) { @@ -4684,12 +4715,8 @@ ctables_table_output (struct ctables *ct, struct ctables_table *t) else if (d == SYSMIS && ct->missing) value = pivot_value_new_user_text (ct->missing, SIZE_MAX); else if (is_ctables_format) - { - char *s = data_out_stretchy (&(union value) { .f = d }, - "UTF-8", &format, - &ct->ctables_formats, NULL); - value = pivot_value_new_user_text_nocopy (s); - } + value = pivot_value_new_user_text_nocopy ( + ctables_format (d, &format, &ct->ctables_formats)); else { value = pivot_value_new_number (d); diff --git a/tests/language/stats/ctables.at b/tests/language/stats/ctables.at index 171e92f83c..9109b7c034 100644 --- a/tests/language/stats/ctables.at +++ b/tests/language/stats/ctables.at @@ -16,7 +16,6 @@ dnl * Date values dnl * THRU (numeric ranges) dnl * OTHERNM dnl - Date/time variables and values -dnl - Special formats for summary functions: NEGPAREN, NEQUAL, PAREN, PCTPAREN. dnl - TITLES: )DATE, )TIME, )TABLE. dnl - Test PCOMPUTE: dnl * PCOMPUTE for more than one kind of summary (e.g. [COUNT, ROWPCT]). @@ -2397,3 +2396,21 @@ maximumColumnWidth="192" minimumColumnWidth="96" ]) AT_CLEANUP + +AT_SETUP([CTABLES special formats]) +AT_KEYWORDS([NEGPAREN NEQUAL PAREN PCTPAREN]) +AT_CHECK([ln $top_srcdir/examples/nhtsa.sav . || cp $top_srcdir/examples/nhtsa.sav .]) +AT_DATA([ctables.sps], +[[GET 'nhtsa.sav'. +COMPUTE x = qnd3 - 4. +CTABLES /TABLE x[MINIMUM NEGPAREN8.1, MINIMUM NEQUAL8.1, MINIMUM PAREN8.1, MINIMUM PCTPAREN8.1, MAXIMUM NEGPAREN8.1, MAXIMUM NEQUAL8.1, MAXIMUM PAREN8.1, MAXIMUM PCTPAREN8.1]. +]]) +AT_CHECK([pspp ctables.sps -O box=unicode], [0], [dnl + Custom Tables +╭─┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────╮ +│ │Minimum│Minimum│Minimum│Minimum│Maximum│Maximum│Maximum│Maximum│ +├─┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ +│x│(3.0) │N=-3.0 │(-3.0) │(-3.0%)│8.0 │N=8.0 │(8.0) │(8.0%) │ +╰─┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────╯ +]) +AT_CLEANUP -- 2.30.2