Cleaning up freeing of regression coefficients
[pspp-builds.git] / lib / linreg / linreg.c
index f8f023a3a3fc7dab8bc67a7512d92e8df4e970c2..17833e57db0dd0bd877a395de00bfd5d8d6a3c0d 100644 (file)
@@ -87,38 +87,39 @@ linreg_mean_std (gsl_vector_const_view v, double *mp, double *sp, double *ssp)
 pspp_linreg_cache *
 pspp_linreg_cache_alloc (size_t n, size_t p)
 {
-  pspp_linreg_cache *cache;
+  pspp_linreg_cache *c;
 
-  cache = (pspp_linreg_cache *) malloc (sizeof (pspp_linreg_cache));
-  cache->param_estimates = gsl_vector_alloc (p + 1);
-  cache->indep_means = gsl_vector_alloc (p);
-  cache->indep_std = gsl_vector_alloc (p);
-  cache->ssx = gsl_vector_alloc (p);   /* Sums of squares for the independent
+  c = (pspp_linreg_cache *) malloc (sizeof (pspp_linreg_cache));
+  c->indep_means = gsl_vector_alloc (p);
+  c->indep_std = gsl_vector_alloc (p);
+  c->ssx = gsl_vector_alloc (p);       /* Sums of squares for the independent
                                           variables.
                                         */
-  cache->ss_indeps = gsl_vector_alloc (p);     /* Sums of squares for the model 
-                                                  parameters. 
-                                                */
-  cache->cov = gsl_matrix_alloc (p + 1, p + 1);        /* Covariance matrix. */
-  cache->n_obs = n;
-  cache->n_indeps = p;
+  c->ss_indeps = gsl_vector_alloc (p); /* Sums of squares for the model 
+                                          parameters. 
+                                        */
+  c->cov = gsl_matrix_alloc (p + 1, p + 1);    /* Covariance matrix. */
+  c->n_obs = n;
+  c->n_indeps = p;
   /*
      Default settings.
    */
-  cache->method = PSPP_LINREG_SWEEP;
+  c->method = PSPP_LINREG_SWEEP;
 
-  return cache;
+  return c;
 }
 
 void
-pspp_linreg_cache_free (pspp_linreg_cache * cache)
+pspp_linreg_cache_free (pspp_linreg_cache * c)
 {
-  gsl_vector_free (cache->param_estimates);
-  gsl_vector_free (cache->indep_means);
-  gsl_vector_free (cache->indep_std);
-  gsl_vector_free (cache->ss_indeps);
-  gsl_matrix_free (cache->cov);
-  free (cache);
+  int i;
+
+  gsl_vector_free (c->indep_means);
+  gsl_vector_free (c->indep_std);
+  gsl_vector_free (c->ss_indeps);
+  gsl_matrix_free (c->cov);
+  pspp_linreg_coeff_free (c->coeff);
+  free (c);
 }
 
 /*
@@ -138,6 +139,7 @@ pspp_linreg (const gsl_vector * Y, const gsl_matrix * X,
   gsl_vector_view xty;
   gsl_vector_view xi;
   gsl_vector_view xj;
+  gsl_vector *param_estimates;
 
   size_t i;
   size_t j;
@@ -145,7 +147,6 @@ pspp_linreg (const gsl_vector * Y, const gsl_matrix * X,
   double m;
   double s;
   double ss;
-  double mse;
 
   if (cache == NULL)
     {
@@ -172,6 +173,9 @@ pspp_linreg (const gsl_vector * Y, const gsl_matrix * X,
   cache->dft = cache->n_obs - 1;
   cache->dfm = cache->n_indeps;
   cache->dfe = cache->dft - cache->dfm;
+  cache->n_coeffs = X->size2 + 1; /* Adjust this later to allow for regression
+                                    through the origin.
+                                 */
   if (cache->method == PSPP_LINREG_SWEEP)
     {
       gsl_matrix *sw;
@@ -181,9 +185,9 @@ pspp_linreg (const gsl_vector * Y, const gsl_matrix * X,
          standard deviations of the independent variables here since doing
          so would cause a miscalculation of the residual sums of
          squares. Dividing by the standard deviation is done GSL's linear
-         regression functions, so if the design matrix has a very poor
+         regression functions, so if the design matrix has a poor
          condition, use QR decomposition.
-         *
+
          The design matrix here does not include a column for the intercept
          (i.e., a column of 1's). If using PSPP_LINREG_QR, we need that column,
          so design is allocated here when sweeping, or below if using QR.
@@ -245,7 +249,7 @@ pspp_linreg (const gsl_vector * Y, const gsl_matrix * X,
       for (i = 0; i < cache->n_indeps; i++)
        {
          tmp = gsl_matrix_get (sw, i, cache->n_indeps);
-         gsl_vector_set (cache->param_estimates, i + 1, tmp);
+         cache->coeff[i + 1].estimate = tmp;
          m -= tmp * gsl_vector_get (cache->indep_means, i);
        }
       /*
@@ -281,7 +285,7 @@ pspp_linreg (const gsl_vector * Y, const gsl_matrix * X,
            }
          gsl_matrix_set (cache->cov, 0, 0, tmp);
 
-         gsl_vector_set (cache->param_estimates, 0, m);
+         cache->coeff[0].estimate = m;
        }
       else
        {
@@ -296,6 +300,8 @@ pspp_linreg (const gsl_vector * Y, const gsl_matrix * X,
       /*
          Use QR decomposition via GSL.
        */
+
+      param_estimates = gsl_vector_alloc (1 + X->size2);
       design = gsl_matrix_alloc (X->size1, 1 + X->size2);
 
       for (j = 0; j < X->size1; j++)
@@ -309,11 +315,16 @@ pspp_linreg (const gsl_vector * Y, const gsl_matrix * X,
        }
       gsl_multifit_linear_workspace *wk =
        gsl_multifit_linear_alloc (design->size1, design->size2);
-      rc = gsl_multifit_linear (design, Y, cache->param_estimates,
+      rc = gsl_multifit_linear (design, Y, param_estimates,
                                cache->cov, &(cache->sse), wk);
+      for (i = 0; i < cache->n_coeffs; i++)
+       {
+         cache->coeff[i].estimate = gsl_vector_get (param_estimates, i);
+       }
       if (rc == GSL_SUCCESS)
        {
          gsl_multifit_linear_free (wk);
+         gsl_vector_free (param_estimates);
        }
       else
        {