case: Introduce new functions for numbers and substrings in cases.
[pspp] / src / math / categoricals.c
index 92bb3d1d3270bfa4878ed2498d72fce799c6c2d6..28d51a9dd704f5bc3a8937b496f05ac0e9cda94c 100644 (file)
@@ -59,6 +59,7 @@ struct variable_node
     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. */
   };
 
 static int
@@ -74,10 +75,11 @@ compare_value_node_3way (const void *vn1_, const void *vn2_, const void *aux)
 }
 
 static struct variable_node *
-lookup_variable (const struct hmap *map, const struct variable *var, unsigned int hash)
+lookup_variable (const struct hmap *map, const struct variable *var)
 {
   struct variable_node *vn;
-  HMAP_FOR_EACH_WITH_HASH (vn, struct variable_node, node, hash, map)
+  HMAP_FOR_EACH_WITH_HASH (vn, struct variable_node, node,
+                           hash_pointer (var, 0), map)
     if (vn->var == var)
       return vn;
   return NULL;
@@ -274,6 +276,7 @@ categoricals_destroy (struct categoricals *cat)
       free (cat->iap[i].enc_sum);
       hmap_destroy (&cat->iap[i].ivmap);
     }
+  free (cat->iap);
 
   /* Interate over each variable and delete its value map.
 
@@ -339,14 +342,14 @@ categoricals_create (struct interaction *const *inter, size_t n_inter,
       for (size_t 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);
+          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);
+              hmap_insert (&cat->varmap, &vn->node, hash_pointer (var, 0));
             }
           iap->varnodes[v] = vn;
         }
@@ -364,7 +367,7 @@ categoricals_update (struct categoricals *cat, const struct ccase *c)
   assert (!cat->cat_to_iact);
 
   double weight;
-  weight = cat->wv ? case_data (c, cat->wv)->f : 1.0;
+  weight = cat->wv ? case_num (c, cat->wv) : 1.0;
   weight = var_force_valid_weight (cat->wv, weight, NULL);
 
   /* Update the frequency table for each variable. */
@@ -380,7 +383,7 @@ categoricals_update (struct categoricals *cat, const struct ccase *c)
         {
           valn = pool_malloc (cat->pool, sizeof *valn);
           valn->index = -1;
-          value_init (&valn->val, width);
+          value_init_pool (cat->pool, &valn->val, width);
           value_copy (&valn->val, val, width);
           hmap_insert (&vn->valmap, &valn->node, hash);
         }
@@ -477,7 +480,7 @@ categoricals_done (const struct categoricals *cat_)
           return;
         }
 
-      struct value_node **nodes = xcalloc (sizeof *nodes, n_vals);
+      struct value_node **nodes = XCALLOC (n_vals,  struct value_node *);
       int x = 0;
       struct value_node *valnd;
       HMAP_FOR_EACH (valnd, struct value_node, node, &vn->valmap)
@@ -577,6 +580,23 @@ categoricals_done (const struct categoricals *cat_)
   cat->sane = true;
 }
 
+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);
+
+      struct value_node *valnd;
+      HMAP_FOR_EACH (valnd, struct value_node, node, &vn->valmap)
+        vn->values[valnd->index] = valnd->val;
+    }
+  return vn->values;
+}
+
 static struct interact_params *
 df_to_iap (const struct categoricals *cat, int subscript)
 {
@@ -704,6 +724,21 @@ categoricals_get_user_data_by_category_real (const struct categoricals *cat,
   return n < hmap_count (&iap->ivmap) ? iap->ivs[n]->user_data : NULL;
 }
 
+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;
+}
+
 /* Return a case containing the set of values corresponding to CAT_INDEX. */
 const struct ccase *
 categoricals_get_case_by_category (const struct categoricals *cat,