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) \
+ \
/* 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_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) \
#if 0 /* Multiple response sets not yet implemented. */
S(CTSF_RESPONSES, "RESPONSES", N_("Responses"), CTF_COUNT, CTFA_MRSETS) \
double e_valid; /* Effective weight */
double e_count;
double e_total;
+ double u_valid; /* Unweighted. */
+ double u_count;
+ double u_total;
+ struct ctables_sum *sums;
+ };
+
+struct ctables_sum
+ {
+ double e_sum;
+ double u_sum;
};
enum ctables_summary_variant
CTPO_CONSTANT, /* 5 */
CTPO_CAT_NUMBER, /* [5] */
CTPO_CAT_STRING, /* ["STRING"] */
- CTPO_CAT_RANGE, /* [LO THRU 5] */
+ CTPO_CAT_NRANGE, /* [LO THRU 5] */
+ CTPO_CAT_SRANGE, /* ["A" THRU "B"] */
CTPO_CAT_MISSING, /* MISSING */
CTPO_CAT_OTHERNM, /* OTHERNM */
CTPO_CAT_SUBTOTAL, /* SUBTOTAL */
/* CTPO_CAT_STRING, in dictionary encoding. */
struct substring string;
- /* CTPO_CAT_RANGE. */
- double range[2];
+ /* CTPO_CAT_NRANGE. */
+ double nrange[2];
+
+ /* CTPO_CAT_SRANGE. */
+ struct substring srange[2];
/* CTPO_CAT_SUBTOTAL. */
size_t subtotal_index;
size_t n_sections;
enum pivot_axis_type summary_axis;
struct ctables_summary_spec_set summary_specs;
+ struct variable **sum_vars;
+ size_t n_sum_vars;
const struct variable *clabels_example;
struct hmap clabels_values_map;
bool is_ctables_format; /* Is 'format' one of CTEF_*? */
size_t axis_idx;
+ size_t sum_var_idx;
};
static void
const struct ctables_summary_spec *src)
{
*dst = *src;
- dst->label = xstrdup (src->label);
+ dst->label = xstrdup_if_nonnull (src->label);
}
static void
case CTSF_LAYERPCT_COUNT:
case CTSF_LAYERROWPCT_COUNT:
case CTSF_LAYERCOLPCT_COUNT:
+ 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:
return true;
case CTSF_ROWPCT_VALIDN:
case CTSF_LAYERPCT_SUM:
case CTSF_LAYERROWPCT_SUM:
case CTSF_LAYERCOLPCT_SUM:
+ 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_UMEAN:
+ case CTSF_UMEDIAN:
+ case CTSF_UMISSING:
+ case CTSF_UMODE:
+ case CTSF_UPTILE:
+ case CTSF_USEMEAN:
+ case CTSF_USTDDEV:
+ case CTSF_USUM:
+ case CSTF_UTOTALN:
+ case CTSF_UVALIDN:
+ 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:
return false;
}
NOT_REACHED ();
}
}
-static char *
-ctables_summary_default_label (enum ctables_summary_function function,
- double percentile)
+static struct pivot_value *
+ctables_summary_label (const struct ctables_summary_spec *spec, double cilevel)
{
- static const char *default_labels[] = {
+ if (!spec->label)
+ {
+ static const char *default_labels[] = {
#define S(ENUM, NAME, LABEL, FORMAT, AVAILABILITY) [ENUM] = LABEL,
- SUMMARIES
+ SUMMARIES
#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]));
+ }
+ else
+ {
+ struct substring in = ss_cstr (spec->label);
+ struct substring target = ss_cstr (")CILEVEL");
- return (function == CTSF_PTILE
- ? xasprintf (_("Percentile %.2f"), percentile)
- : xstrdup (gettext (default_labels[function])));
+ struct string out = DS_EMPTY_INITIALIZER;
+ for (;;)
+ {
+ size_t chunk = ss_find_substring (in, target);
+ ds_put_substring (&out, ss_head (in, chunk));
+ 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);
+ }
+ }
}
static const char *
*dst = (struct ctables_summary_spec) {
.function = function,
.percentile = percentile,
- .label = xstrdup (label),
+ .label = xstrdup_if_nonnull (label),
.format = (format ? *format
: ctables_summary_default_format (function, axis->var)),
.is_ctables_format = is_ctables_format,
}
/* Parse label. */
- char *label;
+ char *label = NULL;
if (lex_is_string (ctx->lexer))
{
label = ss_xstrdup (lex_tokss (ctx->lexer));
lex_get (ctx->lexer);
}
- else
- label = ctables_summary_default_label (function, percentile);
/* Parse format. */
struct fmt_spec format;
best = cat;
break;
- case CTPO_CAT_RANGE:
+ case CTPO_CAT_NRANGE:
if (cat->type == CCT_NRANGE
- && cat->nrange[0] == e->range[0]
- && cat->nrange[1] == e->range[1])
+ && cat->nrange[0] == e->nrange[0]
+ && cat->nrange[1] == e->nrange[1])
+ best = cat;
+ break;
+
+ case CTPO_CAT_SRANGE:
+ if (cat->type == CCT_SRANGE
+ && nullable_substring_equal (&cat->srange[0], &e->srange[0])
+ && nullable_substring_equal (&cat->srange[1], &e->srange[1]))
best = cat;
break;
{
case CTPO_CAT_NUMBER:
case CTPO_CAT_STRING:
- case CTPO_CAT_RANGE:
+ case CTPO_CAT_NRANGE:
case CTPO_CAT_MISSING:
case CTPO_CAT_OTHERNM:
case CTPO_CAT_SUBTOTAL:
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_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:
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);
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_MAXIMUM:
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:
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;
}
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;
+ break;
+
case CTSF_COUNT:
case CTSF_ROWPCT_COUNT:
case CTSF_COLPCT_COUNT:
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;
+ break;
+
case CTSF_VALIDN:
case CTSF_ROWPCT_VALIDN:
case CTSF_COLPCT_VALIDN:
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:
+ if (is_scale
+ ? !is_scale_missing
+ : !is_missing)
+ s->count += 1.0;
+ break;
+
case CTSF_MISSING:
if (is_missing)
s->count += d_weight;
break;
+ case CTSF_UMISSING:
+ if (is_missing)
+ s->count += 1.0;
+ break;
+
case CTSF_ECOUNT:
if (is_scale || !excluded_missing)
s->count += e_weight;
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:
+ if (!is_scale_missing)
+ moments1_add (s->moments, value->f, 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:
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:
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:
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:
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:
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:
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:
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:
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:
+ 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,
{
case CTSF_COUNT:
case CTSF_ECOUNT:
+ case CTSF_UCOUNT:
return s->count;
case CTSF_ROWPCT_COUNT:
: 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:
: SYSMIS);
}
+ 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:
+ {
+ 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);
+ }
+
case CTSF_ROWPCT_TOTALN:
case CTSF_COLPCT_TOTALN:
case CTSF_TABLEPCT_TOTALN:
: SYSMIS);
}
- case CTSF_MISSING:
- return s->count;
+ 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:
+ {
+ 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);
+ }
+ case CTSF_MISSING:
+ case CTSF_UMISSING:
case CSTF_TOTALN:
case CTSF_ETOTALN:
- return s->count;
-
+ case CSTF_UTOTALN:
case CTSF_VALIDN:
- return s->count;
-
+ case CTSF_UVALIDN:
case CTSF_EVALIDN:
return s->count;
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);
}
case CTSF_SEMEAN:
+ case CTSF_USEMEAN:
{
double weight, variance;
moments1_calculate (s->moments, &weight, NULL, &variance, NULL, NULL);
}
case CTSF_STDDEV:
+ case CTSF_USTDDEV:
{
double variance;
moments1_calculate (s->moments, NULL, NULL, &variance, NULL, NULL);
}
case CTSF_SUM:
+ case CTSF_USUM:
{
double weight, mean;
moments1_calculate (s->moments, &weight, &mean, NULL, NULL, NULL);
}
case CTSF_VARIANCE:
+ case CTSF_UVARIANCE:
{
double variance;
moments1_calculate (s->moments, NULL, NULL, &variance, NULL, NULL);
case CTSF_LAYERPCT_SUM:
case CTSF_LAYERROWPCT_SUM:
case CTSF_LAYERCOLPCT_SUM:
- NOT_REACHED ();
+ {
+ 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:
+ {
+ 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;
+ }
case CTSF_MEDIAN:
case CTSF_PTILE:
+ case CTSF_UMEDIAN:
+ case CTSF_UPTILE:
if (s->writer)
{
struct casereader *reader = casewriter_make_reader (s->writer);
return s->ovalue;
case CTSF_MODE:
+ case CTSF_UMODE:
if (s->writer)
{
struct casereader *reader = casewriter_make_reader (s->writer);
not_equal: ;
}
+ struct ctables_sum *sums = (s->table->n_sum_vars
+ ? xzalloc (s->table->n_sum_vars * sizeof *sums)
+ : NULL);
+
d = xmalloc (sizeof *d);
- *d = (struct ctables_domain) { .example = cell };
+ *d = (struct ctables_domain) { .example = cell, .sums = sums };
hmap_insert (&s->domains[domain], &d->node, hash);
return d;
}
struct ctables_domain *d = cell->domains[dt];
d->d_total += d_weight;
d->e_total += e_weight;
+ d->u_total += 1.0;
if (!excluded_missing)
{
d->d_count += d_weight;
d->e_count += e_weight;
+ d->u_count += 1.0;
}
if (!is_missing)
{
d->d_valid += d_weight;
d->e_valid += e_weight;
+ d->u_count += 1.0;
+
+ for (size_t i = 0; i < s->table->n_sum_vars; i++)
+ {
+ /* XXX listwise_missing??? */
+ const struct variable *var = s->table->sum_vars[i];
+ double addend = case_num (c, var);
+ if (!var_is_num_missing (var, addend))
+ {
+ struct ctables_sum *sum = &d->sums[i];
+ sum->e_sum += addend * e_weight;
+ sum->u_sum += addend;
+ }
+ }
}
}
}
return as->function > bs->function ? 1 : -1;
else if (as->percentile != bs->percentile)
return as->percentile < bs->percentile ? 1 : -1;
- return strcmp (as->label, bs->label);
+
+ const char *as_label = as->label ? as->label : "";
+ const char *bs_label = bs->label ? bs->label : "";
+ return strcmp (as_label, bs_label);
}
static struct pivot_value *
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
case CTPO_CONSTANT:
return e->number;
- case CTPO_CAT_RANGE:
+ case CTPO_CAT_NRANGE:
+ case CTPO_CAT_SRANGE:
{
struct ctables_cell_value cv = {
.category = ctables_find_category_for_postcompute (ctx->cats, e)
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);
}
d->hide_all_labels = true;
for (size_t i = 0; i < specs->n; i++)
pivot_category_create_leaf (
- d->root, pivot_value_new_text (specs->specs[i].label));
+ d->root, ctables_summary_label (&specs->specs[i], t->cilevel));
}
bool categories_dimension = t->clabels_example != NULL;
for (size_t m = 0; m < specs->n; m++)
{
int leaf = pivot_category_create_leaf (
- parent, pivot_value_new_text (specs->specs[m].label));
+ parent, ctables_summary_label (&specs->specs[m],
+ t->cilevel));
if (!m)
prev_leaf = leaf;
}
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);
}
return true;
}
+static size_t
+add_sum_var (struct variable *var,
+ struct variable ***sum_vars, size_t *n, size_t *allocated)
+{
+ for (size_t i = 0; i < *n; i++)
+ if (var == (*sum_vars)[i])
+ return i;
+
+ if (*n >= *allocated)
+ *sum_vars = x2nrealloc (*sum_vars, allocated, sizeof **sum_vars);
+ (*sum_vars)[*n] = var;
+ return (*n)++;
+}
+
+static void
+enumerate_sum_vars (const struct ctables_axis *a,
+ struct variable ***sum_vars, size_t *n, size_t *allocated)
+{
+ if (!a)
+ return;
+
+ switch (a->op)
+ {
+ case CTAO_VAR:
+ for (size_t i = 0; i < N_CSVS; i++)
+ 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))
+ spec->sum_var_idx = add_sum_var (a->var, sum_vars, n, allocated);
+ }
+ break;
+
+ case CTAO_STACK:
+ case CTAO_NEST:
+ for (size_t i = 0; i < 2; i++)
+ enumerate_sum_vars (a->subs[i], sum_vars, n, allocated);
+ break;
+ }
+}
+
static bool
ctables_prepare_table (struct ctables_table *t)
{
*specs->specs = (struct ctables_summary_spec) {
.function = function,
.format = ctables_summary_default_format (function, specs->var),
- .label = ctables_summary_default_label (function, 0),
};
if (!specs->var)
specs->var = nest->vars[0];
}
struct ctables_summary_spec_set *merged = &t->summary_specs;
- struct merge_item *items = xnmalloc (2 * stack->n, sizeof *items);
+ struct merge_item *items = xnmalloc (N_CSVS * stack->n, sizeof *items);
size_t n_left = 0;
for (size_t j = 0; j < stack->n; j++)
{
}
#endif
+ size_t allocated_sum_vars = 0;
+ enumerate_sum_vars (t->axes[t->summary_axis],
+ &t->sum_vars, &t->n_sum_vars, &allocated_sum_vars);
+
return (ctables_check_label_position (t, PIVOT_AXIS_ROW)
&& ctables_check_label_position (t, PIVOT_AXIS_COLUMN));
}
ss_dealloc (&e->string);
break;
+ case CTPO_CAT_SRANGE:
+ for (size_t i = 0; i < 2; i++)
+ ss_dealloc (&e->srange[i]);
+ break;
+
case CTPO_ADD:
case CTPO_SUB:
case CTPO_MUL:
case CTPO_CONSTANT:
case CTPO_CAT_NUMBER:
- case CTPO_CAT_RANGE:
+ case CTPO_CAT_NRANGE:
case CTPO_CAT_MISSING:
case CTPO_CAT_OTHERNM:
case CTPO_CAT_SUBTOTAL:
};
static const struct operator *
-match_operator (struct lexer *lexer, const struct operator ops[], size_t n_ops)
+ctable_pcexpr_match_operator (struct lexer *lexer,
+ const struct operator ops[], size_t n_ops)
{
for (const struct operator *op = ops; op < ops + n_ops; op++)
if (lex_token (lexer) == op->token)
}
static struct ctables_pcexpr *
-parse_binary_operators__ (struct lexer *lexer, struct dictionary *dict,
- const struct operator ops[], size_t n_ops,
- parse_recursively_func *parse_next_level,
- const char *chain_warning,
- struct ctables_pcexpr *lhs)
+ctable_pcexpr_parse_binary_operators__ (
+ struct lexer *lexer, struct dictionary *dict,
+ const struct operator ops[], size_t n_ops,
+ parse_recursively_func *parse_next_level,
+ const char *chain_warning, struct ctables_pcexpr *lhs)
{
for (int op_count = 0; ; op_count++)
{
- const struct operator *op = match_operator (lexer, ops, n_ops);
+ const struct operator *op
+ = ctable_pcexpr_match_operator (lexer, ops, n_ops);
if (!op)
{
if (op_count > 1 && chain_warning)
}
static struct ctables_pcexpr *
-parse_binary_operators (struct lexer *lexer, struct dictionary *dict,
- const struct operator ops[], size_t n_ops,
- parse_recursively_func *parse_next_level,
- const char *chain_warning)
+ctable_pcexpr_parse_binary_operators (struct lexer *lexer,
+ struct dictionary *dict,
+ const struct operator ops[], size_t n_ops,
+ parse_recursively_func *parse_next_level,
+ const char *chain_warning)
{
struct ctables_pcexpr *lhs = parse_next_level (lexer, dict);
if (!lhs)
return NULL;
- return parse_binary_operators__ (lexer, dict, ops, n_ops, parse_next_level,
- chain_warning, lhs);
+ return ctable_pcexpr_parse_binary_operators__ (lexer, dict, ops, n_ops,
+ parse_next_level,
+ chain_warning, lhs);
}
-static struct ctables_pcexpr *parse_add (struct lexer *, struct dictionary *);
+static struct ctables_pcexpr *ctable_pcexpr_parse_add (struct lexer *,
+ struct dictionary *);
static struct ctables_pcexpr
-ctpo_cat_range (double low, double high)
+ctpo_cat_nrange (double low, double high)
{
return (struct ctables_pcexpr) {
- .op = CTPO_CAT_RANGE,
- .range = { low, high },
+ .op = CTPO_CAT_NRANGE,
+ .nrange = { low, high },
};
}
static struct ctables_pcexpr *
-parse_primary (struct lexer *lexer, struct dictionary *dict)
+ctable_pcexpr_parse_primary (struct lexer *lexer, struct dictionary *dict)
{
int start_ofs = lex_ofs (lexer);
struct ctables_pcexpr e;
{
if (!lex_force_match_id (lexer, "THRU") || lex_force_num (lexer))
return false;
- e = ctpo_cat_range (-DBL_MAX, lex_number (lexer));
+ e = ctpo_cat_nrange (-DBL_MAX, lex_number (lexer));
lex_get (lexer);
}
else if (lex_is_number (lexer))
if (lex_match_id (lexer, "THRU"))
{
if (lex_match_id (lexer, "HI"))
- e = ctpo_cat_range (number, DBL_MAX);
+ e = ctpo_cat_nrange (number, DBL_MAX);
else
{
if (!lex_force_num (lexer))
return false;
- e = ctpo_cat_range (number, lex_number (lexer));
+ e = ctpo_cat_nrange (number, lex_number (lexer));
lex_get (lexer);
}
}
}
else if (lex_match (lexer, T_LPAREN))
{
- struct ctables_pcexpr *ep = parse_add (lexer, dict);
+ struct ctables_pcexpr *ep = ctable_pcexpr_parse_add (lexer, dict);
if (!ep)
return NULL;
if (!lex_force_match (lexer, T_RPAREN))
}
static struct ctables_pcexpr *
-parse_exp (struct lexer *lexer, struct dictionary *dict)
+ctable_pcexpr_parse_exp (struct lexer *lexer, struct dictionary *dict)
{
static const struct operator op = { T_EXP, CTPO_POW };
"To disable this warning, insert parentheses.");
if (lex_token (lexer) != T_NEG_NUM || lex_next_token (lexer, 1) != T_EXP)
- return parse_binary_operators (lexer, dict, &op, 1,
- parse_primary, chain_warning);
+ return ctable_pcexpr_parse_binary_operators (lexer, dict, &op, 1,
+ ctable_pcexpr_parse_primary,
+ chain_warning);
/* Special case for situations like "-5**6", which must be parsed as
-(5**6). */
};
lex_get (lexer);
- struct ctables_pcexpr *node = parse_binary_operators__ (
- lexer, dict, &op, 1, parse_primary, chain_warning, lhs);
+ struct ctables_pcexpr *node = ctable_pcexpr_parse_binary_operators__ (
+ lexer, dict, &op, 1,
+ ctable_pcexpr_parse_primary, chain_warning, lhs);
if (!node)
return NULL;
/* Parses the unary minus level. */
static struct ctables_pcexpr *
-parse_neg (struct lexer *lexer, struct dictionary *dict)
+ctable_pcexpr_parse_neg (struct lexer *lexer, struct dictionary *dict)
{
int start_ofs = lex_ofs (lexer);
if (!lex_match (lexer, T_DASH))
- return parse_exp (lexer, dict);
+ return ctable_pcexpr_parse_exp (lexer, dict);
- struct ctables_pcexpr *inner = parse_neg (lexer, dict);
+ struct ctables_pcexpr *inner = ctable_pcexpr_parse_neg (lexer, dict);
if (!inner)
return NULL;
/* Parses the multiplication and division level. */
static struct ctables_pcexpr *
-parse_mul (struct lexer *lexer, struct dictionary *dict)
+ctable_pcexpr_parse_mul (struct lexer *lexer, struct dictionary *dict)
{
static const struct operator ops[] =
{
{ T_SLASH, CTPO_DIV },
};
- return parse_binary_operators (lexer, dict, ops, sizeof ops / sizeof *ops,
- parse_neg, NULL);
+ return ctable_pcexpr_parse_binary_operators (lexer, dict, ops,
+ sizeof ops / sizeof *ops,
+ ctable_pcexpr_parse_neg, NULL);
}
/* Parses the addition and subtraction level. */
static struct ctables_pcexpr *
-parse_add (struct lexer *lexer, struct dictionary *dict)
+ctable_pcexpr_parse_add (struct lexer *lexer, struct dictionary *dict)
{
static const struct operator ops[] =
{
{ T_NEG_NUM, CTPO_ADD },
};
- return parse_binary_operators (lexer, dict, ops, sizeof ops / sizeof *ops,
- parse_mul, NULL);
+ return ctable_pcexpr_parse_binary_operators (lexer, dict,
+ ops, sizeof ops / sizeof *ops,
+ ctable_pcexpr_parse_mul, NULL);
}
static struct ctables_postcompute *
}
int expr_start = lex_ofs (lexer);
- struct ctables_pcexpr *expr = parse_add (lexer, dict);
+ struct ctables_pcexpr *expr = ctable_pcexpr_parse_add (lexer, dict);
int expr_end = lex_ofs (lexer) - 1;
if (!expr || !lex_force_match (lexer, T_RPAREN))
{
/* 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;