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