const struct ctables_summary_spec *src)
{
*dst = *src;
- dst->label = xstrdup (src->label);
+ dst->label = xstrdup_if_nonnull (src->label);
}
static void
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 (
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
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[
.cats = cats,
.pc_a = pc_a,
.pc_a_idx = pc_a_idx,
+ .summary_idx = summary_idx,
};
return ctables_pcexpr_evaluate (&ctx, pc->expr);
}
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));
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);
}
/* 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)
.function = function,
.percentile = percentile,
.format = format,
+ .is_ctables_format = is_ctables_format,
};
}
return true;
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)
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.
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
-â\95â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¬────────────────────────────────────────────────────────────╮
-│ │ 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 │
-â\94\9câ\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼─────────┼───────┼────────┼──────┼──────────┤
-│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 │ │ │ │ │ │ │ │
-â\95°â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´─────────┴───────┴────────┴──────┴──────────╯
+â\95â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¬â\94\80────────────────────────────────────────────────────────────╮
+│ │ 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 │
+â\94\9câ\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¼â\94\80─────────┼───────┼────────┼──────┼──────────┤
+│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 │ │ │ │ │ │ │ │
+â\95°â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80─────────┴───────┴────────┴──────┴──────────╯
])
AT_CLEANUP