Fix assertion for proper Huffman merge pattern: 0 == 1 modulo 1.
[pspp] / src / oneway.q
1 /* PSPP - One way ANOVA. -*-c-*-
2
3 Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
4 Author: John Darrington 2004
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21 #include <config.h>
22 #include <gsl/gsl_cdf.h>
23 #include "error.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <math.h>
27 #include "alloc.h"
28 #include "str.h"
29 #include "case.h"
30 #include "dictionary.h"
31 #include "command.h"
32 #include "lexer.h"
33 #include "error.h"
34 #include "magic.h"
35 #include "misc.h"
36 #include "tab.h"
37 #include "som.h"
38 #include "value-labels.h"
39 #include "var.h"
40 #include "vfm.h"
41 #include "hash.h"
42 #include "casefile.h"
43 #include "group_proc.h"
44 #include "group.h"
45 #include "levene.h"
46 /* (headers) */
47
48 /* (specification)
49    "ONEWAY" (oneway_):
50    *variables=custom;
51    +missing=miss:!analysis/listwise,
52    incl:include/!exclude;
53    contrast= double list;
54    statistics[st_]=descriptives,homogeneity.
55 */
56 /* (declarations) */
57 /* (functions) */
58
59
60
61 static int bad_weight_warn = 1;
62
63
64 static struct cmd_oneway cmd;
65
66 /* The independent variable */
67 static struct variable *indep_var;
68
69 /* Number of dependent variables */
70 static int n_vars;
71
72 /* The dependent variables */
73 static struct variable **vars;
74
75
76 /* A  hash table containing all the distinct values of the independent
77    variables */
78 static struct hsh_table *global_group_hash ;
79
80 /* The number of distinct values of the independent variable, when all 
81    missing values are disregarded */
82 static int ostensible_number_of_groups=-1;
83
84
85 /* Function to use for testing for missing values */
86 static is_missing_func value_is_missing;
87
88
89 static void run_oneway(const struct casefile *cf, void *_mode);
90
91
92 /* Routines to show the output tables */
93 static void show_anova_table(void);
94 static void show_descriptives(void);
95 static void show_homogeneity(void);
96
97 static void show_contrast_coeffs(short *);
98 static void show_contrast_tests(short *);
99
100
101 enum stat_table_t {STAT_DESC = 1, STAT_HOMO = 2};
102
103 static enum stat_table_t stat_tables ;
104
105 void output_oneway(void);
106
107
108 int
109 cmd_oneway(void)
110 {
111   int i;
112
113   if ( !parse_oneway(&cmd) )
114     return CMD_FAILURE;
115
116   /* If /MISSING=INCLUDE is set, then user missing values are ignored */
117   if (cmd.incl == ONEWAY_INCLUDE ) 
118     value_is_missing = is_system_missing;
119   else
120     value_is_missing = is_missing;
121
122   /* What statistics were requested */
123   if ( cmd.sbc_statistics ) 
124     {
125
126       for (i = 0 ; i < ONEWAY_ST_count ; ++i ) 
127         {
128           if  ( ! cmd.a_statistics[i]  ) continue;
129
130           switch (i) {
131           case ONEWAY_ST_DESCRIPTIVES:
132             stat_tables |= STAT_DESC;
133             break;
134           case ONEWAY_ST_HOMOGENEITY:
135             stat_tables |= STAT_HOMO;
136             break;
137           }
138         }
139     }
140
141   multipass_procedure_with_splits (run_oneway, &cmd);
142
143
144   return CMD_SUCCESS;
145 }
146
147
148 void
149 output_oneway(void)
150 {
151
152   int i;
153   short *bad_contrast ; 
154
155   bad_contrast = xmalloc ( sizeof (short) * cmd.sbc_contrast );
156
157   /* Check the sanity of the given contrast values */
158   for (i = 0 ; i < cmd.sbc_contrast ; ++i ) 
159     {
160       int j;
161       double sum = 0;
162
163       bad_contrast[i] = 0;
164       if ( subc_list_double_count(&cmd.dl_contrast[i]) != 
165            ostensible_number_of_groups )
166         {
167           msg(SW, 
168               _("Number of contrast coefficients must equal the number of groups"));
169           bad_contrast[i] = 1;
170           continue;
171         }
172
173       for (j=0; j < ostensible_number_of_groups ; ++j )
174         sum += subc_list_double_at(&cmd.dl_contrast[i],j);
175
176       if ( sum != 0.0 ) 
177         msg(SW,_("Coefficients for contrast %d do not total zero"),i + 1);
178     }
179
180   if ( stat_tables & STAT_DESC ) 
181     show_descriptives();
182
183   if ( stat_tables & STAT_HOMO )
184     show_homogeneity();
185
186   show_anova_table();
187      
188   if (cmd.sbc_contrast )
189     {
190       show_contrast_coeffs(bad_contrast);
191       show_contrast_tests(bad_contrast);
192     }
193
194
195   free(bad_contrast);
196
197   /* Clean up */
198   for (i = 0 ; i < n_vars ; ++i ) 
199     {
200       struct hsh_table *group_hash = group_proc_get (vars[i])->group_hash;
201
202       hsh_destroy(group_hash);
203     }
204
205   hsh_destroy(global_group_hash);
206
207 }
208
209
210
211
212 /* Parser for the variables sub command */
213 static int
214 oneway_custom_variables(struct cmd_oneway *cmd UNUSED)
215 {
216
217   lex_match('=');
218
219   if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
220       && token != T_ALL)
221     return 2;
222   
223
224   if (!parse_variables (default_dict, &vars, &n_vars,
225                         PV_DUPLICATE 
226                         | PV_NUMERIC | PV_NO_SCRATCH) )
227     {
228       free (vars);
229       return 0;
230     }
231
232   assert(n_vars);
233
234   if ( ! lex_match(T_BY))
235     return 2;
236
237
238   indep_var = parse_variable();
239
240   if ( !indep_var ) 
241     {
242       msg(SE,_("`%s' is not a variable name"),tokid);
243       return 0;
244     }
245
246
247   return 1;
248 }
249
250
251 /* Show the ANOVA table */
252 static void  
253 show_anova_table(void)
254 {
255   int i;
256   int n_cols =7;
257   int n_rows = n_vars * 3 + 1;
258
259   struct tab_table *t;
260
261
262   t = tab_create (n_cols,n_rows,0);
263   tab_headers (t, 2, 0, 1, 0);
264   tab_dim (t, tab_natural_dimensions);
265
266
267   tab_box (t, 
268            TAL_2, TAL_2,
269            -1, TAL_1,
270            0, 0,
271            n_cols - 1, n_rows - 1);
272
273   tab_hline (t, TAL_2, 0, n_cols - 1, 1 );
274   tab_vline (t, TAL_2, 2, 0, n_rows - 1);
275   tab_vline (t, TAL_0, 1, 0, 0);
276   
277   tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("Sum of Squares"));
278   tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("df"));
279   tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Mean Square"));
280   tab_text (t, 5, 0, TAB_CENTER | TAT_TITLE, _("F"));
281   tab_text (t, 6, 0, TAB_CENTER | TAT_TITLE, _("Significance"));
282
283
284   for ( i=0 ; i < n_vars ; ++i ) 
285     {
286       struct group_statistics *totals = &group_proc_get (vars[i])->ugs;
287       struct hsh_table *group_hash = group_proc_get (vars[i])->group_hash;
288       struct hsh_iterator g;
289       struct group_statistics *gs;
290       double ssa=0;
291
292
293       for (gs =  hsh_first (group_hash,&g); 
294            gs != 0; 
295            gs = hsh_next(group_hash,&g))
296         {
297           ssa += (gs->sum * gs->sum)/gs->n;
298         }
299       
300       ssa -= ( totals->sum * totals->sum ) / totals->n ;
301
302       const char *s = var_to_string(vars[i]);
303
304       tab_text (t, 0, i * 3 + 1, TAB_LEFT | TAT_TITLE, s);
305       tab_text (t, 1, i * 3 + 1, TAB_LEFT | TAT_TITLE, _("Between Groups"));
306       tab_text (t, 1, i * 3 + 2, TAB_LEFT | TAT_TITLE, _("Within Groups"));
307       tab_text (t, 1, i * 3 + 3, TAB_LEFT | TAT_TITLE, _("Total"));
308       
309       if (i > 0)
310         tab_hline(t, TAL_1, 0, n_cols - 1 , i * 3 + 1);
311
312       {
313         struct group_proc *gp = group_proc_get (vars[i]);
314         const double sst = totals->ssq - ( totals->sum * totals->sum) / totals->n ;
315         const double df1 = gp->n_groups - 1;
316         const double df2 = totals->n - gp->n_groups ;
317         const double msa = ssa / df1;
318         
319         gp->mse  = (sst - ssa) / df2;
320         
321         
322         /* Sums of Squares */
323         tab_float (t, 2, i * 3 + 1, 0, ssa, 10, 2);
324         tab_float (t, 2, i * 3 + 3, 0, sst, 10, 2);
325         tab_float (t, 2, i * 3 + 2, 0, sst - ssa, 10, 2);
326
327
328         /* Degrees of freedom */
329         tab_float (t, 3, i * 3 + 1, 0, df1, 4, 0);
330         tab_float (t, 3, i * 3 + 2, 0, df2, 4, 0);
331         tab_float (t, 3, i * 3 + 3, 0, totals->n - 1, 4, 0);
332
333         /* Mean Squares */
334         tab_float (t, 4, i * 3 + 1, TAB_RIGHT, msa, 8, 3);
335         tab_float (t, 4, i * 3 + 2, TAB_RIGHT, gp->mse, 8, 3);
336         
337
338         { 
339           const double F = msa/gp->mse ;
340
341           /* The F value */
342           tab_float (t, 5, i * 3 + 1, 0,  F, 8, 3);
343         
344           /* The significance */
345           tab_float (t, 6, i * 3 + 1, 0, gsl_cdf_fdist_Q(F,df1,df2), 8, 3);
346         }
347
348       }
349
350     }
351
352
353   tab_title (t, 0, _("ANOVA"));
354   tab_submit (t);
355
356
357 }
358
359 /* Show the descriptives table */
360 static void  
361 show_descriptives(void)
362 {
363   int v;
364   int n_cols =10;
365   struct tab_table *t;
366   int row;
367
368   const double confidence=0.95;
369   const double q = (1.0 - confidence) / 2.0;
370
371   
372   int n_rows = 2 ; 
373
374
375
376   for ( v = 0 ; v < n_vars ; ++v ) 
377     n_rows += group_proc_get (vars[v])->n_groups + 1;
378
379   t = tab_create (n_cols,n_rows,0);
380   tab_headers (t, 2, 0, 2, 0);
381   tab_dim (t, tab_natural_dimensions);
382
383
384   /* Put a frame around the entire box, and vertical lines inside */
385   tab_box (t, 
386            TAL_2, TAL_2,
387            -1, TAL_1,
388            0, 0,
389            n_cols - 1, n_rows - 1);
390
391   /* Underline headers */
392   tab_hline (t, TAL_2, 0, n_cols - 1, 2 );
393   tab_vline (t, TAL_2, 2, 0, n_rows - 1);
394   
395   tab_text (t, 2, 1, TAB_CENTER | TAT_TITLE, _("N"));
396   tab_text (t, 3, 1, TAB_CENTER | TAT_TITLE, _("Mean"));
397   tab_text (t, 4, 1, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
398   tab_text (t, 5, 1, TAB_CENTER | TAT_TITLE, _("Std. Error"));
399
400
401   tab_vline(t, TAL_0, 7, 0, 0);
402   tab_hline(t, TAL_1, 6, 7, 1);
403   tab_joint_text (t, 6, 0, 7, 0, TAB_CENTER | TAT_TITLE | TAT_PRINTF, _("%g%% Confidence Interval for Mean"),confidence*100.0);
404
405   tab_text (t, 6, 1, TAB_CENTER | TAT_TITLE, _("Lower Bound"));
406   tab_text (t, 7, 1, TAB_CENTER | TAT_TITLE, _("Upper Bound"));
407
408   tab_text (t, 8, 1, TAB_CENTER | TAT_TITLE, _("Minimum"));
409   tab_text (t, 9, 1, TAB_CENTER | TAT_TITLE, _("Maximum"));
410
411
412   tab_title (t, 0, _("Descriptives"));
413
414
415   row = 2;
416   for ( v=0 ; v < n_vars ; ++v ) 
417     {
418       double T;
419       double std_error;
420       
421       struct group_proc *gp = group_proc_get (vars[v]);
422
423       struct hsh_iterator g;
424       struct group_statistics *gs;
425       struct group_statistics *totals = &gp->ugs; 
426
427       int count = 0 ;      
428       const char *s = var_to_string(vars[v]);
429
430       struct hsh_table *group_hash = gp->group_hash;
431
432
433       tab_text (t, 0, row, TAB_LEFT | TAT_TITLE, s);
434       if ( v > 0) 
435         tab_hline(t, TAL_1, 0, n_cols - 1 , row);
436
437
438       for (gs =  hsh_first (group_hash,&g); 
439            gs != 0; 
440            gs = hsh_next(group_hash,&g))
441         {
442           tab_text (t, 1, row + count, 
443                     TAB_LEFT | TAT_TITLE ,value_to_string(&gs->id,indep_var));
444
445           /* Now fill in the numbers ... */
446
447           tab_float (t, 2, row + count, 0, gs->n, 8,0);
448
449           tab_float (t, 3, row + count, 0, gs->mean,8,2);
450           
451           tab_float (t, 4, row + count, 0, gs->std_dev,8,2);
452
453           std_error = gs->std_dev/sqrt(gs->n) ;
454           tab_float (t, 5, row + count, 0, 
455                      std_error, 8,2);
456
457           /* Now the confidence interval */
458       
459           T = gsl_cdf_tdist_Qinv(q,gs->n - 1);
460
461           tab_float(t, 6, row + count, 0,
462                     gs->mean - T * std_error, 8, 2); 
463
464           tab_float(t, 7, row + count, 0,
465                     gs->mean + T * std_error, 8, 2); 
466
467           /* Min and Max */
468
469           tab_float(t, 8, row + count, 0,  gs->minimum, 8, 2); 
470           tab_float(t, 9, row + count, 0,  gs->maximum, 8, 2); 
471
472           count++ ; 
473         }
474
475       tab_text (t, 1, row + count, 
476                 TAB_LEFT | TAT_TITLE ,_("Total"));
477
478       tab_float (t, 2, row + count, 0, totals->n, 8,0);
479
480       tab_float (t, 3, row + count, 0, totals->mean, 8,2);
481
482       tab_float (t, 4, row + count, 0, totals->std_dev,8,2);
483
484       std_error = totals->std_dev/sqrt(totals->n) ;
485
486       tab_float (t, 5, row + count, 0, std_error, 8,2);
487
488       /* Now the confidence interval */
489       
490       T = gsl_cdf_tdist_Qinv(q,totals->n - 1);
491
492       tab_float(t, 6, row + count, 0,
493                 totals->mean - T * std_error, 8, 2); 
494
495       tab_float(t, 7, row + count, 0,
496                 totals->mean + T * std_error, 8, 2); 
497
498       /* Min and Max */
499
500       tab_float(t, 8, row + count, 0,  totals->minimum, 8, 2); 
501       tab_float(t, 9, row + count, 0,  totals->maximum, 8, 2); 
502
503       row += gp->n_groups + 1;
504     }
505
506
507   tab_submit (t);
508
509
510 }
511
512 /* Show the homogeneity table */
513 static void 
514 show_homogeneity(void)
515 {
516   int v;
517   int n_cols = 5;
518   int n_rows = n_vars + 1;
519
520   struct tab_table *t;
521
522
523   t = tab_create (n_cols,n_rows,0);
524   tab_headers (t, 1, 0, 1, 0);
525   tab_dim (t, tab_natural_dimensions);
526
527   /* Put a frame around the entire box, and vertical lines inside */
528   tab_box (t, 
529            TAL_2, TAL_2,
530            -1, TAL_1,
531            0, 0,
532            n_cols - 1, n_rows - 1);
533
534
535   tab_hline(t, TAL_2, 0, n_cols - 1, 1);
536   tab_vline(t, TAL_2, 1, 0, n_rows - 1);
537
538
539   tab_text (t,  1, 0, TAB_CENTER | TAT_TITLE, _("Levene Statistic"));
540   tab_text (t,  2, 0, TAB_CENTER | TAT_TITLE, _("df1"));
541   tab_text (t,  3, 0, TAB_CENTER | TAT_TITLE, _("df2"));
542   tab_text (t,  4, 0, TAB_CENTER | TAT_TITLE, _("Significance"));
543   
544
545   tab_title (t, 0, _("Test of Homogeneity of Variances"));
546
547   for ( v=0 ; v < n_vars ; ++v ) 
548     {
549       double F;
550       const struct variable *var = vars[v];
551       const struct group_proc *gp = group_proc_get (vars[v]);
552       const char *s = var_to_string(var);
553       const struct group_statistics *totals = &gp->ugs;
554
555       const double df1 = gp->n_groups - 1;
556       const double df2 = totals->n - gp->n_groups ;
557
558       tab_text (t, 0, v + 1, TAB_LEFT | TAT_TITLE, s);
559
560       F = gp->levene;
561       tab_float (t, 1, v + 1, TAB_RIGHT, F, 8,3);
562       tab_float (t, 2, v + 1, TAB_RIGHT, df1 ,8,0);
563       tab_float (t, 3, v + 1, TAB_RIGHT, df2 ,8,0);
564
565       /* Now the significance */
566       tab_float (t, 4, v + 1, TAB_RIGHT,gsl_cdf_fdist_Q(F,df1,df2), 8, 3);
567     }
568
569   tab_submit (t);
570
571
572 }
573
574
575 /* Show the contrast coefficients table */
576 static void 
577 show_contrast_coeffs(short *bad_contrast)
578 {
579   int n_cols = 2 + ostensible_number_of_groups;
580   int n_rows = 2 + cmd.sbc_contrast;
581   struct hsh_iterator g;
582   union value *group_value;
583   int count = 0 ;      
584
585
586   struct tab_table *t;
587
588
589   t = tab_create (n_cols,n_rows,0);
590   tab_headers (t, 2, 0, 2, 0);
591   tab_dim (t, tab_natural_dimensions);
592
593   /* Put a frame around the entire box, and vertical lines inside */
594   tab_box (t, 
595            TAL_2, TAL_2,
596            -1, TAL_1,
597            0, 0,
598            n_cols - 1, n_rows - 1);
599
600
601   tab_box (t, 
602            -1,-1,
603            TAL_0, TAL_0,
604            2, 0,
605            n_cols - 1, 0);
606
607   tab_box (t,
608            -1,-1,
609            TAL_0, TAL_0,
610            0,0,
611            1,1);
612
613
614   tab_hline(t, TAL_1, 2, n_cols - 1, 1);
615
616
617   tab_hline(t, TAL_2, 0, n_cols - 1, 2);
618   tab_vline(t, TAL_2, 2, 0, n_rows - 1);
619
620
621   tab_title (t, 0, _("Contrast Coefficients"));
622
623   tab_text (t,  0, 2, TAB_LEFT | TAT_TITLE, _("Contrast"));
624
625
626
627   tab_joint_text (t, 2, 0, n_cols - 1, 0, TAB_CENTER | TAT_TITLE, 
628                   var_to_string(indep_var));
629
630   for (group_value =  hsh_first (global_group_hash,&g); 
631        group_value != 0; 
632        group_value = hsh_next(global_group_hash,&g))
633     {
634       int i;
635
636       tab_text (t, count + 2, 1, TAB_CENTER | TAT_TITLE, 
637                 value_to_string(group_value,indep_var));
638
639       for (i = 0 ; i < cmd.sbc_contrast ; ++i ) 
640         {
641
642           tab_text(t, 1, i + 2, TAB_CENTER | TAT_PRINTF, "%d", i + 1);
643
644           if ( bad_contrast[i] ) 
645             tab_text(t, count + 2, i + 2, TAB_RIGHT, "?" );
646           else
647             tab_text(t, count + 2, i + 2, TAB_RIGHT | TAT_PRINTF, "%g", 
648                      subc_list_double_at(&cmd.dl_contrast[i],count)
649                      );
650         }
651           
652       count++ ; 
653     }
654
655   tab_submit (t);
656
657 }
658
659
660 /* Show the results of the contrast tests */
661 static void 
662 show_contrast_tests(short *bad_contrast)
663 {
664   int v;
665   int n_cols = 8;
666   int n_rows = 1 + n_vars * 2 * cmd.sbc_contrast;
667
668   struct tab_table *t;
669
670   t = tab_create (n_cols,n_rows,0);
671   tab_headers (t, 3, 0, 1, 0);
672   tab_dim (t, tab_natural_dimensions);
673
674   /* Put a frame around the entire box, and vertical lines inside */
675   tab_box (t, 
676            TAL_2, TAL_2,
677            -1, TAL_1,
678            0, 0,
679            n_cols - 1, n_rows - 1);
680
681   tab_box (t, 
682            -1,-1,
683            TAL_0, TAL_0,
684            0, 0,
685            2, 0);
686
687   tab_hline(t, TAL_2, 0, n_cols - 1, 1);
688   tab_vline(t, TAL_2, 3, 0, n_rows - 1);
689
690
691   tab_title (t, 0, _("Contrast Tests"));
692
693   tab_text (t,  2, 0, TAB_CENTER | TAT_TITLE, _("Contrast"));
694   tab_text (t,  3, 0, TAB_CENTER | TAT_TITLE, _("Value of Contrast"));
695   tab_text (t,  4, 0, TAB_CENTER | TAT_TITLE, _("Std. Error"));
696   tab_text (t,  5, 0, TAB_CENTER | TAT_TITLE, _("t"));
697   tab_text (t,  6, 0, TAB_CENTER | TAT_TITLE, _("df"));
698   tab_text (t,  7, 0, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)"));
699
700   for ( v = 0 ; v < n_vars ; ++v ) 
701     {
702       int i;
703       int lines_per_variable = 2 * cmd.sbc_contrast;
704
705
706       tab_text (t,  0, (v * lines_per_variable) + 1, TAB_LEFT | TAT_TITLE,
707                 var_to_string(vars[v]));
708
709       for ( i = 0 ; i < cmd.sbc_contrast ; ++i ) 
710         {
711           int ci;
712           double contrast_value = 0.0;
713           double coef_msq = 0.0;
714           struct group_proc *grp_data = group_proc_get (vars[v]);
715           struct hsh_table *group_hash = grp_data->group_hash;
716           struct hsh_iterator g;
717           struct group_statistics *gs;
718
719           double T;
720           double std_error_contrast ;
721           double df;
722           double sec_vneq=0.0;
723
724
725           /* Note: The calculation of the degrees of freedom in the variances 
726              not  equal case is painfull!!
727              The following formula may help to understand it:
728              \frac{\left(\sum_{i=1}^k{c_i^2\frac{s_i^2}{n_i}}\right)^2}
729              {
730              \sum_{i=1}^k\left(
731              \frac{\left(c_i^2\frac{s_i^2}{n_i}\right)^2}  {n_i-1}
732              \right)
733              }
734           */
735
736           double df_denominator = 0.0;
737           double df_numerator = 0.0;
738
739           
740           if ( i == 0 ) 
741             {
742               tab_text (t,  1, (v * lines_per_variable) + i + 1, 
743                         TAB_LEFT | TAT_TITLE,
744                         _("Assume equal variances"));
745
746               tab_text (t,  1, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast, 
747                         TAB_LEFT | TAT_TITLE, 
748                         _("Does not assume equal"));
749             }
750
751           tab_text (t,  2, (v * lines_per_variable) + i + 1, 
752                     TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%d",i+1);
753
754
755           tab_text (t,  2, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast,
756                     TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%d",i+1);
757
758
759           if ( bad_contrast[i]) 
760             continue;
761
762           /* FIXME: Potential danger here.
763              We're ASSUMING THE array is in the order corresponding to the 
764              hash order. */
765           for (ci = 0, gs = hsh_first (group_hash,&g);  
766                gs != 0;
767                ++ci, gs = hsh_next(group_hash,&g))
768             {
769
770               const double coef = subc_list_double_at(&cmd.dl_contrast[i],ci);
771               const double winv = (gs->std_dev * gs->std_dev) / gs->n;
772
773               contrast_value += coef * gs->mean;
774
775               coef_msq += (coef * coef) / gs->n ; 
776
777               sec_vneq += (coef * coef) * (gs->std_dev * gs->std_dev ) /gs->n ;
778
779               df_numerator += (coef * coef) * winv;
780               df_denominator += pow2((coef * coef) * winv) / (gs->n - 1);
781
782             }
783           sec_vneq = sqrt(sec_vneq);
784
785           df_numerator = pow2(df_numerator);
786
787           tab_float (t,  3, (v * lines_per_variable) + i + 1, 
788                      TAB_RIGHT, contrast_value, 8,2);
789
790           tab_float (t,  3, (v * lines_per_variable) + i + 1 + 
791                      cmd.sbc_contrast,
792                      TAB_RIGHT, contrast_value, 8,2);
793
794           std_error_contrast = sqrt(grp_data->mse * coef_msq);
795
796           /* Std. Error */
797           tab_float (t,  4, (v * lines_per_variable) + i + 1, 
798                      TAB_RIGHT, std_error_contrast,
799                      8,3);
800
801           T = fabs(contrast_value / std_error_contrast) ;
802
803           /* T Statistic */
804
805           tab_float (t,  5, (v * lines_per_variable) + i + 1, 
806                      TAB_RIGHT, T,
807                      8,3);
808
809           df = grp_data->ugs.n - grp_data->n_groups;
810
811           /* Degrees of Freedom */
812           tab_float (t,  6, (v * lines_per_variable) + i + 1, 
813                      TAB_RIGHT,  df,
814                      8,0);
815
816
817           /* Significance TWO TAILED !!*/
818           tab_float (t,  7, (v * lines_per_variable) + i + 1, 
819                      TAB_RIGHT,  2 * gsl_cdf_tdist_Q(T,df),
820                      8,3);
821
822
823           /* Now for the Variances NOT Equal case */
824
825           /* Std. Error */
826           tab_float (t,  4, 
827                      (v * lines_per_variable) + i + 1 + cmd.sbc_contrast, 
828                      TAB_RIGHT, sec_vneq,
829                      8,3);
830
831
832           T = contrast_value / sec_vneq;
833           tab_float (t,  5, 
834                      (v * lines_per_variable) + i + 1 + cmd.sbc_contrast, 
835                      TAB_RIGHT, T,
836                      8,3);
837
838
839           df = df_numerator / df_denominator;
840
841           tab_float (t,  6, 
842                      (v * lines_per_variable) + i + 1 + cmd.sbc_contrast, 
843                      TAB_RIGHT, df,
844                      8,3);
845
846           /* The Significance */
847
848           tab_float (t, 7, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast,
849                      TAB_RIGHT,  2 * gsl_cdf_tdist_Q(T,df),
850                      8,3);
851
852
853         }
854
855       if ( v > 0 ) 
856         tab_hline(t, TAL_1, 0, n_cols - 1, (v * lines_per_variable) + 1);
857     }
858
859   tab_submit (t);
860
861 }
862
863
864 /* ONEWAY ANOVA Calculations */
865
866 static void  postcalc (  struct cmd_oneway *cmd UNUSED );
867
868 static void  precalc ( struct cmd_oneway *cmd UNUSED );
869
870
871
872 /* Pre calculations */
873 static void 
874 precalc ( struct cmd_oneway *cmd UNUSED )
875 {
876   int i=0;
877
878   for(i=0; i< n_vars ; ++i) 
879     {
880       struct group_proc *gp = group_proc_get (vars[i]);
881       struct group_statistics *totals = &gp->ugs;
882       
883       /* Create a hash for each of the dependent variables.
884          The hash contains a group_statistics structure, 
885          and is keyed by value of the independent variable */
886
887       gp->group_hash = 
888         hsh_create(4, 
889                    (hsh_compare_func *) compare_group,
890                    (hsh_hash_func *) hash_group,
891                    (hsh_free_func *) free_group,
892                    (void *) indep_var->width );
893
894
895       totals->sum=0;
896       totals->n=0;
897       totals->ssq=0;
898       totals->sum_diff=0;
899       totals->maximum = - DBL_MAX;
900       totals->minimum = DBL_MAX;
901     }
902 }
903
904
905 static void 
906 run_oneway(const struct casefile *cf, void *cmd_)
907 {
908   struct casereader *r;
909   struct ccase c;
910
911   struct cmd_oneway *cmd = (struct cmd_oneway *) cmd_;
912
913   global_group_hash = hsh_create(4, 
914                                  (hsh_compare_func *) compare_values,
915                                  (hsh_hash_func *) hash_value,
916                                  0,
917                                  (void *) indep_var->width );
918   precalc(cmd);
919
920   for(r = casefile_get_reader (cf);
921       casereader_read (r, &c) ;
922       case_destroy (&c)) 
923     {
924       int i;
925
926       const double weight = 
927         dict_get_case_weight(default_dict,&c,&bad_weight_warn);
928       
929       const union value *indep_val = case_data (&c, indep_var->fv);
930
931       /* Deal with missing values */
932       if ( value_is_missing(indep_val,indep_var) )
933         continue;
934
935       /* Skip the entire case if /MISSING=LISTWISE is set */
936       if ( cmd->miss == ONEWAY_LISTWISE ) 
937         {
938           for(i = 0; i < n_vars ; ++i) 
939             {
940               const struct variable *v = vars[i];
941               const union value *val = case_data (&c, v->fv);
942
943               if (value_is_missing(val,v) )
944                 break;
945             }
946           if ( i != n_vars ) 
947             continue;
948
949         }
950       
951           
952       hsh_insert ( global_group_hash, (void *) indep_val );
953
954       for ( i = 0 ; i < n_vars ; ++i ) 
955         {
956           const struct variable *v = vars[i];
957
958           const union value *val = case_data (&c, v->fv);
959
960           struct group_proc *gp = group_proc_get (vars[i]);
961           struct hsh_table *group_hash = gp->group_hash;
962
963           struct group_statistics *gs;
964
965           gs = hsh_find(group_hash, (void *) indep_val );
966
967           if ( ! gs ) 
968             {
969               gs = (struct group_statistics *) 
970                 xmalloc (sizeof(struct group_statistics));
971
972               gs->id = *indep_val;
973               gs->sum=0;
974               gs->n=0;
975               gs->ssq=0;
976               gs->sum_diff=0;
977               gs->minimum = DBL_MAX;
978               gs->maximum = -DBL_MAX;
979
980               hsh_insert ( group_hash, (void *) gs );
981             }
982           
983           if (! value_is_missing(val,v) )
984             {
985               struct group_statistics *totals = &gp->ugs;
986
987               totals->n+=weight;
988               totals->sum+=weight * val->f;
989               totals->ssq+=weight * val->f * val->f;
990
991               if ( val->f * weight  < totals->minimum ) 
992                 totals->minimum = val->f * weight;
993
994               if ( val->f * weight  > totals->maximum ) 
995                 totals->maximum = val->f * weight;
996
997               gs->n+=weight;
998               gs->sum+=weight * val->f;
999               gs->ssq+=weight * val->f * val->f;
1000
1001               if ( val->f * weight  < gs->minimum ) 
1002                 gs->minimum = val->f * weight;
1003
1004               if ( val->f * weight  > gs->maximum ) 
1005                 gs->maximum = val->f * weight;
1006             }
1007
1008           gp->n_groups = hsh_count ( group_hash );
1009         }
1010   
1011     }
1012   casereader_destroy (r);
1013
1014   postcalc(cmd);
1015
1016   
1017   if ( stat_tables & STAT_HOMO ) 
1018     levene(cf, indep_var, n_vars, vars, 
1019            (cmd->miss == ONEWAY_LISTWISE) ? LEV_LISTWISE : LEV_ANALYSIS ,
1020            value_is_missing);
1021
1022   ostensible_number_of_groups = hsh_count (global_group_hash);
1023
1024
1025   output_oneway();
1026
1027
1028 }
1029
1030
1031 /* Post calculations for the ONEWAY command */
1032 void 
1033 postcalc (  struct cmd_oneway *cmd UNUSED )
1034 {
1035   int i=0;
1036
1037
1038   for(i = 0; i < n_vars ; ++i) 
1039     {
1040       struct group_proc *gp = group_proc_get (vars[i]);
1041       struct hsh_table *group_hash = gp->group_hash;
1042       struct group_statistics *totals = &gp->ugs;
1043
1044       struct hsh_iterator g;
1045       struct group_statistics *gs;
1046
1047       for (gs =  hsh_first (group_hash,&g); 
1048            gs != 0; 
1049            gs = hsh_next(group_hash,&g))
1050         {
1051           gs->mean=gs->sum / gs->n;
1052           gs->s_std_dev= sqrt(
1053                               ( (gs->ssq / gs->n ) - gs->mean * gs->mean )
1054                               ) ;
1055
1056           gs->std_dev= sqrt(
1057                             gs->n/(gs->n-1) *
1058                             ( (gs->ssq / gs->n ) - gs->mean * gs->mean )
1059                             ) ;
1060
1061           gs->se_mean = gs->std_dev / sqrt(gs->n);
1062           gs->mean_diff= gs->sum_diff / gs->n;
1063
1064         }
1065
1066
1067
1068       totals->mean = totals->sum / totals->n;
1069       totals->std_dev= sqrt(
1070                             totals->n/(totals->n-1) *
1071                             ( (totals->ssq / totals->n ) - totals->mean * totals->mean )
1072                             ) ;
1073
1074       totals->se_mean = totals->std_dev / sqrt(totals->n);
1075         
1076     }
1077 }