GLM: Rewrite interactions module and update glm.c to use it in some places
[pspp] / src / math / interaction.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2011 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
19 #include "interaction.h"
20
21 #include "data/value.h"
22 #include "data/variable.h"
23 #include "libpspp/str.h"
24
25 #include "gl/xalloc.h"
26
27 #include <stdio.h>
28
29
30 /*
31   An interaction is a structure containing a "product" of other
32   variables. The variables can be either string or numeric.
33
34   Interaction is commutative.  That means, that from a mathematical point of
35   view,  the order of the variables is irrelevant.  However, for display
36   purposes, and for matching with an interaction's value the order is 
37   pertinent.
38   
39   Therefore, when using these functions, make sure the orders of variables 
40   and values match when appropriate.
41 */
42
43
44
45 struct interaction *
46 interaction_create (const struct variable *v)
47 {
48   struct interaction  *i = xmalloc (sizeof *i);
49   i->vars = xmalloc (sizeof *i->vars);
50   i->vars[0] = v;
51   i->n_vars = 1;
52   return i;
53 }
54
55 void
56 interaction_destroy (struct interaction *i)
57 {
58   free (i->vars);
59   free (i);
60 }
61
62 void
63 interaction_add_variable (struct interaction *i, const struct variable *v)
64 {
65   i->vars = xrealloc (i->vars, sizeof (*i->vars) * ++i->n_vars);
66   i->vars[i->n_vars - 1] = v;
67 }
68
69
70 void
71 interaction_dump (const struct interaction *i)
72 {
73   int v = 0;
74   printf ("%s", var_get_name (i->vars[v]));
75   for (v = 1; v < i->n_vars; ++v)
76     {
77       printf (" * %s", var_get_name (i->vars[v]));
78     }
79   printf ("\n");
80 }
81
82 /* Appends STR with a representation of the interaction, suitable for user
83    display.
84
85    STR must have been initialised prior to calling this function.
86 */
87 void
88 interaction_to_string (const struct interaction *iact, struct string *str)
89 {
90   int v = 0;
91   ds_put_cstr (str, var_to_string (iact->vars[v]));
92   for (v = 1; v < iact->n_vars; ++v)
93     {
94       ds_put_cstr (str, " * ");
95       ds_put_cstr (str, var_to_string (iact->vars[v]));
96     }
97 }
98
99 unsigned int
100 interaction_value_hash (const struct interaction *iact, const union value *val)
101 {
102   int i;
103   size_t hash = 0;
104   for (i = 0; i < iact->n_vars; ++i)
105     {
106       hash = value_hash (&val[i], var_get_width (iact->vars[i]), hash);
107     }
108
109   return hash;
110 }
111
112 bool
113 interaction_value_equal (const struct interaction *iact, const union value *val1, const union value *val2)
114 {
115   int i;
116   bool same = true;
117
118   for (i = 0; i < iact->n_vars; ++i)
119     {
120       if ( ! value_equal (&val1[i], &val2[i], var_get_width (iact->vars[i])))
121         {
122           same = false;
123           break;
124         }
125     }
126
127   return same;
128 }
129
130
131 bool
132 interaction_value_is_missing (const struct interaction *iact, const union value *val, enum mv_class exclude)
133 {
134   int i;
135   bool missing = false;
136
137   for (i = 0; i < iact->n_vars; ++i)
138     {
139       if ( var_is_value_missing (iact->vars[i], &val[i], exclude))
140         {
141           missing = true;
142           break;
143         }
144     }
145
146   return missing;
147 }