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