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