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