FACTOR: Fix bug interpreting the /CRITERIA=ITERATE subcommand
[pspp] / src / language / stats / factor.c
index 568eb4d0d390c71506fec2f1fe71925e6bdae523..fa9987332fb93bdbdfad55a6f3b58e2750e114a6 100644 (file)
@@ -35,6 +35,7 @@
 #include "language/lexer/lexer.h"
 #include "language/lexer/value-parser.h"
 #include "language/lexer/variable-parser.h"
+#include "libpspp/cast.h"
 #include "libpspp/message.h"
 #include "libpspp/misc.h"
 #include "math/correlation.h"
@@ -151,12 +152,13 @@ struct cmd_factor
   enum extraction_method extraction;
   enum plot_opts plot;
   enum rotation_type rotation;
+  int rotation_iterations;
 
   /* Extraction Criteria */
   int n_factors;
   double min_eigen;
   double econverge;
-  int iterations;
+  int extraction_iterations;
 
   double rconverge;
 
@@ -206,7 +208,7 @@ idata_free (struct idata *id)
   if (id->cov != NULL)
     gsl_matrix_free (id->cov);
   if (id->corr != NULL)
-    gsl_matrix_free (id->corr);
+    gsl_matrix_free (CONST_CAST (gsl_matrix *, id->corr));
 
   free (id);
 }
@@ -657,7 +659,7 @@ rotate (const struct cmd_factor *cf, const gsl_matrix *unrot,
   /* Now perform the rotation iterations */
 
   prev_sv = initial_sv (normalised);
-  for (i = 0 ; i < cf->iterations ; ++i)
+  for (i = 0 ; i < cf->rotation_iterations ; ++i)
     {
       double sv = 0.0;
       for (j = 0 ; j < normalised->size2; ++j)
@@ -812,9 +814,8 @@ static bool run_factor (struct dataset *ds, const struct cmd_factor *factor);
 int
 cmd_factor (struct lexer *lexer, struct dataset *ds)
 {
-  bool extraction_seen = false;
   const struct dictionary *dict = dataset_dict (ds);
-
+  int n_iterations = 25;
   struct cmd_factor factor;
   factor.n_vars = 0;
   factor.vars = NULL;
@@ -825,7 +826,8 @@ cmd_factor (struct lexer *lexer, struct dataset *ds)
   factor.extraction = EXTRACTION_PC;
   factor.n_factors = 0;
   factor.min_eigen = SYSMIS;
-  factor.iterations = 25;
+  factor.extraction_iterations = 25;
+  factor.rotation_iterations = 25;
   factor.econverge = 0.001;
 
   factor.blank = 0;
@@ -926,6 +928,7 @@ cmd_factor (struct lexer *lexer, struct dataset *ds)
                  goto error;
                }
            }
+          factor.rotation_iterations = n_iterations;
        }
       else if (lex_match_id (lexer, "CRITERIA"))
        {
@@ -977,7 +980,7 @@ cmd_factor (struct lexer *lexer, struct dataset *ds)
                  if ( lex_force_match (lexer, T_LPAREN))
                    {
                      lex_force_int (lexer);
-                     factor.iterations = lex_integer (lexer);
+                     n_iterations = lex_integer (lexer);
                      lex_get (lexer);
                      lex_force_match (lexer, T_RPAREN);
                    }
@@ -986,7 +989,7 @@ cmd_factor (struct lexer *lexer, struct dataset *ds)
                {
                  factor.n_factors = 0;
                  factor.min_eigen = 1;
-                 factor.iterations = 25;
+                 n_iterations = 25;
                }
              else
                {
@@ -997,7 +1000,6 @@ cmd_factor (struct lexer *lexer, struct dataset *ds)
        }
       else if (lex_match_id (lexer, "EXTRACTION"))
        {
-         extraction_seen = true;
           lex_match (lexer, T_EQUALS);
           while (lex_token (lexer) != T_ENDCMD && lex_token (lexer) != T_SLASH)
            {
@@ -1023,6 +1025,7 @@ cmd_factor (struct lexer *lexer, struct dataset *ds)
                  goto error;
                }
            }
+          factor.extraction_iterations = n_iterations;
        }
       else if (lex_match_id (lexer, "FORMAT"))
        {
@@ -1736,6 +1739,7 @@ do_factor (const struct cmd_factor *factor, struct casereader *r)
   if (idata->cov == NULL)
     {
       msg (MW, _("The dataset contains no complete observations. No analysis will be performed."));
+      covariance_destroy (cov);
       goto finish;
     }
 
@@ -1955,7 +1959,7 @@ do_factor (const struct cmd_factor *factor, struct casereader *r)
 
        gsl_vector_memcpy (initial_communalities, idata->msr);
 
-       for (i = 0; i < factor->iterations; ++i)
+       for (i = 0; i < factor->extraction_iterations; ++i)
          {
            double min, max;
            gsl_vector_memcpy (diff, idata->msr);