CTABLES
[pspp] / src / math / levene.c
index fe04d294e1acfbf214dadea6a53717ccc9a37646..a005c9436091ecd58b992b936be5e74312a405bd 100644 (file)
@@ -22,6 +22,7 @@
 #include "libpspp/misc.h"
 #include "libpspp/hmap.h"
 #include "data/value.h"
+#include "data/val-type.h"
 
 #include <gl/xalloc.h>
 #include <assert.h>
@@ -44,7 +45,7 @@ struct levene
   /* Width of the categorical variable */
   int gvw ;
 
-  /* The value deviding the the groups. Valid only for dichotomous categorical variable.*/
+  /* The value dividing the groups. Valid only for dichotomous categorical variable.*/
   const union value *cutpoint;
 
 
@@ -92,10 +93,10 @@ cutpoint_cmp (const struct levene *nl, const union value *val0, const union valu
 
   int y = value_compare_3way (val1, nl->cutpoint, nl->gvw);
 
-  if ( x == 0) x = 1;
-  if ( y == 0) y = 1;
+  if (x == 0) x = 1;
+  if (y == 0) y = 1;
 
-  return ( x == y);
+  return (x == y);
 }
 
 
@@ -109,7 +110,6 @@ find_group (const struct levene *nl, const union value *target)
     {
       if (nl->cmp (nl, &l->group, target))
        break;
-      l = NULL;
     }
   return l;
 }
@@ -118,7 +118,7 @@ find_group (const struct levene *nl, const union value *target)
 struct levene *
 levene_create (int indep_width, const union value *cutpoint)
 {
-  struct levene *nl = xzalloc (sizeof *nl);
+  struct levene *nl = XZALLOC (struct levene);
 
   hmap_init (&nl->hmap);
 
@@ -133,20 +133,20 @@ levene_create (int indep_width, const union value *cutpoint)
 
 
 /* Data accumulation. First pass */
-void 
+void
 levene_pass_one (struct levene *nl, double value, double weight, const union value *gv)
 {
   struct lev *lev = find_group (nl, gv);
 
-  if ( nl->pass == 0 ) 
+  if (nl->pass == 0)
     {
       nl->pass = 1;
     }
   assert (nl->pass == 1);
 
-  if ( NULL == lev)
+  if (NULL == lev)
     {
-      struct lev *l = xzalloc (sizeof *l);
+      struct lev *l = XZALLOC (struct lev);
       value_clone (&l->group, gv, nl->gvw);
       hmap_insert (&nl->hmap, &l->node, nl->hash (nl, &l->group));
       lev = l;
@@ -159,12 +159,12 @@ levene_pass_one (struct levene *nl, double value, double weight, const union val
 }
 
 /* Data accumulation. Second pass */
-void 
+void
 levene_pass_two (struct levene *nl, double value, double weight, const union value *gv)
 {
   struct lev *lev = NULL;
 
-  if ( nl->pass == 1 )
+  if (nl->pass == 1)
     {
       struct lev *next;
       struct lev *l;
@@ -185,13 +185,13 @@ levene_pass_two (struct levene *nl, double value, double weight, const union val
 }
 
 /* Data accumulation. Third pass */
-void 
+void
 levene_pass_three (struct levene *nl, double value, double weight, const union value *gv)
 {
   double z;
   struct lev *lev = NULL;
 
-  if ( nl->pass == 2 )
+  if (nl->pass == 2)
     {
       struct lev *next;
       struct lev *l;
@@ -223,12 +223,16 @@ levene_calculate (struct levene *nl)
 
   double numerator = 0.0;
   double nn = 0.0;
-  if ( nl->pass == 3 )
-    {
-      nl->pass = 4;
-    }
 
-  assert (nl->pass == 4);
+  /* The Levene calculation requires three passes.
+     Normally this should have been done prior to calling this function.
+     However, in abnormal circumstances (eg. the dataset is empty) there
+     will have been no passes.
+   */
+  assert (nl->pass == 0 || nl->pass == 3);
+
+  if (nl->pass == 0)
+    return SYSMIS;
 
   nl->denominator *= hmap_count (&nl->hmap) - 1;
 
@@ -239,7 +243,7 @@ levene_calculate (struct levene *nl)
     }
 
   numerator *= nn - hmap_count (&nl->hmap);
-    
+
   return numerator / nl->denominator;
 }