Added remaining calculations for the separate variance contrast tests
[pspp-builds.git] / 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 "case.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 "t-test.h"
43 #include "casefile.h"
44 #include "levene.h"
45
46 /* (specification)
47    "T-TEST" (tts_):
48      +groups=custom;
49      +testval=double;
50      variables=varlist("PV_NO_SCRATCH | PV_NUMERIC");
51      pairs=custom;
52      +missing=miss:!analysis/listwise,
53              incl:include/!exclude;
54      format=fmt:!labels/nolabels;
55      criteria=:cin(d:criteria,"%s > 0. && %s < 1.").
56 */
57 /* (declarations) */
58 /* (functions) */
59
60
61
62
63 /* Function to use for testing for missing values */
64 static is_missing_func value_is_missing;
65
66 /* Variable for the GROUPS subcommand, if given. */
67 static struct variable *indep_var;
68
69 /* GROUPS: Number of values specified by the user; the values
70    specified if any. */
71
72 static int n_group_values;
73 static union value groups_values[2];
74 static enum comparison criteria[2];
75
76
77
78 /* PAIRS: Number of pairs to be compared ; each pair. */
79 static int n_pairs = 0 ;
80 struct pair 
81 {
82   /* The variables comprising the pair */
83   struct variable *v[2];
84
85   /* The number of valid variable pairs */
86   double n;
87
88   /* The sum of the members */
89   double sum[2];
90
91   /* sum of squares of the members */
92   double ssq[2];
93
94   /* Std deviation of the members */
95   double std_dev[2];
96
97
98   /* Sample Std deviation of the members */
99   double s_std_dev[2];
100
101   /* The means of the members */
102   double mean[2];
103
104   /* The correlation coefficient between the variables */
105   double correlation;
106
107   /* The sum of the differences */
108   double sum_of_diffs;
109
110   /* The sum of the products */
111   double sum_of_prod;
112
113   /* The mean of the differences */
114   double mean_diff;
115
116   /* The sum of the squares of the differences */
117   double ssq_diffs;
118
119   /* The std deviation of the differences */
120   double std_dev_diff;
121 };
122
123 static struct pair *pairs=0;
124
125 static int parse_value (union value * v, int type) ;
126
127 /* Structures and Functions for the Statistics Summary Box */
128 struct ssbox;
129 typedef void populate_ssbox_func(struct ssbox *ssb,
130                                             struct cmd_t_test *cmd);
131 typedef void finalize_ssbox_func(struct ssbox *ssb);
132
133 struct ssbox
134 {
135   struct tab_table *t;
136
137   populate_ssbox_func *populate;
138   finalize_ssbox_func *finalize;
139
140 };
141
142 /* Create a ssbox */
143 void ssbox_create(struct ssbox *ssb,   struct cmd_t_test *cmd, int mode);
144
145 /* Populate a ssbox according to cmd */
146 void ssbox_populate(struct ssbox *ssb, struct cmd_t_test *cmd);
147
148 /* Submit and destroy a ssbox */
149 void ssbox_finalize(struct ssbox *ssb);
150
151 /* A function to create, populate and submit the Paired Samples Correlation 
152    box */
153 void pscbox(void);
154
155
156 /* Structures and Functions for the Test Results Box */
157 struct trbox;
158
159 typedef void populate_trbox_func(struct trbox *trb,
160                                  struct cmd_t_test *cmd);
161 typedef void finalize_trbox_func(struct trbox *trb);
162
163 struct trbox {
164   struct tab_table *t;
165   populate_trbox_func *populate;
166   finalize_trbox_func *finalize;
167 };
168
169 /* Create a trbox */
170 void trbox_create(struct trbox *trb,   struct cmd_t_test *cmd, int mode);
171
172 /* Populate a ssbox according to cmd */
173 void trbox_populate(struct trbox *trb, struct cmd_t_test *cmd);
174
175 /* Submit and destroy a ssbox */
176 void trbox_finalize(struct trbox *trb);
177
178 /* Which mode was T-TEST invoked */
179 enum {
180   T_1_SAMPLE = 0 ,
181   T_IND_SAMPLES, 
182   T_PAIRED
183 };
184
185
186 static int common_calc (const struct ccase *, void *);
187 static void common_precalc (struct cmd_t_test *);
188 static void common_postcalc (struct cmd_t_test *);
189
190 static int one_sample_calc (const struct ccase *, void *);
191 static void one_sample_precalc (struct cmd_t_test *);
192 static void one_sample_postcalc (struct cmd_t_test *);
193
194 static int  paired_calc (const struct ccase *, void *);
195 static void paired_precalc (struct cmd_t_test *);
196 static void paired_postcalc (struct cmd_t_test *);
197
198 static void group_precalc (struct cmd_t_test *);
199 static int  group_calc (const struct ccase *, struct cmd_t_test *);
200 static void group_postcalc (struct cmd_t_test *);
201
202
203 static int compare_var_name (const void *a_, const void *b_, void *v_ UNUSED);
204 static unsigned hash_var_name (const void *a_, void *v_ UNUSED);
205
206 static void calculate(const struct casefile *cf, void *_mode);
207
208 static  int mode;
209
210 static struct cmd_t_test cmd;
211
212 static int bad_weight_warn;
213
214 int
215 cmd_t_test(void)
216 {
217
218   if ( !parse_t_test(&cmd) )
219     return CMD_FAILURE;
220
221   if (! cmd.sbc_criteria)
222     cmd.criteria=0.95;
223
224   {
225     int m=0;
226     if (cmd.sbc_testval) ++m;
227     if (cmd.sbc_groups) ++m;
228     if (cmd.sbc_pairs) ++m;
229
230     if ( m != 1)
231       {
232         msg(SE, 
233             _("TESTVAL, GROUPS and PAIRS subcommands are mutually exclusive.")
234             );
235         return CMD_FAILURE;
236       }
237   }
238
239   if (cmd.sbc_testval) 
240     mode=T_1_SAMPLE;
241   else if (cmd.sbc_groups)
242     mode=T_IND_SAMPLES;
243   else
244     mode=T_PAIRED;
245
246   if ( mode == T_PAIRED) 
247     {
248       if (cmd.sbc_variables) 
249         {
250           msg(SE, _("VARIABLES subcommand is not appropriate with PAIRS"));
251           return CMD_FAILURE;
252         }
253       else
254         {
255           /* Iterate through the pairs and put each variable that is a 
256              member of a pair into cmd.v_variables */
257
258           int i;
259           struct hsh_iterator hi;
260           struct hsh_table *hash;
261           struct variable *v;
262
263           hash=hsh_create(n_pairs,compare_var_name,hash_var_name,0,0);
264
265           for (i=0; i < n_pairs; ++i)
266             {
267               hsh_insert(hash,pairs[i].v[0]);
268               hsh_insert(hash,pairs[i].v[1]);
269             }
270
271           assert(cmd.n_variables == 0);
272           cmd.n_variables = hsh_count(hash);
273
274           cmd.v_variables = xrealloc(cmd.v_variables,
275                                      sizeof(struct variable) * cmd.n_variables);
276           /* Iterate through the hash */
277           for (i=0,v = (struct variable *) hsh_first(hash,&hi);
278                v != 0;
279                v=hsh_next(hash,&hi) ) 
280             cmd.v_variables[i++]=v;
281
282           hsh_destroy(hash);
283         }
284     }
285   else if ( !cmd.sbc_variables) 
286     {
287       msg(SE, _("One or more VARIABLES must be specified."));
288       return CMD_FAILURE;
289     }
290
291
292   /* If /MISSING=INCLUDE is set, then user missing values are ignored */
293   if (cmd.incl == TTS_INCLUDE ) 
294     value_is_missing = is_system_missing;
295   else
296     value_is_missing = is_missing;
297
298   bad_weight_warn = 1;
299
300   multipass_procedure_with_splits (calculate, &cmd);
301
302   n_pairs=0;
303   free(pairs);
304   pairs=0;
305
306   if ( mode == T_IND_SAMPLES) 
307     {
308       int i;
309       /* Destroy any group statistics we created */
310       for (i= 0 ; i < cmd.n_variables ; ++i ) 
311         {
312           free(cmd.v_variables[i]->p.t_t.gs);
313         }
314     }
315     
316   return CMD_SUCCESS;
317 }
318
319 static int
320 tts_custom_groups (struct cmd_t_test *cmd UNUSED)
321 {
322
323   lex_match('=');
324
325   if (token != T_ALL && 
326       (token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
327      ) 
328   {
329     msg(SE,_("`%s' is not a variable name"),tokid);
330     return 0;
331   }
332
333   indep_var = parse_variable ();
334   if (!indep_var)
335     {
336       lex_error ("expecting variable name in GROUPS subcommand");
337       return 0;
338     }
339
340   if (indep_var->type == T_STRING && indep_var->width > MAX_SHORT_STRING)
341     {
342       msg (SE, _("Long string variable %s is not valid here."),
343            indep_var->name);
344       return 0;
345     }
346
347   if (!lex_match ('('))
348     {
349       if (indep_var->type == NUMERIC)
350         {
351           groups_values[0].f = 1;
352           groups_values[1].f = 2;
353           criteria[0] = criteria[1] = CMP_EQ;
354           n_group_values = 2;
355           return 1;
356         }
357       else
358         {
359           msg (SE, _("When applying GROUPS to a string variable, at "
360                      "least one value must be specified."));
361           return 0;
362         }
363     }
364
365   if (!parse_value (&groups_values[0],indep_var->type))
366       return 0;
367
368   lex_match (',');
369   if (lex_match (')'))
370     {
371       criteria[0] =  CMP_LE;
372       criteria[1] =  CMP_GT;
373       groups_values[1] = groups_values[0];
374       n_group_values = 1;
375       return 1;
376     }
377
378   if (!parse_value (&groups_values[1],indep_var->type))
379     return 0;
380   
381   n_group_values = 2;
382   if (!lex_force_match (')'))
383     return 0;
384
385   criteria[0] = criteria[1] = CMP_EQ;
386   return 1;
387 }
388
389
390 static int
391 tts_custom_pairs (struct cmd_t_test *cmd UNUSED)
392 {
393   struct variable **vars;
394   int n_vars;
395   int n_pairs_local;
396
397   int n_before_WITH ;
398   int n_after_WITH = -1;
399   int paired ; /* Was the PAIRED keyword given ? */
400
401   lex_match('=');
402
403   if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
404       && token != T_ALL)
405     {
406       msg(SE,_("`%s' is not a variable name"),tokid);
407       return 0;
408     }
409
410   n_vars=0;
411   if (!parse_variables (default_dict, &vars, &n_vars,
412                         PV_DUPLICATE | PV_NUMERIC | PV_NO_SCRATCH))
413     {
414       free (vars);
415       return 0;
416     }
417   assert (n_vars);
418
419   n_before_WITH=0;
420   if (lex_match (T_WITH))
421     {
422       n_before_WITH = n_vars;
423       if (!parse_variables (default_dict, &vars, &n_vars,
424                             PV_DUPLICATE | PV_APPEND
425                             | PV_NUMERIC | PV_NO_SCRATCH))
426         {
427           free (vars);
428           return 0;
429         }
430       n_after_WITH = n_vars - n_before_WITH;
431     }
432
433   paired = (lex_match ('(') && lex_match_id ("PAIRED") && lex_match (')'));
434
435   /* Determine the number of pairs needed */
436   if (paired)
437     {
438       if (n_before_WITH != n_after_WITH)
439         {
440           free (vars);
441           msg (SE, _("PAIRED was specified but the number of variables "
442                      "preceding WITH (%d) did not match the number "
443                      "following (%d)."),
444                n_before_WITH, n_after_WITH );
445           return 0;
446         }
447       n_pairs_local=n_before_WITH;
448     }
449   else if (n_before_WITH > 0) /* WITH keyword given, but not PAIRED keyword */
450     {
451       n_pairs_local=n_before_WITH * n_after_WITH ;
452     }
453   else /* Neither WITH nor PAIRED keyword given */
454     {
455       if (n_vars < 2)
456         {
457           free (vars);
458           msg (SE, _("At least two variables must be specified "
459                      "on PAIRS."));
460           return 0;
461         }
462
463       /* how many ways can you pick 2 from n_vars ? */
464       n_pairs_local = n_vars * (n_vars -1 ) /2 ;
465     }
466
467
468   /* Allocate storage for the pairs */
469   pairs = xrealloc(pairs, sizeof(struct pair) * (n_pairs + n_pairs_local) );
470
471   /* Populate the pairs with the appropriate variables */
472   if ( paired ) 
473     {
474       int i;
475
476       assert(n_pairs_local == n_vars/2);
477       for (i = 0; i < n_pairs_local ; ++i)
478         {
479           pairs[i].v[n_pairs+0] = vars[i];
480           pairs[i].v[n_pairs+1] = vars[i+n_pairs_local];
481         }
482     }
483   else if (n_before_WITH > 0) /* WITH keyword given, but not PAIRED keyword */
484     {
485       int i,j;
486       int p=n_pairs;
487
488       for(i=0 ; i < n_before_WITH ; ++i ) 
489         {
490           for(j=0 ; j < n_after_WITH ; ++j)
491             {
492               pairs[p].v[0] = vars[i];
493               pairs[p].v[1] = vars[j+n_before_WITH];
494               ++p;
495             }
496         }
497     }
498   else /* Neither WITH nor PAIRED given */
499     {
500       int i,j;
501       int p=n_pairs;
502       
503       for(i=0 ; i < n_vars ; ++i ) 
504         {
505           for(j=i+1 ; j < n_vars ; ++j)
506             {
507               pairs[p].v[0] = vars[i];
508               pairs[p].v[1] = vars[j];
509               ++p;
510             }
511         }
512     }
513
514   n_pairs+=n_pairs_local;
515
516   free (vars);
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 - 1);
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 - 1);
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 - 1);
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 - 1);
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 = case_data (c, 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 = case_data (c, 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 = case_data (c, 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 = case_data (c, 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 = case_data (c, 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 = case_data (c, v0->fv);
1529           const union value *val1 = case_data (c, 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 = case_data (c, v0->fv);
1545       const union value *val1 = case_data (c, 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 = case_data (c, 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 = case_data (c, v->fv);
1694
1695           if (value_is_missing(val,v) )
1696             {
1697               return 0;
1698             }
1699         }
1700     }
1701
1702
1703   gv = case_data (c, 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 = case_data (c, 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   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       case_destroy (&c)) 
1779     {
1780       common_calc(&c,cmd);
1781     }
1782   casereader_destroy (r);
1783   common_postcalc(cmd);
1784
1785   switch(mode)
1786     {
1787     case T_1_SAMPLE:
1788       one_sample_precalc(cmd);
1789       for(r = casefile_get_reader (cf);
1790           casereader_read (r, &c) ;
1791           case_destroy (&c)) 
1792         {
1793           one_sample_calc(&c,cmd);
1794         }
1795       casereader_destroy (r);
1796       one_sample_postcalc(cmd);
1797
1798       break;
1799     case T_PAIRED:
1800       paired_precalc(cmd);
1801       for(r = casefile_get_reader (cf);
1802           casereader_read (r, &c) ;
1803           case_destroy (&c)) 
1804         {
1805           paired_calc(&c,cmd);
1806         }
1807       casereader_destroy (r);
1808       paired_postcalc(cmd);
1809
1810       break;
1811     case T_IND_SAMPLES:
1812
1813       group_precalc(cmd);
1814       for(r = casefile_get_reader (cf);
1815           casereader_read (r, &c) ;
1816           case_destroy (&c)) 
1817         {
1818           group_calc(&c,cmd);
1819         }
1820       casereader_destroy (r);
1821       group_postcalc(cmd);
1822
1823
1824       levene(cf, indep_var, cmd->n_variables, cmd->v_variables,
1825              (cmd->miss == TTS_LISTWISE)?LEV_LISTWISE:LEV_ANALYSIS ,
1826              value_is_missing);
1827       break;
1828     }
1829
1830   ssbox_create(&stat_summary_box,cmd,mode);
1831   ssbox_populate(&stat_summary_box,cmd);
1832   ssbox_finalize(&stat_summary_box);
1833
1834   if ( mode == T_PAIRED) 
1835       pscbox();
1836
1837   trbox_create(&test_results_box,cmd,mode);
1838   trbox_populate(&test_results_box,cmd);
1839   trbox_finalize(&test_results_box);
1840
1841 }