376477c3f52fbf48877204c40f727fe9935c4324
[pspp] / src / t-test.q
1 /* PSPP - computes sample statistics. -*-c-*-
2
3    Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
4    Written by John Williams <johnr.williams@stonebow.otago.ac.nz>.
5    Almost completly re-written by John Darrington 2004
6
7    This program is free software; you can redistribute it and/or
8    modify it under the terms of the GNU General Public License as
9    published by the Free Software Foundation; either version 2 of the
10    License, or (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20    02111-1307, USA. */
21
22 #include <config.h>
23 #include <gsl/gsl_cdf.h>
24 #include "error.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <math.h>
28 #include "alloc.h"
29 #include "str.h"
30 #include "command.h"
31 #include "lexer.h"
32 #include "error.h"
33 #include "magic.h"
34 #include "misc.h"
35 #include "tab.h"
36 #include "som.h"
37 #include "value-labels.h"
38 #include "var.h"
39 #include "vfm.h"
40 #include "hash.h"
41 #include "t-test.h"
42 #include "casefile.h"
43 #include "levene.h"
44
45 /* (specification)
46    "T-TEST" (tts_):
47      +groups=custom;
48      +testval=double;
49      variables=varlist("PV_NO_SCRATCH | PV_NUMERIC");
50      pairs=custom;
51      +missing=miss:!analysis/listwise,
52              incl:include/!exclude;
53      format=fmt:!labels/nolabels;
54      criteria=:cin(d:criteria,"%s > 0. && %s < 1.").
55 */
56 /* (declarations) */
57 /* (functions) */
58
59
60
61
62 /* Function to use for testing for missing values */
63 static is_missing_func value_is_missing;
64
65 /* Variable for the GROUPS subcommand, if given. */
66 static struct variable *indep_var;
67
68 /* GROUPS: Number of values specified by the user; the values
69    specified if any. */
70
71 static int n_group_values;
72 static union value groups_values[2];
73 static enum comparison criteria[2];
74
75
76
77 /* PAIRS: Number of pairs to be compared ; each pair. */
78 static int n_pairs = 0 ;
79 struct pair 
80 {
81   /* The variables comprising the pair */
82   struct variable *v[2];
83
84   /* The number of valid variable pairs */
85   double n;
86
87   /* The sum of the members */
88   double sum[2];
89
90   /* sum of squares of the members */
91   double ssq[2];
92
93   /* Std deviation of the members */
94   double std_dev[2];
95
96
97   /* Sample Std deviation of the members */
98   double s_std_dev[2];
99
100   /* The means of the members */
101   double mean[2];
102
103   /* The correlation coefficient between the variables */
104   double correlation;
105
106   /* The sum of the differences */
107   double sum_of_diffs;
108
109   /* The sum of the products */
110   double sum_of_prod;
111
112   /* The mean of the differences */
113   double mean_diff;
114
115   /* The sum of the squares of the differences */
116   double ssq_diffs;
117
118   /* The std deviation of the differences */
119   double std_dev_diff;
120 };
121
122 static struct pair *pairs=0;
123
124 static int parse_value (union value * v, int type) ;
125
126 /* Structures and Functions for the Statistics Summary Box */
127 struct ssbox;
128 typedef void populate_ssbox_func(struct ssbox *ssb,
129                                             struct cmd_t_test *cmd);
130 typedef void finalize_ssbox_func(struct ssbox *ssb);
131
132 struct ssbox
133 {
134   struct tab_table *t;
135
136   populate_ssbox_func *populate;
137   finalize_ssbox_func *finalize;
138
139 };
140
141 /* Create a ssbox */
142 void ssbox_create(struct ssbox *ssb,   struct cmd_t_test *cmd, int mode);
143
144 /* Populate a ssbox according to cmd */
145 void ssbox_populate(struct ssbox *ssb, struct cmd_t_test *cmd);
146
147 /* Submit and destroy a ssbox */
148 void ssbox_finalize(struct ssbox *ssb);
149
150 /* A function to create, populate and submit the Paired Samples Correlation 
151    box */
152 void pscbox(void);
153
154
155 /* Structures and Functions for the Test Results Box */
156 struct trbox;
157
158 typedef void populate_trbox_func(struct trbox *trb,
159                                  struct cmd_t_test *cmd);
160 typedef void finalize_trbox_func(struct trbox *trb);
161
162 struct trbox {
163   struct tab_table *t;
164   populate_trbox_func *populate;
165   finalize_trbox_func *finalize;
166 };
167
168 /* Create a trbox */
169 void trbox_create(struct trbox *trb,   struct cmd_t_test *cmd, int mode);
170
171 /* Populate a ssbox according to cmd */
172 void trbox_populate(struct trbox *trb, struct cmd_t_test *cmd);
173
174 /* Submit and destroy a ssbox */
175 void trbox_finalize(struct trbox *trb);
176
177 /* Which mode was T-TEST invoked */
178 enum {
179   T_1_SAMPLE = 0 ,
180   T_IND_SAMPLES, 
181   T_PAIRED
182 };
183
184
185 static int common_calc (const struct ccase *, void *);
186 static void common_precalc (struct cmd_t_test *);
187 static void common_postcalc (struct cmd_t_test *);
188
189 static int one_sample_calc (const struct ccase *, void *);
190 static void one_sample_precalc (struct cmd_t_test *);
191 static void one_sample_postcalc (struct cmd_t_test *);
192
193 static int  paired_calc (const struct ccase *, void *);
194 static void paired_precalc (struct cmd_t_test *);
195 static void paired_postcalc (struct cmd_t_test *);
196
197 static void group_precalc (struct cmd_t_test *);
198 static int  group_calc (const struct ccase *, struct cmd_t_test *);
199 static void group_postcalc (struct cmd_t_test *);
200
201
202 static int compare_var_name (const void *a_, const void *b_, void *v_ UNUSED);
203 static unsigned hash_var_name (const void *a_, void *v_ UNUSED);
204
205 static void calculate(const struct casefile *cf, void *_mode);
206
207 static  int mode;
208
209 static struct cmd_t_test cmd;
210
211 static int bad_weight_warn;
212
213 int
214 cmd_t_test(void)
215 {
216
217
218
219   if ( !parse_t_test(&cmd) )
220     return CMD_FAILURE;
221
222   if (! cmd.sbc_criteria)
223     cmd.criteria=0.95;
224
225   {
226     int m=0;
227     if (cmd.sbc_testval) ++m;
228     if (cmd.sbc_groups) ++m;
229     if (cmd.sbc_pairs) ++m;
230
231     if ( m != 1)
232       {
233         msg(SE, 
234             _("TESTVAL, GROUPS and PAIRS subcommands are mutually exclusive.")
235             );
236         return CMD_FAILURE;
237       }
238   }
239
240   if (cmd.sbc_testval) 
241     mode=T_1_SAMPLE;
242   else if (cmd.sbc_groups)
243     mode=T_IND_SAMPLES;
244   else
245     mode=T_PAIRED;
246
247   if ( mode == T_PAIRED) 
248     {
249       if (cmd.sbc_variables) 
250         {
251           msg(SE, _("VARIABLES subcommand is not appropriate with PAIRS"));
252           return CMD_FAILURE;
253         }
254       else
255         {
256           /* Iterate through the pairs and put each variable that is a 
257              member of a pair into cmd.v_variables */
258
259           int i;
260           struct hsh_iterator hi;
261           struct hsh_table *hash;
262           struct variable *v;
263
264           hash=hsh_create(n_pairs,compare_var_name,hash_var_name,0,0);
265
266           for (i=0; i < n_pairs; ++i)
267             {
268               hsh_insert(hash,pairs[i].v[0]);
269               hsh_insert(hash,pairs[i].v[1]);
270             }
271
272           assert(cmd.n_variables == 0);
273           cmd.n_variables = hsh_count(hash);
274
275           cmd.v_variables = xrealloc(cmd.v_variables,
276                                      sizeof(struct variable) * cmd.n_variables);
277           /* Iterate through the hash */
278           for (i=0,v = (struct variable *) hsh_first(hash,&hi);
279                v != 0;
280                v=hsh_next(hash,&hi) ) 
281             cmd.v_variables[i++]=v;
282
283           hsh_destroy(hash);
284         }
285     }
286   else if ( !cmd.sbc_variables) 
287     {
288       msg(SE, _("One or more VARIABLES must be specified."));
289       return CMD_FAILURE;
290     }
291
292
293   /* If /MISSING=INCLUDE is set, then user missing values are ignored */
294   if (cmd.incl == TTS_INCLUDE ) 
295     value_is_missing = is_system_missing;
296   else
297     value_is_missing = is_missing;
298
299   bad_weight_warn = 1;
300
301   multipass_procedure_with_splits (calculate, &cmd);
302
303   n_pairs=0;
304   free(pairs);
305   pairs=0;
306
307   if ( mode == T_IND_SAMPLES) 
308     {
309       int i;
310       /* Destroy any group statistics we created */
311       for (i= 0 ; i < cmd.n_variables ; ++i ) 
312         {
313           free(cmd.v_variables[i]->p.t_t.gs);
314         }
315     }
316     
317   return CMD_SUCCESS;
318 }
319
320 static int
321 tts_custom_groups (struct cmd_t_test *cmd UNUSED)
322 {
323
324   lex_match('=');
325
326   if (token != T_ALL && 
327       (token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
328      ) 
329   {
330     msg(SE,_("`%s' is not a variable name"),tokid);
331     return 0;
332   }
333
334   indep_var = parse_variable ();
335   if (!indep_var)
336     {
337       lex_error ("expecting variable name in GROUPS subcommand");
338       return 0;
339     }
340
341   if (indep_var->type == T_STRING && indep_var->width > MAX_SHORT_STRING)
342     {
343       msg (SE, _("Long string variable %s is not valid here."),
344            indep_var->name);
345       return 0;
346     }
347
348   if (!lex_match ('('))
349     {
350       if (indep_var->type == NUMERIC)
351         {
352           groups_values[0].f = 1;
353           groups_values[1].f = 2;
354           criteria[0] = criteria[1] = CMP_EQ;
355           n_group_values = 2;
356           return 1;
357         }
358       else
359         {
360           msg (SE, _("When applying GROUPS to a string variable, at "
361                      "least one value must be specified."));
362           return 0;
363         }
364     }
365
366   if (!parse_value (&groups_values[0],indep_var->type))
367       return 0;
368
369   lex_match (',');
370   if (lex_match (')'))
371     {
372       criteria[0] =  CMP_LE;
373       criteria[1] =  CMP_GT;
374       groups_values[1] = groups_values[0];
375       n_group_values = 1;
376       return 1;
377     }
378
379   if (!parse_value (&groups_values[1],indep_var->type))
380     return 0;
381   
382   n_group_values = 2;
383   if (!lex_force_match (')'))
384     return 0;
385
386   criteria[0] = criteria[1] = CMP_EQ;
387   return 1;
388 }
389
390
391 static int
392 tts_custom_pairs (struct cmd_t_test *cmd UNUSED)
393 {
394   struct variable **vars;
395   int n_vars;
396   int n_pairs_local;
397
398   int n_before_WITH ;
399   int n_after_WITH = -1;
400   int paired ; /* Was the PAIRED keyword given ? */
401
402   lex_match('=');
403
404   if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
405       && token != T_ALL)
406     {
407       msg(SE,_("`%s' is not a variable name"),tokid);
408       return 0;
409     }
410
411   n_vars=0;
412   if (!parse_variables (default_dict, &vars, &n_vars,
413                         PV_DUPLICATE | PV_NUMERIC | PV_NO_SCRATCH))
414     {
415       free (vars);
416       return 0;
417     }
418   assert (n_vars);
419
420   n_before_WITH=0;
421   if (lex_match (T_WITH))
422     {
423       n_before_WITH = n_vars;
424       if (!parse_variables (default_dict, &vars, &n_vars,
425                             PV_DUPLICATE | PV_APPEND
426                             | PV_NUMERIC | PV_NO_SCRATCH))
427         {
428           free (vars);
429           return 0;
430         }
431       n_after_WITH = n_vars - n_before_WITH;
432     }
433
434   paired = (lex_match ('(') && lex_match_id ("PAIRED") && lex_match (')'));
435
436   /* Determine the number of pairs needed */
437   if (paired)
438     {
439       if (n_before_WITH != n_after_WITH)
440         {
441           free (vars);
442           msg (SE, _("PAIRED was specified but the number of variables "
443                      "preceding WITH (%d) did not match the number "
444                      "following (%d)."),
445                n_before_WITH, n_after_WITH );
446           return 0;
447         }
448       n_pairs_local=n_before_WITH;
449     }
450   else if (n_before_WITH > 0) /* WITH keyword given, but not PAIRED keyword */
451     {
452       n_pairs_local=n_before_WITH * n_after_WITH ;
453     }
454   else /* Neither WITH nor PAIRED keyword given */
455     {
456       if (n_vars < 2)
457         {
458           free (vars);
459           msg (SE, _("At least two variables must be specified "
460                      "on PAIRS."));
461           return 0;
462         }
463
464       /* how many ways can you pick 2 from n_vars ? */
465       n_pairs_local = n_vars * (n_vars -1 ) /2 ;
466     }
467
468
469   /* Allocate storage for the pairs */
470   pairs = xrealloc(pairs, sizeof(struct pair) * (n_pairs + n_pairs_local) );
471
472   /* Populate the pairs with the appropriate variables */
473   if ( paired ) 
474     {
475       int i;
476
477       assert(n_pairs_local == n_vars/2);
478       for (i = 0; i < n_pairs_local ; ++i)
479         {
480           pairs[i].v[n_pairs+0] = vars[i];
481           pairs[i].v[n_pairs+1] = vars[i+n_pairs_local];
482         }
483     }
484   else if (n_before_WITH > 0) /* WITH keyword given, but not PAIRED keyword */
485     {
486       int i,j;
487       int p=n_pairs;
488
489       for(i=0 ; i < n_before_WITH ; ++i ) 
490         {
491           for(j=0 ; j < n_after_WITH ; ++j)
492             {
493               pairs[p].v[0] = vars[i];
494               pairs[p].v[1] = vars[j+n_before_WITH];
495               ++p;
496             }
497         }
498     }
499   else /* Neither WITH nor PAIRED given */
500     {
501       int i,j;
502       int p=n_pairs;
503       
504       for(i=0 ; i < n_vars ; ++i ) 
505         {
506           for(j=i+1 ; j < n_vars ; ++j)
507             {
508               pairs[p].v[0] = vars[i];
509               pairs[p].v[1] = vars[j];
510               ++p;
511             }
512         }
513     }
514
515   n_pairs+=n_pairs_local;
516
517   return 1;
518 }
519
520 /* Parses the current token (numeric or string, depending on type)
521     value v and returns success. */
522 static int
523 parse_value (union value * v, int type )
524 {
525   if (type == NUMERIC)
526     {
527       if (!lex_force_num ())
528         return 0;
529       v->f = tokval;
530     }
531   else
532     {
533       if (!lex_force_string ())
534         return 0;
535       strncpy (v->s, ds_c_str (&tokstr), ds_length (&tokstr));
536     }
537
538   lex_get ();
539
540   return 1;
541 }
542
543
544 /* Implementation of the SSBOX object */
545
546 void ssbox_base_init(struct ssbox *this, int cols,int rows);
547
548 void ssbox_base_finalize(struct ssbox *ssb);
549
550 void ssbox_one_sample_init(struct ssbox *this, 
551                            struct cmd_t_test *cmd );
552
553 void ssbox_independent_samples_init(struct ssbox *this,
554                                     struct cmd_t_test *cmd);
555
556 void ssbox_paired_init(struct ssbox *this,
557                            struct cmd_t_test *cmd);
558
559 /* Factory to create an ssbox */
560 void 
561 ssbox_create(struct ssbox *ssb, struct cmd_t_test *cmd, int mode)
562 {
563     switch (mode) 
564       {
565       case T_1_SAMPLE:
566         ssbox_one_sample_init(ssb,cmd);
567         break;
568       case T_IND_SAMPLES:
569         ssbox_independent_samples_init(ssb,cmd);
570         break;
571       case T_PAIRED:
572         ssbox_paired_init(ssb,cmd);
573         break;
574       default:
575         assert(0);
576       }
577 }
578
579
580 /* Despatcher for the populate method */
581 void
582 ssbox_populate(struct ssbox *ssb,struct cmd_t_test *cmd)
583 {
584   ssb->populate(ssb,cmd);
585 }
586
587
588 /* Despatcher for finalize */
589 void
590 ssbox_finalize(struct ssbox *ssb)
591 {
592   ssb->finalize(ssb);
593 }
594
595
596 /* Submit the box and clear up */
597 void 
598 ssbox_base_finalize(struct ssbox *ssb)
599 {
600   tab_submit(ssb->t);
601 }
602
603 /* Initialize a ssbox struct */
604 void 
605 ssbox_base_init(struct ssbox *this, int cols,int rows)
606 {
607   this->finalize = ssbox_base_finalize;
608   this->t = tab_create (cols, rows, 0);
609
610   tab_columns (this->t, SOM_COL_DOWN, 1);
611   tab_headers (this->t,0,0,1,0); 
612   tab_box (this->t, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols -1, rows -1 );
613   tab_hline(this->t, TAL_2,0,cols-1,1);
614   tab_dim (this->t, tab_natural_dimensions);
615 }
616
617 void  ssbox_one_sample_populate(struct ssbox *ssb,
618                               struct cmd_t_test *cmd);
619
620 /* Initialize the one_sample ssbox */
621 void 
622 ssbox_one_sample_init(struct ssbox *this, 
623                            struct cmd_t_test *cmd )
624 {
625   const int hsize=5;
626   const int vsize=cmd->n_variables+1;
627
628   this->populate = ssbox_one_sample_populate;
629
630   ssbox_base_init(this, hsize,vsize);
631   tab_title (this->t, 0, _("One-Sample Statistics"));
632   tab_vline(this->t, TAL_2, 1,0,vsize);
633   tab_text (this->t, 1, 0, TAB_CENTER | TAT_TITLE, _("N"));
634   tab_text (this->t, 2, 0, TAB_CENTER | TAT_TITLE, _("Mean"));
635   tab_text (this->t, 3, 0, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
636   tab_text (this->t, 4, 0, TAB_CENTER | TAT_TITLE, _("SE. Mean"));
637 }
638
639 void ssbox_independent_samples_populate(struct ssbox *ssb,
640                                         struct cmd_t_test *cmd);
641
642 /* Initialize the independent samples ssbox */
643 void 
644 ssbox_independent_samples_init(struct ssbox *this, 
645         struct cmd_t_test *cmd)
646 {
647   int hsize=6;
648   int vsize = cmd->n_variables*2 +1;
649
650   this->populate = ssbox_independent_samples_populate;
651
652   ssbox_base_init(this, hsize,vsize);
653   tab_title (this->t, 0, _("Group Statistics"));
654   tab_vline(this->t,0,1,0,vsize);
655   tab_text (this->t, 1, 0, TAB_CENTER | TAT_TITLE, indep_var->name);
656   tab_text (this->t, 2, 0, TAB_CENTER | TAT_TITLE, _("N"));
657   tab_text (this->t, 3, 0, TAB_CENTER | TAT_TITLE, _("Mean"));
658   tab_text (this->t, 4, 0, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
659   tab_text (this->t, 5, 0, TAB_CENTER | TAT_TITLE, _("SE. Mean"));
660 }
661
662
663 /* Populate the ssbox for independent samples */
664 void 
665 ssbox_independent_samples_populate(struct ssbox *ssb,
666                               struct cmd_t_test *cmd)
667 {
668   int i;
669
670   char *val_lab0=0;
671   char *val_lab1=0;
672
673   char prefix[2][3]={"",""};
674
675   if ( indep_var->type == NUMERIC ) 
676     {
677       val_lab0 = val_labs_find( indep_var->val_labs,groups_values[0]); 
678       val_lab1 = val_labs_find( indep_var->val_labs,groups_values[1]);
679     }
680   else
681     {
682       val_lab0 = groups_values[0].s;
683       val_lab1 = groups_values[1].s;
684     }
685
686   if (n_group_values == 1) 
687     {
688       strcpy(prefix[0],"< ");
689       strcpy(prefix[1],">=");
690     }
691
692   assert(ssb->t);
693
694   for (i=0; i < cmd->n_variables; ++i)
695     {
696       int g;
697
698       tab_text (ssb->t, 0, i*2+1, TAB_LEFT, cmd->v_variables[i]->name);
699
700       if (val_lab0)
701         tab_text (ssb->t, 1, i*2+1, TAB_LEFT | TAT_PRINTF, 
702                   "%s%s", prefix[0], val_lab0);
703       else
704         tab_text (ssb->t, 1, i*2+1, TAB_LEFT | TAT_PRINTF, 
705                   "%s%g", prefix[0], groups_values[0].f); 
706
707
708       if (val_lab1)
709         tab_text (ssb->t, 1, i*2+1+1, TAB_LEFT | TAT_PRINTF, 
710                   "%s%s", prefix[1], val_lab1);
711       else
712         tab_text (ssb->t, 1, i*2+1+1, TAB_LEFT | TAT_PRINTF, 
713                   "%s%g", prefix[1], groups_values[1].f); 
714
715       /* Fill in the group statistics */
716       for ( g=0; g < 2 ; ++g ) 
717         {
718           struct group_statistics *gs = &cmd->v_variables[i]->p.t_t.gs[g];
719
720           tab_float(ssb->t, 2 ,i*2+g+1, TAB_RIGHT, gs->n, 2, 0);
721           tab_float(ssb->t, 3 ,i*2+g+1, TAB_RIGHT, gs->mean, 8, 2);
722           tab_float(ssb->t, 4 ,i*2+g+1, TAB_RIGHT, gs->std_dev, 8, 3);
723           tab_float(ssb->t, 5 ,i*2+g+1, TAB_RIGHT, gs->se_mean, 8, 3);
724         }
725     }
726 }
727
728
729 void ssbox_paired_populate(struct ssbox *ssb,
730                            struct cmd_t_test *cmd);
731
732 /* Initialize the paired values ssbox */
733 void 
734 ssbox_paired_init(struct ssbox *this, struct cmd_t_test *cmd UNUSED)
735 {
736   int hsize=6;
737
738   int vsize = n_pairs*2+1;
739
740   this->populate = ssbox_paired_populate;
741
742   ssbox_base_init(this, hsize,vsize);
743   tab_title (this->t, 0, _("Paired Sample Statistics"));
744   tab_vline(this->t,TAL_0,1,0,vsize-1);
745   tab_vline(this->t,TAL_2,2,0,vsize-1);
746   tab_text (this->t, 2, 0, TAB_CENTER | TAT_TITLE, _("Mean"));
747   tab_text (this->t, 3, 0, TAB_CENTER | TAT_TITLE, _("N"));
748   tab_text (this->t, 4, 0, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
749   tab_text (this->t, 5, 0, TAB_CENTER | TAT_TITLE, _("SE. Mean"));
750 }
751
752
753 /* Populate the ssbox for paired values */
754 void 
755 ssbox_paired_populate(struct ssbox *ssb,struct cmd_t_test *cmd UNUSED)
756 {
757   int i;
758
759   assert(ssb->t);
760
761   for (i=0; i < n_pairs; ++i)
762     {
763       int j;
764
765       tab_text (ssb->t, 0, i*2+1, TAB_LEFT | TAT_PRINTF , _("Pair %d"),i);
766
767       for (j=0 ; j < 2 ; ++j) 
768         {
769           struct group_statistics *gs;
770
771           gs=&pairs[i].v[j]->p.t_t.ugs;
772
773           /* Titles */
774
775           tab_text (ssb->t, 1, i*2+j+1, TAB_LEFT, pairs[i].v[j]->name);
776
777           /* Values */
778           tab_float (ssb->t,2, i*2+j+1, TAB_RIGHT, pairs[i].mean[j], 8, 2);
779           tab_float (ssb->t,3, i*2+j+1, TAB_RIGHT, pairs[i].n, 2, 0);
780           tab_float (ssb->t,4, i*2+j+1, TAB_RIGHT, pairs[i].std_dev[j], 8, 3);
781           tab_float (ssb->t,5, i*2+j+1, TAB_RIGHT, pairs[i].std_dev[j]/sqrt(pairs[i].n), 8, 3);
782
783         }
784     }
785 }
786
787 /* Populate the one sample ssbox */
788 void 
789 ssbox_one_sample_populate(struct ssbox *ssb, struct cmd_t_test *cmd)
790 {
791   int i;
792
793   assert(ssb->t);
794
795   for (i=0; i < cmd->n_variables; ++i)
796     {
797       struct group_statistics *gs;
798       gs= &cmd->v_variables[i]->p.t_t.ugs;
799
800       tab_text (ssb->t, 0, i+1, TAB_LEFT, cmd->v_variables[i]->name);
801       tab_float (ssb->t,1, i+1, TAB_RIGHT, gs->n, 2, 0);
802       tab_float (ssb->t,2, i+1, TAB_RIGHT, gs->mean, 8, 2);
803       tab_float (ssb->t,3, i+1, TAB_RIGHT, gs->std_dev, 8, 2);
804       tab_float (ssb->t,4, i+1, TAB_RIGHT, gs->se_mean, 8, 3);
805     }
806   
807 }
808
809
810
811 /* Implementation of the Test Results box struct */
812
813 void trbox_base_init(struct trbox *self,int n_vars, int cols);
814 void trbox_base_finalize(struct trbox *trb);
815
816 void trbox_independent_samples_init(struct trbox *trb,
817                                     struct cmd_t_test *cmd );
818
819 void trbox_independent_samples_populate(struct trbox *trb,
820                                         struct cmd_t_test *cmd);
821
822 void trbox_one_sample_init(struct trbox *self,
823                       struct cmd_t_test *cmd );
824
825 void trbox_one_sample_populate(struct trbox *trb,
826                                struct cmd_t_test *cmd);
827
828 void trbox_paired_init(struct trbox *self,
829                        struct cmd_t_test *cmd );
830
831 void trbox_paired_populate(struct trbox *trb,
832                       struct cmd_t_test *cmd);
833
834
835
836 /* Create a trbox according to mode*/
837 void 
838 trbox_create(struct trbox *trb,   
839              struct cmd_t_test *cmd, int mode)
840 {
841     switch (mode) 
842       {
843       case T_1_SAMPLE:
844         trbox_one_sample_init(trb,cmd);
845         break;
846       case T_IND_SAMPLES:
847         trbox_independent_samples_init(trb,cmd);
848         break;
849       case T_PAIRED:
850         trbox_paired_init(trb,cmd);
851         break;
852       default:
853         assert(0);
854       }
855 }
856
857 /* Populate a trbox according to cmd */
858 void 
859 trbox_populate(struct trbox *trb, struct cmd_t_test *cmd)
860 {
861   trb->populate(trb,cmd);
862 }
863
864 /* Submit and destroy a trbox */
865 void 
866 trbox_finalize(struct trbox *trb)
867 {
868   trb->finalize(trb);
869 }
870
871 /* Initialize the independent samples trbox */
872 void 
873 trbox_independent_samples_init(struct trbox *self,
874                            struct cmd_t_test *cmd UNUSED)
875 {
876   const int hsize=11;
877   const int vsize=cmd->n_variables*2+3;
878
879   assert(self);
880   self->populate = trbox_independent_samples_populate;
881
882   trbox_base_init(self,cmd->n_variables*2,hsize);
883   tab_title(self->t,0,_("Independent Samples Test"));
884   tab_hline(self->t,TAL_1,2,hsize-1,1);
885   tab_vline(self->t,TAL_2,2,0,vsize-1);
886   tab_vline(self->t,TAL_1,4,0,vsize-1);
887   tab_box(self->t,-1,-1,-1,TAL_1, 2,1,hsize-2,vsize-1);
888   tab_hline(self->t,TAL_1, hsize-2,hsize-1,2);
889   tab_box(self->t,-1,-1,-1,TAL_1, hsize-2,2,hsize-1,vsize-1);
890   tab_joint_text(self->t, 2, 0, 3, 0, 
891                  TAB_CENTER,_("Levene's Test for Equality of Variances"));
892   tab_joint_text(self->t, 4,0,hsize-1,0,
893                  TAB_CENTER,_("t-test for Equality of Means"));
894
895   tab_text(self->t,2,2, TAB_CENTER | TAT_TITLE,_("F"));
896   tab_text(self->t,3,2, TAB_CENTER | TAT_TITLE,_("Sig."));
897   tab_text(self->t,4,2, TAB_CENTER | TAT_TITLE,_("t"));
898   tab_text(self->t,5,2, TAB_CENTER | TAT_TITLE,_("df"));
899   tab_text(self->t,6,2, TAB_CENTER | TAT_TITLE,_("Sig. (2-tailed)"));
900   tab_text(self->t,7,2, TAB_CENTER | TAT_TITLE,_("Mean Difference"));
901   tab_text(self->t,8,2, TAB_CENTER | TAT_TITLE,_("Std. Error Difference"));
902   tab_text(self->t,9,2, TAB_CENTER | TAT_TITLE,_("Lower"));
903   tab_text(self->t,10,2, TAB_CENTER | TAT_TITLE,_("Upper"));
904
905   tab_joint_text(self->t, 9, 1, 10, 1, TAB_CENTER | TAT_PRINTF, 
906                  _("%g%% Confidence Interval of the Difference"),
907                  cmd->criteria*100.0);
908
909 }
910
911 /* Populate the independent samples trbox */
912 void 
913 trbox_independent_samples_populate(struct trbox *self,
914                                    struct cmd_t_test *cmd )
915 {
916   int i;
917
918   assert(self);
919   for (i=0; i < cmd->n_variables; ++i)
920     {
921       double p,q;
922
923       double t;
924       double df;
925
926       double df1, df2;
927
928       double pooled_variance;
929       double std_err_diff;
930       double mean_diff;
931
932       struct group_statistics *gs0 = &cmd->v_variables[i]->p.t_t.gs[0];
933       struct group_statistics *gs1 = &cmd->v_variables[i]->p.t_t.gs[1];
934           
935       tab_text (self->t, 0, i*2+3, TAB_LEFT, cmd->v_variables[i]->name);
936
937       tab_text (self->t, 1, i*2+3, TAB_LEFT, _("Equal variances assumed"));
938
939
940       tab_float(self->t, 2, i*2+3, TAB_CENTER, 
941                 cmd->v_variables[i]->p.t_t.levene, 8,3);
942
943       /* Now work out the significance of the Levene test */
944       df1 = 1; df2 = cmd->v_variables[i]->p.t_t.ugs.n - 2;
945       q = gsl_cdf_fdist_Q(cmd->v_variables[i]->p.t_t.levene, df1, df2);
946
947       tab_float(self->t, 3, i*2+3, TAB_CENTER, q, 8,3 );
948
949       df = gs0->n + gs1->n - 2.0 ;
950       tab_float (self->t, 5, i*2+3, TAB_RIGHT, df, 2, 0);
951
952       pooled_variance = ( (gs0->n )*pow2(gs0->s_std_dev)
953                           + 
954                           (gs1->n )*pow2(gs1->s_std_dev) 
955                         ) / df  ;
956
957       t = (gs0->mean - gs1->mean) / sqrt(pooled_variance) ;
958       t /= sqrt((gs0->n + gs1->n)/(gs0->n*gs1->n)); 
959
960       tab_float (self->t, 4, i*2+3, TAB_RIGHT, t, 8, 3);
961
962       p = gsl_cdf_tdist_P(t, df);
963       q = gsl_cdf_tdist_Q(t, df);
964
965       tab_float(self->t, 6, i*2+3, TAB_RIGHT, 2.0*(t>0?q:p) , 8, 3);
966
967       mean_diff = gs0->mean - gs1->mean;
968       tab_float(self->t, 7, i*2+3, TAB_RIGHT, mean_diff, 8, 3);
969
970
971       std_err_diff = sqrt( pow2(gs0->se_mean) + pow2(gs1->se_mean));
972       tab_float(self->t, 8, i*2+3, TAB_RIGHT, std_err_diff, 8, 3);
973
974
975       /* Now work out the confidence interval */
976       q = (1 - cmd->criteria)/2.0;  /* 2-tailed test */
977
978       t = gsl_cdf_tdist_Qinv(q,df);
979       tab_float(self->t, 9, i*2+3, TAB_RIGHT, 
980                 mean_diff - t * std_err_diff, 8, 3); 
981
982       tab_float(self->t, 10, i*2+3, TAB_RIGHT, 
983                 mean_diff + t * std_err_diff, 8, 3); 
984
985
986       {
987         double se2;
988       /* Now for the \sigma_1 != \sigma_2 case */
989       tab_text (self->t, 1, i*2+3+1, 
990                 TAB_LEFT, _("Equal variances not assumed"));
991
992
993       se2 = (pow2(gs0->s_std_dev)/(gs0->n -1) ) +
994         (pow2(gs1->s_std_dev)/(gs1->n -1) );
995
996       t = mean_diff / sqrt(se2) ;
997       tab_float (self->t, 4, i*2+3+1, TAB_RIGHT, t, 8, 3);
998                 
999       df = pow2(se2) / ( 
1000                        (pow2(pow2(gs0->s_std_dev)/(gs0->n - 1 )) 
1001                         /(gs0->n -1 )
1002                         )
1003                        + 
1004                        (pow2(pow2(gs1->s_std_dev)/(gs1->n - 1 ))
1005                         /(gs1->n -1 )
1006                         )
1007                        ) ;
1008       tab_float (self->t, 5, i*2+3+1, TAB_RIGHT, df, 8, 3);
1009
1010       p = gsl_cdf_tdist_P(t, df);
1011       q = gsl_cdf_tdist_Q(t, df);
1012
1013       tab_float(self->t, 6, i*2+3+1, TAB_RIGHT, 2.0*(t>0?q:p) , 8, 3);
1014
1015       /* Now work out the confidence interval */
1016       q = (1 - cmd->criteria)/2.0;  /* 2-tailed test */
1017
1018       t = gsl_cdf_tdist_Qinv(q, df);
1019
1020       tab_float(self->t, 7, i*2+3+1, TAB_RIGHT, mean_diff, 8, 3);
1021
1022
1023       tab_float(self->t, 8, i*2+3+1, TAB_RIGHT, std_err_diff, 8, 3);
1024
1025
1026       tab_float(self->t, 9, i*2+3+1, TAB_RIGHT, 
1027                 mean_diff - t * std_err_diff, 8, 3); 
1028
1029       tab_float(self->t, 10, i*2+3+1, TAB_RIGHT, 
1030                 mean_diff + t * std_err_diff, 8, 3); 
1031
1032       }
1033     }
1034 }
1035
1036 /* Initialize the paired samples trbox */
1037 void 
1038 trbox_paired_init(struct trbox *self,
1039                            struct cmd_t_test *cmd UNUSED)
1040 {
1041
1042   const int hsize=10;
1043   const int vsize=n_pairs+3;
1044
1045   self->populate = trbox_paired_populate;
1046
1047   trbox_base_init(self,n_pairs,hsize);
1048   tab_title (self->t, 0, _("Paired Samples Test"));
1049   tab_hline(self->t,TAL_1,2,6,1);
1050   tab_vline(self->t,TAL_2,2,0,vsize);
1051   tab_joint_text(self->t,2,0,6,0,TAB_CENTER,_("Paired Differences"));
1052   tab_box(self->t,-1,-1,-1,TAL_1, 2,1,6,vsize-1);
1053   tab_box(self->t,-1,-1,-1,TAL_1, 6,0,hsize-1,vsize-1);
1054   tab_hline(self->t,TAL_1,5,6, 2);
1055   tab_vline(self->t,TAL_0,6,0,1);
1056
1057   tab_joint_text(self->t, 5, 1, 6, 1, TAB_CENTER | TAT_PRINTF, 
1058                  _("%g%% Confidence Interval of the Difference"),
1059                  cmd->criteria*100.0);
1060
1061   tab_text (self->t, 2, 2, TAB_CENTER | TAT_TITLE, _("Mean"));
1062   tab_text (self->t, 3, 2, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
1063   tab_text (self->t, 4, 2, TAB_CENTER | TAT_TITLE, _("Std. Error Mean"));
1064   tab_text (self->t, 5, 2, TAB_CENTER | TAT_TITLE, _("Lower"));
1065   tab_text (self->t, 6, 2, TAB_CENTER | TAT_TITLE, _("Upper"));
1066   tab_text (self->t, 7, 2, TAB_CENTER | TAT_TITLE, _("t"));
1067   tab_text (self->t, 8, 2, TAB_CENTER | TAT_TITLE, _("df"));
1068   tab_text (self->t, 9, 2, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)"));
1069 }
1070
1071 /* Populate the paired samples trbox */
1072 void 
1073 trbox_paired_populate(struct trbox *trb,
1074                               struct cmd_t_test *cmd UNUSED)
1075 {
1076   int i;
1077
1078   for (i=0; i < n_pairs; ++i)
1079     {
1080       double p,q;
1081       double se_mean;
1082
1083       double n = pairs[i].n;
1084       double t;
1085       double df = n - 1;
1086       
1087       tab_text (trb->t, 0, i+3, TAB_LEFT | TAT_PRINTF, _("Pair %d"),i); 
1088
1089       tab_text (trb->t, 1, i+3, TAB_LEFT | TAT_PRINTF, "%s - %s",
1090                 pairs[i].v[0]->name, pairs[i].v[1]->name);
1091
1092       tab_float(trb->t, 2, i+3, TAB_RIGHT, pairs[i].mean_diff, 8, 4);
1093
1094       tab_float(trb->t, 3, i+3, TAB_RIGHT, pairs[i].std_dev_diff, 8, 5);
1095
1096       /* SE Mean */
1097       se_mean = pairs[i].std_dev_diff / sqrt(n) ;
1098       tab_float(trb->t, 4, i+3, TAB_RIGHT, se_mean, 8,5 );
1099
1100       /* Now work out the confidence interval */
1101       q = (1 - cmd->criteria)/2.0;  /* 2-tailed test */
1102
1103       t = gsl_cdf_tdist_Qinv(q, df);
1104
1105       tab_float(trb->t, 5, i+3, TAB_RIGHT, 
1106                 pairs[i].mean_diff - t * se_mean , 8, 4); 
1107
1108       tab_float(trb->t, 6, i+3, TAB_RIGHT, 
1109                 pairs[i].mean_diff + t * se_mean , 8, 4); 
1110
1111       t = (pairs[i].mean[0] - pairs[i].mean[1])
1112         / sqrt (
1113                 ( pow2 (pairs[i].s_std_dev[0]) + pow2 (pairs[i].s_std_dev[1]) -
1114                   2 * pairs[i].correlation * 
1115                   pairs[i].s_std_dev[0] * pairs[i].s_std_dev[1] )
1116                 / (n - 1)
1117                 );
1118
1119       tab_float(trb->t, 7, i+3, TAB_RIGHT, t , 8,3 );
1120
1121       /* Degrees of freedom */
1122       tab_float(trb->t, 8, i+3, TAB_RIGHT, df , 2, 0 );
1123
1124       p = gsl_cdf_tdist_P(t,df);
1125       q = gsl_cdf_tdist_P(t,df);
1126
1127       tab_float(trb->t, 9, i+3, TAB_RIGHT, 2.0*(t>0?q:p) , 8, 3);
1128
1129     }
1130 }
1131
1132 /* Initialize the one sample trbox */
1133 void 
1134 trbox_one_sample_init(struct trbox *self, struct cmd_t_test *cmd )
1135 {
1136   const int hsize=7;
1137   const int vsize=cmd->n_variables+3;
1138
1139   self->populate = trbox_one_sample_populate;
1140
1141   trbox_base_init(self, cmd->n_variables,hsize);
1142   tab_title (self->t, 0, _("One-Sample Test"));
1143   tab_hline(self->t, TAL_1, 1, hsize - 1, 1);
1144   tab_vline(self->t, TAL_2, 1, 0, vsize);
1145
1146   tab_joint_text(self->t, 1, 0, hsize-1,0, TAB_CENTER | TAT_PRINTF, 
1147                  _("Test Value = %f"),cmd->n_testval);
1148
1149   tab_box(self->t, -1, -1, -1, TAL_1, 1,1,hsize-1,vsize-1);
1150
1151
1152   tab_joint_text(self->t,5,1,6,1,TAB_CENTER  | TAT_PRINTF, 
1153                  _("%g%% Confidence Interval of the Difference"),
1154                  cmd->criteria*100.0);
1155
1156   tab_vline(self->t,TAL_0,6,1,1);
1157   tab_hline(self->t,TAL_1,5,6,2);
1158   tab_text (self->t, 1, 2, TAB_CENTER | TAT_TITLE, _("t"));
1159   tab_text (self->t, 2, 2, TAB_CENTER | TAT_TITLE, _("df"));
1160   tab_text (self->t, 3, 2, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)"));
1161   tab_text (self->t, 4, 2, TAB_CENTER | TAT_TITLE, _("Mean Difference"));
1162   tab_text (self->t, 5, 2, TAB_CENTER | TAT_TITLE, _("Lower"));
1163   tab_text (self->t, 6, 2, TAB_CENTER | TAT_TITLE, _("Upper"));
1164
1165 }
1166
1167
1168 /* Populate the one sample trbox */
1169 void 
1170 trbox_one_sample_populate(struct trbox *trb, struct cmd_t_test *cmd)
1171 {
1172   int i;
1173
1174   assert(trb->t);
1175
1176   for (i=0; i < cmd->n_variables; ++i)
1177     {
1178       double t;
1179       double p,q;
1180       double df;
1181       struct group_statistics *gs;
1182       gs= &cmd->v_variables[i]->p.t_t.ugs;
1183
1184
1185       tab_text (trb->t, 0, i+3, TAB_LEFT, cmd->v_variables[i]->name);
1186
1187       t = (gs->mean - cmd->n_testval ) * sqrt(gs->n) / gs->std_dev ;
1188
1189       tab_float (trb->t, 1, i+3, TAB_RIGHT, t, 8,3);
1190
1191       /* degrees of freedom */
1192       df = gs->n - 1;
1193
1194       tab_float (trb->t, 2, i+3, TAB_RIGHT, df, 8,0);
1195
1196       p = gsl_cdf_tdist_P(t, df);
1197       q = gsl_cdf_tdist_Q(t, df);
1198
1199       /* Multiply by 2 to get 2-tailed significance, makeing sure we've got 
1200          the correct tail*/
1201       tab_float (trb->t, 3, i+3, TAB_RIGHT, 2.0*(t>0?q:p), 8,3);
1202
1203       tab_float (trb->t, 4, i+3, TAB_RIGHT, gs->mean_diff, 8,3);
1204
1205
1206       q = (1 - cmd->criteria)/2.0;  /* 2-tailed test */
1207       t = gsl_cdf_tdist_Qinv(q, df);
1208
1209       tab_float (trb->t, 5, i+3, TAB_RIGHT,
1210                  gs->mean_diff - t * gs->se_mean, 8,4);
1211
1212       tab_float (trb->t, 6, i+3, TAB_RIGHT,
1213                  gs->mean_diff + t * gs->se_mean, 8,4);
1214     }
1215 }
1216
1217 /* Base initializer for the generalized trbox */
1218 void 
1219 trbox_base_init(struct trbox *self, int data_rows, int cols)
1220 {
1221   const int rows = 3 + data_rows;
1222
1223   self->finalize = trbox_base_finalize;
1224   self->t = tab_create (cols, rows, 0);
1225   tab_headers (self->t,0,0,3,0); 
1226   tab_box (self->t, TAL_2, TAL_2, TAL_0, TAL_0, 0, 0, cols -1, rows -1);
1227   tab_hline(self->t, TAL_2,0,cols-1,3);
1228   tab_dim (self->t, tab_natural_dimensions);
1229 }
1230
1231
1232 /* Base finalizer for the trbox */
1233 void 
1234 trbox_base_finalize(struct trbox *trb)
1235 {
1236   tab_submit(trb->t);
1237 }
1238
1239
1240 /* Create , populate and submit the Paired Samples Correlation box */
1241 void
1242 pscbox(void)
1243 {
1244   const int rows=1+n_pairs;
1245   const int cols=5;
1246   int i;
1247   
1248   struct tab_table *table;
1249   
1250   table = tab_create (cols,rows,0);
1251
1252   tab_columns (table, SOM_COL_DOWN, 1);
1253   tab_headers (table,0,0,1,0); 
1254   tab_box (table, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols -1, rows -1 );
1255   tab_hline(table, TAL_2, 0, cols - 1, 1);
1256   tab_vline(table, TAL_2, 2, 0, rows - 1);
1257   tab_dim(table, tab_natural_dimensions);
1258   tab_title(table, 0, _("Paired Samples Correlations"));
1259
1260   /* column headings */
1261   tab_text(table, 2,0, TAB_CENTER | TAT_TITLE, _("N"));
1262   tab_text(table, 3,0, TAB_CENTER | TAT_TITLE, _("Correlation"));
1263   tab_text(table, 4,0, TAB_CENTER | TAT_TITLE, _("Sig."));
1264
1265   for (i=0; i < n_pairs; ++i)
1266     {
1267       double p,q;
1268
1269       double df = pairs[i].n -2;
1270
1271       double correlation_t = 
1272         pairs[i].correlation * sqrt(df) /
1273         sqrt(1 - pow2(pairs[i].correlation));
1274
1275
1276       /* row headings */
1277       tab_text(table, 0,i+1, TAB_LEFT | TAT_TITLE | TAT_PRINTF, 
1278                _("Pair %d"), i);
1279       
1280       tab_text(table, 1,i+1, TAB_LEFT | TAT_TITLE | TAT_PRINTF, 
1281                _("%s & %s"), pairs[i].v[0]->name, pairs[i].v[1]->name);
1282
1283
1284       /* row data */
1285       tab_float(table, 2, i+1, TAB_RIGHT, pairs[i].n, 4, 0);
1286       tab_float(table, 3, i+1, TAB_RIGHT, pairs[i].correlation, 8, 3);
1287
1288       p = gsl_cdf_tdist_P(correlation_t, df);
1289       q = gsl_cdf_tdist_Q(correlation_t, df);
1290
1291       tab_float(table, 4, i+1, TAB_RIGHT, 2.0*(correlation_t>0?q:p), 8, 3);
1292     }
1293
1294   tab_submit(table);
1295 }
1296
1297
1298
1299 /* Calculation Implementation */
1300
1301 /* Per case calculations common to all variants of the T test */
1302 static int 
1303 common_calc (const struct ccase *c, void *_cmd)
1304 {
1305   int i;
1306   struct cmd_t_test *cmd = (struct cmd_t_test *)_cmd;  
1307
1308   double weight = dict_get_case_weight(default_dict,c,&bad_weight_warn);
1309
1310
1311   /* Skip the entire case if /MISSING=LISTWISE is set */
1312   if ( cmd->miss == TTS_LISTWISE ) 
1313     {
1314       for(i=0; i< cmd->n_variables ; ++i) 
1315         {
1316           struct variable *v = cmd->v_variables[i];
1317           const union value *val = &c->data[v->fv];
1318
1319           if (value_is_missing(val,v) )
1320             {
1321               return 0;
1322             }
1323         }
1324     }
1325
1326   /* Listwise has to be implicit if the independent variable is missing ?? */
1327   if ( cmd->sbc_groups )
1328     {
1329       const union value *gv = &c->data[indep_var->fv];
1330       if ( value_is_missing(gv,indep_var) )
1331         {
1332           return 0;
1333         }
1334     }
1335
1336
1337   for(i=0; i< cmd->n_variables ; ++i) 
1338     {
1339       struct group_statistics *gs;
1340       struct variable *v = cmd->v_variables[i];
1341       const union value *val = &c->data[v->fv];
1342
1343       gs= &cmd->v_variables[i]->p.t_t.ugs;
1344
1345       if (! value_is_missing(val,v) )
1346         {
1347           gs->n+=weight;
1348           gs->sum+=weight * val->f;
1349           gs->ssq+=weight * val->f * val->f;
1350         }
1351     }
1352   return 0;
1353 }
1354
1355 /* Pre calculations common to all variants of the T test */
1356 static void 
1357 common_precalc ( struct cmd_t_test *cmd )
1358 {
1359   int i=0;
1360
1361   for(i=0; i< cmd->n_variables ; ++i) 
1362     {
1363       struct group_statistics *gs;
1364       gs= &cmd->v_variables[i]->p.t_t.ugs;
1365       
1366       gs->sum=0;
1367       gs->n=0;
1368       gs->ssq=0;
1369       gs->sum_diff=0;
1370     }
1371 }
1372
1373 /* Post calculations common to all variants of the T test */
1374 void 
1375 common_postcalc (  struct cmd_t_test *cmd )
1376 {
1377   int i=0;
1378
1379
1380   for(i=0; i< cmd->n_variables ; ++i) 
1381     {
1382       struct group_statistics *gs;
1383       gs= &cmd->v_variables[i]->p.t_t.ugs;
1384       
1385       gs->mean=gs->sum / gs->n;
1386       gs->s_std_dev= sqrt(
1387                          ( (gs->ssq / gs->n ) - gs->mean * gs->mean )
1388                          ) ;
1389
1390       gs->std_dev= sqrt(
1391                          gs->n/(gs->n-1) *
1392                          ( (gs->ssq / gs->n ) - gs->mean * gs->mean )
1393                          ) ;
1394
1395       gs->se_mean = gs->std_dev / sqrt(gs->n);
1396       gs->mean_diff= gs->sum_diff / gs->n;
1397     }
1398 }
1399
1400 /* Per case calculations for one sample t test  */
1401 static int 
1402 one_sample_calc (const struct ccase *c, void *cmd_)
1403 {
1404   int i;
1405   struct cmd_t_test *cmd = (struct cmd_t_test *)cmd_;
1406
1407
1408   double weight = dict_get_case_weight(default_dict,c,&bad_weight_warn);
1409
1410   /* Skip the entire case if /MISSING=LISTWISE is set */
1411   if ( cmd->miss == TTS_LISTWISE ) 
1412     {
1413       for(i=0; i< cmd->n_variables ; ++i) 
1414         {
1415           struct variable *v = cmd->v_variables[i];
1416           const union value *val = &c->data[v->fv];
1417
1418           if (value_is_missing(val,v) )
1419             {
1420               return 0;
1421             }
1422         }
1423     }
1424
1425   for(i=0; i< cmd->n_variables ; ++i) 
1426     {
1427       struct group_statistics *gs;
1428       struct variable *v = cmd->v_variables[i];
1429       const union value *val = &c->data[v->fv];
1430
1431       gs= &cmd->v_variables[i]->p.t_t.ugs;
1432       
1433       if ( ! value_is_missing(val,v))
1434         gs->sum_diff += weight * (val->f - cmd->n_testval);
1435     }
1436
1437   return 0;
1438 }
1439
1440 /* Pre calculations for one sample t test */
1441 static void 
1442 one_sample_precalc ( struct cmd_t_test *cmd )
1443 {
1444   int i=0; 
1445  
1446   for(i=0; i< cmd->n_variables ; ++i) 
1447     {
1448       struct group_statistics *gs;
1449       gs= &cmd->v_variables[i]->p.t_t.ugs;
1450       
1451       gs->sum_diff=0;
1452     }
1453 }
1454
1455 /* Post calculations for one sample t test */
1456 static void 
1457 one_sample_postcalc (struct cmd_t_test *cmd)
1458 {
1459   int i=0;
1460   
1461   for(i=0; i< cmd->n_variables ; ++i) 
1462     {
1463       struct group_statistics *gs;
1464       gs= &cmd->v_variables[i]->p.t_t.ugs;
1465
1466       gs->mean_diff = gs->sum_diff / gs->n ;
1467     }
1468 }
1469
1470
1471
1472 static int
1473 compare_var_name (const void *a_, const void *b_, void *v_ UNUSED)
1474 {
1475   const struct variable *a = a_;
1476   const struct variable *b = b_;
1477
1478   return strcmp(a->name,b->name);
1479 }
1480
1481 static unsigned
1482 hash_var_name (const void *a_, void *v_ UNUSED)
1483 {
1484   const struct variable *a = a_;
1485
1486   return hsh_hash_bytes (a->name, strlen(a->name));
1487 }
1488
1489
1490
1491 static void 
1492 paired_precalc (struct cmd_t_test *cmd UNUSED)
1493 {
1494   int i;
1495
1496   for(i=0; i < n_pairs ; ++i )
1497     {
1498       pairs[i].n = 0;
1499       pairs[i].sum[0] = 0;      pairs[i].sum[1] = 0;
1500       pairs[i].ssq[0] = 0;      pairs[i].ssq[1] = 0;
1501       pairs[i].sum_of_prod = 0;
1502       pairs[i].correlation = 0;
1503       pairs[i].sum_of_diffs = 0;
1504       pairs[i].ssq_diffs = 0;
1505     }
1506
1507 }
1508
1509
1510 static int  
1511 paired_calc (const struct ccase *c, void *cmd_)
1512 {
1513   int i;
1514
1515   struct cmd_t_test *cmd  = (struct cmd_t_test *) cmd_;
1516
1517   double weight = dict_get_case_weight(default_dict,c,&bad_weight_warn);
1518
1519   /* Skip the entire case if /MISSING=LISTWISE is set , 
1520    AND one member of a pair is missing */
1521   if ( cmd->miss == TTS_LISTWISE ) 
1522     {
1523       for(i=0; i < n_pairs ; ++i )
1524         {
1525           struct variable *v0 = pairs[i].v[0];
1526           struct variable *v1 = pairs[i].v[1];
1527
1528           const union value *val0 = &c->data[v0->fv];
1529           const union value *val1 = &c->data[v1->fv];
1530           
1531           if ( value_is_missing(val0,v0) ||
1532                value_is_missing(val1,v1) )
1533             {
1534               return 0;
1535             }
1536         }
1537     }
1538
1539   for(i=0; i < n_pairs ; ++i )
1540     {
1541       struct variable *v0 = pairs[i].v[0];
1542       struct variable *v1 = pairs[i].v[1];
1543
1544       const union value *val0 = &c->data[v0->fv];
1545       const union value *val1 = &c->data[v1->fv];
1546
1547       if ( ( !value_is_missing(val0,v0) && !value_is_missing(val1,v1) ) )
1548       {
1549         pairs[i].n += weight;
1550         pairs[i].sum[0] += weight * val0->f;
1551         pairs[i].sum[1] += weight * val1->f;
1552
1553         pairs[i].ssq[0] += weight * pow2(val0->f);
1554         pairs[i].ssq[1] += weight * pow2(val1->f);
1555
1556         pairs[i].sum_of_prod += weight * val0->f * val1->f ;
1557
1558         pairs[i].sum_of_diffs += weight * ( val0->f - val1->f ) ;
1559         pairs[i].ssq_diffs += weight * pow2(val0->f - val1->f);
1560       }
1561     }
1562
1563   return 0;
1564 }
1565
1566 static void 
1567 paired_postcalc (struct cmd_t_test *cmd UNUSED)
1568 {
1569   int i;
1570
1571   for(i=0; i < n_pairs ; ++i )
1572     {
1573       int j;
1574       const double n = pairs[i].n;
1575
1576       for (j=0; j < 2 ; ++j) 
1577         {
1578           pairs[i].mean[j] = pairs[i].sum[j] / n ;
1579           pairs[i].s_std_dev[j] = sqrt((pairs[i].ssq[j] / n - 
1580                                               pow2(pairs[i].mean[j]))
1581                                      );
1582
1583           pairs[i].std_dev[j] = sqrt(n/(n-1)*(pairs[i].ssq[j] / n - 
1584                                               pow2(pairs[i].mean[j]))
1585                                      );
1586         }
1587       
1588       pairs[i].correlation = pairs[i].sum_of_prod / pairs[i].n - 
1589         pairs[i].mean[0] * pairs[i].mean[1] ;
1590       /* correlation now actually contains the covariance */
1591       
1592       pairs[i].correlation /= pairs[i].std_dev[0] * pairs[i].std_dev[1];
1593       pairs[i].correlation *= pairs[i].n / ( pairs[i].n - 1 );
1594       
1595       pairs[i].mean_diff = pairs[i].sum_of_diffs / n ;
1596
1597       pairs[i].std_dev_diff = sqrt (  n / (n - 1) * (
1598                                     ( pairs[i].ssq_diffs / n )
1599                                     - 
1600                                     pow2(pairs[i].mean_diff )
1601                                     ) );
1602     }
1603 }
1604
1605 /* Return the group # corresponding to the 
1606    independent variable with the value val 
1607 */
1608 static int
1609 get_group(const union value *val, struct variable *indep)
1610 {
1611   int i; 
1612
1613   for (i = 0; i < 2  ; ++i )
1614     {
1615       const int cmp = compare_values(val,&groups_values[i],indep->width) ;
1616       switch ( criteria[i])
1617         {
1618         case CMP_EQ: 
1619           if ( 0 == cmp )   return i;
1620           break;           
1621         case CMP_LT:       
1622           if ( 0 >  cmp )  return i;
1623           break;           
1624         case CMP_LE:       
1625           if ( cmp <= 0 )   return i;
1626           break;
1627         case CMP_GT:
1628           if ( cmp > 0 ) return i;
1629           break;
1630         case CMP_GE:
1631           if ( cmp >= 0 ) return i;
1632           break;
1633         default:
1634           assert(0);
1635         };
1636     }
1637
1638   /* No groups matched */
1639   return -1;
1640 }
1641
1642
1643 static void 
1644 group_precalc (struct cmd_t_test *cmd )
1645 {
1646   int i;
1647   int j;
1648
1649   for(i=0; i< cmd->n_variables ; ++i) 
1650     {
1651       struct t_test_proc *ttpr = &cmd->v_variables[i]->p.t_t;
1652
1653       /* There's always 2 groups for a T - TEST */
1654       ttpr->n_groups = 2;
1655       ttpr->gs = xmalloc(sizeof(struct group_statistics) * 2) ;
1656
1657       for (j=0 ; j < 2 ; ++j)
1658         {
1659           ttpr->gs[j].sum = 0;
1660           ttpr->gs[j].n = 0;
1661           ttpr->gs[j].ssq = 0;
1662         
1663           if ( n_group_values == 2 ) 
1664             ttpr->gs[j].id = groups_values[j];
1665           else
1666             ttpr->gs[j].id = groups_values[0];
1667           ttpr->gs[j].criterion = criteria[j];
1668         }
1669     }
1670
1671 }
1672
1673 static int  
1674 group_calc (const struct ccase *c, struct cmd_t_test *cmd)
1675 {
1676   int i;
1677   int g;
1678
1679   const union value *gv = &c->data[indep_var->fv];
1680
1681   const double weight = dict_get_case_weight(default_dict,c,&bad_weight_warn);
1682
1683   if ( value_is_missing(gv,indep_var) )
1684     {
1685       return 0;
1686     }
1687
1688   if ( cmd->miss == TTS_LISTWISE ) 
1689     {
1690       for(i=0; i< cmd->n_variables ; ++i) 
1691         {
1692           struct variable *v = cmd->v_variables[i];
1693           const union value *val = &c->data[v->fv];
1694
1695           if (value_is_missing(val,v) )
1696             {
1697               return 0;
1698             }
1699         }
1700     }
1701
1702
1703   gv = &c->data[indep_var->fv];
1704
1705   g = get_group(gv,indep_var);
1706
1707
1708   /* If the independent variable doesn't match either of the values 
1709      for this case then move on to the next case */
1710   if (g == -1 ) 
1711     return 0;
1712
1713   for(i=0; i< cmd->n_variables ; ++i) 
1714     {
1715       struct variable *var = cmd->v_variables[i];
1716
1717       struct group_statistics *gs = &var->p.t_t.gs[g];
1718
1719       const union value *val=&c->data[var->fv];
1720
1721       if ( !value_is_missing(val,var) )
1722         {
1723           gs->n+=weight;
1724           gs->sum+=weight * val->f;
1725           gs->ssq+=weight * pow2(val->f);
1726         }
1727     }
1728
1729   return 0;
1730 }
1731
1732
1733 static void 
1734 group_postcalc ( struct cmd_t_test *cmd )
1735 {
1736   int i;
1737   int j;
1738
1739   for(i=0; i< cmd->n_variables ; ++i) 
1740     {
1741       for (j=0 ; j < 2 ; ++j)
1742         {
1743           struct group_statistics *gs;
1744           gs=&cmd->v_variables[i]->p.t_t.gs[j];
1745
1746           gs->mean = gs->sum / gs->n;
1747           
1748           gs->s_std_dev= sqrt(
1749                          ( (gs->ssq / gs->n ) - gs->mean * gs->mean )
1750                          ) ;
1751
1752           gs->std_dev= sqrt(
1753                          gs->n/(gs->n-1) *
1754                          ( (gs->ssq / gs->n ) - gs->mean * gs->mean )
1755                          ) ;
1756           
1757           gs->se_mean = gs->std_dev / sqrt(gs->n);
1758         }
1759     }
1760 }
1761
1762
1763
1764 static void 
1765 calculate(const struct casefile *cf, void *cmd_)
1766 {
1767   struct ssbox stat_summary_box;
1768   struct trbox test_results_box;
1769
1770   struct casereader *r;
1771   const struct ccase *c;
1772
1773   struct cmd_t_test *cmd = (struct cmd_t_test *) cmd_;
1774
1775   common_precalc(cmd);
1776   for(r = casefile_get_reader (cf);
1777       casereader_read (r, &c) ; ) 
1778     {
1779       common_calc(c,cmd);
1780     }
1781   casereader_destroy (r);
1782   common_postcalc(cmd);
1783
1784   switch(mode)
1785     {
1786     case T_1_SAMPLE:
1787       one_sample_precalc(cmd);
1788       for(r = casefile_get_reader (cf);
1789           casereader_read (r, &c) ; ) 
1790         {
1791           one_sample_calc(c,cmd);
1792         }
1793       casereader_destroy (r);
1794       one_sample_postcalc(cmd);
1795
1796       break;
1797     case T_PAIRED:
1798       paired_precalc(cmd);
1799       for(r = casefile_get_reader (cf);
1800           casereader_read (r, &c) ; ) 
1801         {
1802           paired_calc(c,cmd);
1803         }
1804       casereader_destroy (r);
1805       paired_postcalc(cmd);
1806
1807       break;
1808     case T_IND_SAMPLES:
1809
1810       group_precalc(cmd);
1811       for(r = casefile_get_reader (cf);
1812           casereader_read (r, &c) ; ) 
1813         {
1814           group_calc(c,cmd);
1815         }
1816       casereader_destroy (r);
1817       group_postcalc(cmd);
1818
1819
1820       levene(cf, indep_var, cmd->n_variables, cmd->v_variables,
1821              (cmd->miss == TTS_LISTWISE)?LEV_LISTWISE:LEV_ANALYSIS ,
1822              value_is_missing);
1823       break;
1824     }
1825
1826   ssbox_create(&stat_summary_box,cmd,mode);
1827   ssbox_populate(&stat_summary_box,cmd);
1828   ssbox_finalize(&stat_summary_box);
1829
1830   if ( mode == T_PAIRED) 
1831       pscbox();
1832
1833   trbox_create(&test_results_box,cmd,mode);
1834   trbox_populate(&test_results_box,cmd);
1835   trbox_finalize(&test_results_box);
1836
1837 }