Fix assertion for proper Huffman merge pattern: 0 == 1 modulo 1.
[pspp] / src / vars-atr.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3    Written by Ben Pfaff <blp@gnu.org>.
4
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18    02111-1307, USA. */
19
20 #include <config.h>
21 #include "var.h"
22 #include "error.h"
23 #include <stdlib.h>
24 #include "alloc.h"
25 #include "command.h"
26 #include "dictionary.h"
27 #include "do-ifP.h"
28 #include "expr.h"
29 #include "file-handle.h"
30 #include "hash.h"
31 #include "misc.h"
32 #include "str.h"
33 #include "value-labels.h"
34 #include "vfm.h"
35
36 #include "debug-print.h"
37
38 void *
39 var_attach_aux (struct variable *v,
40                 void *aux, void (*aux_dtor) (struct variable *)) 
41 {
42   assert (v->aux == NULL);
43   assert (aux != NULL);
44   v->aux = aux;
45   v->aux_dtor = aux_dtor;
46   return aux;
47 }
48
49 void *
50 var_detach_aux (struct variable *v) 
51 {
52   void *aux = v->aux;
53   assert (aux != NULL);
54   v->aux = NULL;
55   return aux;
56 }
57
58 void
59 var_clear_aux (struct variable *v) 
60 {
61   assert (v != NULL);
62   if (v->aux != NULL) 
63     {
64       if (v->aux_dtor != NULL)
65         v->aux_dtor (v);
66       v->aux = NULL;
67     }
68 }
69
70 void
71 var_dtor_free (struct variable *v) 
72 {
73   free (v->aux);
74 }
75
76 /* Compares A and B, which both have the given WIDTH, and returns
77    a strcmp()-type result. */
78 int
79 compare_values (const union value *a, const union value *b, int width) 
80 {
81   if (width == 0) 
82     return a->f < b->f ? -1 : a->f > b->f;
83   else
84     return memcmp (a->s, b->s, min(MAX_SHORT_STRING, width));
85 }
86
87 /* Create a hash of v */
88 unsigned 
89 hash_value(const union value  *v, int width)
90 {
91   unsigned id_hash;
92
93   if ( 0 == width ) 
94     id_hash = hsh_hash_double (v->f);
95   else
96     id_hash = hsh_hash_bytes (v->s, min(MAX_SHORT_STRING, width));
97
98   return id_hash;
99 }
100
101
102
103 /* Discards all the current state in preparation for a data-input
104    command like DATA LIST or GET. */
105 void
106 discard_variables (void)
107 {
108   dict_clear (default_dict);
109   default_handle = NULL;
110
111   n_lag = 0;
112   
113   if (vfm_source != NULL)
114     {
115       free_case_source (vfm_source);
116       vfm_source = NULL;
117     }
118
119   cancel_transformations ();
120
121   ctl_stack = NULL;
122
123   expr_free (process_if_expr);
124   process_if_expr = NULL;
125
126   cancel_temporary ();
127
128   pgm_state = STATE_INIT;
129 }
130
131 /* Return nonzero only if X is a user-missing value for numeric
132    variable V. */
133 inline int
134 is_num_user_missing (double x, const struct variable *v)
135 {
136   switch (v->miss_type)
137     {
138     case MISSING_NONE:
139       return 0;
140     case MISSING_1:
141       return x == v->missing[0].f;
142     case MISSING_2:
143       return x == v->missing[0].f || x == v->missing[1].f;
144     case MISSING_3:
145       return (x == v->missing[0].f || x == v->missing[1].f
146               || x == v->missing[2].f);
147     case MISSING_RANGE:
148       return x >= v->missing[0].f && x <= v->missing[1].f;
149     case MISSING_LOW:
150       return x <= v->missing[0].f;
151     case MISSING_HIGH:
152       return x >= v->missing[0].f;
153     case MISSING_RANGE_1:
154       return ((x >= v->missing[0].f && x <= v->missing[1].f)
155               || x == v->missing[2].f);
156     case MISSING_LOW_1:
157       return x <= v->missing[0].f || x == v->missing[1].f;
158     case MISSING_HIGH_1:
159       return x >= v->missing[0].f || x == v->missing[1].f;
160     default:
161       assert (0);
162     }
163   abort ();
164 }
165
166 /* Return nonzero only if string S is a user-missing variable for
167    string variable V. */
168 inline int
169 is_str_user_missing (const unsigned char s[], const struct variable *v)
170 {
171   switch (v->miss_type)
172     {
173     case MISSING_NONE:
174       return 0;
175     case MISSING_1:
176       return !strncmp (s, v->missing[0].s, v->width);
177     case MISSING_2:
178       return (!strncmp (s, v->missing[0].s, v->width)
179               || !strncmp (s, v->missing[1].s, v->width));
180     case MISSING_3:
181       return (!strncmp (s, v->missing[0].s, v->width)
182               || !strncmp (s, v->missing[1].s, v->width)
183               || !strncmp (s, v->missing[2].s, v->width));
184     default:
185       assert (0);
186     }
187   abort ();
188 }
189
190 /* Return nonzero only if value VAL is system-missing for variable
191    V. */
192 int
193 is_system_missing (const union value *val, const struct variable *v)
194 {
195   return v->type == NUMERIC && val->f == SYSMIS;
196 }
197
198 /* Return nonzero only if value VAL is system- or user-missing for
199    variable V. */
200 int
201 is_missing (const union value *val, const struct variable *v)
202 {
203   switch (v->type)
204     {
205     case NUMERIC:
206       if (val->f == SYSMIS)
207         return 1;
208       return is_num_user_missing (val->f, v);
209     case ALPHA:
210       return is_str_user_missing (val->s, v);
211     default:
212       assert (0);
213     }
214   abort ();
215 }
216
217 /* Return nonzero only if value VAL is user-missing for variable V. */
218 int
219 is_user_missing (const union value *val, const struct variable *v)
220 {
221   switch (v->type)
222     {
223     case NUMERIC:
224       return is_num_user_missing (val->f, v);
225     case ALPHA:
226       return is_str_user_missing (val->s, v);
227     default:
228       assert (0);
229     }
230   abort ();
231 }
232 \f
233 /* A hsh_compare_func that orders variables A and B by their
234    names. */
235 int
236 compare_variables (const void *a_, const void *b_, void *foo UNUSED) 
237 {
238   const struct variable *a = a_;
239   const struct variable *b = b_;
240
241   return strcmp (a->name, b->name);
242 }
243
244 /* A hsh_hash_func that hashes variable V based on its name. */
245 unsigned
246 hash_variable (const void *v_, void *foo UNUSED) 
247 {
248   const struct variable *v = v_;
249
250   return hsh_hash_string (v->name);
251 }