};
-typedef void *stat_create (const struct means *, struct pool *pool);
-
-typedef void stat_update (const struct means *, void *stat, double w, double x);
-
-typedef double stat_get (const struct means *, struct per_var_data *, void *aux);
-
+typedef void *stat_create (struct pool *pool);
+typedef void stat_update (void *stat, double w, double x);
+typedef double stat_get (const struct per_var_data *, void *aux);
struct cell_spec
{
stat_get *sd;
};
-
struct harmonic_mean
{
double rsum;
double n;
};
-
static void *
-harmonic_create (const struct means *means UNUSED, struct pool *pool)
+harmonic_create (struct pool *pool)
{
struct harmonic_mean *hm = pool_alloc (pool, sizeof *hm);
static void
-harmonic_update (const struct means *means UNUSED, void *stat, double w, double x)
+harmonic_update (void *stat, double w, double x)
{
struct harmonic_mean *hm = stat;
hm->rsum += w / x;
static double
-harmonic_get (const struct means *means UNUSED, struct per_var_data *pvd UNUSED, void *stat)
+harmonic_get (const struct per_var_data *pvd UNUSED, void *stat)
{
struct harmonic_mean *hm = stat;
static void *
-geometric_create (const struct means *means UNUSED, struct pool *pool)
+geometric_create (struct pool *pool)
{
struct geometric_mean *gm = pool_alloc (pool, sizeof *gm);
static void
-geometric_update (const struct means *means UNUSED, void *stat, double w, double x)
+geometric_update (void *stat, double w, double x)
{
struct geometric_mean *gm = stat;
gm->prod *= pow (x, w);
static double
-geometric_get (const struct means *means UNUSED, struct per_var_data *pvd UNUSED, void *stat)
+geometric_get (const struct per_var_data *pvd UNUSED, void *stat)
{
struct geometric_mean *gm = stat;
\f
static double
-sum_get (const struct means *means UNUSED, struct per_var_data *pvd, void *stat UNUSED)
+sum_get (const struct per_var_data *pvd, void *stat UNUSED)
{
double n, mean;
static double
-n_get (const struct means *means UNUSED, struct per_var_data *pvd, void *stat UNUSED)
+n_get (const struct per_var_data *pvd, void *stat UNUSED)
{
double n;
}
static double
-arithmean_get (const const struct means *means UNUSED, struct per_var_data *pvd, void *stat UNUSED)
+arithmean_get (const struct per_var_data *pvd, void *stat UNUSED)
{
double n, mean;
}
static double
-variance_get (const const struct means *means UNUSED, struct per_var_data *pvd, void *stat UNUSED)
+variance_get (const struct per_var_data *pvd, void *stat UNUSED)
{
double n, mean, variance;
static double
-stddev_get (const const struct means *means UNUSED, struct per_var_data *pvd, void *stat)
+stddev_get (const struct per_var_data *pvd, void *stat)
{
- return sqrt (variance_get (means, pvd, stat));
+ return sqrt (variance_get (pvd, stat));
}
\f
static double
-skew_get (const const struct means *means UNUSED, struct per_var_data *pvd, void *stat UNUSED)
+skew_get (const struct per_var_data *pvd, void *stat UNUSED)
{
double skew;
}
static double
-sekurt_get (const const struct means *means UNUSED, struct per_var_data *pvd, void *stat UNUSED)
+sekurt_get (const struct per_var_data *pvd, void *stat UNUSED)
{
double n;
return calc_sekurt (n);
}
-
-
static double
-seskew_get (const const struct means *means UNUSED, struct per_var_data *pvd, void *stat UNUSED)
+seskew_get (const struct per_var_data *pvd, void *stat UNUSED)
{
double n;
return calc_seskew (n);
}
-
-
static double
-kurt_get (const const struct means *means UNUSED, struct per_var_data *pvd, void *stat UNUSED)
+kurt_get (const struct per_var_data *pvd, void *stat UNUSED)
{
double kurt;
return kurt;
}
-
static double
-semean_get (const struct means *means UNUSED, struct per_var_data *pvd, void *stat UNUSED)
+semean_get (const struct per_var_data *pvd, void *stat UNUSED)
{
double n, var;
return sqrt (var / n);
}
-
-
\f
static void *
-min_create (const struct means *means UNUSED, struct pool *pool)
+min_create (struct pool *pool)
{
double *r = pool_alloc (pool, sizeof *r);
}
static void
-min_update (const struct means *means UNUSED, void *stat, double w UNUSED, double x)
+min_update (void *stat, double w UNUSED, double x)
{
double *r = stat;
}
static double
-min_get (const const struct means *means UNUSED, struct per_var_data *pvd UNUSED, void *stat)
+min_get (const struct per_var_data *pvd UNUSED, void *stat)
{
double *r = stat;
}
static void *
-max_create (const struct means *means UNUSED, struct pool *pool)
+max_create (struct pool *pool)
{
double *r = pool_alloc (pool, sizeof *r);
}
static void
-max_update (const struct means *means UNUSED, void *stat, double w UNUSED, double x)
+max_update (void *stat, double w UNUSED, double x)
{
double *r = stat;
}
static double
-max_get (const const struct means *means UNUSED, struct per_var_data *pvd UNUSED, void *stat)
+max_get (const struct per_var_data *pvd UNUSED, void *stat)
{
double *r = stat;
};
static void *
-range_create (const struct means *means UNUSED, struct pool *pool)
+range_create (struct pool *pool)
{
struct range *r = pool_alloc (pool, sizeof *r);
}
static void
-range_update (const struct means *means UNUSED, void *stat, double w UNUSED, double x)
+range_update (void *stat, double w UNUSED, double x)
{
struct range *r = stat;
}
static double
-range_get (const const struct means *means UNUSED, struct per_var_data *pvd UNUSED, void *stat)
+range_get (const struct per_var_data *pvd UNUSED, void *stat)
{
struct range *r = stat;
\f
static void *
-last_create (const struct means *means UNUSED, struct pool *pool)
+last_create (struct pool *pool)
{
double *l = pool_alloc (pool, sizeof *l);
}
static void
-last_update (const struct means *means UNUSED, void *stat, double w UNUSED, double x)
+last_update (void *stat, double w UNUSED, double x)
{
double *l = stat;
}
static double
-last_get (const const struct means *means UNUSED, struct per_var_data *pvd UNUSED, void *stat)
+last_get (const struct per_var_data *pvd UNUSED, void *stat)
{
double *l = stat;
static void *
-first_create (const struct means *means UNUSED, struct pool *pool)
+first_create (struct pool *pool)
{
double *f = pool_alloc (pool, sizeof *f);
- *f = SYSMIS;
+ *f = SYSMIS;
return f;
}
static void
-first_update (const struct means *means UNUSED, void *stat, double w UNUSED, double x)
+first_update (void *stat, double w UNUSED, double x)
{
double *f = stat;
}
static double
-first_get (const const struct means *means UNUSED, struct per_var_data *pvd UNUSED, void *stat)
+first_get (const struct per_var_data *pvd UNUSED, void *stat)
{
double *f = stat;
return *f;
}
-
+enum
+ {
+ MEANS_MEAN = 0,
+ MEANS_N,
+ MEANS_STDDEV
+ };
/* Table of cell_specs */
static const struct cell_spec cell_spec[] = {
};
+struct layer
+{
+ size_t n_factor_vars;
+ const struct variable **factor_vars;
+};
+
/* The thing parsed after TABLES= */
struct mtable
{
size_t n_dep_vars;
const struct variable **dep_vars;
- size_t n_interactions;
+ int n_layers;
+ struct layer *layers;
+
struct interaction **interactions;
struct summary *summary;
- size_t *n_factor_vars;
- const struct variable ***factor_vars;
-
int ii;
- int n_layers;
-
struct categoricals *cats;
};
/* Missing value class for dependent variables */
enum mv_class dep_exclude;
+ bool listwise_exclude;
+
/* an array indicating which statistics are to be calculated */
int *cells;
run_means (struct means *cmd, struct casereader *input,
const struct dataset *ds);
-/* Append all the variables belonging to layer and all subsequent layers
- to iact. And then append iact to the means->interaction.
- This is a recursive function.
- */
-static void
-iact_append_factor (struct mtable *means, int layer,
- const struct interaction *iact)
-{
- int v;
- const struct variable **fv;
-
- if (layer >= means->n_layers)
- return;
-
- fv = means->factor_vars[layer];
-
- for (v = 0; v < means->n_factor_vars[layer]; ++v)
- {
- struct interaction *nexti = interaction_clone (iact);
-
- interaction_add_variable (nexti, fv[v]);
- iact_append_factor (means, layer + 1, nexti);
-
- if (layer == means->n_layers - 1)
- {
- means->interactions[means->ii++] = nexti;
- }
- }
-}
static bool
parse_means_table_syntax (struct lexer *lexer, const struct means *cmd, struct mtable *table)
{
table->ii = 0;
table->n_layers = 0;
- table->factor_vars = NULL;
- table->n_factor_vars = NULL;
+ table->layers = NULL;
/* Dependent variable (s) */
- if (!parse_variables_const (lexer, cmd->dict,
+ if (!parse_variables_const_pool (lexer, cmd->pool, cmd->dict,
&table->dep_vars, &table->n_dep_vars,
PV_NO_DUPLICATE | PV_NUMERIC))
return false;
if (lex_match (lexer, T_BY))
{
table->n_layers++;
- table->factor_vars =
- xrealloc (table->factor_vars,
- sizeof (*table->factor_vars) * table->n_layers);
-
- table->n_factor_vars =
- xrealloc (table->n_factor_vars,
- sizeof (*table->n_factor_vars) * table->n_layers);
-
- if (!parse_variables_const (lexer, cmd->dict,
- &table->factor_vars[table->n_layers - 1],
- &table->n_factor_vars[table->n_layers -
- 1],
- PV_NO_DUPLICATE))
+ table->layers =
+ pool_realloc (cmd->pool, table->layers,
+ sizeof (*table->layers) * table->n_layers);
+
+ if (!parse_variables_const_pool
+ (lexer, cmd->pool, cmd->dict,
+ &table->layers[table->n_layers - 1].factor_vars,
+ &table->layers[table->n_layers - 1].n_factor_vars,
+ PV_NO_DUPLICATE))
return false;
}
}
+ /* There is always at least one layer.
+ However the final layer is the total, and not
+ normally considered by the user as a
+ layer.
+ */
+
+ table->n_layers++;
+ table->layers =
+ pool_realloc (cmd->pool, table->layers,
+ sizeof (*table->layers) * table->n_layers);
+ table->layers[table->n_layers - 1].factor_vars = NULL;
+ table->layers[table->n_layers - 1].n_factor_vars = 0;
+
return true;
}
struct means means;
bool more_tables = true;
+ means.pool = pool_create ();
+
means.exclude = MV_ANY;
means.dep_exclude = MV_ANY;
+ means.listwise_exclude = false;
means.table = NULL;
means.n_tables = 0;
means.dict = dataset_dict (ds);
means.n_cells = 3;
- means.cells = xcalloc (means.n_cells, sizeof (*means.cells));
+ means.cells = pool_calloc (means.pool, means.n_cells, sizeof (*means.cells));
/* The first three items (MEAN, COUNT, STDDEV) are the default */
while (more_tables)
{
means.n_tables ++;
- means.table = xrealloc (means.table, means.n_tables * sizeof (*means.table));
+ means.table = pool_realloc (means.pool, means.table, means.n_tables * sizeof (*means.table));
if (! parse_means_table_syntax (lexer, &means,
&means.table[means.n_tables - 1]))
be dropped FOR THAT TABLE ONLY.
*/
{
- means.exclude = MV_ANY;
- means.dep_exclude = MV_ANY;
+ means.listwise_exclude = true;
}
else if (lex_match_id (lexer, "DEPENDENT"))
/*
while (lex_token (lexer) != T_ENDCMD
&& lex_token (lexer) != T_SLASH)
{
- int k;
- for (k = 0; k < n_C; ++k)
+ int k = 0;
+ if (lex_match (lexer, T_ALL))
{
- if (lex_match_id (lexer, cell_spec[k].keyword))
- {
- means.cells =
- xrealloc (means.cells,
- ++means.n_cells * sizeof (*means.cells));
+ int x;
+ means.cells =
+ pool_realloc (means.pool, means.cells,
+ (means.n_cells += n_C) * sizeof (*means.cells));
- means.cells[means.n_cells - 1] = k;
- break;
+ for (x = 0; x < n_C; ++x)
+ means.cells[means.n_cells - (n_C - 1 - x) - 1] = x;
+ }
+ else if (lex_match_id (lexer, "NONE"))
+ {
+ /* Do nothing */
+ }
+ else if (lex_match_id (lexer, "DEFAULT"))
+ {
+ means.cells =
+ pool_realloc (means.pool, means.cells,
+ (means.n_cells += 3) * sizeof (*means.cells));
+
+ means.cells[means.n_cells - 2 - 1] = MEANS_MEAN;
+ means.cells[means.n_cells - 1 - 1] = MEANS_N;
+ means.cells[means.n_cells - 0 - 1] = MEANS_STDDEV;
+ }
+ else
+ {
+ for (; k < n_C; ++k)
+ {
+ if (lex_match_id (lexer, cell_spec[k].keyword))
+ {
+ means.cells =
+ pool_realloc (means.pool, means.cells,
+ ++means.n_cells * sizeof (*means.cells));
+
+ means.cells[means.n_cells - 1] = k;
+ break;
+ }
}
}
if (k >= n_C)
}
}
- means.pool = pool_create ();
for (t = 0; t < means.n_tables; ++t)
{
struct mtable *table = &means.table[t];
- table->n_interactions = 1;
- for (l = 0; l < table->n_layers; ++l)
- {
- const int n_vars = table->n_factor_vars[l];
- table->n_interactions *= n_vars;
- }
table->interactions =
- xcalloc (table->n_interactions, sizeof (*table->interactions));
+ pool_calloc (means.pool, table->n_layers, sizeof (*table->interactions));
table->summary =
- xcalloc (table->n_dep_vars * table->n_interactions, sizeof (*table->summary));
-
-
- if (table->n_layers > 0)
- iact_append_factor (table, 0, interaction_create (NULL));
- else
- table->interactions[0] = interaction_create (NULL);
+ pool_calloc (means.pool, table->n_dep_vars * table->n_layers, sizeof (*table->summary));
+ for (l = 0; l < table->n_layers; ++l)
+ {
+ int v;
+ const struct layer *lyr = &table->layers[l];
+ const int n_vars = lyr->n_factor_vars;
+ table->interactions[l] = interaction_create (NULL);
+ for (v = 0 ; v < n_vars ; ++v)
+ {
+ interaction_add_variable (table->interactions[l],
+ lyr->factor_vars[v]);
+ }
+ }
}
-
{
struct casegrouper *grouper;
struct casereader *group;
}
+ pool_destroy (means.pool);
return CMD_SUCCESS;
error:
+ pool_destroy (means.pool);
return CMD_FAILURE;
}
bool warn;
};
+
+static void
+destroy_n (const void *aux1 UNUSED, void *aux2, void *user_data)
+{
+ struct mtable *table = aux2;
+ int v;
+ struct per_cat_data *per_cat_data = user_data;
+ struct per_var_data *pvd = per_cat_data->pvd;
+
+ for (v = 0; v < table->n_dep_vars; ++v)
+ {
+ struct per_var_data *pp = &pvd[v];
+ moments1_destroy (pp->mom);
+ }
+}
+
static void *
create_n (const void *aux1, void *aux2)
{
int i, v;
const struct means *means = aux1;
struct mtable *table = aux2;
- struct per_cat_data *per_cat_data = xmalloc (sizeof *per_cat_data);
+ struct per_cat_data *per_cat_data = pool_malloc (means->pool, sizeof *per_cat_data);
- struct per_var_data *pvd = xcalloc (table->n_dep_vars, sizeof *pvd);
+ struct per_var_data *pvd = pool_calloc (means->pool, table->n_dep_vars, sizeof *pvd);
for (v = 0; v < table->n_dep_vars; ++v)
{
enum moment maxmom = MOMENT_KURTOSIS;
struct per_var_data *pp = &pvd[v];
- pp->cell_stats = xcalloc (means->n_cells, sizeof *pp->cell_stats);
+ pp->cell_stats = pool_calloc (means->pool, means->n_cells, sizeof *pp->cell_stats);
for (i = 0; i < means->n_cells; ++i)
const struct cell_spec *cs = &cell_spec[csi];
if (cs->sc)
{
- pp->cell_stats[i] = cs->sc (means, means->pool);
+ pp->cell_stats[i] = cs->sc (means->pool);
}
}
pp->mom = moments1_create (maxmom);
}
static void
-update_n (const void *aux1, void *aux2, void *user_data, const struct ccase *c)
+update_n (const void *aux1, void *aux2, void *user_data, const struct ccase *c, double weight)
{
int i;
int v = 0;
struct mtable *table = aux2;
struct per_cat_data *per_cat_data = user_data;
- double weight = dict_get_case_weight (means->dict, c, &per_cat_data->warn);
-
for (v = 0; v < table->n_dep_vars; ++v)
{
struct per_var_data *pvd = &per_cat_data->pvd[v];
const double x = case_data (c, table->dep_vars[v])->f;
- for (i = 0; i < table->n_interactions; ++i)
+ for (i = 0; i < table->n_layers; ++i)
{
- if ( is_missing (means, table->dep_vars[v], table->interactions[i], c))
+ if ( is_missing (means, table->dep_vars[v],
+ table->interactions[i], c))
goto end;
}
if (cs->su)
- cs->su (means,
- pvd->cell_stats[i],
+ cs->su (pvd->cell_stats[i],
weight, x);
}
const struct cell_spec *cs = &cell_spec[csi];
if (cs->su)
- cs->sd (means, pvd, pvd->cell_stats[i]);
+ cs->sd (pvd, pvd->cell_stats[i]);
}
}
}
-
static void
run_means (struct means *cmd, struct casereader *input,
const struct dataset *ds UNUSED)
{
- int i,t;
+ int t;
const struct variable *wv = dict_get_weight (cmd->dict);
struct ccase *c;
struct casereader *reader;
struct payload payload;
payload.create = create_n;
payload.update = update_n;
- payload.destroy = calculate_n;
+ payload.calculate = calculate_n;
+ payload.destroy = destroy_n;
for (t = 0; t < cmd->n_tables; ++t)
{
struct mtable *table = &cmd->table[t];
table->cats
= categoricals_create (table->interactions,
- table->n_interactions, wv, cmd->exclude);
+ table->n_layers, wv, cmd->dep_exclude, cmd->exclude);
categoricals_set_payload (table->cats, &payload, cmd, table);
}
- for (reader = casereader_clone (input);
+ for (reader = input;
(c = casereader_read (reader)) != NULL; case_unref (c))
{
for (t = 0; t < cmd->n_tables; ++t)
{
+ bool something_missing = false;
int v;
struct mtable *table = &cmd->table[t];
for (v = 0; v < table->n_dep_vars; ++v)
{
int i;
- for (i = 0; i < table->n_interactions; ++i)
+ for (i = 0; i < table->n_layers; ++i)
{
const bool missing =
is_missing (cmd, table->dep_vars[v],
table->interactions[i], c);
if (missing)
- table->summary[v * table->n_interactions + i].missing++;
+ {
+ something_missing = true;
+ table->summary[v * table->n_layers + i].missing++;
+ }
else
- table->summary[v * table->n_interactions + i].non_missing++;
+ table->summary[v * table->n_layers + i].non_missing++;
}
}
+ if ( something_missing && cmd->listwise_exclude)
+ continue;
+
categoricals_update (table->cats, c);
}
}
for (t = 0; t < cmd->n_tables; ++t)
{
+ int i;
const struct mtable *table = &cmd->table[t];
output_case_processing_summary (table);
- for (i = 0; i < table->n_interactions; ++i)
+ for (i = 0; i < table->n_layers; ++i)
{
output_report (cmd, i, table);
}
-
categoricals_destroy (table->cats);
}
+
}
+
static void
output_case_processing_summary (const struct mtable *table)
{
const int heading_rows = 3;
struct tab_table *t;
- const int nr = heading_rows + table->n_interactions * table->n_dep_vars;
+ const int nr = heading_rows + table->n_layers * table->n_dep_vars;
const int nc = 7;
t = tab_create (nc, nr);
{
const struct variable *var = table->dep_vars[v];
const char *dv_name = var_to_string (var);
- for (i = 0; i < table->n_interactions; ++i)
+ for (i = 0; i < table->n_layers; ++i)
{
- const int row = v * table->n_interactions + i;
+ const int row = v * table->n_layers + i;
const struct interaction *iact = table->interactions[i];
casenumber n_total;
}
-
static void
output_report (const struct means *cmd, int iact_idx,
const struct mtable *table)
tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, nc - 1, nr - 1);
tab_hline (t, TAL_2, 0, nc - 1, heading_rows);
- tab_vline (t, TAL_2, iact->n_vars, 0, nr - 1);
+ tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
for (i = 0; i < iact->n_vars; ++i)
{
tab_text (t, 0,
heading_rows + dv * n_cats,
TAB_RIGHT | TAT_TITLE,
- var_get_name (table->dep_vars[dv])
+ var_to_string (table->dep_vars[dv])
);
if ( dv > 0)
const int csi = cmd->cells[i];
const struct cell_spec *cs = &cell_spec[csi];
- double result = cs->sd (cmd, pvd, pvd->cell_stats[i]);
+ double result = cs->sd (pvd, pvd->cell_stats[i]);
tab_double (t, heading_columns + i,
heading_rows + grp + dv * n_cats,