Return 0.0 for mean of a categorical variable. Fixes bug mentioned in bug report...
[pspp-builds.git] / src / math / linreg.c
index a7fa15657344bd1cf52aad870acffd80c9d661f6..baf9cb737e8250b59a8814dac93dc5ca5b768390 100644 (file)
@@ -24,7 +24,6 @@
 #include <math/coefficient.h>
 #include <math/linreg.h>
 #include <math/coefficient.h>
-#include <math/covariance-matrix.h>
 #include <math/design-matrix.h>
 #include <src/data/category.h>
 #include <src/data/variable.h>
@@ -96,10 +95,10 @@ linreg_mean_std (gsl_vector_const_view v, double *mp, double *sp, double *ssp)
   The return value is the number of distinct variables found.
  */
 int
-pspp_linreg_get_vars (const void *c_, struct variable **v)
+pspp_linreg_get_vars (const void *c_, const struct variable **v)
 {
   const pspp_linreg_cache *c = c_;
-  struct variable *tmp;
+  const struct variable *tmp;
   int i;
   int j;
   int result = 0;
@@ -642,7 +641,7 @@ double pspp_linreg_get_indep_variable_mean (pspp_linreg_cache *c, const struct v
       coef = pspp_linreg_get_coeff (c, v, NULL);
       return pspp_coeff_get_mean (coef);
     }
-  return GSL_NAN;
+  return 0.0;
 }
 
 void pspp_linreg_set_indep_variable_mean (pspp_linreg_cache *c, const struct variable *v, 
@@ -661,24 +660,28 @@ void pspp_linreg_set_indep_variable_mean (pspp_linreg_cache *c, const struct var
   only variables in the model are in the covariance matrix. 
  */
 static struct design_matrix *
-rearrange_covariance_matrix (const struct design_matrix *cov, pspp_linreg_cache *c)
+rearrange_covariance_matrix (const struct covariance_matrix *cm, pspp_linreg_cache *c)
 {
-  struct variable **model_vars;
+  const struct variable **model_vars;
+  struct design_matrix *cov;
   struct design_matrix *result;
   size_t *permutation;
   size_t i;
   size_t j;
   size_t k;
+  size_t n_coeffs = 0;
 
+  assert (cm != NULL);
+  cov = covariance_to_design (cm);
   assert (cov != NULL);
   assert (c != NULL);
   assert (cov->m->size1 > 0);
   assert (cov->m->size2 == cov->m->size1);
-  permutation = xnmalloc (cov->m->size2, sizeof (*permutation));
   model_vars = xnmalloc (1 + c->n_indeps, sizeof (*model_vars));
 
   /*
     Put the model variables in the right order in MODEL_VARS.
+    Count the number of coefficients.
    */
   for (i = 0; i < c->n_indeps; i++)
     {
@@ -686,19 +689,22 @@ rearrange_covariance_matrix (const struct design_matrix *cov, pspp_linreg_cache
     }
   model_vars[i] = c->depvar;
   result = covariance_matrix_create (1 + c->n_indeps, model_vars);
+  permutation = xnmalloc (design_matrix_get_n_cols (result), sizeof (*permutation));
+
   for (j = 0; j < cov->m->size2; j++)
     {
-      for (k = 0; k < result->m->size2; k++)
+      k = 0;
+      while (k < result->m->size2)
        {
          if (design_matrix_col_to_var (cov, j) == design_matrix_col_to_var (result, k)) 
            {
              permutation[k] = j;
-             break;
            }
+         k++;
        }
     }
-  for (j = 0; j < result->m->size2; j++)
-    for (i = 0; i < result->m->size1; i++)
+  for (i = 0; i < result->m->size1; i++)
+    for (j = 0; j < result->m->size2; j++)
       {
        gsl_matrix_set (result->m, i, j, gsl_matrix_get (cov->m, permutation[i], permutation[j]));
       }
@@ -718,8 +724,8 @@ rearrange_covariance_matrix (const struct design_matrix *cov, pspp_linreg_cache
   having to alter it. The problem is that this means the caller must
   set CACHE->N_COEFFS.
 */
-int
-pspp_linreg_with_cov (const struct design_matrix *full_cov, 
+void
+pspp_linreg_with_cov (const struct covariance_matrix *full_cov, 
                      pspp_linreg_cache * cache)
 {
   struct design_matrix *cov;
@@ -731,6 +737,11 @@ pspp_linreg_with_cov (const struct design_matrix *full_cov,
   cache_init (cache);
   reg_sweep (cov->m);
   post_sweep_computations (cache, cov, cov->m);  
-  covariance_matrix_destroy (cov);
+  design_matrix_destroy (cov);
 }
 
+double pspp_linreg_mse (const pspp_linreg_cache *c)
+{
+  assert (c != NULL);
+  return (c->sse / c->dfe);
+}