Initial version of interaction
[pspp-builds.git] / src / math / interaction.c
1 /* PSPP - Creates data structures to store interactions for
2    statistical routines.  
3
4    Copyright (C) 2007 Free Software Foundation, Inc.
5
6    This program is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19    02110-1301, USA. */
20
21 /*
22   An interaction is a gsl_vector containing a "product" of other
23   variables. The variables can be either categorical or numeric.
24   If the variables are all numeric, the interaction is just the
25   scalar product. If any of the variables are categorical, their
26   product is a vector containing 0's in all but one entry. This entry
27   is found by combining the vectors corresponding to the variables'
28   OBS_VALS member. If there are K categorical variables, each with
29   N_1, N_2, ..., N_K categories, then the interaction will have
30   N_1 * N_2 * N_3 *...* N_K - 1 entries.
31  */
32 #include <assert.h>
33 #include <libpspp/alloc.h>
34 #include <gsl/gsl_math.h>
35 #include <gsl/gsl_vector.h>
36 #include <data/category.h>
37 #include <data/variable.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 }