Rename compare_values, hash_values with "_short" suffix.
[pspp] / src / math / interaction.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2007 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   An interaction is a gsl_vector containing a "product" of other
19   variables. The variables can be either categorical or numeric.
20   If the variables are all numeric, the interaction is just the
21   scalar product. If any of the variables are categorical, their
22   product is a vector containing 0's in all but one entry. This entry
23   is found by combining the vectors corresponding to the variables'
24   OBS_VALS member. If there are K categorical variables, each with
25   N_1, N_2, ..., N_K categories, then the interaction will have
26   N_1 * N_2 * N_3 *...* N_K - 1 entries.
27  */
28
29 #include <config.h>
30 #include <assert.h>
31 #include <gsl/gsl_math.h>
32 #include <gsl/gsl_vector.h>
33 #include <data/category.h>
34 #include <data/variable.h>
35 #include "interaction.h"
36
37 #include "xalloc.h"
38
39 /*
40   Convert a list of values to a binary vector. The order of VALS must
41   correspond to the order of V.
42  */
43 gsl_vector *
44 get_interaction (union value **vals, const struct variable **v, size_t n_vars)
45 {
46   gsl_vector *result = NULL;
47   size_t *subs = NULL;
48   size_t length = 1;
49   size_t i;
50   size_t j;
51   double tmp = 1.0;
52
53   assert (n_vars > 0);
54   for (i = 0; i < n_vars; i++)
55     {
56       if (var_is_alpha (v[i]))
57         {
58           length *= cat_get_n_categories (v[i]);
59         }
60       else
61         {
62           length = (length > 0) ? length : 1;
63         }
64     }
65   if (length > 0)
66     {
67       length--;
68     }
69
70   result = gsl_vector_calloc (length);
71   subs = xnmalloc (n_vars, sizeof (*subs));
72   for (j = 0; j < n_vars; j++)
73     {
74       if (var_is_alpha (v[j]))
75         {
76           subs[j] = cat_value_find (v[j], vals[j]);
77         }
78     }
79   j = subs[0];
80   for (i = 1; i < n_vars; i++)
81     {
82       j = j * cat_get_n_categories (v[i]) + subs[i];
83     }
84   gsl_vector_set (result, j, 1.0);
85   /*
86      If any of the variables are numeric, the interaction of that
87      variable with another is just a scalar product.
88    */
89   for (i = 1; i < n_vars; i++)
90     {
91       if (var_is_numeric (v[i]))
92         {
93           tmp *= vals[i]->f;
94         }
95     }
96   if (fabs (tmp - 1.0) > GSL_DBL_EPSILON)
97     {
98       gsl_vector_set (result, j, tmp);
99     }
100   free (subs);
101
102   return result;
103 }