Fixed bug 23567. Added accessor functions to get/set means and standard deviations...
[pspp-builds.git] / src / math / coefficient.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 /*
18   Accessor functions for matching coefficients and variables.
19  */
20 #include <config.h>
21 #include <math/coefficient.h>
22 #include "src/math/design-matrix.h"
23
24 #include <gl/xalloc.h>
25
26
27 struct varinfo
28 {
29   const struct variable *v;     /* Variable associated with this
30                                    coefficient. Note this variable
31                                    may not be unique. In other words,
32                                    a coefficient structure may have
33                                    other v_info's, each with its own
34                                    variable. */
35   const union value *val;       /* Value of the variable v which this varinfo
36                                    refers to. This member is relevant only to
37                                    categorical variables. */
38   double mean; /* Mean for this variable */
39   double sd; /* Standard deviation for this variable */
40 };
41
42 void
43 pspp_coeff_free (struct pspp_coeff *c)
44 {
45   free (c->v_info);
46   free (c);
47 }
48
49 /*
50   Initialize the variable and value pointers inside the
51   coefficient structures for the model.
52  */
53 void
54 pspp_coeff_init (struct pspp_coeff ** coeff, const struct design_matrix *X)
55 {
56   size_t i;
57   int n_vals = 1;
58
59   assert (coeff != NULL);
60   for (i = 0; i < X->m->size2; i++)
61     {
62       coeff[i] = xmalloc (sizeof (*coeff[i]));
63       coeff[i]->n_vars = n_vals;        /* Currently, no procedures allow
64                                            interactions.  This line will have to
65                                            change when procedures that allow
66                                            interaction terms are written.
67                                         */
68       coeff[i]->v_info = xnmalloc (coeff[i]->n_vars, sizeof (*coeff[i]->v_info));
69       assert (coeff[i]->v_info != NULL);
70       coeff[i]->v_info->v = design_matrix_col_to_var (X, i);
71       
72       if (var_is_alpha (coeff[i]->v_info->v))
73         {
74           size_t k;
75           k = design_matrix_var_to_column (X, coeff[i]->v_info->v);
76           assert (k <= i);
77           k = i - k;
78           coeff[i]->v_info->val =
79             cat_subscript_to_value (k, coeff[i]->v_info->v);
80         }
81       coeff[i]->v_info->mean = 0.0;
82       coeff[i]->v_info->sd = 0.0;
83     }
84 }
85 void
86 pspp_coeff_set_estimate (struct pspp_coeff *coef, double estimate)
87 {
88   coef->estimate = estimate;
89 }
90
91 void
92 pspp_coeff_set_std_err (struct pspp_coeff *coef, double std_err)
93 {
94   coef->std_err = std_err;
95 }
96
97 /*
98   Return the estimated value of the coefficient.
99  */
100 double
101 pspp_coeff_get_est (const struct pspp_coeff *coef)
102 {
103   if (coef == NULL)
104     {
105       return 0.0;
106     }
107   return coef->estimate;
108 }
109
110 /*
111   Return the standard error of the estimated coefficient.
112 */
113 double
114 pspp_coeff_get_std_err (const struct pspp_coeff *coef)
115 {
116   if (coef == NULL)
117     {
118       return 0.0;
119     }
120   return coef->std_err;
121 }
122
123 /*
124   How many variables are associated with this coefficient?
125  */
126 int
127 pspp_coeff_get_n_vars (struct pspp_coeff *coef)
128 {
129   if (coef == NULL)
130     {
131       return 0;
132     }
133   return coef->n_vars;
134 }
135
136 /*
137   Which variable does this coefficient match? I should be
138   0 unless the coefficient refers to an interaction term.
139  */
140 const struct variable *
141 pspp_coeff_get_var (struct pspp_coeff *coef, int i)
142 {
143   if (coef == NULL)
144     {
145       return NULL;
146     }
147   assert (i < coef->n_vars);
148   return (coef->v_info + i)->v;
149 }
150
151 /*
152   Which coefficient does this variable match? If the variable is
153   categorical, and has more than one coefficient, use the VAL to find
154   its coefficient.
155  */
156 const struct pspp_coeff *
157 pspp_coeff_var_to_coeff (const struct variable *v, struct pspp_coeff **coefs, 
158                          size_t n_coef, const union value *val)
159 {
160   size_t i = 0;
161   size_t j = 0;
162   size_t v_idx;
163   struct pspp_coeff *result = NULL;
164
165   if (v != NULL)
166     {
167       v_idx = var_get_dict_index (v);
168       while (i < n_coef && var_get_dict_index (coefs[i]->v_info->v) != v_idx)
169         {
170           i++;
171         }
172       result = coefs[i];
173       if (var_is_alpha (v))
174         {
175           /*
176             Use the VAL to find the coefficient.
177            */
178           if (val != NULL)
179             {
180               j = i;
181               while (j < n_coef && compare_values (pspp_coeff_get_value (coefs[j], v),
182                                                    val, var_get_width (v)) != 0)
183                 {
184                   j++;
185                 }
186               result = ((j < n_coef) ? coefs[j] : NULL);
187             }
188         }
189     }
190   return result;
191 }
192
193 /*
194   Which value is associated with this coefficient/variable combination?
195  */
196 const union value *
197 pspp_coeff_get_value (struct pspp_coeff *coef,
198                              const struct variable *v)
199 {
200   int i = 0;
201   const struct variable *candidate;
202
203   if (coef == NULL || v == NULL)
204     {
205       return NULL;
206     }
207   if (var_is_numeric (v))
208     {
209       return NULL;
210     }
211   while (i < coef->n_vars)
212     {
213       candidate = pspp_coeff_get_var (coef, i);
214       if (v == candidate)
215         {
216           return (coef->v_info + i)->val;
217         }
218       i++;
219     }
220   return NULL;
221 }
222
223 /*
224   Get or set the standard deviation of the variable associated with this coefficient.
225  */
226 double pspp_coeff_get_sd (const struct pspp_coeff *coef)
227 {
228   return coef->v_info->sd;
229 }
230 void pspp_coeff_set_sd (struct pspp_coeff *coef, double s)
231 {
232   coef->v_info->sd = s;
233 }
234
235 /*
236   Get or set the mean for the variable associated with this coefficient.
237 */
238 double pspp_coeff_get_mean (const struct pspp_coeff *coef)
239 {
240   return coef->v_info->mean;
241 }
242
243 void pspp_coeff_set_mean (struct pspp_coeff *coef, double m)
244 {
245   coef->v_info->mean = m;
246 }
247