ONEWAY: Fixed crash when the dependent variable contained only missing values.
[pspp-builds.git] / src / math / categoricals.c
index 88d0d5c238e87c8746f90fb9d2ef7acc9409d9c0..d8606031c943b0925a1edc953e454693a9d8de8c 100644 (file)
@@ -264,6 +264,9 @@ categoricals_destroy (struct categoricals *cat)
        {
          case_unref (iv->ccase);
        }
+
+      free (cat->iap[i].enc_sum);
+      free (cat->iap[i].df_prod);
       hmap_destroy (&cat->iap[i].ivmap);
     }
 
@@ -437,7 +440,8 @@ categoricals_df (const struct categoricals *cat, size_t n)
 size_t
 categoricals_n_total (const struct categoricals *cat)
 {
-  assert (cat->reverse_variable_map_long);
+  if (!categoricals_is_complete (cat))
+    return 0;
 
   return cat->n_cats_total;
 }
@@ -448,9 +452,16 @@ categoricals_df_total (const struct categoricals *cat)
   return cat->df_sum;
 }
 
+bool
+categoricals_is_complete (const struct categoricals *cat)
+{
+  return (NULL != cat->reverse_variable_map_short);
+}
+
+
 /* This function must be called *before* any call to categoricals_get_*_by subscript and
  *after* all calls to categoricals_update */
-void
+bool
 categoricals_done (const struct categoricals *cat_)
 {
   /* Implementation Note: Whilst this function is O(n) in cat->n_cats_total, in most
@@ -483,6 +494,9 @@ categoricals_done (const struct categoricals *cat_)
 
          struct variable_node *vn = lookup_variable (&cat->varmap, var, hash_pointer (var, 0));
 
+         if  (hmap_count (&vn->valmap) == 0)
+           return false;
+
          cat->iap[i].df_prod[v] = df * (hmap_count (&vn->valmap) - 1);
          df = cat->iap[i].df_prod[v];
 
@@ -558,11 +572,13 @@ categoricals_done (const struct categoricals *cat_)
          struct interaction_value *iv = iap->reverse_interaction_value_map[y];
          for (x = iap->base_subscript_short; x < iap->base_subscript_short + df ;++x)
            {
-             const double bin = categoricals_get_binary_by_subscript (cat, x, iv->ccase); \
+             const double bin = categoricals_get_code_for_case (cat, x, iv->ccase); \
              iap->enc_sum [x - iap->base_subscript_short] += bin * iv->cc;
            }
        }
     }
+
+  return true;
 }
 
 
@@ -596,21 +612,6 @@ categoricals_get_interaction_by_subscript (const struct categoricals *cat, int s
   return cat->iap[index].iact;
 }
 
-/* Return the case corresponding to SUBSCRIPT */
-static const struct ccase *
-categoricals_get_case_by_subscript (const struct categoricals *cat, int subscript)
-{
-  int vindex = reverse_variable_lookup_short (cat, subscript);
-  const struct interact_params *vp = &cat->iap[vindex];
-  const struct interaction_value *vn = vp->reverse_interaction_value_map [subscript - vp->base_subscript_short];
-
-  if ( vn == NULL)
-    return NULL;
-
-  return vn->ccase;
-}
-
-
 double
 categoricals_get_weight_by_subscript (const struct categoricals *cat, int subscript)
 {
@@ -632,8 +633,7 @@ categoricals_get_sum_by_subscript (const struct categoricals *cat, int subscript
 /* Returns unity if the value in case C at SUBSCRIPT is equal to the category
    for that subscript */
 double
-categoricals_get_binary_by_subscript (const struct categoricals *cat,
-                                     int subscript,
+categoricals_get_code_for_case (const struct categoricals *cat, int subscript,
                                      const struct ccase *c)
 {
   const struct interaction *iact = categoricals_get_interaction_by_subscript (cat, subscript);