INPUT PROGRAM: Avoid infinite loop for trivially empty input program.
[pspp] / src / language / stats / factor.c
index e67cdbc1d8afaa6ea1ba07ea73f09efc7f9149ab..f3933268431c646e70ed741fd74b7856567ab011 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -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"
@@ -205,6 +206,8 @@ idata_free (struct idata *id)
   gsl_matrix_free (id->evec);
   if (id->cov != NULL)
     gsl_matrix_free (id->cov);
+  if (id->corr != NULL)
+    gsl_matrix_free (CONST_CAST (gsl_matrix *, id->corr));
 
   free (id);
 }
@@ -725,6 +728,7 @@ rotate (const struct cmd_factor *cf, const gsl_matrix *unrot,
                  h_sqrt, normalised,  0.0,   result);
 
   gsl_matrix_free (h_sqrt);
+  gsl_matrix_free (normalised);
 
 
   /* reflect negative sums and populate the rotated loadings vector*/
@@ -809,7 +813,6 @@ 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);
 
   struct cmd_factor factor;
@@ -994,7 +997,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)
            {
@@ -1536,16 +1538,12 @@ show_explained_variance (const struct cmd_factor * factor, struct idata *idata,
       const double e_lambda = gsl_vector_get (extracted_eigenvalues, i);
       double e_percent = 100.0 * e_lambda / e_total ;
 
-      const double r_lambda = gsl_vector_get (rotated_loadings, i);
-      double r_percent = 100.0 * r_lambda / e_total ;
-
       c = 0;
 
       tab_text_format (t, c++, i + heading_rows, TAB_LEFT | TAT_TITLE, _("%zu"), i + 1);
 
       i_cum += i_percent;
       e_cum += e_percent;
-      r_cum += r_percent;
 
       /* Initial Eigenvalues */
       if (factor->print & PRINT_INITIAL)
@@ -1567,16 +1565,22 @@ show_explained_variance (const struct cmd_factor * factor, struct idata *idata,
            }
        }
 
-      if (factor->print & PRINT_ROTATION)
-       {
-         if (i < idata->n_extractions)
-           {
-             tab_double (t, c++, i + heading_rows, 0, r_lambda, NULL);
-             tab_double (t, c++, i + heading_rows, 0, r_percent, NULL);
-             tab_double (t, c++, i + heading_rows, 0, r_cum, NULL);
-           }
-      }
+      if (rotated_loadings != NULL)
+        {
+          const double r_lambda = gsl_vector_get (rotated_loadings, i);
+          double r_percent = 100.0 * r_lambda / e_total ;
 
+          if (factor->print & PRINT_ROTATION)
+            {
+              if (i < idata->n_extractions)
+                {
+                  r_cum += r_percent;
+                  tab_double (t, c++, i + heading_rows, 0, r_lambda, NULL);
+                  tab_double (t, c++, i + heading_rows, 0, r_percent, NULL);
+                  tab_double (t, c++, i + heading_rows, 0, r_cum, NULL);
+                }
+            }
+        }
     }
 
   tab_submit (t);
@@ -1731,12 +1735,14 @@ 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;
     }
 
   var_matrix = covariance_moments (cov, MOMENT_VARIANCE);
   mean_matrix = covariance_moments (cov, MOMENT_MEAN);
   idata->n = covariance_moments (cov, MOMENT_NONE);
+  
 
   if ( factor->method == METHOD_CORR)
     {
@@ -1747,6 +1753,7 @@ do_factor (const struct cmd_factor *factor, struct casereader *r)
   else
     analysis_matrix = idata->cov;
 
+
   if (factor->print & PRINT_DETERMINANT
       || factor->print & PRINT_KMO)
     {
@@ -1894,13 +1901,16 @@ do_factor (const struct cmd_factor *factor, struct casereader *r)
     }
 
   show_correlation_matrix (factor, idata);
+  covariance_destroy (cov);
 
   {
+    gsl_matrix *am = matrix_dup (analysis_matrix);
     gsl_eigen_symmv_workspace *workspace = gsl_eigen_symmv_alloc (factor->n_vars);
     
-    gsl_eigen_symmv (matrix_dup (analysis_matrix), idata->eval, idata->evec, workspace);
+    gsl_eigen_symmv (am, idata->eval, idata->evec, workspace);
 
     gsl_eigen_symmv_free (workspace);
+    gsl_matrix_free (am);
   }
 
   gsl_eigen_symmv_sort (idata->eval, idata->evec, GSL_EIGEN_SORT_ABS_DESC);
@@ -2012,6 +2022,8 @@ do_factor (const struct cmd_factor *factor, struct casereader *r)
 
 
 
+    gsl_matrix_free (factor_matrix);
+    gsl_vector_free (rotated_loadings);
     gsl_vector_free (initial_communalities);
     gsl_vector_free (extracted_communalities);
   }