589e64a8abc4b57c65ae7f85ebb2a8bbb797cccb
[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
41 /* (specification)
42    "T-TEST" (tts_):
43      groups=custom;
44      testval=double;
45      variables=varlist("PV_NO_SCRATCH | PV_NUMERIC");
46      pairs=custom;
47      +missing=miss:!analysis/listwise,
48              incl:include/!exclude;
49      format=fmt:!labels/nolabels;
50      criteria=:cin(d:criteria,"%s > 0. && %s < 1.").
51 */
52 /* (declarations) */
53 /* (functions) */
54
55 static struct cmd_t_test cmd;
56
57
58 static struct pool *t_test_pool ;
59
60 /* Variable for the GROUPS subcommand, if given. */
61 static struct variable *groups;
62
63 /* GROUPS: Number of values specified by the user; the values
64    specified if any. */
65 static int n_groups_values;
66 static union value groups_values[2];
67
68 /* PAIRS: Number of pairs to be compared ; each pair. */
69 static int n_pairs ;
70 typedef struct variable *pair_t[2] ;
71 static pair_t *pairs;
72
73
74 static int parse_value (union value * v, int type) ;
75
76
77 /* Structures and Functions for the Statistics Summary Box */
78 struct ssbox;
79 typedef void populate_ssbox_func(struct ssbox *ssb,
80                                             struct cmd_t_test *cmd);
81 typedef void finalize_ssbox_func(struct ssbox *ssb);
82
83 struct ssbox
84 {
85   struct tab_table *t;
86
87   populate_ssbox_func *populate;
88   finalize_ssbox_func *finalize;
89
90 };
91
92 /* Create a ssbox */
93 void ssbox_create(struct ssbox *ssb,   struct cmd_t_test *cmd, int mode);
94
95 /* Populate a ssbox according to cmd */
96 void ssbox_populate(struct ssbox *ssb, struct cmd_t_test *cmd);
97
98 /* Submit and destroy a ssbox */
99 void ssbox_finalize(struct ssbox *ssb);
100
101
102
103 /* Structures and Functions for the Test Results Box */
104 struct trbox;
105
106 typedef void populate_trbox_func(struct trbox *trb,
107                                  struct cmd_t_test *cmd);
108 typedef void finalize_trbox_func(struct trbox *trb);
109
110 struct trbox {
111   struct tab_table *t;
112   populate_trbox_func *populate;
113   finalize_trbox_func *finalize;
114 };
115
116 /* Create a trbox */
117 void trbox_create(struct trbox *trb,   struct cmd_t_test *cmd, int mode);
118
119 /* Populate a ssbox according to cmd */
120 void trbox_populate(struct trbox *trb, struct cmd_t_test *cmd);
121
122 /* Submit and destroy a ssbox */
123 void trbox_finalize(struct trbox *trb);
124
125 /* Which mode was T-TEST invoked */
126 enum {
127   T_1_SAMPLE = 0 ,
128   T_IND_SAMPLES, 
129   T_PAIRED
130 };
131
132 int
133 cmd_t_test(void)
134 {
135   int mode;
136
137   struct ssbox stat_summary_box;
138   struct trbox test_results_box;
139
140   if (!lex_force_match_id ("T"))
141     return CMD_FAILURE;
142
143   lex_match ('-');
144   lex_match_id ("TEST");
145
146   if ( !parse_t_test(&cmd) )
147     return CMD_FAILURE;
148
149   if (! cmd.sbc_criteria)
150     cmd.criteria=0.95;
151
152   if ( cmd.sbc_testval + cmd.sbc_groups + cmd.sbc_pairs != 1 ) 
153     {
154       msg(SE, 
155           _("Exactly one of TESTVAL, GROUPS or PAIRS subcommands is required")
156           );
157       return CMD_FAILURE;
158     }
159
160   if (cmd.sbc_testval) 
161     mode=T_1_SAMPLE;
162   else if (cmd.sbc_groups)
163     mode=T_IND_SAMPLES;
164   else
165     mode=T_PAIRED;
166
167   if ( mode == T_PAIRED && cmd.sbc_variables) 
168     {
169       msg(SE, _("VARIABLES subcommand is not appropriate with PAIRS"));
170       return CMD_FAILURE;
171     }
172
173   t_test_pool = pool_create ();
174
175   ssbox_create(&stat_summary_box,&cmd,mode);
176   trbox_create(&test_results_box,&cmd,mode);
177
178   ssbox_populate(&stat_summary_box,&cmd);
179   trbox_populate(&test_results_box,&cmd);
180
181   ssbox_finalize(&stat_summary_box);
182   trbox_finalize(&test_results_box);
183
184   pool_destroy (t_test_pool);
185
186   t_test_pool=0;
187     
188   return CMD_SUCCESS;
189 }
190
191 static int
192 tts_custom_groups (struct cmd_t_test *cmd unused)
193 {
194   lex_match('=');
195
196   if (token != T_ALL && 
197       (token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
198      ) 
199   {
200     msg(SE,_("`%s' is not a variable name"),tokid);
201     return 0;
202   }
203
204   groups = parse_variable ();
205   if (!groups)
206     {
207       lex_error ("expecting variable name in GROUPS subcommand");
208       return 0;
209     }
210
211   if (groups->type == T_STRING && groups->width > MAX_SHORT_STRING)
212     {
213       msg (SE, _("Long string variable %s is not valid here."),
214            groups->name);
215       return 0;
216     }
217
218   if (!lex_match ('('))
219     {
220       if (groups->type == NUMERIC)
221         {
222           n_groups_values = 2;
223           groups_values[0].f = 1;
224           groups_values[1].f = 2;
225           return 1;
226         }
227       else
228         {
229           msg (SE, _("When applying GROUPS to a string variable, at "
230                      "least one value must be specified."));
231           return 0;
232         }
233     }
234
235   if (!parse_value (&groups_values[0],groups->type))
236     return 0;
237   n_groups_values = 1;
238
239   lex_match (',');
240   if (lex_match (')'))
241     return 1;
242
243   if (!parse_value (&groups_values[1],groups->type))
244     return 0;
245   n_groups_values = 2;
246
247   if (!lex_force_match (')'))
248     return 0;
249
250   return 1;
251 }
252
253 static int
254 tts_custom_pairs (struct cmd_t_test *cmd unused)
255 {
256   struct variable **vars;
257   int n_vars;
258   int n_before_WITH ;
259   int n_after_WITH = -1;
260   int paired ; /* Was the PAIRED keyword given ? */
261
262   lex_match('=');
263
264   if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
265       && token != T_ALL)
266     {
267       msg(SE,_("`%s' is not a variable name"),tokid);
268       return 0;
269     }
270
271   n_vars=0;
272   if (!parse_variables (default_dict, &vars, &n_vars,
273                         PV_DUPLICATE | PV_NUMERIC | PV_NO_SCRATCH))
274     {
275       free (vars);
276       return 0;
277     }
278   assert (n_vars);
279
280   n_before_WITH=0;
281   if (lex_match (T_WITH))
282     {
283       n_before_WITH = n_vars;
284       if (!parse_variables (default_dict, &vars, &n_vars,
285                             PV_DUPLICATE | PV_APPEND
286                             | PV_NUMERIC | PV_NO_SCRATCH))
287         {
288           free (vars);
289           return 0;
290         }
291       n_after_WITH = n_vars - n_before_WITH;
292     }
293
294   paired = (lex_match ('(') && lex_match_id ("PAIRED") && lex_match (')'));
295
296   /* Determine the number of pairs needed */
297   if (paired)
298     {
299       if (n_before_WITH != n_after_WITH)
300         {
301           free (vars);
302           msg (SE, _("PAIRED was specified but the number of variables "
303                      "preceding WITH (%d) did not match the number "
304                      "following (%d)."),
305                n_before_WITH, n_after_WITH );
306           return 0;
307         }
308       n_pairs=n_before_WITH;
309     }
310   else if (n_before_WITH > 0) /* WITH keyword given, but not PAIRED keyword */
311     {
312       n_pairs=n_before_WITH * n_after_WITH ;
313     }
314   else /* Neither WITH nor PAIRED keyword given */
315     {
316       if (n_vars < 2)
317         {
318           free (vars);
319           msg (SE, _("At least two variables must be specified "
320                      "on PAIRS."));
321           return 0;
322         }
323
324       /* how many ways can you pick 2 from n_vars ? */
325       n_pairs = n_vars * (n_vars -1 ) /2 ;
326     }
327
328   /* Allocate storage for the pairs */
329   pairs = xrealloc(pairs,sizeof(pair_t) *n_pairs);
330
331   /* Populate the pairs with the appropriate variables */
332   if ( paired ) 
333     {
334       int i;
335
336       assert(n_pairs == n_vars/2);
337       for (i = 0; i < n_pairs ; ++i)
338         {
339           pairs[i][0] = vars[i];
340           pairs[i][1] = vars[i+n_pairs];
341         }
342     }
343   else if (n_before_WITH > 0) /* WITH keyword given, but not PAIRED keyword */
344     {
345       int i,j;
346       int p=0;
347
348       for(i=0 ; i < n_before_WITH ; ++i ) 
349         {
350           for(j=0 ; j < n_after_WITH ; ++j)
351             {
352               pairs[p][0] = vars[i];
353               pairs[p][1] = vars[j+n_before_WITH];
354               ++p;
355             }
356         }
357     }
358   else /* Neither WITH nor PAIRED given */
359     {
360       int i,j;
361       int p=0;
362       
363       for(i=0 ; i < n_vars ; ++i ) 
364         {
365           for(j=i+1 ; j < n_vars ; ++j)
366             {
367               pairs[p][0] = vars[i];
368               pairs[p][1] = vars[j];
369               ++p;
370             }
371         }
372     }
373
374   return 1;
375 }
376
377 /* Parses the current token (numeric or string, depending on type)
378     value v and returns success. */
379 static int
380 parse_value (union value * v, int type )
381 {
382   if (type == NUMERIC)
383     {
384       if (!lex_force_num ())
385         return 0;
386       v->f = tokval;
387     }
388   else
389     {
390       if (!lex_force_string ())
391         return 0;
392       strncpy (v->s, ds_value (&tokstr), ds_length (&tokstr));
393     }
394
395   lex_get ();
396
397   return 1;
398 }
399
400
401 /* Implementation of the SSBOX object */
402
403 void ssbox_base_init(struct ssbox *this, int cols,int rows);
404
405 void ssbox_base_finalize(struct ssbox *ssb);
406
407 void ssbox_one_sample_init(struct ssbox *this, 
408                            struct cmd_t_test *cmd );
409
410 void ssbox_independent_samples_init(struct ssbox *this,
411                                     struct cmd_t_test *cmd);
412
413 void ssbox_paired_init(struct ssbox *this,
414                            struct cmd_t_test *cmd);
415
416 /* Factory to create an ssbox */
417 void 
418 ssbox_create(struct ssbox *ssb, struct cmd_t_test *cmd, int mode)
419 {
420     switch (mode) 
421       {
422       case T_1_SAMPLE:
423         ssbox_one_sample_init(ssb,cmd);
424         break;
425       case T_IND_SAMPLES:
426         ssbox_independent_samples_init(ssb,cmd);
427         break;
428       case T_PAIRED:
429         ssbox_paired_init(ssb,cmd);
430         break;
431       default:
432         assert(0);
433       }
434 }
435
436
437 /* Despatcher for the populate method */
438 void
439 ssbox_populate(struct ssbox *ssb,struct cmd_t_test *cmd)
440 {
441   ssb->populate(ssb,cmd);
442 }
443
444
445 /* Despatcher for finalize */
446 void
447 ssbox_finalize(struct ssbox *ssb)
448 {
449   ssb->finalize(ssb);
450 }
451
452
453 /* Submit the box and clear up */
454 void 
455 ssbox_base_finalize(struct ssbox *ssb)
456 {
457   tab_submit(ssb->t);
458 }
459
460 /* Initialize a ssbox struct */
461 void 
462 ssbox_base_init(struct ssbox *this, int cols,int rows)
463 {
464   this->finalize = ssbox_base_finalize;
465   this->t = tab_create (cols, rows, 0);
466
467   tab_columns (this->t, SOM_COL_DOWN, 1);
468   tab_headers (this->t,0,0,1,0); 
469   tab_box (this->t, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols -1, rows -1 );
470   tab_hline(this->t, TAL_2,0,cols-1,1);
471   tab_dim (this->t, tab_natural_dimensions);
472 }
473
474 void  ssbox_one_sample_populate(struct ssbox *ssb,
475                               struct cmd_t_test *cmd);
476
477 /* Initialize the one_sample ssbox */
478 void 
479 ssbox_one_sample_init(struct ssbox *this, 
480                            struct cmd_t_test *cmd )
481 {
482   const int hsize=5;
483   const int vsize=cmd->n_variables+1;
484
485   this->populate = ssbox_one_sample_populate;
486
487   ssbox_base_init(this, hsize,vsize);
488   tab_title (this->t, 0, _("One-Sample Statistics"));
489   tab_vline(this->t, TAL_2, 1,0,vsize);
490   tab_text (this->t, 1, 0, TAB_CENTER | TAT_TITLE, _("N"));
491   tab_text (this->t, 2, 0, TAB_CENTER | TAT_TITLE, _("Mean"));
492   tab_text (this->t, 3, 0, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
493   tab_text (this->t, 4, 0, TAB_CENTER | TAT_TITLE, _("SE. Mean"));
494 }
495
496 void ssbox_independent_samples_populate(struct ssbox *ssb,
497                                         struct cmd_t_test *cmd);
498
499 /* Initialize the independent samples ssbox */
500 void 
501 ssbox_independent_samples_init(struct ssbox *this, 
502         struct cmd_t_test *cmd)
503 {
504   int hsize=6;
505   int vsize = cmd->n_variables*2 +1;
506
507   this->populate = ssbox_independent_samples_populate;
508
509   ssbox_base_init(this, hsize,vsize);
510   tab_title (this->t, 0, _("Group Statistics"));
511   tab_vline(this->t,0,1,0,vsize);
512   tab_text (this->t, 1, 0, TAB_CENTER | TAT_TITLE, groups->name);
513   tab_text (this->t, 2, 0, TAB_CENTER | TAT_TITLE, _("N"));
514   tab_text (this->t, 3, 0, TAB_CENTER | TAT_TITLE, _("Mean"));
515   tab_text (this->t, 4, 0, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
516   tab_text (this->t, 5, 0, TAB_CENTER | TAT_TITLE, _("SE. Mean"));
517 }
518
519
520 /* Populate the ssbox for independent samples */
521 void 
522 ssbox_independent_samples_populate(struct ssbox *ssb,
523                               struct cmd_t_test *cmd)
524 {
525   int i;
526
527   char *val_lab1=0;
528   char *val_lab2=0;
529
530   if ( groups->type == NUMERIC ) 
531     {
532       val_lab1 = val_labs_find( groups->val_labs,groups_values[0]); 
533       val_lab2 = val_labs_find( groups->val_labs,groups_values[1]);
534     }
535   else
536     {
537       val_lab1 = groups_values[0].s;
538       val_lab2 = groups_values[1].s;
539     }
540
541   assert(ssb->t);
542
543   for (i=0; i < cmd->n_variables; ++i)
544     {
545       tab_text (ssb->t, 0, i*2+1, TAB_LEFT, cmd->v_variables[i]->name);
546
547       if (val_lab1)
548         tab_text (ssb->t, 1, i*2+1, TAB_LEFT, val_lab1);
549       else
550         tab_float(ssb->t, 1 ,i*2+1, TAB_LEFT, groups_values[0].f, 2,0);
551
552       if (val_lab2)
553         tab_text (ssb->t, 1, i*2+1+1, TAB_LEFT, val_lab2);
554       else
555         tab_float(ssb->t, 1 ,i*2+1+1, TAB_LEFT, groups_values[1].f,2,0);
556     }
557 }
558
559
560 void ssbox_paired_populate(struct ssbox *ssb,
561                            struct cmd_t_test *cmd);
562
563 /* Initialize the paired values ssbox */
564 void 
565 ssbox_paired_init(struct ssbox *this, struct cmd_t_test *cmd unused)
566 {
567   int hsize=6;
568
569   int vsize = n_pairs*2+1;
570
571   this->populate = ssbox_paired_populate;
572
573   ssbox_base_init(this, hsize,vsize);
574   tab_title (this->t, 0, _("Paired Sample Statistics"));
575   tab_vline(this->t,TAL_0,1,0,vsize-1);
576   tab_vline(this->t,TAL_2,2,0,vsize-1);
577   tab_text (this->t, 2, 0, TAB_CENTER | TAT_TITLE, _("Mean"));
578   tab_text (this->t, 3, 0, TAB_CENTER | TAT_TITLE, _("N"));
579   tab_text (this->t, 4, 0, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
580   tab_text (this->t, 5, 0, TAB_CENTER | TAT_TITLE, _("SE. Mean"));
581 }
582
583
584 /* Populate the ssbox for paired values */
585 void 
586 ssbox_paired_populate(struct ssbox *ssb,struct cmd_t_test *cmd unused)
587 {
588   int i;
589   struct string ds;
590
591   assert(ssb->t);
592   ds_init(t_test_pool,&ds,15);
593
594   for (i=0; i < n_pairs; ++i)
595     {
596       ds_clear(&ds);
597
598       ds_printf(&ds,_("Pair %d"),i);
599
600       tab_text (ssb->t, 0, i*2+1, TAB_LEFT, ds.string);
601       tab_text (ssb->t, 1, i*2+1, TAB_LEFT, pairs[i][0]->name);
602       tab_text (ssb->t, 1, i*2+2, TAB_LEFT, pairs[i][1]->name);
603     }
604
605   ds_destroy(&ds);
606 }
607
608 /* Populate the one sample ssbox */
609 void 
610 ssbox_one_sample_populate(struct ssbox *ssb, struct cmd_t_test *cmd)
611 {
612   int i;
613
614   assert(ssb->t);
615
616   for (i=0; i < cmd->n_variables; ++i)
617     {
618       tab_text (ssb->t, 0, i+1, TAB_LEFT, cmd->v_variables[i]->name);
619     }
620   
621 }
622
623
624
625 /* Implementation of the Test Results box struct */
626
627 void trbox_base_init(struct trbox *self,int n_vars, int cols);
628 void trbox_base_finalize(struct trbox *trb);
629
630 void trbox_independent_samples_init(struct trbox *trb,
631                                     struct cmd_t_test *cmd );
632
633 void trbox_independent_samples_populate(struct trbox *trb,
634                                         struct cmd_t_test *cmd);
635
636 void trbox_one_sample_init(struct trbox *self,
637                       struct cmd_t_test *cmd );
638
639 void trbox_one_sample_populate(struct trbox *trb,
640                                struct cmd_t_test *cmd);
641
642 void trbox_paired_init(struct trbox *self,
643                        struct cmd_t_test *cmd );
644
645 void trbox_paired_populate(struct trbox *trb,
646                       struct cmd_t_test *cmd);
647
648
649
650 /* Create a trbox according to mode*/
651 void 
652 trbox_create(struct trbox *trb,   
653              struct cmd_t_test *cmd, int mode)
654 {
655     switch (mode) 
656       {
657       case T_1_SAMPLE:
658         trbox_one_sample_init(trb,cmd);
659         break;
660       case T_IND_SAMPLES:
661         trbox_independent_samples_init(trb,cmd);
662         break;
663       case T_PAIRED:
664         trbox_paired_init(trb,cmd);
665         break;
666       default:
667         assert(0);
668       }
669 }
670
671 /* Populate a trbox according to cmd */
672 void 
673 trbox_populate(struct trbox *trb, struct cmd_t_test *cmd)
674 {
675   trb->populate(trb,cmd);
676 }
677
678 /* Submit and destroy a trbox */
679 void 
680 trbox_finalize(struct trbox *trb)
681 {
682   trb->finalize(trb);
683 }
684
685 /* Initialize the independent samples trbox */
686 void 
687 trbox_independent_samples_init(struct trbox *self,
688                            struct cmd_t_test *cmd unused)
689 {
690   const int hsize=11;
691   const int vsize=cmd->n_variables*2+3;
692
693   struct string ds;
694
695   assert(self);
696   self->populate = trbox_independent_samples_populate;
697
698   trbox_base_init(self,cmd->n_variables*2,hsize);
699   tab_title(self->t,0,_("Independent Samples Test"));
700   tab_hline(self->t,TAL_1,2,hsize-1,1);
701   tab_vline(self->t,TAL_2,2,0,vsize-1);
702   tab_vline(self->t,TAL_1,4,0,vsize-1);
703   tab_box(self->t,-1,-1,-1,TAL_1, 2,1,hsize-2,vsize-1);
704   tab_hline(self->t,TAL_1, hsize-2,hsize-1,2);
705   tab_box(self->t,-1,-1,-1,TAL_1, hsize-2,2,hsize-1,vsize-1);
706   tab_joint_text(self->t, 2, 0, 3, 0, 
707                  TAB_CENTER,_("Levine's Test for Equality of Variances"));
708   tab_joint_text(self->t, 4,0,hsize-1,0,
709                  TAB_CENTER,_("t-test for Equality of Means"));
710
711   tab_text(self->t,2,2, TAB_CENTER | TAT_TITLE,_("F"));
712   tab_text(self->t,3,2, TAB_CENTER | TAT_TITLE,_("Sig."));
713   tab_text(self->t,4,2, TAB_CENTER | TAT_TITLE,_("t"));
714   tab_text(self->t,5,2, TAB_CENTER | TAT_TITLE,_("df"));
715   tab_text(self->t,6,2, TAB_CENTER | TAT_TITLE,_("Sig. (2-tailed)"));
716   tab_text(self->t,7,2, TAB_CENTER | TAT_TITLE,_("Mean Difference"));
717   tab_text(self->t,8,2, TAB_CENTER | TAT_TITLE,_("Std. Error Difference"));
718   tab_text(self->t,9,2, TAB_CENTER | TAT_TITLE,_("Lower"));
719   tab_text(self->t,10,2, TAB_CENTER | TAT_TITLE,_("Upper"));
720
721   ds_init(t_test_pool,&ds,80);
722                 
723   ds_printf(&ds,_("%d%% Confidence Interval of the Difference"),
724             (int)round(cmd->criteria*100.0));
725
726   tab_joint_text(self->t,9,1,10,1,TAB_CENTER, ds.string);
727
728   ds_destroy(&ds);
729 }
730
731 /* Populate the independent samples trbox */
732 void 
733 trbox_independent_samples_populate(struct trbox *self,
734                                    struct cmd_t_test *cmd )
735 {
736   int i;
737
738   assert(self);
739   for (i=0; i < cmd->n_variables; ++i)
740     {
741       tab_text (self->t, 0, i*2+3, TAB_LEFT, cmd->v_variables[i]->name);
742
743       tab_text (self->t, 1, i*2+3, TAB_LEFT, _("Equal variances assumed"));
744
745       tab_text (self->t, 1, i*2+3+1, 
746                 TAB_LEFT, _("Equal variances not assumed"));
747     }
748 }
749
750 /* Initialize the paired samples trbox */
751 void 
752 trbox_paired_init(struct trbox *self,
753                            struct cmd_t_test *cmd unused)
754 {
755
756   const int hsize=10;
757   const int vsize=n_pairs*2+3;
758
759   struct string ds;
760
761   self->populate = trbox_paired_populate;
762
763   trbox_base_init(self,n_pairs*2,hsize);
764   tab_title (self->t, 0, _("Paired Samples Test"));
765   tab_hline(self->t,TAL_1,2,6,1);
766   tab_vline(self->t,TAL_2,2,0,vsize);
767   tab_joint_text(self->t,2,0,6,0,TAB_CENTER,_("Paired Differences"));
768   tab_box(self->t,-1,-1,-1,TAL_1, 2,1,6,vsize-1);
769   tab_box(self->t,-1,-1,-1,TAL_1, 6,0,hsize-1,vsize-1);
770   tab_hline(self->t,TAL_1,5,6, 2);
771   tab_vline(self->t,TAL_0,6,0,1);
772
773   ds_init(t_test_pool,&ds,80);
774                 
775   ds_printf(&ds,_("%d%% Confidence Interval of the Difference"),
776             (int)round(cmd->criteria*100.0));
777
778   tab_joint_text(self->t,5,1,6,1,TAB_CENTER, ds.string);
779
780   ds_destroy(&ds);
781
782   tab_text (self->t, 2, 2, TAB_CENTER | TAT_TITLE, _("Mean"));
783   tab_text (self->t, 3, 2, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
784   tab_text (self->t, 4, 2, TAB_CENTER | TAT_TITLE, _("Std. Error Mean"));
785   tab_text (self->t, 5, 2, TAB_CENTER | TAT_TITLE, _("Lower"));
786   tab_text (self->t, 6, 2, TAB_CENTER | TAT_TITLE, _("Upper"));
787   tab_text (self->t, 7, 2, TAB_CENTER | TAT_TITLE, _("t"));
788   tab_text (self->t, 8, 2, TAB_CENTER | TAT_TITLE, _("df"));
789   tab_text (self->t, 9, 2, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)"));
790 }
791
792 /* Populate the paired samples trbox */
793 void 
794 trbox_paired_populate(struct trbox *trb,
795                               struct cmd_t_test *cmd unused)
796 {
797   int i;
798   struct string ds;
799
800   ds_init(t_test_pool,&ds,15);  
801
802   for (i=0; i < n_pairs; ++i)
803     {
804       ds_clear(&ds);
805       ds_printf(&ds,_("Pair %d"),i);
806
807       tab_text (trb->t, 0, i*2+3, TAB_LEFT, ds.string);
808       tab_text (trb->t, 1, i*2+3, TAB_LEFT, pairs[i][0]->name);
809       tab_text (trb->t, 1, i*2+4, TAB_LEFT, pairs[i][1]->name);
810     }
811   ds_destroy(&ds);
812 }
813
814 /* Initialize the one sample trbox */
815 void 
816 trbox_one_sample_init(struct trbox *self, struct cmd_t_test *cmd )
817 {
818   const int hsize=7;
819   const int vsize=cmd->n_variables+3;
820
821   struct string ds;
822   
823   self->populate = trbox_one_sample_populate;
824
825   trbox_base_init(self, cmd->n_variables,hsize);
826   tab_title (self->t, 0, _("One-Sample Test"));
827   tab_hline(self->t, TAL_1, 1, hsize - 1, 1);
828   tab_vline(self->t, TAL_2, 1, 0, vsize);
829   ds_init(t_test_pool, &ds, 80);
830   ds_printf(&ds,_("Test Value = %f"),cmd->n_testval);
831   tab_joint_text(self->t, 1, 0, hsize-1,0, TAB_CENTER,ds.string);
832   tab_box(self->t, -1, -1, -1, TAL_1, 1,1,hsize-1,vsize-1);
833
834   ds_clear(&ds);
835   ds_printf(&ds,_("%d%% Confidence Interval of the Difference"),
836             (int)round(cmd->criteria*100.0));
837   tab_joint_text(self->t,5,1,6,1,TAB_CENTER, ds.string);
838   ds_destroy(&ds);
839   tab_vline(self->t,TAL_0,6,1,1);
840   tab_hline(self->t,TAL_1,5,6,2);
841   tab_text (self->t, 1, 2, TAB_CENTER | TAT_TITLE, _("t"));
842   tab_text (self->t, 2, 2, TAB_CENTER | TAT_TITLE, _("df"));
843   tab_text (self->t, 3, 2, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)"));
844   tab_text (self->t, 4, 2, TAB_CENTER | TAT_TITLE, _("Mean Difference"));
845   tab_text (self->t, 5, 2, TAB_CENTER | TAT_TITLE, _("Lower"));
846   tab_text (self->t, 6, 2, TAB_CENTER | TAT_TITLE, _("Upper"));
847 }
848
849
850 /* Populate the one sample trbox */
851 void 
852 trbox_one_sample_populate(struct trbox *trb, struct cmd_t_test *cmd)
853 {
854   int i;
855
856   assert(trb->t);
857
858   for (i=0; i < cmd->n_variables; ++i)
859     {
860       tab_text (trb->t, 0, i+3, TAB_LEFT, cmd->v_variables[i]->name);
861     }
862 }
863
864 /* Base initializer for the generalized trbox */
865 void 
866 trbox_base_init(struct trbox *self, int data_rows, int cols)
867 {
868   const int rows = 3 + data_rows;
869
870   self->finalize = trbox_base_finalize;
871   self->t = tab_create (cols, rows, 0);
872   tab_headers (self->t,0,0,3,0); 
873   tab_box (self->t, TAL_2, TAL_2, TAL_0, TAL_0, 0, 0, cols -1, rows -1);
874   tab_hline(self->t, TAL_2,0,cols-1,3);
875   tab_dim (self->t, tab_natural_dimensions);
876 }
877
878
879 /* Base finalizer for the trbox */
880 void 
881 trbox_base_finalize(struct trbox *trb)
882 {
883   tab_submit(trb->t);
884 }