Removed use of coefficient 0 as intercept; removed subcommand EXPORT.
[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   Is the coefficient COEF contained in the list of coefficients
24   COEF_LIST?
25  */
26 static int
27 has_coefficient (const struct pspp_coeff **coef_list, const struct pspp_coeff *coef,
28                  size_t n)
29 {
30   size_t i = 0;
31
32   while (i < n)
33     {
34       if (coef_list[i] == coef)
35         {
36           return 1;
37         }
38       i++;
39     }
40   return 0;
41 }
42 /*
43   Predict the value of the dependent variable with the
44   new set of predictors. PREDICTORS must point to a list
45   of variables, each of whose values are stored in VALS,
46   in the same order.
47  */
48 double
49 pspp_linreg_predict (const struct variable **predictors,
50                      const union value **vals, const void *c_, int n_vals)
51 {
52   const pspp_linreg_cache *c = c_;
53   int j;
54   size_t next_coef = 0;
55   const struct pspp_coeff **coef_list;
56   const struct pspp_coeff *coe;
57   double result;
58   double tmp;
59
60   if (predictors == NULL || vals == NULL || c == NULL)
61     {
62       return GSL_NAN;
63     }
64   if (c->coeff == NULL)
65     {
66       /* The stupid model: just guess the mean. */
67       return c->depvar_mean;
68     }
69   coef_list = xnmalloc (c->n_coeffs, sizeof (*coef_list));
70   result = c->intercept;
71
72   /*
73      The loops guard against the possibility that the caller passed us
74      inadequate information, such as too few or too many values, or
75      a redundant list of variable names.
76    */
77   for (j = 0; j < n_vals; j++)
78     {
79       coe = pspp_linreg_get_coeff (c, predictors[j], vals[j]);
80       if (!has_coefficient (coef_list, coe, next_coef))
81         {
82           tmp = pspp_coeff_get_est (coe);
83           if (var_is_numeric (predictors[j]))
84             {
85               tmp *= vals[j]->f;
86             }
87           result += tmp;
88           coef_list[next_coef++] = coe;
89         }
90     }
91   free (coef_list);
92
93   return result;
94 }
95
96 double
97 pspp_linreg_residual (const struct variable **predictors,
98                       const union value **vals,
99                       const union value *obs, const void *c, int n_vals)
100 {
101   double pred;
102   double result;
103
104   if (predictors == NULL || vals == NULL || c == NULL || obs == NULL)
105     {
106       return GSL_NAN;
107     }
108   pred = pspp_linreg_predict (predictors, vals, c, n_vals);
109
110   result = gsl_isnan (pred) ? GSL_NAN : (obs->f - pred);
111   return result;
112 }