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