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