-{
- struct hmap_node node; /* Node in hash map. */
- const struct variable *var; /* The variable */
+ {
+ struct hmap_node node; /* In struct categorical's 'varmap'. */
+ const struct variable *var; /* The variable. */
+ struct hmap valmap; /* Contains "struct value_node"s. */
+ union value *values; /* Values in valmap, as a sorted array. */
+ };
- struct variable_node *vn = NULL;
- HMAP_FOR_EACH_WITH_HASH (vn, struct variable_node, node, hash, map)
- {
- if (vn->var == var)
- break;
- }
-
- return vn;
+ struct variable_node *vn;
+ HMAP_FOR_EACH_WITH_HASH (vn, struct variable_node, node,
+ hash_pointer (var, 0), map)
+ if (vn->var == var)
+ return vn;
+ return NULL;
- {
- int v;
- struct string str;
- const struct interact_params *iap = &cat->iap[i];
- const struct interaction *iact = iap->iact;
-
- ds_init_empty (&str);
- interaction_to_string (iact, &str);
-
- printf ("\nInteraction: \"%s\" (number of categories: %d); ", ds_cstr (&str), iap->n_cats);
- ds_destroy (&str);
- printf ("Base index (df/categories): %d/%d\n", iap->base_df, iap->base_cats);
-
- printf ("\t(");
- for (v = 0; v < hmap_count (&iap->ivmap); ++v)
- {
- int vv;
- const struct interaction_value *iv = iap->ivs[v];
-
- if (v > 0) printf (" ");
- printf ("{");
- for (vv = 0; vv < iact->n_vars; ++vv)
- {
- const struct variable *var = iact->vars[vv];
- const union value *val = case_data (iv->ccase, var);
- struct variable_node *vn = iap->varnodes[vv];
-
- const int width = var_get_width (var);
- unsigned int valhash = value_hash (val, width, 0);
- struct value_node *valn = lookup_value (&vn->valmap, val, valhash, width);
-
- assert (vn->var == var);
-
- printf ("%.*g(%d)", DBL_DIG + 1, val->f, valn->index);
- if (vv < iact->n_vars - 1)
- printf (", ");
- }
- printf ("}");
- }
- printf (")\n");
- }
+ {
+ int v;
+ struct string str;
+ const struct interact_params *iap = &cat->iap[i];
+ const struct interaction *iact = iap->iact;
+
+ ds_init_empty (&str);
+ interaction_to_string (iact, &str);
+
+ printf ("\nInteraction: \"%s\" (number of categories: %d); ", ds_cstr (&str), iap->n_cats);
+ ds_destroy (&str);
+ printf ("Base index (df/categories): %d/%d\n", iap->base_df, iap->base_cats);
+
+ printf ("\t(");
+ for (v = 0; v < hmap_count (&iap->ivmap); ++v)
+ {
+ int vv;
+ const struct interaction_value *iv = iap->ivs[v];
+
+ if (v > 0) printf (" ");
+ printf ("{");
+ for (vv = 0; vv < iact->n_vars; ++vv)
+ {
+ const struct variable *var = iact->vars[vv];
+ const union value *val = case_data (iv->ccase, var);
+ struct variable_node *vn = iap->varnodes[vv];
+ const int width = var_get_width (var);
+ unsigned int valhash = value_hash (val, width, 0);
+ struct value_node *valn = lookup_value (&vn->valmap, val, valhash, width);
+
+ assert (vn->var == var);
+
+ printf ("%.*g(%d)", DBL_DIG + 1, val->f, valn->index);
+ if (vv < iact->n_vars - 1)
+ printf (", ");
+ }
+ printf ("}");
+ }
+ printf (")\n");
+ }
- {
- if (cat->payload && cat->payload->destroy)
- cat->payload->destroy (cat->aux1, cat->aux2, iv->user_data);
- case_unref (iv->ccase);
- }
+ {
+ if (cat->payload && cat->payload->destroy)
+ cat->payload->destroy (cat->aux1, cat->aux2, iv->user_data);
+ case_unref (iv->ccase);
+ }
-categoricals_create (struct interaction *const*inter, size_t n_inter,
- const struct variable *wv, enum mv_class fctr_excl)
+categoricals_create (struct interaction *const *inter, size_t n_inter,
+ const struct variable *wv, enum mv_class fctr_excl)
- int v;
- hmap_init (&cat->iap[i].ivmap);
- cat->iap[i].iact = inter[i];
- cat->iap[i].cc = 0.0;
- cat->iap[i].varnodes = pool_nmalloc (cat->pool, cat->iap[i].iact->n_vars,
- sizeof *cat->iap[i].varnodes);
- for (v = 0; v < inter[i]->n_vars; ++v)
- {
- const struct variable *var = inter[i]->vars[v];
- unsigned int hash = hash_pointer (var, 0);
- struct variable_node *vn = lookup_variable (&cat->varmap, var, hash);
- if (vn == NULL)
- {
- vn = pool_malloc (cat->pool, sizeof *vn);
- vn->var = var;
- vn->n_vals = 0;
- hmap_init (&vn->valmap);
-
- hmap_insert (&cat->varmap, &vn->node, hash);
- }
- cat->iap[i].varnodes[v] = vn;
- }
+ struct interact_params *iap = &cat->iap[i];
+ hmap_init (&iap->ivmap);
+ iap->iact = inter[i];
+ iap->cc = 0.0;
+ iap->varnodes = pool_nmalloc (cat->pool, iap->iact->n_vars,
+ sizeof *iap->varnodes);
+ for (size_t v = 0; v < inter[i]->n_vars; ++v)
+ {
+ const struct variable *var = inter[i]->vars[v];
+ struct variable_node *vn = lookup_variable (&cat->varmap, var);
+ if (!vn)
+ {
+ vn = pool_malloc (cat->pool, sizeof *vn);
+ vn->var = var;
+ vn->values = NULL;
+ hmap_init (&vn->valmap);
+ hmap_insert (&cat->varmap, &vn->node, hash_pointer (var, 0));
+ }
+ iap->varnodes[v] = vn;
+ }
weight = cat->wv ? case_data (c, cat->wv)->f : 1.0;
weight = var_force_valid_weight (cat->wv, weight, NULL);
weight = cat->wv ? case_data (c, cat->wv)->f : 1.0;
weight = var_force_valid_weight (cat->wv, weight, NULL);
- assert (NULL == cat->df_to_iact);
- assert (NULL == cat->cat_to_iact);
-
- /* Interate over each variable, and add the value of that variable
- to the appropriate map, if it's not already present. */
+ /* Update the frequency table for each variable. */
+ struct variable_node *vn;
HMAP_FOR_EACH (vn, struct variable_node, node, &cat->varmap)
{
const int width = var_get_width (vn->var);
HMAP_FOR_EACH (vn, struct variable_node, node, &cat->varmap)
{
const int width = var_get_width (vn->var);
- {
- valn = pool_malloc (cat->pool, sizeof *valn);
- valn->index = -1;
- vn->n_vals++;
- value_init (&valn->val, width);
- value_copy (&valn->val, val, width);
- hmap_insert (&vn->valmap, &valn->node, hash);
- }
+ {
+ valn = pool_malloc (cat->pool, sizeof *valn);
+ valn->index = -1;
+ value_init_pool (cat->pool, &valn->val, width);
+ value_copy (&valn->val, val, width);
+ hmap_insert (&vn->valmap, &valn->node, hash);
+ }
- const struct interaction *iact = cat->iap[i].iact;
-
- size_t hash;
- struct interaction_value *node;
-
- if ( interaction_case_is_missing (iact, c, cat->fctr_excl))
- continue;
-
- hash = interaction_case_hash (iact, c, 0);
- node = lookup_case (&cat->iap[i].ivmap, iact, c);
+ struct interact_params *iap = &cat->iap[i];
+ const struct interaction *iact = iap->iact;
+ if (interaction_case_is_missing (iact, c, cat->fctr_excl))
+ continue;
- if ( NULL == node)
- {
- node = pool_malloc (cat->pool, sizeof *node);
- node->ccase = case_ref (c);
- node->cc = weight;
+ unsigned int hash = interaction_case_hash (iact, c, 0);
+ struct interaction_value *node = lookup_case (&iap->ivmap, iact, c);
+ if (!node)
+ {
+ node = pool_malloc (cat->pool, sizeof *node);
+ node->ccase = case_ref (c);
+ node->cc = weight;
/* This function must be called (once) before any call to the *_by_subscript or
*_by_category functions, but AFTER any calls to categoricals_update. If this
function returns false, then no calls to _by_subscript or *_by_category are
/* This function must be called (once) before any call to the *_by_subscript or
*_by_category functions, but AFTER any calls to categoricals_update. If this
function returns false, then no calls to _by_subscript or *_by_category are
/* Assign 'index' to each variables' value_nodes, counting up from 0 in
ascending order by value. */
struct variable_node *vn;
/* Assign 'index' to each variables' value_nodes, counting up from 0 in
ascending order by value. */
struct variable_node *vn;
- int df = 1;
- const struct interaction *iact = cat->iap[i].iact;
-
- cat->iap[i].df_prod = iact->n_vars ? xcalloc (iact->n_vars, sizeof (int)) : NULL;
-
- cat->iap[i].n_cats = 1;
-
- for (v = 0 ; v < iact->n_vars; ++v)
- {
- struct variable_node *vn = cat->iap[i].varnodes[v];
- cat->iap[i].df_prod[v] = df * (vn->n_vals - 1);
- df = cat->iap[i].df_prod[v];
+ struct interact_params *iap = &cat->iap[i];
+ const struct interaction *iact = iap->iact;
sort (iap->ivs, x, sizeof *iap->ivs,
compare_interaction_value_3way, iap);
sort (iap->ivs, x, sizeof *iap->ivs,
compare_interaction_value_3way, iap);
- const int df = iap->df_prod ? iap->df_prod [iact->n_vars - 1] : 0;
-
- iap->enc_sum = xcalloc (df, sizeof (*(iap->enc_sum)));
-
- for (y = 0; y < hmap_count (&iap->ivmap); ++y)
- {
- struct interaction_value *iv = iap->ivs[y];
- for (x = iap->base_df; x < iap->base_df + df ;++x)
- {
- const double bin = categoricals_get_effects_code_for_case (cat, x, iv->ccase);
- iap->enc_sum [x - iap->base_df] += bin * iv->cc;
- }
- if (cat->payload && cat->payload->calculate)
- cat->payload->calculate (cat->aux1, cat->aux2, iv->user_data);
- }
+ const int df = iact->n_vars ? iap->df_prod : 0;
+
+ iap->enc_sum = xcalloc (df, sizeof *iap->enc_sum);
+
+ for (int y = 0; y < hmap_count (&iap->ivmap); ++y)
+ {
+ struct interaction_value *iv = iap->ivs[y];
+ for (int x = iap->base_df;
+ x < iap->base_df + df; ++x)
+ {
+ const double bin = categoricals_get_effects_code_for_case (
+ cat, x, iv->ccase);
+ iap->enc_sum[x - iap->base_df] += bin * iv->cc;
+ }
+ if (cat->payload && cat->payload->calculate)
+ cat->payload->calculate (cat->aux1, cat->aux2, iv->user_data);
+ }
+union value *
+categoricals_get_var_values (const struct categoricals *cat,
+ const struct variable *var, size_t *np)
+{
+ struct variable_node *vn = lookup_variable (&cat->varmap, var);
+ *np = hmap_count (&vn->valmap);
+ if (!vn->values)
+ {
+ vn->values = pool_nalloc (cat->pool, *np, sizeof *vn->values);
{
const struct variable *var = iact->vars[v];
const union value *val = case_data (c, var);
const int width = var_get_width (var);
{
const struct variable *var = iact->vars[v];
const union value *val = case_data (c, var);
const int width = var_get_width (var);
- /* Translate the subscript into an index for the individual variable */
- const int index = ((subscript - base_index) % iap->df_prod[v] ) / dfp;
- dfp = iap->df_prod [v];
-
- if (effects_coding && valn->index == df )
- bin = -1.0;
- else if ( valn->index != index )
- bin = 0;
-
- result *= bin;
+ if (effects_coding && valn->index == df)
+ result = -result;
+ else
+ {
+ /* Translate subscript into an index for the individual variable. */
+ const int index = ((subscript - iap->base_df) % dfpn) / dfp;
+ if (valn->index != index)
+ return 0.0;
+ }
+ dfp = dfpn;
+int
+categoricals_get_value_index_by_category_real (const struct categoricals *cat,
+ int iact_idx, int cat_idx,
+ int var_idx)
+{
+ const struct interact_params *iap = &cat->iap[iact_idx];
+ const struct interaction_value *ivn = iap->ivs[cat_idx];
+ const struct variable *var = iap->iact->vars[var_idx];
+ const struct variable_node *vn = iap->varnodes[var_idx];
+ const union value *val = case_data (ivn->ccase, var);
+ int width = var_get_width (var);
+ unsigned int hash = value_hash (val, width, 0);
+ return lookup_value (&vn->valmap, val, hash, width)->index;
+}