checkin of 0.3.0
[pspp-builds.git] / src / means.q
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 <stdlib.h>
22 #include <stdio.h>
23 #include <assert.h>
24 #include "alloc.h"
25 #include "avl.h"
26 #include "command.h"
27 #include "lexer.h"
28 #include "error.h"
29 #include "magic.h"
30 #include "var.h"
31 /* (headers) */
32
33 #undef DEBUGGING
34 #define DEBUGGING 1
35 #include "debug-print.h"
36
37 /* (specification)
38    means (mns_):
39      *tables=custom;
40      +variables=custom;
41      +crossbreak=custom;
42      +format=lab:!labels/nolabels/nocatlabs,
43             name:!names/nonames,
44             val:!values/novalues,
45             fmt:!table/tree;
46      +missing=miss:!table/include/dependent;
47      +cells[cl_]=default,count,sum,mean,stddev,variance,all;
48      +statistics[st_]=anova,linearity,all,none.
49 */
50 /* (declarations) */
51 /* (functions) */
52
53 #if DEBUGGING
54 static void debug_print (struct cmd_means *cmd);
55 #endif
56
57 /* TABLES: Variable lists for each dimension. */
58 int n_dim;              /* Number of dimensions. */
59 int *nv_dim;            /* Number of variables in each dimension. */
60 struct variable ***v_dim;       /* Variables in each dimension.  */
61
62 /* VARIABLES: List of variables. */
63 int n_var;
64 struct variable **v_var;
65
66 /* Parses and executes the T-TEST procedure. */
67 int
68 cmd_means (void)
69 {
70   struct cmd_means cmd;
71   int success = CMD_FAILURE;
72   
73   n_dim = 0;
74   nv_dim = NULL;
75   v_dim = NULL;
76   v_var = NULL;
77
78   lex_match_id ("MEANS");
79   if (!parse_means (&cmd))
80     goto free;
81
82   if (cmd.sbc_cells)
83     {
84       int i;
85       for (i = 0; i < MNS_CL_count; i++)
86         if (cmd.a_cells[i])
87           break;
88       if (i >= MNS_CL_count)
89         cmd.a_cells[MNS_CL_ALL] = 1;
90     }
91   else
92     cmd.a_cells[MNS_CL_DEFAULT] = 1;
93   if (cmd.a_cells[MNS_CL_DEFAULT] || cmd.a_cells[MNS_CL_ALL])
94     cmd.a_cells[MNS_CL_MEAN] = cmd.a_cells[MNS_CL_STDDEV] = cmd.a_cells[MNS_CL_COUNT] = 1;
95   if (cmd.a_cells[MNS_CL_ALL])
96     cmd.a_cells[MNS_CL_SUM] = cmd.a_cells[MNS_CL_VARIANCE] = 1;
97
98   if (cmd.sbc_statistics)
99     {
100       if (!cmd.a_statistics[MNS_ST_ANOVA] && !cmd.a_statistics[MNS_ST_LINEARITY])
101         cmd.a_statistics[MNS_ST_ANOVA] = 1;
102       if (cmd.a_statistics[MNS_ST_ALL])
103         cmd.a_statistics[MNS_ST_ANOVA] = cmd.a_statistics[MNS_ST_LINEARITY] = 1;
104     }
105
106   if (!cmd.sbc_tables)
107     {
108       msg (SE, _("Missing required subcommand TABLES."));
109       goto free;
110     }
111
112 #if DEBUGGING
113   debug_print (&cmd);
114 #endif
115   
116   success = CMD_SUCCESS;
117
118 free:
119   {
120     int i;
121     
122     for (i = 0; i < n_dim; i++)
123       free (v_dim[i]);
124     free (nv_dim);
125     free (v_dim);
126     free (v_var);
127   }
128   
129   return success;
130 }
131
132 /* Returns nonzero only if value V is valid as an endpoint for a
133    dependent variable in integer mode. */
134 int
135 validate_dependent_endpoint (double V)
136 {
137   return V == (int) V && V != LOWEST && V != HIGHEST;
138 }
139
140 /* Parses the TABLES subcommand. */
141 static int
142 mns_custom_tables (struct cmd_means *cmd)
143 {
144   struct dictionary *dict;
145   struct dictionary temp_dict;
146   
147   if (!lex_match_id ("TABLES")
148       && (token != T_ID || !is_varname (tokid))
149       && token != T_ALL)
150     return 2;
151   lex_match ('=');
152
153   if (cmd->sbc_tables || cmd->sbc_crossbreak)
154     {
155       msg (SE, _("TABLES or CROSSBREAK subcommand may not appear more "
156                  "than once."));
157       return 0;
158     }
159
160   if (cmd->sbc_variables)
161     {
162       dict = &temp_dict;
163       temp_dict.var = v_var;
164       temp_dict.nvar = n_var;
165       
166       {
167         int i;
168       
169         temp_dict.var_by_name = avl_create (NULL, cmp_variable, NULL);
170         for (i = 0; i < temp_dict.nvar; i++)
171           avl_force_insert (temp_dict.var_by_name, temp_dict.var[i]);
172       }
173     }
174   else
175     dict = &default_dict;
176
177   do
178     {
179       int nvl;
180       struct variable **vl;
181         
182       if (!parse_variables (dict, &vl, &nvl, PV_NO_DUPLICATE | PV_NO_SCRATCH))
183         return 0;
184       
185       n_dim++;
186       nv_dim = xrealloc (nv_dim, n_dim * sizeof (int));
187       v_dim = xrealloc (v_dim, n_dim * sizeof (struct variable **));
188
189       nv_dim[n_dim - 1] = nvl;
190       v_dim[n_dim - 1] = vl;
191
192       if (cmd->sbc_variables)
193         {
194           int i;
195
196           for (i = 0; i < nv_dim[0]; i++)
197             {
198               struct means_proc *v_inf = &v_dim[0][i]->p.mns;
199
200               if (v_inf->min == SYSMIS)
201                 {
202                   msg (SE, _("Variable %s specified on TABLES or "
203                              "CROSSBREAK, but not specified on "
204                              "VARIABLES."),
205                        v_dim[0][i]->name);
206                   return 0;
207                 }
208               
209               if (n_dim == 1)
210                 {
211                   v_inf->min = (int) v_inf->min;
212                   v_inf->max = (int) v_inf->max;
213                 } else {
214                   if (v_inf->min == LOWEST || v_inf->max == HIGHEST)
215                     {
216                       msg (SE, _("LOWEST and HIGHEST may not be used "
217                                  "for independent variables (%s)."),
218                            v_dim[0][i]->name);
219                       return 0;
220                     }
221                   if (v_inf->min != (int) v_inf->min
222                       || v_inf->max != (int) v_inf->max)
223                     {
224                       msg (SE, _("Independent variables (%s) may not "
225                                  "have noninteger endpoints in their "
226                                  "ranges."),
227                            v_dim[0][i]->name);
228                       return 0;
229                     }
230                 }
231             }
232         }
233     }
234   while (lex_match (T_BY));
235
236   /* Check for duplicates. */
237   {
238     int i;
239     
240     for (i = 0; i < default_dict.nvar; i++)
241       default_dict.var[i]->foo = 0;
242     for (i = 0; i < dict->nvar; i++)
243       if (dict->var[i]->foo++)
244         {
245           msg (SE, _("Variable %s is multiply specified on TABLES "
246                      "or CROSSBREAK."),
247                dict->var[i]->name);
248           return 0;
249         }
250   }
251   
252   if (cmd->sbc_variables)
253     avl_destroy (temp_dict.var_by_name, NULL);
254
255   return 1;
256 }
257
258 /* Parse CROSSBREAK subcommand. */
259 static int
260 mns_custom_crossbreak (struct cmd_means *cmd)
261 {
262   return mns_custom_tables (cmd);
263 }
264
265 /* Parses the VARIABLES subcommand. */
266 static int
267 mns_custom_variables (struct cmd_means *cmd)
268 {
269   if (cmd->sbc_tables)
270     {
271       msg (SE, _("VARIABLES must precede TABLES."));
272       return 0;
273     }
274
275   if (cmd->sbc_variables == 1)
276     {
277       int i;
278       
279       for (i = 0; i < default_dict.nvar; i++)
280         default_dict.var[i]->p.mns.min = SYSMIS;
281     }
282   
283   do
284     {
285       int orig_n = n_var;
286       
287       double min, max;
288       
289       if (!parse_variables (&default_dict, &v_var, &n_var,
290                             PV_APPEND | PV_NO_DUPLICATE | PV_NO_SCRATCH))
291         return 0;
292
293       if (!lex_force_match ('('))
294         return 0;
295
296       /* Lower value. */
297       if (token == T_ID
298           && (!strcmp (tokid, "LO") || lex_id_match ("LOWEST", tokid)))
299         min = LOWEST;
300       else
301         {
302           if (!lex_force_num ())
303             return 0;
304           min = tokval;
305         }
306       lex_get ();
307
308       lex_match (',');
309
310       /* Higher value. */
311       if (token == T_ID
312           && (!strcmp (tokid, "HI") || lex_id_match ("HIGHEST", tokid)))
313         max = HIGHEST;
314       else
315         {
316           if (!lex_force_num ())
317             return 0;
318           max = tokval;
319         }
320       lex_get ();
321
322       if (!lex_force_match (')'))
323         return 0;
324
325       /* Range check. */
326       if (max < min)
327         {
328           msg (SE, _("Upper value (%g) is less than lower value "
329                      "(%g) on VARIABLES subcommand."), max, min);
330           return 0;
331         }
332       
333       {
334         int i;
335
336         for (i = orig_n; i < n_var; i++)
337           {
338             struct means_proc *v_inf = &v_var[i]->p.mns;
339
340             v_inf->min = min;
341             v_inf->max = max;
342           }
343       }
344     }
345   while (token != '/' && token != '.');
346   
347   return 1;
348 }
349
350 #if DEBUGGING
351 static void
352 debug_print (struct cmd_means *cmd)
353 {
354   int i;
355   
356   printf ("MEANS");
357
358   if (cmd->sbc_variables)
359     {
360       int j = 0;
361       
362       printf (" VARIABLES=");
363       for (i = 0; i < default_dict.nvar; i++)
364         {
365           struct variable *v = default_dict.var[i];
366           
367           if (v->p.mns.min == SYSMIS)
368             continue;
369           if (j++)
370             printf (" ");
371           printf ("%s(", v->name);
372           if (v->p.mns.min == LOWEST)
373             printf ("LO");
374           else
375             printf ("%g", v->p.mns.min);
376           printf (",");
377           if (v->p.mns.max == HIGHEST)
378             printf ("HI");
379           else
380             printf ("%g", v->p.mns.max);
381           printf (")");
382         }
383       printf ("\n");
384     }
385
386   printf (" TABLES=");
387   for (i = 0; i < n_dim; i++)
388     {
389       int j;
390
391       if (i)
392         printf (" BY");
393
394       for (j = 0; j < nv_dim[i]; j++)
395         {
396           if (i || j)
397             printf (" ");
398           printf (v_dim[i][j]->name);
399         }
400     }
401   printf ("\n");
402 }
403 #endif /* DEBUGGING */
404
405 /* 
406    Local Variables:
407    mode: c
408    End:
409 */