8e628a4dba27b475bc4c63eee2153e1383d3699b
[pspp-builds.git] / src / math / linreg / predict.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2005 Free Software Foundation, Inc. 
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18 #include <math/linreg/linreg.h>
19 #include <math/coefficient.h>
20 #include <gl/xalloc.h>
21
22 /*
23   Predict the value of the dependent variable with the
24   new set of predictors. PREDICTORS must point to a list
25   of variables, each of whose values are stored in VALS,
26   in the same order.
27  */
28 double
29 pspp_linreg_predict (const struct variable **predictors,
30                      const union value **vals, const void *c_, int n_vals)
31 {
32   const pspp_linreg_cache *c = c_;
33   int i;
34   int j;
35   const struct pspp_coeff **found;
36   const struct pspp_coeff *coe;
37   double result;
38   double tmp;
39
40   if (predictors == NULL || vals == NULL || c == NULL)
41     {
42       return GSL_NAN;
43     }
44   if (c->coeff == NULL)
45     {
46       /* The stupid model: just guess the mean. */
47       return c->depvar_mean;
48     }
49   found = xnmalloc (c->n_coeffs, sizeof (*found));
50   *found = c->coeff[0];
51   result = c->coeff[0]->estimate;       /* Intercept. */
52
53   /*
54      The loops guard against the possibility that the caller passed us
55      inadequate information, such as too few or too many values, or
56      a redundant list of variable names.
57    */
58   for (j = 0; j < n_vals; j++)
59     {
60       coe = pspp_linreg_get_coeff (c, predictors[j], vals[j]);
61       i = 1;
62       while (found[i] == coe && i < c->n_coeffs)
63         {
64           i++;
65         }
66       if (i < c->n_coeffs)
67         {
68           found[i] = coe;
69           tmp = pspp_coeff_get_est (coe);
70           if (var_is_numeric (predictors[j]))
71             {
72               tmp *= vals[j]->f;
73             }
74           result += tmp;
75         }
76     }
77   free (found);
78
79   return result;
80 }
81
82 double
83 pspp_linreg_residual (const struct variable **predictors,
84                       const union value **vals,
85                       const union value *obs, const void *c, int n_vals)
86 {
87   double pred;
88   double result;
89
90   if (predictors == NULL || vals == NULL || c == NULL || obs == NULL)
91     {
92       return GSL_NAN;
93     }
94   pred = pspp_linreg_predict (predictors, vals, c, n_vals);
95
96   result = gsl_isnan (pred) ? GSL_NAN : (obs->f - pred);
97   return result;
98 }