Change how checking for missing values works.
[pspp] / src / language / stats / quick-cluster.c
index 23f67b00b0d6cf5df21c870a51ca8d4008e68251..9dd07f591b33bdef5635ec62e408d809c98a12db 100644 (file)
@@ -247,7 +247,7 @@ dist_from_case (const struct Kmeans *kmeans, const struct ccase *c,
   for (j = 0; j < qc->n_vars; j++)
     {
       const union value *val = case_data (c, qc->vars[j]);
-      if (var_is_value_missing (qc->vars[j], val, qc->exclude))
+      if (var_is_value_missing (qc->vars[j], val) & qc->exclude)
        NOT_REACHED ();
 
       dist += pow2 (gsl_matrix_get (kmeans->centers, which, j) - val->f);
@@ -302,7 +302,7 @@ kmeans_initial_centers (struct Kmeans *kmeans,
       for (j = 0; j < qc->n_vars; ++j)
        {
          const union value *val = case_data (c, qc->vars[j]);
-         if (var_is_value_missing (qc->vars[j], val, qc->exclude))
+         if (var_is_value_missing (qc->vars[j], val) & qc->exclude)
            {
              missing = true;
              break;
@@ -385,7 +385,7 @@ kmeans_get_nearest_group (const struct Kmeans *kmeans, struct ccase *c,
       for (j = 0; j < qc->n_vars; j++)
        {
          const union value *val = case_data (c, qc->vars[j]);
-         if (var_is_value_missing (qc->vars[j], val, qc->exclude))
+         if (var_is_value_missing (qc->vars[j], val) & qc->exclude)
            continue;
 
          dist += pow2 (gsl_matrix_get (kmeans->centers, i, j) - val->f);
@@ -462,7 +462,7 @@ kmeans_cluster (struct Kmeans *kmeans, struct casereader *reader,
              for (j = 0; j < qc->n_vars; j++)
                {
                  const union value *val = case_data (c, qc->vars[j]);
-                 if (var_is_value_missing (qc->vars[j], val, qc->exclude))
+                 if (var_is_value_missing (qc->vars[j], val) & qc->exclude)
                    missing = true;
                }
 
@@ -482,16 +482,16 @@ kmeans_cluster (struct Kmeans *kmeans, struct casereader *reader,
                }
 
              long *n = gsl_vector_long_ptr (kmeans->num_elements_groups, group);
-             *n += qc->wv ? case_data (c, qc->wv)->f : 1.0;
+             *n += qc->wv ? case_num (c, qc->wv) : 1.0;
              kmeans->n++;
 
              for (j = 0; j < qc->n_vars; ++j)
                {
                  const union value *val = case_data (c, qc->vars[j]);
-                 if (var_is_value_missing (qc->vars[j], val, qc->exclude))
+                 if (var_is_value_missing (qc->vars[j], val) & qc->exclude)
                    continue;
                  double *x = gsl_matrix_ptr (kmeans->updated_centers, group, j);
-                 *x += val->f * (qc->wv ? case_data (c, qc->wv)->f : 1.0);
+                 *x += val->f * (qc->wv ? case_num (c, qc->wv) : 1.0);
                }
            }
 
@@ -529,7 +529,7 @@ kmeans_cluster (struct Kmeans *kmeans, struct casereader *reader,
            for (j = 0; j < qc->n_vars; ++j)
              {
                const union value *val = case_data (c, qc->vars[j]);
-               if (var_is_value_missing (qc->vars[j], val, qc->exclude))
+               if (var_is_value_missing (qc->vars[j], val) & qc->exclude)
                  continue;
 
                double *x = gsl_matrix_ptr (kmeans->updated_centers, group, j);
@@ -537,7 +537,7 @@ kmeans_cluster (struct Kmeans *kmeans, struct casereader *reader,
              }
 
            long *n = gsl_vector_long_ptr (kmeans->num_elements_groups, group);
-           *n += qc->wv ? case_data (c, qc->wv)->f : 1.0;
+           *n += qc->wv ? case_num (c, qc->wv) : 1.0;
            kmeans->n++;
          }
        casereader_destroy (cs);
@@ -610,7 +610,7 @@ quick_cluster_show_centers (struct Kmeans *kmeans, bool initial, const struct qc
 /* A transformation function which juxtaposes the dataset with the
    (pre-prepared) dataset containing membership and/or distance
    values.  */
-static int
+static enum trns_result
 save_trans_func (void *aux, struct ccase **c, casenumber x UNUSED)
 {
   const struct save_trans_data *std = aux;
@@ -621,10 +621,10 @@ save_trans_func (void *aux, struct ccase **c, casenumber x UNUSED)
   *c = case_unshare (*c);
 
   if (std->CASE_IDX_MEMBERSHIP >= 0)
-    case_data_rw (*c, std->membership)->f = case_data_idx (ca, std->CASE_IDX_MEMBERSHIP)->f;
+    *case_num_rw (*c, std->membership) = case_num_idx (ca, std->CASE_IDX_MEMBERSHIP);
 
   if (std->CASE_IDX_DISTANCE >= 0)
-    case_data_rw (*c, std->distance)->f = case_data_idx (ca, std->CASE_IDX_DISTANCE)->f;
+    *case_num_rw (*c, std->distance) = case_num_idx (ca, std->CASE_IDX_DISTANCE);
 
   case_unref (ca);
 
@@ -708,10 +708,10 @@ quick_cluster_show_membership (struct Kmeans *kmeans,
        /* Calculate the membership and distance values.  */
        struct ccase *outc = case_create (proto);
        if (qc->save_values & SAVE_MEMBERSHIP)
-         case_data_rw_idx (outc, qc->save_trans_data->CASE_IDX_MEMBERSHIP)->f = cluster + 1;
+         *case_num_rw_idx (outc, qc->save_trans_data->CASE_IDX_MEMBERSHIP) = cluster + 1;
 
        if (qc->save_values & SAVE_DISTANCE)
-         case_data_rw_idx (outc, qc->save_trans_data->CASE_IDX_DISTANCE)->f
+         *case_num_rw_idx (outc, qc->save_trans_data->CASE_IDX_DISTANCE)
            = sqrt (dist_from_case (kmeans, c, qc, clust));
 
        casewriter_write (qc->save_trans_data->writer, outc);
@@ -920,14 +920,9 @@ quick_cluster_parse (struct lexer *lexer, struct qc *qc)
              if (lex_match_id (lexer, "CLUSTERS"))
                {
                  if (lex_force_match (lexer, T_LPAREN) &&
-                     lex_force_int (lexer))
+                     lex_force_int_range (lexer, "CLUSTERS", 1, INT_MAX))
                    {
                      qc->ngroups = lex_integer (lexer);
-                     if (qc->ngroups <= 0)
-                       {
-                         lex_error (lexer, _("The number of clusters must be positive"));
-                         return false;
-                       }
                      lex_get (lexer);
                      if (!lex_force_match (lexer, T_RPAREN))
                        return false;
@@ -952,14 +947,9 @@ quick_cluster_parse (struct lexer *lexer, struct qc *qc)
              else if (lex_match_id (lexer, "MXITER"))
                {
                  if (lex_force_match (lexer, T_LPAREN) &&
-                     lex_force_int (lexer))
+                     lex_force_int_range (lexer, "MXITER", 1, INT_MAX))
                    {
                      qc->maxiter = lex_integer (lexer);
-                     if (qc->maxiter <= 0)
-                       {
-                         lex_error (lexer, _("The number of iterations must be positive"));
-                         return false;
-                       }
                      lex_get (lexer);
                      if (!lex_force_match (lexer, T_RPAREN))
                        return false;
@@ -1086,7 +1076,12 @@ cmd_quick_cluster (struct lexer *lexer, struct dataset *ds)
          std->distance = dict_create_var_assert (qc.dict, qc.var_distance, 0);
        }
 
-      add_transformation (qc.dataset, save_trans_func, save_trans_destroy, std);
+      static const struct trns_class trns_class = {
+        .name = "QUICK CLUSTER",
+        .execute = save_trans_func,
+        .destroy = save_trans_destroy,
+      };
+      add_transformation (qc.dataset, &trns_class, std);
     }
 
   free (qc.var_distance);