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