#include "language/lexer/format-parser.h"
#include "language/lexer/lexer.h"
#include "language/lexer/variable-parser.h"
-#include "language/stats/freq.h"
#include "libpspp/array.h"
#include "libpspp/assertion.h"
#include "libpspp/hmap.h"
enum ctables_vlabel
{
- CTVL_DEFAULT = SETTINGS_VALUE_SHOW_DEFAULT,
+ CTVL_NONE = SETTINGS_VALUE_SHOW_DEFAULT,
CTVL_NAME = SETTINGS_VALUE_SHOW_VALUE,
CTVL_LABEL = SETTINGS_VALUE_SHOW_LABEL,
CTVL_BOTH = SETTINGS_VALUE_SHOW_BOTH,
- CTVL_NONE,
};
-static void UNUSED
-ctables_vlabel_unique (enum ctables_vlabel vlabel)
-{
- /* This ensures that all of the values are unique. */
- switch (vlabel)
- {
- case CTVL_DEFAULT:
- case CTVL_NAME:
- case CTVL_LABEL:
- case CTVL_BOTH:
- case CTVL_NONE:
- abort ();
- }
-}
/* XXX:
- unweighted summaries (U*)
NOT_REACHED ();
}
+struct ctables_freq
+ {
+ struct hmap_node node; /* Element in hash table. */
+ double count;
+ union value values[]; /* The value. */
+ };
+
+static struct ctables_freq *
+ctables_freq_allocate (size_t n_values)
+{
+ struct ctables_freq *f;
+ return xmalloc (sizeof *f + n_values * sizeof *f->values);
+}
+
struct ctables_freqtab
{
struct var_array vars;
- struct hmap data; /* Contains "struct freq"s. */
- struct freq **sorted;
+ struct hmap data; /* Contains "struct ctables_freq"s. */
+ struct ctables_freq **sorted;
};
static int
-compare_freq_3way (const void *a_, const void *b_, const void *vars_)
+ctables_freq_compare_3way (const void *a_, const void *b_, const void *vars_)
{
const struct var_array *vars = vars_;
- struct freq *const *a = a_;
- struct freq *const *b = b_;
+ struct ctables_freq *const *a = a_;
+ struct ctables_freq *const *b = b_;
for (size_t i = 0; i < vars->n; i++)
{
if (cmp)
return cmp;
}
-
return 0;
}
hash = value_hash (case_data (c, var), var_get_width (var), hash);
}
- struct freq *f;
- HMAP_FOR_EACH_WITH_HASH (f, struct freq, node, hash, &ft->data)
+ struct ctables_freq *f;
+ HMAP_FOR_EACH_WITH_HASH (f, struct ctables_freq, node, hash, &ft->data)
{
for (size_t k = 0; k < ft->vars.n; k++)
{
next_hash_node: ;
}
- f = xmalloc (table_entry_size (ft->vars.n));
+ f = ctables_freq_allocate (ft->vars.n);
f->count = weight;
for (size_t k = 0; k < ft->vars.n; k++)
{
struct ctables_freqtab *ft = t->fts[j];
ft->sorted = xnmalloc (ft->data.count, sizeof *ft->sorted);
- struct freq *f;
+ struct ctables_freq *f;
size_t n = 0;
- HMAP_FOR_EACH (f, struct freq, node, &ft->data)
+ HMAP_FOR_EACH (f, struct ctables_freq, node, &ft->data)
ft->sorted[n++] = f;
assert (n == ft->data.count);
sort (ft->sorted, n, sizeof *ft->sorted,
- compare_freq_3way, &ft->vars);
+ ctables_freq_compare_3way, &ft->vars);
struct pivot_category **groups = xnmalloc (ft->vars.n,
sizeof *groups);
for (size_t k = 0; k < n; k++)
{
- struct freq *prev = k > 0 ? ft->sorted[k - 1] : NULL;
- struct freq *f = ft->sorted[k];
+ struct ctables_freq *prev = k > 0 ? ft->sorted[k - 1] : NULL;
+ struct ctables_freq *f = ft->sorted[k];
size_t n_common = 0;
if (prev)
var_get_type (ft->vars.vars[n_common])))
break;
- for (size_t m = n_common; m + 1 < ft->vars.n; m++)
- groups[m] = pivot_category_create_group__ (
- m > 0 ? groups[m - 1] : d->root,
- pivot_value_new_var_value (ft->vars.vars[m], &f->values[m]));
+ for (size_t m = n_common; m < ft->vars.n; m++)
+ {
+ struct pivot_category *parent = m > 0 ? groups[m - 1] : d->root;
+ const struct variable *var = ft->vars.vars[m];
+ enum ctables_vlabel vlabel = ct->vlabels[var_get_dict_index (var)];
+
+ if (vlabel != CTVL_NONE)
+ parent = pivot_category_create_group__ (
+ parent, pivot_value_new_variable (ft->vars.vars[m]));
- int leaf = pivot_category_create_leaf (
- ft->vars.n > 1 ? groups[ft->vars.n - 2] : d->root,
- pivot_value_new_var_value (ft->vars.vars[ft->vars.n - 1],
- &f->values[ft->vars.n - 1]));
+ if (m + 1 < ft->vars.n)
+ parent = pivot_category_create_group__ (
+ parent,
+ pivot_value_new_var_value (ft->vars.vars[m], &f->values[m]));
+ groups[m] = parent;
- pivot_table_put1 (pt, leaf, pivot_value_new_number (f->count));
+ if (m == ft->vars.n - 1)
+ {
+ int leaf = pivot_category_create_leaf (
+ parent,
+ pivot_value_new_var_value (ft->vars.vars[ft->vars.n - 1],
+ &f->values[ft->vars.n - 1]));
+ pivot_table_put1 (pt, leaf, pivot_value_new_number (f->count));
+ }
+ }
}
free (groups);
}
for (size_t j = 0; j < t->n_fts; j++)
{
struct ctables_freqtab *ft = t->fts[j];
- struct freq *f, *next;
- HMAP_FOR_EACH_SAFE (f, next, struct freq, node, &ft->data)
+ struct ctables_freq *f, *next;
+ HMAP_FOR_EACH_SAFE (f, next, struct ctables_freq, node, &ft->data)
{
hmap_delete (&ft->data, &f->node);
for (size_t k = 0; k < ft->vars.n; k++)
{
size_t n_vars = dict_get_n_vars (dataset_dict (ds));
enum ctables_vlabel *vlabels = xnmalloc (n_vars, sizeof *vlabels);
+ enum settings_value_show tvars = settings_get_show_variables ();
for (size_t i = 0; i < n_vars; i++)
- vlabels[i] = CTVL_DEFAULT;
+ vlabels[i] = (enum ctables_vlabel) tvars;
struct ctables *ct = xmalloc (sizeof *ct);
*ct = (struct ctables) {
enum ctables_vlabel vlabel;
if (lex_match_id (lexer, "DEFAULT"))
- vlabel = CTVL_DEFAULT;
+ vlabel = (enum ctables_vlabel) settings_get_show_variables ();
else if (lex_match_id (lexer, "NAME"))
vlabel = CTVL_NAME;
else if (lex_match_id (lexer, "LABEL"))