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