From 53ff82a9f850b2ba9ab7985183551da514fc5d9d Mon Sep 17 00:00:00 2001
From: Jason Stover <jhs@math.gcsu.edu>
Date: Mon, 17 Apr 2006 16:26:44 +0000
Subject: [PATCH] added transformation to compute residuals

---
 src/language/stats/ChangeLog    | 13 ++++++
 src/language/stats/regression.q | 82 +++++++++++++++++++++------------
 2 files changed, 65 insertions(+), 30 deletions(-)

diff --git a/src/language/stats/ChangeLog b/src/language/stats/ChangeLog
index ffdee8ac08..05cede62a1 100644
--- a/src/language/stats/ChangeLog
+++ b/src/language/stats/ChangeLog
@@ -1,3 +1,16 @@
+2006-04-17  Jason Stover  <jhs@math.gcsu.edu>
+
+	* regression.q (regression_trns_proc): New function.
+
+	* regression.q (subcommand_save): Create variable residuals and
+	add a transformation to assign values to them. Also free the
+	linreg_cache if the SAVE command was not called. Removed the
+	casereading loop. Placed actual computation of residuals in
+	regression_trns_proc.
+
+	* regression.q (run_regression): Moved call to free
+	pspp_linreg_cache to subcommand_save.
+
 Sat Apr 15 18:01:03 2006  Ben Pfaff  <blp@gnu.org>
 
 	* examine.q (output_examine): Add casts to fix warnings.
diff --git a/src/language/stats/regression.q b/src/language/stats/regression.q
index 737a25fdce..417bb5c17f 100644
--- a/src/language/stats/regression.q
+++ b/src/language/stats/regression.q
@@ -501,43 +501,66 @@ subcommand_statistics (int *keywords, pspp_linreg_cache * c)
   statistics_keyword_output (reg_stats_tol, keywords[tol], c);
   statistics_keyword_output (reg_stats_selection, keywords[selection], c);
 }
-static void
-subcommand_save (int save, pspp_linreg_cache *lc, const struct casefile *cf, int *is_missing)
+static int
+regression_trns_proc (void *m, struct ccase *c, size_t case_idx)
 {
-  int i;
-  int case_num;
-  double residual;
+  size_t i;
+  size_t n_vars;
+  pspp_linreg_cache *model = m;
+  union value *output;
   const union value **vals = NULL;
   const union value *obs = NULL;
-  struct casereader *r;
-  struct ccase c;
-
-  assert (lc != NULL);
-  assert (lc->depvar != NULL);
-  assert (is_missing != NULL);
+  struct variable **vars = NULL;
+  struct variable *resid = NULL;
+  
+  assert (model != NULL);
+  assert (model->depvar != NULL);
+  
+  vals = xnmalloc (n_variables, sizeof (*vals));
+  dict_get_vars (default_dict, &vars, &n_vars, 1u << DC_ORDINARY);
+  resid = dict_get_var (default_dict, case_idx);
+  assert (resid != NULL);
+  output = case_data_rw (c, resid->fv);
+  assert (output);
 
-  if (save)
+  for (i = 0; i < n_vars; i++)
     {
-      vals = xnmalloc (n_variables, sizeof (*vals));
-      for (r = casefile_get_reader (cf); casereader_read (r, &c);
-	   case_destroy (&c))
+      if (i != case_idx) /* Do not use the residual variable as a predictor. */
 	{
-	  case_num = casereader_cnum (r) - 1;
-	  if (!is_missing[case_num])
+	  if (vars[i]->index == model->depvar->index) 
 	    {
-	      for (i = 0; i < n_variables; ++i)
-		{
-		  vals[i] = case_data (&c, v_variables[i]->fv);
-		  if (v_variables[i]->index == lc->depvar->index)
-		    {
-		      obs = vals[i];
-		    }
-		}
-	      residual = (*lc->residual) ((const struct variable **) v_variables, 
-					  (const union value **) vals, obs, lc, n_variables);
+	      /* Do not use the dependent variable as a predictor. */
+	      obs = case_data (c, i);
+	      assert (obs != NULL);
+	    }
+	  else
+	    {
+	      vals[i] = case_data (c, i);
 	    }
 	}
-      free (vals);
+    }
+  output->f = (*model->residual) ((const struct variable **) vars, 
+				  vals, obs, model, i);
+  free (vals);
+  return TRNS_CONTINUE;
+}
+static void
+subcommand_save (int save, pspp_linreg_cache *lc)
+{
+  struct variable *residuals = NULL;
+
+  assert (lc != NULL);
+  assert (lc->depvar != NULL);
+
+  if (save)
+    {
+      residuals = dict_create_var_assert (default_dict, "residuals", 0);
+      assert (residuals != NULL);
+      add_transformation (regression_trns_proc, pspp_linreg_cache_free, lc);
+    }
+  else 
+    {
+      pspp_linreg_cache_free (lc);
     }
 }
 static int
@@ -1042,12 +1065,11 @@ run_regression (const struct casefile *cf, void *cmd_ UNUSED)
        */
       pspp_linreg ((const gsl_vector *) Y, X->m, &lopts, lcache);
       subcommand_statistics (cmd.a_statistics, lcache);
-      subcommand_save (cmd.sbc_save, lcache, cf, is_missing_case);
       subcommand_export (cmd.sbc_export, lcache);
+      subcommand_save (cmd.sbc_save, lcache);
       gsl_vector_free (Y);
       design_matrix_destroy (X);
       free (indep_vars);
-      pspp_linreg_cache_free (lcache);
       free (lopts.get_indep_mean_std);
       casereader_destroy (r);
     }
-- 
2.30.2