Add an Emacs header line to output files that makes generated .c files
[pspp] / src / crosstabs.q
1 /* PSPP - computes sample statistics.
2    Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3    Written by Ben Pfaff <blp@gnu.org>.
4
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18    02111-1307, USA. */
19
20 /* FIXME:
21
22    - Pearson's R (but not Spearman!) is off a little.
23    - T values for Spearman's R and Pearson's R are wrong.
24    - How to calculate significance of symmetric and directional measures?
25    - Asymmetric ASEs and T values for lambda are wrong.
26    - ASE of Goodman and Kruskal's tau is not calculated.
27    - ASE of symmetric somers' d is wrong.
28    - Approx. T of uncertainty coefficient is wrong.
29
30 */
31
32 #include <config.h>
33 #include <assert.h>
34 #include <ctype.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include "algorithm.h"
38 #include "alloc.h"
39 #include "hash.h"
40 #include "pool.h"
41 #include "command.h"
42 #include "lexer.h"
43 #include "error.h"
44 #include "magic.h"
45 #include "misc.h"
46 #include "stats.h"
47 #include "output.h"
48 #include "tab.h"
49 #include "value-labels.h"
50 #include "var.h"
51 #include "vfm.h"
52
53 #include "debug-print.h"
54
55 /* (specification)
56    crosstabs (crs_):
57      *tables=custom;
58      +variables=custom;
59      +missing=miss:!table/include/report;
60      +write[wr_]=none,cells,all;
61      +format=fmt:!labels/nolabels/novallabs,
62              val:!avalue/dvalue,
63              indx:!noindex/index,
64              tabl:!tables/notables,
65              box:!box/nobox,
66              pivot:!pivot/nopivot;
67      +cells[cl_]=count,none,row,column,total,expected,residual,sresidual,
68                  asresidual,all;
69      +statistics[st_]=chisq,phi,cc,lambda,uc,none,btau,ctau,risk,gamma,d,
70                       kappa,eta,corr,all.
71 */
72 /* (declarations) */
73 /* (functions) */
74
75 /* Number of chi-square statistics. */
76 #define N_CHISQ 5
77
78 /* Number of symmetric statistics. */
79 #define N_SYMMETRIC 9
80
81 /* Number of directional statistics. */
82 #define N_DIRECTIONAL 13
83
84 /* A single table entry for general mode. */
85 struct table_entry
86   {
87     int table;          /* Flattened table number. */
88     union
89       {
90         double freq;    /* Frequency count. */
91         double *data;   /* Crosstabulation table for integer mode. */
92       }
93     u;
94     union value values[1];      /* Values. */
95   };
96
97 /* A crosstabulation. */
98 struct crosstab
99   {
100     int nvar;                   /* Number of variables. */
101     double missing;             /* Missing cases count. */
102     int ofs;                    /* Integer mode: Offset into sorted_tab[]. */
103     struct variable *vars[2];   /* At least two variables; sorted by
104                                    larger indices first. */
105   };
106
107 /* Indexes into crosstab.v. */
108 enum
109   {
110     ROW_VAR = 0,
111     COL_VAR = 1
112   };
113
114 /* General mode crosstabulation table. */
115 static struct hsh_table *gen_tab;       /* Hash table. */
116 static int n_sorted_tab;                /* Number of entries in sorted_tab. */
117 static struct table_entry **sorted_tab; /* Sorted table. */
118
119 /* Variables specifies on VARIABLES. */
120 static struct variable **variables;
121 static size_t variables_cnt;
122
123 /* TABLES. */
124 static struct crosstab **xtab;
125 static int nxtab;
126
127 /* Integer or general mode? */
128 enum
129   {
130     INTEGER,
131     GENERAL
132   };
133 static int mode;
134
135 /* CELLS. */
136 static int num_cells;           /* Number of cells requested. */
137 static int cells[8];            /* Cells requested. */
138 static int expected;            /* Nonzero if expected value is needed. */
139
140 /* WRITE. */
141 static int write;               /* One of WR_* that specifies the WRITE style. */
142
143 /* Command parsing info. */
144 static struct cmd_crosstabs cmd;
145
146 /* Pools. */
147 static struct pool *pl_tc;      /* For table cells. */
148 static struct pool *pl_col;     /* For column data. */
149
150 static int internal_cmd_crosstabs (void);
151 static void precalc (void *);
152 static int calc_general (struct ccase *, void *);
153 static int calc_integer (struct ccase *, void *);
154 static void postcalc (void *);
155 static void submit (struct tab_table *);
156
157 static void format_short (char *s, const struct fmt_spec *fp,
158                          const union value *v);
159
160 #if DEBUGGING
161 static void debug_print (void);
162 static void print_table_entries (struct table_entry **tab);
163 #endif
164
165 /* Parse and execute CROSSTABS, then clean up. */
166 int
167 cmd_crosstabs (void)
168 {
169   int result = internal_cmd_crosstabs ();
170
171   free (variables);
172   pool_destroy (pl_tc);
173   pool_destroy (pl_col);
174   
175   return result;
176 }
177
178 /* Parses and executes the CROSSTABS procedure. */
179 static int
180 internal_cmd_crosstabs (void)
181 {
182   variables = NULL;
183   variables_cnt = 0;
184   xtab = NULL;
185   nxtab = 0;
186   pl_tc = pool_create ();
187   pl_col = pool_create ();
188
189   lex_match_id ("CROSSTABS");
190   if (!parse_crosstabs (&cmd))
191     return CMD_FAILURE;
192
193 #if DEBUGGING
194   /* Needs variables. */
195   debug_print ();
196 #endif
197
198   mode = variables ? INTEGER : GENERAL;
199
200   /* CELLS. */
201   expected = 0;
202   if (!cmd.sbc_cells)
203     {
204       cmd.a_cells[CRS_CL_COUNT] = 1;
205       num_cells = 1;
206     }
207   else 
208     {
209       int i;
210       int count = 0;
211
212       for (i = 0; i < CRS_CL_count; i++)
213         if (cmd.a_cells[i])
214           count++;
215       if (count == 0)
216         {
217           cmd.a_cells[CRS_CL_COUNT] = 1;
218           cmd.a_cells[CRS_CL_ROW] = 1;
219           cmd.a_cells[CRS_CL_COLUMN] = 1;
220           cmd.a_cells[CRS_CL_TOTAL] = 1;
221         }
222       if (cmd.a_cells[CRS_CL_ALL])
223         {
224           for (i = 0; i < CRS_CL_count; i++)
225             cmd.a_cells[i] = 1;
226           cmd.a_cells[CRS_CL_ALL] = 0;
227         }
228       cmd.a_cells[CRS_CL_NONE] = 0;
229       for (num_cells = i = 0; i < CRS_CL_count; i++)
230         if (cmd.a_cells[i])
231           {
232             if (i >= CRS_CL_EXPECTED)
233               expected = 1;
234             cmd.a_cells[num_cells++] = i;
235           }
236     }
237
238   /* STATISTICS. */
239   if (cmd.sbc_statistics)
240     {
241       int i;
242       int count = 0;
243
244       for (i = 0; i < CRS_ST_count; i++)
245         if (cmd.a_statistics[i])
246           count++;
247       if (count == 0)
248         cmd.a_statistics[CRS_ST_CHISQ] = 1;
249       if (cmd.a_statistics[CRS_ST_ALL])
250         for (i = 0; i < CRS_ST_count; i++)
251           cmd.a_statistics[i] = 1;
252     }
253   
254   /* MISSING. */
255   if (cmd.miss == CRS_REPORT && mode == GENERAL)
256     {
257       msg (SE, _("Missing mode REPORT not allowed in general mode.  "
258                  "Assuming MISSING=TABLE."));
259       cmd.miss = CRS_TABLE;
260     }
261
262   /* WRITE. */
263   if (cmd.a_write[CRS_WR_ALL] && cmd.a_write[CRS_WR_CELLS])
264     cmd.a_write[CRS_WR_ALL] = 0;
265   if (cmd.a_write[CRS_WR_ALL] && mode == GENERAL)
266     {
267       msg (SE, _("Write mode ALL not allowed in general mode.  "
268                  "Assuming WRITE=CELLS."));
269       cmd.a_write[CRS_WR_CELLS] = 1;
270     }
271   if (cmd.sbc_write
272       && (cmd.a_write[CRS_WR_NONE]
273           + cmd.a_write[CRS_WR_ALL]
274           + cmd.a_write[CRS_WR_CELLS] == 0))
275     cmd.a_write[CRS_WR_CELLS] = 1;
276   if (cmd.a_write[CRS_WR_CELLS])
277     write = CRS_WR_CELLS;
278   else if (cmd.a_write[CRS_WR_ALL])
279     write = CRS_WR_ALL;
280   else
281     write = CRS_WR_NONE;
282
283   procedure (precalc, mode == GENERAL ? calc_general : calc_integer, postcalc,
284              NULL);
285
286   return CMD_SUCCESS;
287 }
288
289 /* Parses the TABLES subcommand. */
290 static int
291 crs_custom_tables (struct cmd_crosstabs *cmd UNUSED)
292 {
293   struct var_set *var_set;
294   int n_by;
295   struct variable ***by = NULL;
296   int *by_nvar = NULL;
297   int nx = 1;
298   int success = 0;
299
300   /* Ensure that this is a TABLES subcommand. */
301   if (!lex_match_id ("TABLES")
302       && (token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
303       && token != T_ALL)
304     return 2;
305   lex_match ('=');
306
307   if (variables != NULL)
308     var_set = var_set_create_from_array (variables, variables_cnt);
309   else
310     var_set = var_set_create_from_dict (default_dict);
311   assert (var_set != NULL);
312   
313   for (n_by = 0; ;)
314     {
315       by = xrealloc (by, sizeof *by * (n_by + 1));
316       by_nvar = xrealloc (by_nvar, sizeof *by_nvar * (n_by + 1));
317       if (!parse_var_set_vars (var_set, &by[n_by], &by_nvar[n_by],
318                                PV_NO_DUPLICATE | PV_NO_SCRATCH))
319         goto done;
320       nx *= by_nvar[n_by];
321       n_by++;
322
323       if (!lex_match (T_BY))
324         {
325           if (n_by < 1)
326             {
327               lex_error (_("expecting BY"));
328               goto done;
329             }
330           else 
331             break;
332         }
333     }
334   
335   {
336     int *by_iter = xcalloc (sizeof *by_iter * n_by);
337     int i;
338
339     xtab = xrealloc (xtab, sizeof *xtab * (nxtab + nx));
340     for (i = 0; i < nx; i++)
341       {
342         struct crosstab *x;
343
344         x = xmalloc (sizeof *x + sizeof (struct variable *) * (n_by - 2));
345         x->nvar = n_by;
346         x->missing = 0.;
347
348         {
349           int i;
350
351           for (i = 0; i < n_by; i++)
352             x->vars[i] = by[i][by_iter[i]];
353         }
354         
355         {
356           int i;
357
358           for (i = n_by - 1; i >= 0; i--)
359             {
360               if (++by_iter[i] < by_nvar[i])
361                 break;
362               by_iter[i] = 0;
363             }
364         }
365
366         xtab[nxtab++] = x;
367       }
368     free (by_iter);
369   }
370   success = 1;
371
372  done:
373   /* All return paths lead here. */
374   {
375     int i;
376
377     for (i = 0; i < n_by; i++)
378       free (by[i]);
379     free (by);
380     free (by_nvar);
381   }
382
383   var_set_destroy (var_set);
384
385   return success;
386 }
387
388 /* Parses the VARIABLES subcommand. */
389 static int
390 crs_custom_variables (struct cmd_crosstabs *cmd UNUSED)
391 {
392   if (nxtab)
393     {
394       msg (SE, _("VARIABLES must be specified before TABLES."));
395       return 0;
396     }
397
398   lex_match ('=');
399   
400   for (;;)
401     {
402       int orig_nv = variables_cnt;
403       int i;
404
405       long min, max;
406       
407       if (!parse_variables (default_dict, &variables, &variables_cnt,
408                             (PV_APPEND | PV_NUMERIC
409                              | PV_NO_DUPLICATE | PV_NO_SCRATCH)))
410         return 0;
411
412       if (token != '(')
413         {
414           lex_error ("expecting `('");
415           goto lossage;
416         }
417       lex_get ();
418
419       if (!lex_force_int ())
420         goto lossage;
421       min = lex_integer ();
422       lex_get ();
423
424       lex_match (',');
425
426       if (!lex_force_int ())
427         goto lossage;
428       max = lex_integer ();
429       if (max < min)
430         {
431           msg (SE, _("Maximum value (%ld) less than minimum value (%ld)."),
432                max, min);
433           goto lossage;
434         }
435       lex_get ();
436
437       if (token != ')')
438         {
439           lex_error ("expecting `)'");
440           goto lossage;
441         }
442       lex_get ();
443       
444       for (i = orig_nv; i < variables_cnt; i++)
445         {
446           variables[i]->p.crs.min = min;
447           variables[i]->p.crs.max = max + 1.;
448           variables[i]->p.crs.count = max - min + 1;
449         }
450       
451       if (token == '/')
452         break;
453     }
454   
455   return 1;
456
457  lossage:
458   free (variables);
459   variables = NULL;
460   return 0;
461 }
462
463 #if DEBUGGING
464 static void
465 debug_print (void)
466 {
467   printf ("CROSSTABS\n");
468
469   if (variables != NULL)
470     {
471       int i;
472
473       printf ("\t/VARIABLES=");
474       for (i = 0; i < variables_cnt; i++)
475         {
476           struct variable *v = variables[i];
477
478           printf ("%s ", v->name);
479           if (i < variables_cnt - 1)
480             {
481               struct variable *nv = variables[i + 1];
482               
483               if (v->p.crs.min == nv->p.crs.min
484                   && v->p.crs.max == nv->p.crs.max)
485                 continue;
486             }
487           printf ("(%d,%d) ", v->p.crs.min, v->p.crs.max - 1);
488         }
489       printf ("\n");
490     }
491   
492   {
493     int i;
494
495     printf ("\t/TABLES=");
496     for (i = 0; i < nxtab; i++)
497       {
498         struct crosstab *x = xtab[i];
499         int j;
500
501         if (i)
502           printf("\t\t");
503         for (j = 0; j < x->nvar; j++)
504           {
505             if (j)
506               printf (" BY ");
507             printf ("%s", x->v[j]->name);
508           }
509         printf ("\n");
510       }
511   }
512 }
513 #endif /* DEBUGGING */
514 \f
515 /* Data file processing. */
516
517 static int compare_table_entry (const void *, const void *, void *);
518 static unsigned hash_table_entry (const void *, void *);
519
520 /* Set up the crosstabulation tables for processing. */
521 static void
522 precalc (void *aux UNUSED)
523 {
524   if (mode == GENERAL)
525     {
526       gen_tab = hsh_create (512, compare_table_entry, hash_table_entry,
527                             NULL, NULL);
528     }
529   else 
530     {
531       int i;
532
533       sorted_tab = NULL;
534       n_sorted_tab = 0;
535
536       for (i = 0; i < nxtab; i++)
537         {
538           struct crosstab *x = xtab[i];
539           int count = 1;
540           int *v;
541           int j;
542
543           x->ofs = n_sorted_tab;
544
545           for (j = 2; j < x->nvar; j++)
546             count *= x->vars[j - 2]->p.crs.count;
547
548           sorted_tab = xrealloc (sorted_tab,
549                                  sizeof *sorted_tab * (n_sorted_tab + count));
550           v = local_alloc (sizeof *v * x->nvar);
551           for (j = 2; j < x->nvar; j++)
552             v[j] = x->vars[j]->p.crs.min;
553           for (j = 0; j < count; j++)
554             {
555               struct table_entry *te;
556               int k;
557
558               te = sorted_tab[n_sorted_tab++]
559                 = xmalloc (sizeof *te + sizeof (union value) * (x->nvar - 1));
560               te->table = i;
561               
562               {
563                 const int mat_size = (x->vars[0]->p.crs.count
564                                       * x->vars[1]->p.crs.count);
565                 int m;
566                 
567                 te->u.data = xmalloc (sizeof *te->u.data * mat_size);
568                 for (m = 0; m < mat_size; m++)
569                   te->u.data[m] = 0.;
570               }
571               
572               for (k = 2; k < x->nvar; k++)
573                 te->values[k].f = v[k];
574               for (k = 2; k < x->nvar; k++)
575                 if (++v[k] >= x->vars[k]->p.crs.max)
576                   v[k] = x->vars[k]->p.crs.min;
577                 else
578                   break;
579             }
580           local_free (v);
581         }
582
583       sorted_tab = xrealloc (sorted_tab,
584                              sizeof *sorted_tab * (n_sorted_tab + 1));
585       sorted_tab[n_sorted_tab] = NULL;
586     }
587 }
588
589 /* Form crosstabulations for general mode. */
590 static int
591 calc_general (struct ccase *c, void *aux UNUSED)
592 {
593   /* Case weight. */
594   double weight = dict_get_case_weight (default_dict, c);
595
596   /* Flattened current table index. */
597   int t;
598
599   for (t = 0; t < nxtab; t++)
600     {
601       struct crosstab *x = xtab[t];
602       const size_t entry_size = (sizeof (struct table_entry)
603                                  + sizeof (union value) * (x->nvar - 1));
604       struct table_entry *te = local_alloc (entry_size);
605
606       /* Construct table entry for the current record and table. */
607       te->table = t;
608       {
609         int j;
610
611         assert (x != NULL);
612         for (j = 0; j < x->nvar; j++)
613           {
614             if ((cmd.miss == CRS_TABLE
615                  && is_missing (&c->data[x->vars[j]->fv], x->vars[j]))
616                 || (cmd.miss == CRS_INCLUDE
617                     && is_system_missing (&c->data[x->vars[j]->fv],
618                                           x->vars[j])))
619               {
620                 x->missing += weight;
621                 goto next_crosstab;
622               }
623               
624             if (x->vars[j]->type == NUMERIC)
625               te->values[j].f = c->data[x->vars[j]->fv].f;
626             else
627               {
628                 memcpy (te->values[j].s, c->data[x->vars[j]->fv].s,
629                         x->vars[j]->width);
630               
631                 /* Necessary in order to simplify comparisons. */
632                 memset (&te->values[j].s[x->vars[j]->width], 0,
633                         sizeof (union value) - x->vars[j]->width);
634               }
635           }
636       }
637
638       /* Add record to hash table. */
639       {
640         struct table_entry **tepp
641           = (struct table_entry **) hsh_probe (gen_tab, te);
642         if (*tepp == NULL)
643           {
644             struct table_entry *tep = pool_alloc (pl_tc, entry_size);
645             
646             te->u.freq = weight;
647             memcpy (tep, te, entry_size);
648             
649             *tepp = tep;
650           }
651         else
652           (*tepp)->u.freq += weight;
653       }
654
655     next_crosstab:
656       local_free (te);
657     }
658   
659   return 1;
660 }
661
662 static int
663 calc_integer (struct ccase *c, void *aux UNUSED)
664 {
665   /* Case weight. */
666   double weight = dict_get_case_weight (default_dict, c);
667   
668   /* Flattened current table index. */
669   int t;
670   
671   for (t = 0; t < nxtab; t++)
672     {
673       struct crosstab *x = xtab[t];
674       int i, fact, ofs;
675       
676       fact = i = 1;
677       ofs = x->ofs;
678       for (i = 0; i < x->nvar; i++)
679         {
680           struct variable *const v = x->vars[i];
681           double value = c->data[v->fv].f;
682           
683           /* Note that the first test also rules out SYSMIS. */
684           if ((value < v->p.crs.min || value >= v->p.crs.max)
685               || (cmd.miss == CRS_TABLE && is_num_user_missing (value, v)))
686             {
687               x->missing += weight;
688               goto next_crosstab;
689             }
690           
691           if (i > 1)
692             {
693               ofs += fact * ((int) value - v->p.crs.min);
694               fact *= v->p.crs.count;
695             }
696         }
697       
698       {
699         const int row = c->data[x->vars[ROW_VAR]->fv].f - x->vars[ROW_VAR]->p.crs.min;
700         const int col = c->data[x->vars[COL_VAR]->fv].f - x->vars[COL_VAR]->p.crs.min;
701         const int col_dim = x->vars[COL_VAR]->p.crs.count;
702
703         sorted_tab[ofs]->u.data[col + row * col_dim] += weight;
704       }
705       
706     next_crosstab: ;
707     }
708   
709   return 1;
710 }
711
712 #if DEBUGGING
713 /* Print out all table entries in NULL-terminated TAB for use by a
714    debugger (a person, not a program). */
715 static void
716 print_table_entries (struct table_entry **tab)
717 {
718   printf ("raw crosstabulation data:\n");
719   for (; *tab; tab++)
720     {
721       const struct crosstab *x = xtab[(*tab)->table];
722       int i;
723
724       printf ("(%g) table:%d ", (*tab)->u.freq, (*tab)->table);
725       for (i = 0; i < x->nvar; i++)
726         {
727           if (i)
728             printf (", ");
729           printf ("%s:", x->v[i]->name);
730           
731           if (x->v[i]->type == NUMERIC)
732             printf ("%g", (*tab)->v[i].f);
733           else
734             printf ("%.*s", x->v[i]->width, (*tab)->v[i].s);
735         }
736       printf ("\n");
737     }
738   fflush (stdout);
739 }
740 #endif
741
742 /* Compare the table_entry's at A and B and return a strcmp()-type
743    result. */
744 static int 
745 compare_table_entry (const void *a_, const void *b_, void *foo UNUSED)
746 {
747   const struct table_entry *a = a_;
748   const struct table_entry *b = b_;
749
750   if (a->table > b->table)
751     return 1;
752   else if (a->table < b->table)
753     return -1;
754   
755   {
756     const struct crosstab *x = xtab[a->table];
757     int i;
758
759     for (i = x->nvar - 1; i >= 0; i--)
760       if (x->vars[i]->type == NUMERIC)
761         {
762           const double diffnum = a->values[i].f - b->values[i].f;
763           if (diffnum < 0)
764             return -1;
765           else if (diffnum > 0)
766             return 1;
767         }
768       else 
769         {
770           assert (x->vars[i]->type == ALPHA);
771           {
772             const int diffstr = strncmp (a->values[i].s, b->values[i].s,
773                                          x->vars[i]->width);
774             if (diffstr)
775               return diffstr;
776           }
777         }
778   }
779   
780   return 0;
781 }
782
783 /* Calculate a hash value from table_entry A. */
784 static unsigned
785 hash_table_entry (const void *a_, void *foo UNUSED)
786 {
787   const struct table_entry *a = a_;
788   unsigned long hash;
789   int i;
790
791   hash = a->table;
792   for (i = 0; i < xtab[a->table]->nvar; i++)
793     hash ^= hsh_hash_bytes (&a->values[i], sizeof a->values[i]);
794   
795   return hash;
796 }
797 \f
798 /* Post-data reading calculations. */
799
800 static struct table_entry **find_pivot_extent (struct table_entry **,
801                                                int *cnt, int pivot);
802 static void enum_var_values (struct table_entry **entries, int entry_cnt,
803                              int var_idx,
804                              union value **values, int *value_cnt);
805 static void output_pivot_table (struct table_entry **, struct table_entry **,
806                                 double **, double **, double **,
807                                 int *, int *, int *);
808 static void make_summary_table (void);
809
810 static void
811 postcalc (void *aux UNUSED)
812 {
813   if (mode == GENERAL)
814     {
815       n_sorted_tab = hsh_count (gen_tab);
816       sorted_tab = (struct table_entry **) hsh_sort (gen_tab);
817 #if DEBUGGING
818       print_table_entries (sorted_tab);
819 #endif
820     }
821   
822   make_summary_table ();
823   
824   /* Identify all the individual crosstabulation tables, and deal with
825      them. */
826   {
827     struct table_entry **pb = sorted_tab, **pe; /* Pivot begin, pivot end. */
828     int pc = n_sorted_tab;                      /* Pivot count. */
829
830     double *mat = NULL, *row_tot = NULL, *col_tot = NULL;
831     int maxrows = 0, maxcols = 0, maxcells = 0;
832
833     for (;;)
834       {
835         pe = find_pivot_extent (pb, &pc, cmd.pivot == CRS_PIVOT);
836         if (pe == NULL)
837           break;
838         
839         output_pivot_table (pb, pe, &mat, &row_tot, &col_tot,
840                             &maxrows, &maxcols, &maxcells);
841           
842         pb = pe;
843       }
844     free (mat);
845     free (row_tot);
846     free (col_tot);
847   }
848   
849   hsh_destroy (gen_tab);
850 }
851
852 static void insert_summary (struct tab_table *, int tab_index, double valid);
853
854 /* Output a table summarizing the cases processed. */
855 static void
856 make_summary_table (void)
857 {
858   struct tab_table *summary;
859   
860   struct table_entry **pb = sorted_tab, **pe;
861   int pc = n_sorted_tab;
862   int cur_tab = 0;
863
864   summary = tab_create (7, 3 + nxtab, 1);
865   tab_title (summary, 0, _("Summary."));
866   tab_headers (summary, 1, 0, 3, 0);
867   tab_joint_text (summary, 1, 0, 6, 0, TAB_CENTER, _("Cases"));
868   tab_joint_text (summary, 1, 1, 2, 1, TAB_CENTER, _("Valid"));
869   tab_joint_text (summary, 3, 1, 4, 1, TAB_CENTER, _("Missing"));
870   tab_joint_text (summary, 5, 1, 6, 1, TAB_CENTER, _("Total"));
871   tab_hline (summary, TAL_1, 1, 6, 1);
872   tab_hline (summary, TAL_1, 1, 6, 2);
873   tab_vline (summary, TAL_1, 3, 1, 1);
874   tab_vline (summary, TAL_1, 5, 1, 1);
875   {
876     int i;
877
878     for (i = 0; i < 3; i++)
879       {
880         tab_text (summary, 1 + i * 2, 2, TAB_RIGHT, _("N"));
881         tab_text (summary, 2 + i * 2, 2, TAB_RIGHT, _("Percent"));
882       }
883   }
884   tab_offset (summary, 0, 3);
885                   
886   for (;;)
887     {
888       double valid;
889       
890       pe = find_pivot_extent (pb, &pc, cmd.pivot == CRS_PIVOT);
891       if (pe == NULL)
892         break;
893
894       while (cur_tab < (*pb)->table)
895         insert_summary (summary, cur_tab++, 0.);
896
897       if (mode == GENERAL)
898         for (valid = 0.; pb < pe; pb++)
899           valid += (*pb)->u.freq;
900       else
901         {
902           const struct crosstab *const x = xtab[(*pb)->table];
903           const int n_cols = x->vars[COL_VAR]->p.crs.count;
904           const int n_rows = x->vars[ROW_VAR]->p.crs.count;
905           const int count = n_cols * n_rows;
906             
907           for (valid = 0.; pb < pe; pb++)
908             {
909               const double *data = (*pb)->u.data;
910               int i;
911                 
912               for (i = 0; i < count; i++)
913                 valid += *data++;
914             }
915         }
916       insert_summary (summary, cur_tab++, valid);
917
918       pb = pe;
919     }
920   
921   while (cur_tab < nxtab)
922     insert_summary (summary, cur_tab++, 0.);
923
924   submit (summary);
925 }
926
927 /* Inserts a line into T describing the crosstabulation at index
928    TAB_INDEX, which has VALID valid observations. */
929 static void
930 insert_summary (struct tab_table *t, int tab_index, double valid)
931 {
932   struct crosstab *x = xtab[tab_index];
933
934   tab_hline (t, TAL_1, 0, 6, 0);
935   
936   /* Crosstabulation name. */
937   {
938     char *buf = local_alloc (128 * x->nvar);
939     char *cp = buf;
940     int i;
941
942     for (i = 0; i < x->nvar; i++)
943       {
944         if (i > 0)
945           cp = stpcpy (cp, " * ");
946
947         cp = stpcpy (cp,
948                      x->vars[i]->label ? x->vars[i]->label : x->vars[i]->name);
949       }
950     tab_text (t, 0, 0, TAB_LEFT, buf);
951
952     local_free (buf);
953   }
954     
955   /* Counts and percentages. */
956   {
957     double n[3];
958     int i;
959
960     n[0] = valid;
961     n[1] = x->missing;
962     n[2] = n[0] + n[1];
963
964
965     for (i = 0; i < 3; i++)
966       {
967         tab_float (t, i * 2 + 1, 0, TAB_RIGHT, n[i], 8, 0);
968         tab_text (t, i * 2 + 2, 0, TAB_RIGHT | TAT_PRINTF, "%.1f%%",
969                   n[i] / n[2] * 100.);
970       }
971   }
972   
973   tab_next_row (t);
974 }
975 \f
976 /* Output. */
977
978 /* Tables. */
979 static struct tab_table *table; /* Crosstabulation table. */
980 static struct tab_table *chisq; /* Chi-square table. */
981 static struct tab_table *sym;           /* Symmetric measures table. */
982 static struct tab_table *risk;          /* Risk estimate table. */
983 static struct tab_table *direct;        /* Directional measures table. */
984
985 /* Statistics. */
986 static int chisq_fisher;        /* Did any rows include Fisher's exact test? */
987
988 /* Column values, number of columns. */
989 static union value *cols;
990 static int n_cols;
991
992 /* Row values, number of rows. */
993 static union value *rows;
994 static int n_rows;
995               
996 /* Number of statistically interesting columns/rows (columns/rows with
997    data in them). */
998 static int ns_cols, ns_rows;
999
1000 /* Crosstabulation. */
1001 static struct crosstab *x;
1002
1003 /* Number of variables from the crosstabulation to consider.  This is
1004    either x->nvar, if pivoting is on, or 2, if pivoting is off. */
1005 static int nvar;
1006
1007 /* Matrix contents. */
1008 static double *mat;             /* Matrix proper. */
1009 static double *row_tot;         /* Row totals. */
1010 static double *col_tot;         /* Column totals. */
1011 static double W;                /* Grand total. */
1012
1013 static void display_dimensions (struct tab_table *, int first_difference,
1014                                 struct table_entry *);
1015 static void display_crosstabulation (void);
1016 static void display_chisq (void);
1017 static void display_symmetric (void);
1018 static void display_risk (void);
1019 static void display_directional (void);
1020 static void crosstabs_dim (struct tab_table *, struct outp_driver *);
1021 static void table_value_missing (struct tab_table *table, int c, int r,
1022                                  unsigned char opt, const union value *v,
1023                                  const struct variable *var);
1024 static void delete_missing (void);
1025
1026 /* Output pivot table beginning at PB and continuing until PE,
1027    exclusive.  For efficiency, *MATP is a pointer to a matrix that can
1028    hold *MAXROWS entries. */
1029 static void
1030 output_pivot_table (struct table_entry **pb, struct table_entry **pe,
1031                     double **matp, double **row_totp, double **col_totp,
1032                     int *maxrows, int *maxcols, int *maxcells)
1033 {
1034   /* Subtable. */
1035   struct table_entry **tb = pb, **te;   /* Table begin, table end. */
1036   int tc = pe - pb;             /* Table count. */
1037
1038   /* Table entry for header comparison. */
1039   struct table_entry *cmp;
1040
1041   x = xtab[(*pb)->table];
1042   enum_var_values (pb, pe - pb, COL_VAR, &cols, &n_cols);
1043
1044   nvar = cmd.pivot == CRS_PIVOT ? x->nvar : 2;
1045
1046   /* Crosstabulation table initialization. */
1047   if (num_cells)
1048     {
1049       table = tab_create (nvar + n_cols,
1050                           (pe - pb) / n_cols * 3 / 2 * num_cells + 10, 1);
1051       tab_headers (table, nvar - 1, 0, 2, 0);
1052
1053       /* First header line. */
1054       tab_joint_text (table, nvar - 1, 0, (nvar - 1) + (n_cols - 1), 0,
1055                       TAB_CENTER | TAT_TITLE, x->vars[COL_VAR]->name);
1056   
1057       tab_hline (table, TAL_1, nvar - 1, nvar + n_cols - 2, 1);
1058              
1059       /* Second header line. */
1060       {
1061         int i;
1062
1063         for (i = 2; i < nvar; i++)
1064           tab_joint_text (table, nvar - i - 1, 0, nvar - i - 1, 1,
1065                           TAB_RIGHT | TAT_TITLE,
1066                           (x->vars[i]->label
1067                            ? x->vars[i]->label : x->vars[i]->name));
1068         tab_text (table, nvar - 2, 1, TAB_RIGHT | TAT_TITLE,
1069                   x->vars[ROW_VAR]->name);
1070         for (i = 0; i < n_cols; i++)
1071           table_value_missing (table, nvar + i - 1, 1, TAB_RIGHT, &cols[i],
1072                                x->vars[COL_VAR]);
1073         tab_text (table, nvar + n_cols - 1, 1, TAB_CENTER, _("Total"));
1074       }
1075
1076       tab_hline (table, TAL_1, 0, nvar + n_cols - 1, 2);
1077       tab_vline (table, TAL_1, nvar + n_cols - 1, 0, 1);
1078
1079       /* Title. */
1080       {
1081         char *title = local_alloc (x->nvar * 64 + 128);
1082         char *cp = title;
1083         int i;
1084     
1085         if (cmd.pivot == CRS_PIVOT)
1086           for (i = 0; i < nvar; i++)
1087             {
1088               if (i)
1089                 cp = stpcpy (cp, " by ");
1090               cp = stpcpy (cp, x->vars[i]->name);
1091             }
1092         else
1093           {
1094             cp = spprintf (cp, "%s by %s for",
1095                            x->vars[0]->name, x->vars[1]->name);
1096             for (i = 2; i < nvar; i++)
1097               {
1098                 char buf[64], *bufp;
1099
1100                 if (i > 2)
1101                   *cp++ = ',';
1102                 *cp++ = ' ';
1103                 cp = stpcpy (cp, x->vars[i]->name);
1104                 *cp++ = '=';
1105                 format_short (buf, &x->vars[i]->print, &(*pb)->values[i]);
1106                 for (bufp = buf; isspace ((unsigned char) *bufp); bufp++)
1107                   ;
1108                 cp = stpcpy (cp, bufp);
1109               }
1110           }
1111
1112         cp = stpcpy (cp, " [");
1113         for (i = 0; i < num_cells; i++)
1114           {
1115             struct tuple
1116               {
1117                 int value;
1118                 const char *name;
1119               };
1120         
1121             static const struct tuple cell_names[] = 
1122               {
1123                 {CRS_CL_COUNT, N_("count")},
1124                 {CRS_CL_ROW, N_("row %")},
1125                 {CRS_CL_COLUMN, N_("column %")},
1126                 {CRS_CL_TOTAL, N_("total %")},
1127                 {CRS_CL_EXPECTED, N_("expected")},
1128                 {CRS_CL_RESIDUAL, N_("residual")},
1129                 {CRS_CL_SRESIDUAL, N_("std. resid.")},
1130                 {CRS_CL_ASRESIDUAL, N_("adj. resid.")},
1131                 {-1, NULL},
1132               };
1133
1134             const struct tuple *t;
1135
1136             for (t = cell_names; t->value != cells[i]; t++)
1137               assert (t->value != -1);
1138             if (i)
1139               cp = stpcpy (cp, ", ");
1140             cp = stpcpy (cp, gettext (t->name));
1141           }
1142         strcpy (cp, "].");
1143
1144         tab_title (table, 0, title);
1145         local_free (title);
1146       }
1147       
1148       tab_offset (table, 0, 2);
1149     }
1150   else
1151     table = NULL;
1152   
1153   /* Chi-square table initialization. */
1154   if (cmd.a_statistics[CRS_ST_CHISQ])
1155     {
1156       chisq = tab_create (6 + (nvar - 2),
1157                           (pe - pb) / n_cols * 3 / 2 * N_CHISQ + 10, 1);
1158       tab_headers (chisq, 1 + (nvar - 2), 0, 1, 0);
1159
1160       tab_title (chisq, 0, "Chi-square tests.");
1161       
1162       tab_offset (chisq, nvar - 2, 0);
1163       tab_text (chisq, 0, 0, TAB_LEFT | TAT_TITLE, _("Statistic"));
1164       tab_text (chisq, 1, 0, TAB_RIGHT | TAT_TITLE, _("Value"));
1165       tab_text (chisq, 2, 0, TAB_RIGHT | TAT_TITLE, _("df"));
1166       tab_text (chisq, 3, 0, TAB_RIGHT | TAT_TITLE,
1167                 _("Asymp. Sig. (2-sided)"));
1168       tab_text (chisq, 4, 0, TAB_RIGHT | TAT_TITLE,
1169                 _("Exact. Sig. (2-sided)"));
1170       tab_text (chisq, 5, 0, TAB_RIGHT | TAT_TITLE,
1171                 _("Exact. Sig. (1-sided)"));
1172       chisq_fisher = 0;
1173       tab_offset (chisq, 0, 1);
1174     }
1175   else
1176     chisq = NULL;
1177   
1178   /* Symmetric measures. */
1179   if (cmd.a_statistics[CRS_ST_PHI] || cmd.a_statistics[CRS_ST_CC]
1180       || cmd.a_statistics[CRS_ST_BTAU] || cmd.a_statistics[CRS_ST_CTAU]
1181       || cmd.a_statistics[CRS_ST_GAMMA] || cmd.a_statistics[CRS_ST_CORR]
1182       || cmd.a_statistics[CRS_ST_KAPPA])
1183     {
1184       sym = tab_create (6 + (nvar - 2), (pe - pb) / n_cols * 7 + 10, 1);
1185       tab_headers (sym, 2 + (nvar - 2), 0, 1, 0);
1186       tab_title (sym, 0, "Symmetric measures.");
1187
1188       tab_offset (sym, nvar - 2, 0);
1189       tab_text (sym, 0, 0, TAB_LEFT | TAT_TITLE, _("Category"));
1190       tab_text (sym, 1, 0, TAB_LEFT | TAT_TITLE, _("Statistic"));
1191       tab_text (sym, 2, 0, TAB_RIGHT | TAT_TITLE, _("Value"));
1192       tab_text (sym, 3, 0, TAB_RIGHT | TAT_TITLE, _("Asymp. Std. Error"));
1193       tab_text (sym, 4, 0, TAB_RIGHT | TAT_TITLE, _("Approx. T"));
1194       tab_text (sym, 5, 0, TAB_RIGHT | TAT_TITLE, _("Approx. Sig."));
1195       tab_offset (sym, 0, 1);
1196     }
1197   else
1198     sym = NULL;
1199
1200   /* Risk estimate. */
1201   if (cmd.a_statistics[CRS_ST_RISK])
1202     {
1203       risk = tab_create (4 + (nvar - 2), (pe - pb) / n_cols * 4 + 10, 1);
1204       tab_headers (risk, 1 + nvar - 2, 0, 2, 0);
1205       tab_title (risk, 0, "Risk estimate.");
1206
1207       tab_offset (risk, nvar - 2, 0);
1208       tab_joint_text (risk, 2, 0, 3, 0, TAB_CENTER | TAT_TITLE | TAT_PRINTF,
1209                       _(" 95%% Confidence Interval"));
1210       tab_text (risk, 0, 1, TAB_LEFT | TAT_TITLE, _("Statistic"));
1211       tab_text (risk, 1, 1, TAB_RIGHT | TAT_TITLE, _("Value"));
1212       tab_text (risk, 2, 1, TAB_RIGHT | TAT_TITLE, _("Lower"));
1213       tab_text (risk, 3, 1, TAB_RIGHT | TAT_TITLE, _("Upper"));
1214       tab_hline (risk, TAL_1, 2, 3, 1);
1215       tab_vline (risk, TAL_1, 2, 0, 1);
1216       tab_offset (risk, 0, 2);
1217     }
1218   else
1219     risk = NULL;
1220
1221   /* Directional measures. */
1222   if (cmd.a_statistics[CRS_ST_LAMBDA] || cmd.a_statistics[CRS_ST_UC]
1223       || cmd.a_statistics[CRS_ST_D] || cmd.a_statistics[CRS_ST_ETA])
1224     {
1225       direct = tab_create (7 + (nvar - 2), (pe - pb) / n_cols * 7 + 10, 1);
1226       tab_headers (direct, 3 + (nvar - 2), 0, 1, 0);
1227       tab_title (direct, 0, "Directional measures.");
1228
1229       tab_offset (direct, nvar - 2, 0);
1230       tab_text (direct, 0, 0, TAB_LEFT | TAT_TITLE, _("Category"));
1231       tab_text (direct, 1, 0, TAB_LEFT | TAT_TITLE, _("Statistic"));
1232       tab_text (direct, 2, 0, TAB_LEFT | TAT_TITLE, _("Type"));
1233       tab_text (direct, 3, 0, TAB_RIGHT | TAT_TITLE, _("Value"));
1234       tab_text (direct, 4, 0, TAB_RIGHT | TAT_TITLE, _("Asymp. Std. Error"));
1235       tab_text (direct, 5, 0, TAB_RIGHT | TAT_TITLE, _("Approx. T"));
1236       tab_text (direct, 6, 0, TAB_RIGHT | TAT_TITLE, _("Approx. Sig."));
1237       tab_offset (direct, 0, 1);
1238     }
1239   else
1240     direct = NULL;
1241
1242   for (;;)
1243     {
1244       /* Find pivot subtable if applicable. */
1245       te = find_pivot_extent (tb, &tc, 0);
1246       if (te == NULL)
1247         break;
1248
1249       /* Find all the row variable values. */
1250       enum_var_values (tb, te - tb, ROW_VAR, &rows, &n_rows);
1251
1252       /* Allocate memory space for the column and row totals. */
1253       if (n_rows > *maxrows)
1254         {
1255           *row_totp = xrealloc (*row_totp, sizeof **row_totp * n_rows);
1256           row_tot = *row_totp;
1257           *maxrows = n_rows;
1258         }
1259       if (n_cols > *maxcols)
1260         {
1261           *col_totp = xrealloc (*col_totp, sizeof **col_totp * n_cols);
1262           col_tot = *col_totp;
1263           *maxcols = n_cols;
1264         }
1265       
1266       /* Allocate table space for the matrix. */
1267       if (table && tab_row (table) + (n_rows + 1) * num_cells > tab_nr (table))
1268         tab_realloc (table, -1,
1269                      max (tab_nr (table) + (n_rows + 1) * num_cells,
1270                           tab_nr (table) * (pe - pb) / (te - tb)));
1271
1272       if (mode == GENERAL)
1273         {
1274           /* Allocate memory space for the matrix. */
1275           if (n_cols * n_rows > *maxcells)
1276             {
1277               *matp = xrealloc (*matp, sizeof **matp * n_cols * n_rows);
1278               *maxcells = n_cols * n_rows;
1279             }
1280           
1281           mat = *matp;
1282
1283           /* Build the matrix and calculate column totals. */
1284           {
1285             union value *cur_col = cols;
1286             union value *cur_row = rows;
1287             double *mp = mat;
1288             double *cp = col_tot;
1289             struct table_entry **p;
1290
1291             *cp = 0.;
1292             for (p = &tb[0]; p < te; p++)
1293               {
1294                 for (; memcmp (cur_col, &(*p)->values[COL_VAR], sizeof *cur_col);
1295                      cur_row = rows)
1296                   {
1297                     *++cp = 0.;
1298                     for (; cur_row < &rows[n_rows]; cur_row++)
1299                       {
1300                         *mp = 0.;
1301                         mp += n_cols;
1302                       }
1303                     cur_col++;
1304                     mp = &mat[cur_col - cols];
1305                   }
1306
1307                 for (; memcmp (cur_row, &(*p)->values[ROW_VAR], sizeof *cur_row);
1308                      cur_row++)
1309                   {
1310                     *mp = 0.;
1311                     mp += n_cols;
1312                   }
1313
1314                 *cp += *mp = (*p)->u.freq;
1315                 mp += n_cols;
1316                 cur_row++;
1317               }
1318
1319             /* Zero out the rest of the matrix. */
1320             for (; cur_row < &rows[n_rows]; cur_row++)
1321               {
1322                 *mp = 0.;
1323                 mp += n_cols;
1324               }
1325             cur_col++;
1326             if (cur_col < &cols[n_cols])
1327               {
1328                 const int rem_cols = n_cols - (cur_col - cols);
1329                 int c, r;
1330
1331                 for (c = 0; c < rem_cols; c++)
1332                   *++cp = 0.;
1333                 mp = &mat[cur_col - cols];
1334                 for (r = 0; r < n_rows; r++)
1335                   {
1336                     for (c = 0; c < rem_cols; c++)
1337                       *mp++ = 0.;
1338                     mp += n_cols - rem_cols;
1339                   }
1340               }
1341           }
1342         }
1343       else
1344         {
1345           int r, c;
1346           double *tp = col_tot;
1347           
1348           assert (mode == INTEGER);
1349           mat = (*tb)->u.data;
1350           ns_cols = n_cols;
1351
1352           /* Calculate column totals. */
1353           for (c = 0; c < n_cols; c++)
1354             {
1355               double cum = 0.;
1356               double *cp = &mat[c];
1357               
1358               for (r = 0; r < n_rows; r++)
1359                 cum += cp[r * n_cols];
1360               *tp++ = cum;
1361             }
1362         }
1363       
1364       {
1365         double *cp;
1366         
1367         for (ns_cols = 0, cp = col_tot; cp < &col_tot[n_cols]; cp++)
1368           ns_cols += *cp != 0.;
1369       }
1370
1371       /* Calculate row totals. */
1372       {
1373         double *mp = mat;
1374         double *rp = row_tot;
1375         int r, c;
1376                 
1377         for (ns_rows = 0, r = n_rows; r--; )
1378           {
1379             double cum = 0.;
1380             for (c = n_cols; c--; )
1381               cum += *mp++;
1382             *rp++ = cum;
1383             if (cum != 0.)
1384               ns_rows++;
1385           }
1386       }
1387
1388       /* Calculate grand total. */
1389       {
1390         double *tp;
1391         double cum = 0.;
1392         int n;
1393
1394         if (n_rows < n_cols)
1395           tp = row_tot, n = n_rows;
1396         else
1397           tp = col_tot, n = n_cols;
1398         while (n--)
1399           cum += *tp++;
1400         W = cum;
1401       }
1402       
1403 #if DEBUGGING
1404       /* Print the matrix. */
1405       {
1406         int i, r, c;
1407
1408         printf ("%s by %s for", x->v[0]->name, x->v[1]->name);
1409         for (i = 2; i < nvar; i++)
1410           printf (" %s=%g", x->v[i]->name, tb[0]->v[i].f);
1411         printf ("\n");
1412         printf ("     ");
1413         for (c = 0; c < n_cols; c++)
1414           printf ("%4g", cols[c].f);
1415         printf ("\n");
1416         for (r = 0; r < n_rows; r++)
1417           {
1418             printf ("%4g:", rows[r].f);
1419             for (c = 0; c < n_cols; c++)
1420               printf ("%4g", mat[c + r * n_cols]);
1421             printf ("%4g", row_tot[r]);
1422             printf ("\n");
1423           }
1424         printf ("     ");
1425         for (c = 0; c < n_cols; c++)
1426           printf ("%4g", col_tot[c]);
1427         printf ("%4g", W);
1428         printf ("\n\n");
1429       }
1430 #endif
1431
1432       /* Find the first variable that differs from the last subtable,
1433          then display the values of the dimensioning variables for
1434          each table that needs it. */
1435       {
1436         int first_difference = nvar - 1;
1437         
1438         if (tb != pb)
1439           for (; ; first_difference--)
1440             {
1441               assert (first_difference >= 2);
1442               if (memcmp (&cmp->values[first_difference],
1443                           &(*tb)->values[first_difference],
1444                           sizeof *cmp->values))
1445                 break;
1446             }
1447         cmp = *tb;
1448             
1449         if (table)
1450           display_dimensions (table, first_difference, *tb);
1451         if (chisq)
1452           display_dimensions (chisq, first_difference, *tb);
1453         if (sym)
1454           display_dimensions (sym, first_difference, *tb);
1455         if (risk)
1456           display_dimensions (risk, first_difference, *tb);
1457         if (direct)
1458           display_dimensions (direct, first_difference, *tb);
1459       }
1460
1461       if (table)
1462         display_crosstabulation ();
1463       if (cmd.miss == CRS_REPORT)
1464         delete_missing ();
1465       if (chisq)
1466         display_chisq ();
1467       if (sym)
1468         display_symmetric ();
1469       if (risk)
1470         display_risk ();
1471       if (direct)
1472         display_directional ();
1473                 
1474       tb = te;
1475       free (rows);
1476     }
1477
1478   submit (table);
1479   
1480   if (chisq)
1481     {
1482       if (!chisq_fisher)
1483         tab_resize (chisq, 4 + (nvar - 2), -1);
1484       submit (chisq);
1485     }
1486
1487   submit (sym);
1488   submit (risk);
1489   submit (direct);
1490
1491   free (cols);
1492 }
1493
1494 /* Delete missing rows and columns for statistical analysis when
1495    /MISSING=REPORT. */
1496 static void
1497 delete_missing (void)
1498 {
1499   {
1500     int r;
1501
1502     for (r = 0; r < n_rows; r++)
1503       if (is_num_user_missing (rows[r].f, x->vars[ROW_VAR]))
1504         {
1505           int c;
1506
1507           for (c = 0; c < n_cols; c++)
1508             mat[c + r * n_cols] = 0.;
1509           ns_rows--;
1510         }
1511   }
1512   
1513   {
1514     int c;
1515
1516     for (c = 0; c < n_cols; c++)
1517       if (is_num_user_missing (cols[c].f, x->vars[COL_VAR]))
1518         {
1519           int r;
1520
1521           for (r = 0; r < n_rows; r++)
1522             mat[c + r * n_cols] = 0.;
1523           ns_cols--;
1524         }
1525   }
1526 }
1527
1528 /* Prepare table T for submission, and submit it. */
1529 static void
1530 submit (struct tab_table *t)
1531 {
1532   int i;
1533   
1534   if (t == NULL)
1535     return;
1536   
1537   tab_resize (t, -1, 0);
1538   if (tab_nr (t) == tab_t (t))
1539     {
1540       tab_destroy (t);
1541       return;
1542     }
1543   tab_offset (t, 0, 0);
1544   if (t != table)
1545     for (i = 2; i < nvar; i++)
1546       tab_text (t, nvar - i - 1, 0, TAB_RIGHT | TAT_TITLE,
1547                 x->vars[i]->label ? x->vars[i]->label : x->vars[i]->name);
1548   tab_box (t, TAL_2, TAL_2, -1, -1, 0, 0, tab_nc (t) - 1, tab_nr (t) - 1);
1549   tab_box (t, -1, -1, -1, TAL_1, tab_l (t), tab_t (t) - 1, tab_nc (t) - 1,
1550            tab_nr (t) - 1);
1551   tab_box (t, -1, -1, -1, TAL_1 | TAL_SPACING, 0, tab_t (t), tab_l (t) - 1,
1552            tab_nr (t) - 1);
1553   tab_vline (t, TAL_2, tab_l (t), 0, tab_nr (t) - 1);
1554   tab_dim (t, crosstabs_dim);
1555   tab_submit (t);
1556 }
1557
1558 /* Sets the widths of all the columns and heights of all the rows in
1559    table T for driver D. */
1560 static void
1561 crosstabs_dim (struct tab_table *t, struct outp_driver *d)
1562 {
1563   int i;
1564   
1565   /* Width of a numerical column. */
1566   int c = outp_string_width (d, "0.000000");
1567   if (cmd.miss == CRS_REPORT)
1568     c += outp_string_width (d, "M");
1569
1570   /* Set width for header columns. */
1571   if (t->l != 0)
1572     {
1573       int w = (d->width - t->vr_tot - c * (t->nc - t->l)) / t->l;
1574       
1575       if (w < d->prop_em_width * 8)
1576         w = d->prop_em_width * 8;
1577
1578       if (w > d->prop_em_width * 15)
1579         w = d->prop_em_width * 15;
1580
1581       for (i = 0; i < t->l; i++)
1582         t->w[i] = w;
1583     }
1584
1585   for (i = t->l; i < t->nc; i++)
1586     t->w[i] = c;
1587
1588   for (i = 0; i < t->nr; i++)
1589     t->h[i] = tab_natural_height (t, d, i);
1590 }
1591
1592 static struct table_entry **find_pivot_extent_general (struct table_entry **tp,
1593                                                 int *cnt, int pivot);
1594 static struct table_entry **find_pivot_extent_integer (struct table_entry **tp,
1595                                                 int *cnt, int pivot);
1596
1597 /* Calls find_pivot_extent_general or find_pivot_extent_integer, as
1598    appropriate. */
1599 static struct table_entry **
1600 find_pivot_extent (struct table_entry **tp, int *cnt, int pivot)
1601 {
1602   return (mode == GENERAL
1603           ? find_pivot_extent_general (tp, cnt, pivot)
1604           : find_pivot_extent_integer (tp, cnt, pivot));
1605 }
1606
1607 /* Find the extent of a region in TP that contains one table.  If
1608    PIVOT != 0 that means a set of table entries with identical table
1609    number; otherwise they also have to have the same values for every
1610    dimension after the row and column dimensions.  The table that is
1611    searched starts at TP and has length CNT.  Returns the first entry
1612    after the last one in the table; sets *CNT to the number of
1613    remaining values.  If there are no entries in TP at all, returns
1614    NULL.  A yucky interface, admittedly, but it works. */
1615 static struct table_entry **
1616 find_pivot_extent_general (struct table_entry **tp, int *cnt, int pivot)
1617 {
1618   struct table_entry *fp = *tp;
1619   struct crosstab *x;
1620
1621   if (*cnt == 0)
1622     return NULL;
1623   x = xtab[(*tp)->table];
1624   for (;;)
1625     {
1626       tp++;
1627       if (--*cnt == 0)
1628         break;
1629       assert (*cnt > 0);
1630
1631       if ((*tp)->table != fp->table)
1632         break;
1633       if (pivot)
1634         continue;
1635
1636       if (memcmp (&(*tp)->values[2], &fp->values[2], sizeof (union value) * (x->nvar - 2)))
1637         break;
1638     }
1639
1640   return tp;
1641 }
1642
1643 /* Integer mode correspondent to find_pivot_extent_general().  This
1644    could be optimized somewhat, but I just don't give a crap about
1645    CROSSTABS performance in integer mode, which is just a
1646    CROSSTABS wart as far as I'm concerned.
1647
1648    That said, feel free to send optimization patches to me. */
1649 static struct table_entry **
1650 find_pivot_extent_integer (struct table_entry **tp, int *cnt, int pivot)
1651 {
1652   struct table_entry *fp = *tp;
1653   struct crosstab *x;
1654
1655   if (*cnt == 0)
1656     return NULL;
1657   x = xtab[(*tp)->table];
1658   for (;;)
1659     {
1660       tp++;
1661       if (--*cnt == 0)
1662         break;
1663       assert (*cnt > 0);
1664
1665       if ((*tp)->table != fp->table)
1666         break;
1667       if (pivot)
1668         continue;
1669       
1670       if (memcmp (&(*tp)->values[2], &fp->values[2],
1671                   sizeof (union value) * (x->nvar - 2)))
1672         break;
1673     }
1674
1675   return tp;
1676 }
1677
1678 /* Compares `union value's A_ and B_ and returns a strcmp()-like
1679    result.  WIDTH_ points to an int which is either 0 for a
1680    numeric value or a string width for a string value. */
1681 static int
1682 compare_value (const void *a_, const void *b_, void *width_)
1683 {
1684   const union value *a = a_;
1685   const union value *b = b_;
1686   const int *pwidth = width_;
1687   const int width = *pwidth;
1688
1689   if (width == 0)
1690     return (a->f < b->f) ? -1 : (a->f > b->f);
1691   else
1692     return strncmp (a->s, b->s, width);
1693 }
1694
1695 /* Given an array of ENTRY_CNT table_entry structures starting at
1696    ENTRIES, creates a sorted list of the values that the variable
1697    with index VAR_INDEX takes on.  The values are returned as a
1698    malloc()'darray stored in *VALUES, with the number of values
1699    stored in *VALUE_CNT.
1700    */
1701 static void 
1702 enum_var_values (struct table_entry **entries, int entry_cnt, int var_idx,
1703                  union value **values, int *value_cnt)
1704 {
1705   if (mode == GENERAL)
1706     {
1707       int width = xtab[(*entries)->table]->vars[var_idx]->width;
1708       int i;
1709
1710       *values = xmalloc (sizeof **values * entry_cnt);
1711       for (i = 0; i < entry_cnt; i++)
1712         (*values)[i] = entries[i]->values[var_idx];
1713       *value_cnt = sort_unique (*values, entry_cnt, sizeof **values,
1714                                 compare_value, &width);
1715     }
1716   else
1717     {
1718       struct crosstab_proc *crs
1719         = &xtab[(*entries)->table]->vars[var_idx]->p.crs;
1720       int i;
1721       
1722       assert (mode == INTEGER);
1723       *values = xmalloc (sizeof **values * crs->count);
1724       for (i = 0; i < crs->count; i++)
1725         (*values)[i].f = i + crs->min;
1726       *value_cnt = crs->count;
1727     }
1728 }
1729
1730 /* Sets cell (C,R) in TABLE, with options OPT, to have a value taken
1731    from V, displayed with print format spec from variable VAR.  When
1732    in REPORT missing-value mode, missing values have an M appended. */
1733 static void
1734 table_value_missing (struct tab_table *table, int c, int r, unsigned char opt,
1735                      const union value *v, const struct variable *var)
1736 {
1737   struct len_string s;
1738
1739   const char *label = val_labs_find (var->val_labs, *v);
1740   if (label) 
1741     {
1742       tab_text (table, c, r, TAB_LEFT, label);
1743       return;
1744     }
1745
1746   s.string = tab_alloc (table, var->print.w);
1747   format_short (s.string, &var->print, v);
1748   s.length = strlen (s.string);
1749   if (cmd.miss == CRS_REPORT && is_num_user_missing (v->f, var))
1750     s.string[s.length++] = 'M';
1751   while (s.length && *s.string == ' ')
1752     {
1753       s.length--;
1754       s.string++;
1755     }
1756   tab_raw (table, c, r, opt, &s);
1757 }
1758
1759 /* Draws a line across TABLE at the current row to indicate the most
1760    major dimension variable with index FIRST_DIFFERENCE out of NVAR
1761    that changed, and puts the values that changed into the table.  TB
1762    and X must be the corresponding table_entry and crosstab,
1763    respectively. */
1764 static void
1765 display_dimensions (struct tab_table *table, int first_difference, struct table_entry *tb)
1766 {
1767   tab_hline (table, TAL_1, nvar - first_difference - 1, tab_nc (table) - 1, 0);
1768
1769   for (; first_difference >= 2; first_difference--)
1770     table_value_missing (table, nvar - first_difference - 1, 0,
1771                          TAB_RIGHT, &tb->values[first_difference],
1772                          x->vars[first_difference]);
1773 }
1774
1775 /* Put value V into cell (C,R) of TABLE, suffixed with letter M. */
1776 static void
1777 float_M_suffix (struct tab_table *table, int c, int r, double v)
1778 {
1779   static const struct fmt_spec f = {FMT_F, 8, 0};
1780   struct len_string s;
1781
1782   s.length = 9;
1783   s.string = tab_alloc (table, 9);
1784   s.string[8] = 'M';
1785   format_short (s.string, &f, (union value *) &v);
1786   while (*s.string == ' ')
1787     {
1788       s.length--;
1789       s.string++;
1790     }
1791   tab_raw (table, c, r, TAB_RIGHT, &s);
1792 }
1793
1794 /* Displays the crosstabulation table. */
1795 static void
1796 display_crosstabulation (void)
1797 {
1798   {
1799     int r;
1800         
1801     for (r = 0; r < n_rows; r++)
1802       table_value_missing (table, nvar - 2, r * num_cells,
1803                            TAB_RIGHT, &rows[r], x->vars[ROW_VAR]);
1804   }
1805   tab_text (table, nvar - 2, n_rows * num_cells,
1806             TAB_LEFT, _("Total"));
1807       
1808   /* Put in the actual cells. */
1809   {
1810     double *mp = mat;
1811     int r, c, i;
1812
1813     tab_offset (table, nvar - 1, -1);
1814     for (r = 0; r < n_rows; r++)
1815       {
1816         if (num_cells > 1)
1817           tab_hline (table, TAL_1, -1, n_cols, 0);
1818         for (c = 0; c < n_cols; c++)
1819           {
1820             double expected_value;
1821
1822             if (expected)
1823               expected_value = row_tot[r] * col_tot[c] / W;
1824             for (i = 0; i < num_cells; i++)
1825               {
1826                 double v;
1827
1828                 switch (cells[i])
1829                   {
1830                   case CRS_CL_COUNT:
1831                     v = *mp;
1832                     break;
1833                   case CRS_CL_ROW:
1834                     v = *mp / row_tot[r] * 100.;
1835                     break;
1836                   case CRS_CL_COLUMN:
1837                     v = *mp / col_tot[c] * 100.;
1838                     break;
1839                   case CRS_CL_TOTAL:
1840                     v = *mp / W * 100.;
1841                     break;
1842                   case CRS_CL_EXPECTED:
1843                     v = expected_value;
1844                     break;
1845                   case CRS_CL_RESIDUAL:
1846                     v = *mp - expected_value;
1847                     break;
1848                   case CRS_CL_SRESIDUAL:
1849                     v = (*mp - expected_value) / sqrt (expected_value);
1850                     break;
1851                   case CRS_CL_ASRESIDUAL:
1852                     v = ((*mp - expected_value)
1853                          / sqrt (expected_value
1854                                  * (1. - row_tot[r] / W)
1855                                  * (1. - col_tot[c] / W)));
1856                     break;
1857                   default:
1858                     assert (0);
1859                   }
1860
1861                 if (cmd.miss == CRS_REPORT
1862                     && (is_num_user_missing (cols[c].f, x->vars[COL_VAR])
1863                         || is_num_user_missing (rows[r].f, x->vars[ROW_VAR])))
1864                   float_M_suffix (table, c, i, v);
1865                 else if (v != 0.)
1866                   tab_float (table, c, i, TAB_RIGHT, v, 8, 0);
1867               }
1868
1869             mp++;
1870           }
1871
1872         tab_offset (table, -1, tab_row (table) + num_cells);
1873       }
1874   }
1875
1876   /* Row totals. */
1877   {
1878     int r, i;
1879
1880     tab_offset (table, -1, tab_row (table) - num_cells * n_rows);
1881     for (r = 0; r < n_rows; r++)
1882       for (i = 0; i < num_cells; i++)
1883         {
1884           double v;
1885
1886           switch (cells[i])
1887             {
1888             case CRS_CL_COUNT:
1889               v = row_tot[r];
1890               break;
1891             case CRS_CL_ROW:
1892               v = 100.;
1893               break;
1894             case CRS_CL_COLUMN:
1895               v = row_tot[r] / W * 100.;
1896               break;
1897             case CRS_CL_TOTAL:
1898               v = row_tot[r] / W * 100.;
1899               break;
1900             case CRS_CL_EXPECTED:
1901             case CRS_CL_RESIDUAL:
1902             case CRS_CL_SRESIDUAL:
1903             case CRS_CL_ASRESIDUAL:
1904               v = 0.;
1905               break;
1906             default:
1907               assert (0);
1908             }
1909
1910           if (cmd.miss == CRS_REPORT
1911               && is_num_user_missing (rows[r].f, x->vars[ROW_VAR]))
1912             float_M_suffix (table, n_cols, 0, v);
1913           else if (v != 0.)
1914             tab_float (table, n_cols, 0, TAB_RIGHT, v, 8, 0);
1915
1916           tab_next_row (table);
1917         }
1918   }
1919
1920   /* Column totals, grand total. */
1921   {
1922     int c, j;
1923
1924     if (num_cells > 1)
1925       tab_hline (table, TAL_1, -1, n_cols, 0);
1926     for (c = 0; c <= n_cols; c++)
1927       {
1928         double ct = c < n_cols ? col_tot[c] : W;
1929         int i;
1930             
1931         for (i = j = 0; i < num_cells; i++)
1932           {
1933             double v;
1934
1935             switch (cells[i])
1936               {
1937               case CRS_CL_COUNT:
1938                 v = ct;
1939                 break;
1940               case CRS_CL_ROW:
1941                 v = ct / W * 100.;
1942                 break;
1943               case CRS_CL_COLUMN:
1944                 v = 100.;
1945                 break;
1946               case CRS_CL_TOTAL:
1947                 v = ct / W * 100.;
1948                 break;
1949               case CRS_CL_EXPECTED:
1950               case CRS_CL_RESIDUAL:
1951               case CRS_CL_SRESIDUAL:
1952               case CRS_CL_ASRESIDUAL:
1953                 continue;
1954               default:
1955                 assert (0);
1956               }
1957
1958             if (cmd.miss == CRS_REPORT && c < n_cols 
1959                 && is_num_user_missing (cols[c].f, x->vars[COL_VAR]))
1960               float_M_suffix (table, c, j, v);
1961             else if (v != 0.)
1962               tab_float (table, c, j, TAB_RIGHT, v, 8, 0);
1963
1964             j++;
1965           }
1966       }
1967
1968     tab_offset (table, -1, tab_row (table) + j);
1969   }
1970   
1971   tab_offset (table, 0, -1);
1972 }
1973
1974 static void calc_r (double *X, double *Y, double *, double *, double *);
1975 static void calc_chisq (double[N_CHISQ], int[N_CHISQ], double *, double *);
1976
1977 /* Display chi-square statistics. */
1978 static void
1979 display_chisq (void)
1980 {
1981   static const char *chisq_stats[N_CHISQ] = 
1982     {
1983       N_("Pearson Chi-Square"),
1984       N_("Likelihood Ratio"),
1985       N_("Fisher's Exact Test"),
1986       N_("Continuity Correction"),
1987       N_("Linear-by-Linear Association"),
1988     };
1989   double chisq_v[N_CHISQ];
1990   double fisher1, fisher2;
1991   int df[N_CHISQ];
1992   int s = 0;
1993
1994   int i;
1995               
1996   calc_chisq (chisq_v, df, &fisher1, &fisher2);
1997
1998   tab_offset (chisq, nvar - 2, -1);
1999   
2000   for (i = 0; i < N_CHISQ; i++)
2001     {
2002       if ((i != 2 && chisq_v[i] == SYSMIS)
2003           || (i == 2 && fisher1 == SYSMIS))
2004         continue;
2005       s = 1;
2006       
2007       tab_text (chisq, 0, 0, TAB_LEFT, gettext (chisq_stats[i]));
2008       if (i != 2)
2009         {
2010           tab_float (chisq, 1, 0, TAB_RIGHT, chisq_v[i], 8, 3);
2011           tab_float (chisq, 2, 0, TAB_RIGHT, df[i], 8, 0);
2012           tab_float (chisq, 3, 0, TAB_RIGHT,
2013                      chisq_sig (chisq_v[i], df[i]), 8, 3);
2014         }
2015       else
2016         {
2017           chisq_fisher = 1;
2018           tab_float (chisq, 4, 0, TAB_RIGHT, fisher2, 8, 3);
2019           tab_float (chisq, 5, 0, TAB_RIGHT, fisher1, 8, 3);
2020         }
2021       tab_next_row (chisq);
2022     }
2023
2024   tab_text (chisq, 0, 0, TAB_LEFT, _("N of Valid Cases"));
2025   tab_float (chisq, 1, 0, TAB_RIGHT, W, 8, 0);
2026   tab_next_row (chisq);
2027     
2028   tab_offset (chisq, 0, -1);
2029 }
2030
2031 static int calc_symmetric (double[N_SYMMETRIC], double[N_SYMMETRIC],
2032                            double[N_SYMMETRIC]);
2033
2034 /* Display symmetric measures. */
2035 static void
2036 display_symmetric (void)
2037 {
2038   static const char *categories[] = 
2039     {
2040       N_("Nominal by Nominal"),
2041       N_("Ordinal by Ordinal"),
2042       N_("Interval by Interval"),
2043       N_("Measure of Agreement"),
2044     };
2045
2046   static const char *stats[N_SYMMETRIC] =
2047     {
2048       N_("Phi"),
2049       N_("Cramer's V"),
2050       N_("Contingency Coefficient"),
2051       N_("Kendall's tau-b"),
2052       N_("Kendall's tau-c"),
2053       N_("Gamma"),
2054       N_("Spearman Correlation"),
2055       N_("Pearson's R"),
2056       N_("Kappa"),
2057     };
2058
2059   static const int stats_categories[N_SYMMETRIC] =
2060     {
2061       0, 0, 0, 1, 1, 1, 1, 2, 3,
2062     };
2063
2064   int last_cat = -1;
2065   double sym_v[N_SYMMETRIC], sym_ase[N_SYMMETRIC], sym_t[N_SYMMETRIC];
2066   int i;
2067
2068   if (!calc_symmetric (sym_v, sym_ase, sym_t))
2069     return;
2070
2071   tab_offset (sym, nvar - 2, -1);
2072   
2073   for (i = 0; i < N_SYMMETRIC; i++)
2074     {
2075       if (sym_v[i] == SYSMIS)
2076         continue;
2077
2078       if (stats_categories[i] != last_cat)
2079         {
2080           last_cat = stats_categories[i];
2081           tab_text (sym, 0, 0, TAB_LEFT, gettext (categories[last_cat]));
2082         }
2083       
2084       tab_text (sym, 1, 0, TAB_LEFT, gettext (stats[i]));
2085       tab_float (sym, 2, 0, TAB_RIGHT, sym_v[i], 8, 3);
2086       if (sym_ase[i] != SYSMIS)
2087         tab_float (sym, 3, 0, TAB_RIGHT, sym_ase[i], 8, 3);
2088       if (sym_t[i] != SYSMIS)
2089         tab_float (sym, 4, 0, TAB_RIGHT, sym_t[i], 8, 3);
2090       /*tab_float (sym, 5, 0, TAB_RIGHT, normal_sig (sym_v[i]), 8, 3);*/
2091       tab_next_row (sym);
2092     }
2093
2094   tab_text (sym, 0, 0, TAB_LEFT, _("N of Valid Cases"));
2095   tab_float (sym, 2, 0, TAB_RIGHT, W, 8, 0);
2096   tab_next_row (sym);
2097     
2098   tab_offset (sym, 0, -1);
2099 }
2100
2101 static int calc_risk (double[], double[], double[], union value *);
2102
2103 /* Display risk estimate. */
2104 static void
2105 display_risk (void)
2106 {
2107   char buf[256];
2108   double risk_v[3], lower[3], upper[3];
2109   union value c[2];
2110   int i;
2111   
2112   if (!calc_risk (risk_v, upper, lower, c))
2113     return;
2114   
2115   tab_offset (risk, nvar - 2, -1);
2116   
2117   for (i = 0; i < 3; i++)
2118     {
2119       if (risk_v[i] == SYSMIS)
2120         continue;
2121
2122       switch (i)
2123         {
2124         case 0:
2125           if (x->vars[COL_VAR]->type == NUMERIC)
2126             sprintf (buf, _("Odds Ratio for %s (%g / %g)"),
2127                      x->vars[COL_VAR]->name, c[0].f, c[1].f);
2128           else
2129             sprintf (buf, _("Odds Ratio for %s (%.*s / %.*s)"),
2130                      x->vars[COL_VAR]->name,
2131                      x->vars[COL_VAR]->width, c[0].s,
2132                      x->vars[COL_VAR]->width, c[1].s);
2133           break;
2134         case 1:
2135         case 2:
2136           if (x->vars[ROW_VAR]->type == NUMERIC)
2137             sprintf (buf, _("For cohort %s = %g"),
2138                      x->vars[ROW_VAR]->name, rows[i - 1].f);
2139           else
2140             sprintf (buf, _("For cohort %s = %.*s"),
2141                      x->vars[ROW_VAR]->name,
2142                      x->vars[ROW_VAR]->width, rows[i - 1].s);
2143           break;
2144         }
2145                    
2146       tab_text (risk, 0, 0, TAB_LEFT, buf);
2147       tab_float (risk, 1, 0, TAB_RIGHT, risk_v[i], 8, 3);
2148       tab_float (risk, 2, 0, TAB_RIGHT, lower[i], 8, 3);
2149       tab_float (risk, 3, 0, TAB_RIGHT, upper[i], 8, 3);
2150       tab_next_row (risk);
2151     }
2152
2153   tab_text (risk, 0, 0, TAB_LEFT, _("N of Valid Cases"));
2154   tab_float (risk, 1, 0, TAB_RIGHT, W, 8, 0);
2155   tab_next_row (risk);
2156     
2157   tab_offset (risk, 0, -1);
2158 }
2159
2160 static int calc_directional (double[N_DIRECTIONAL], double[N_DIRECTIONAL],
2161                              double[N_DIRECTIONAL]);
2162
2163 /* Display directional measures. */
2164 static void
2165 display_directional (void)
2166 {
2167   static const char *categories[] = 
2168     {
2169       N_("Nominal by Nominal"),
2170       N_("Ordinal by Ordinal"),
2171       N_("Nominal by Interval"),
2172     };
2173
2174   static const char *stats[] =
2175     {
2176       N_("Lambda"),
2177       N_("Goodman and Kruskal tau"),
2178       N_("Uncertainty Coefficient"),
2179       N_("Somers' d"),
2180       N_("Eta"),
2181     };
2182
2183   static const char *types[] = 
2184     {
2185       N_("Symmetric"),
2186       N_("%s Dependent"),
2187       N_("%s Dependent"),
2188     };
2189
2190   static const int stats_categories[N_DIRECTIONAL] =
2191     {
2192       0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2,
2193     };
2194   
2195   static const int stats_stats[N_DIRECTIONAL] = 
2196     {
2197       0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4,
2198     };
2199
2200   static const int stats_types[N_DIRECTIONAL] = 
2201     {
2202       0, 1, 2, 1, 2, 0, 1, 2, 0, 1, 2, 1, 2,
2203     };
2204
2205   static const int *stats_lookup[] = 
2206     {
2207       stats_categories,
2208       stats_stats,
2209       stats_types,
2210     };
2211
2212   static const char **stats_names[] =
2213     {
2214       categories,
2215       stats,
2216       types,
2217     };
2218
2219   int last[3] =
2220     {
2221       -1, -1, -1,
2222     };
2223     
2224   double direct_v[N_DIRECTIONAL];
2225   double direct_ase[N_DIRECTIONAL];
2226   double direct_t[N_DIRECTIONAL];
2227   
2228   int i;
2229
2230   if (!calc_directional (direct_v, direct_ase, direct_t))
2231     return;
2232
2233   tab_offset (direct, nvar - 2, -1);
2234   
2235   for (i = 0; i < N_DIRECTIONAL; i++)
2236     {
2237       if (direct_v[i] == SYSMIS)
2238         continue;
2239       
2240       {
2241         int j;
2242
2243         for (j = 0; j < 3; j++)
2244           if (last[j] != stats_lookup[j][i])
2245             {
2246               if (j < 2)
2247                 tab_hline (direct, TAL_1, j, 6, 0);
2248               
2249               for (; j < 3; j++)
2250                 {
2251                   char *string;
2252                   int k = last[j] = stats_lookup[j][i];
2253
2254                   if (k == 0)
2255                     string = NULL;
2256                   else if (k == 1)
2257                     string = x->vars[0]->name;
2258                   else
2259                     string = x->vars[1]->name;
2260                   
2261                   tab_text (direct, j, 0, TAB_LEFT | TAT_PRINTF,
2262                             gettext (stats_names[j][k]), string);
2263                 }
2264             }
2265       }
2266       
2267       tab_float (direct, 3, 0, TAB_RIGHT, direct_v[i], 8, 3);
2268       if (direct_ase[i] != SYSMIS)
2269         tab_float (direct, 4, 0, TAB_RIGHT, direct_ase[i], 8, 3);
2270       if (direct_t[i] != SYSMIS)
2271         tab_float (direct, 5, 0, TAB_RIGHT, direct_t[i], 8, 3);
2272       /*tab_float (direct, 6, 0, TAB_RIGHT, normal_sig (direct_v[i]), 8, 3);*/
2273       tab_next_row (direct);
2274     }
2275
2276   tab_offset (direct, 0, -1);
2277 }
2278 \f
2279 /* Statistical calculations. */
2280
2281 /* Returns the value of the gamma (factorial) function for an integer
2282    argument X. */
2283 static double
2284 gamma_int (double x)
2285 {
2286   double r = 1;
2287   int i;
2288   
2289   for (i = 2; i < x; i++)
2290     r *= i;
2291   return r;
2292 }
2293
2294 /* Calculate P_r as specified in _SPSS Statistical Algorithms_,
2295    Appendix 5. */
2296 static inline double
2297 Pr (int a, int b, int c, int d)
2298 {
2299   return (gamma_int (a + b + 1.) / gamma_int (a + 1.)
2300           * gamma_int (c + d + 1.) / gamma_int (b + 1.)
2301           * gamma_int (a + c + 1.) / gamma_int (c + 1.)
2302           * gamma_int (b + d + 1.) / gamma_int (d + 1.)
2303           / gamma_int (a + b + c + d + 1.));
2304 }
2305
2306 /* Swap the contents of A and B. */
2307 static inline void
2308 swap (int *a, int *b)
2309 {
2310   int t = *a;
2311   *a = *b;
2312   *b = t;
2313 }
2314
2315 /* Calculate significance for Fisher's exact test as specified in
2316    _SPSS Statistical Algorithms_, Appendix 5. */
2317 static void
2318 calc_fisher (int a, int b, int c, int d, double *fisher1, double *fisher2)
2319 {
2320   int x;
2321   
2322   if (min (c, d) < min (a, b))
2323     swap (&a, &c), swap (&b, &d);
2324   if (min (b, d) < min (a, c))
2325     swap (&a, &b), swap (&c, &d);
2326   if (b * c < a * d)
2327     {
2328       if (b < c)
2329         swap (&a, &b), swap (&c, &d);
2330       else
2331         swap (&a, &c), swap (&b, &d);
2332     }
2333
2334   *fisher1 = 0.;
2335   for (x = 0; x <= a; x++)
2336     *fisher1 += Pr (a - x, b + x, c + x, d - x);
2337
2338   *fisher2 = *fisher1;
2339   for (x = 1; x <= b; x++)
2340     *fisher2 += Pr (a + x, b - x, c - x, d + x);
2341 }
2342
2343 /* Calculates chi-squares into CHISQ.  MAT is a matrix with N_COLS
2344    columns with values COLS and N_ROWS rows with values ROWS.  Values
2345    in the matrix sum to W. */
2346 static void
2347 calc_chisq (double chisq[N_CHISQ], int df[N_CHISQ],
2348             double *fisher1, double *fisher2)
2349 {
2350   int r, c;
2351
2352   chisq[0] = chisq[1] = 0.;
2353   chisq[2] = chisq[3] = chisq[4] = SYSMIS;
2354   *fisher1 = *fisher2 = SYSMIS;
2355
2356   df[0] = df[1] = (ns_cols - 1) * (ns_rows - 1);
2357
2358   if (ns_rows <= 1 || ns_cols <= 1)
2359     {
2360       chisq[0] = chisq[1] = SYSMIS;
2361       return;
2362     }
2363
2364   for (r = 0; r < n_rows; r++)
2365     for (c = 0; c < n_cols; c++)
2366       {
2367         const double expected = row_tot[r] * col_tot[c] / W;
2368         const double freq = mat[n_cols * r + c];
2369         const double residual = freq - expected;
2370     
2371         if (expected)
2372           chisq[0] += residual * residual / expected;
2373         if (freq)
2374           chisq[1] += freq * log (expected / freq);
2375       }
2376
2377   if (chisq[0] == 0.)
2378     chisq[0] = SYSMIS;
2379
2380   if (chisq[1] != 0.)
2381     chisq[1] *= -2.;
2382   else
2383     chisq[1] = SYSMIS;
2384
2385   /* Calculate Yates and Fisher exact test. */
2386   if (ns_cols == 2 && ns_rows == 2)
2387     {
2388       double f11, f12, f21, f22;
2389       
2390       {
2391         int nz_cols[2];
2392         int i, j;
2393
2394         for (i = j = 0; i < n_cols; i++)
2395           if (col_tot[i] != 0.)
2396             {
2397               nz_cols[j++] = i;
2398               if (j == 2)
2399                 break;
2400             }
2401
2402         assert (j == 2);
2403
2404         f11 = mat[nz_cols[0]];
2405         f12 = mat[nz_cols[1]];
2406         f21 = mat[nz_cols[0] + n_cols];
2407         f22 = mat[nz_cols[1] + n_cols];
2408       }
2409
2410       /* Yates. */
2411       {
2412         const double x = fabs (f11 * f22 - f12 * f21) - 0.5 * W;
2413
2414         if (x > 0.)
2415           chisq[3] = (W * x * x
2416                       / (f11 + f12) / (f21 + f22)
2417                       / (f11 + f21) / (f12 + f22));
2418         else
2419           chisq[3] = 0.;
2420
2421         df[3] = 1.;
2422       }
2423
2424       /* Fisher. */
2425       if (f11 < 5. || f12 < 5. || f21 < 5. || f22 < 5.)
2426         calc_fisher (f11 + .5, f12 + .5, f21 + .5, f22 + .5, fisher1, fisher2);
2427     }
2428
2429   /* Calculate Mantel-Haenszel. */
2430   if (x->vars[ROW_VAR]->type == NUMERIC && x->vars[COL_VAR]->type == NUMERIC)
2431     {
2432       double r, ase_0, ase_1;
2433       calc_r ((double *) rows, (double *) cols, &r, &ase_0, &ase_1);
2434     
2435       chisq[4] = (W - 1.) * r * r;
2436       df[4] = 1;
2437     }
2438 }
2439
2440 /* Calculate the value of Pearson's r.  r is stored into R, ase_1 into
2441    ASE_1, and ase_0 into ASE_0.  The row and column values must be
2442    passed in X and Y. */
2443 static void
2444 calc_r (double *X, double *Y, double *r, double *ase_0, double *ase_1)
2445 {
2446   double SX, SY, S, T;
2447   double Xbar, Ybar;
2448   double sum_XYf, sum_X2Y2f;
2449   double sum_Xr, sum_X2r;
2450   double sum_Yc, sum_Y2c;
2451   int i, j;
2452
2453   for (sum_X2Y2f = sum_XYf = 0., i = 0; i < n_rows; i++)
2454     for (j = 0; j < n_cols; j++)
2455       {
2456         double fij = mat[j + i * n_cols];
2457         double product = X[i] * Y[j];
2458         double temp = fij * product;
2459         sum_XYf += temp;
2460         sum_X2Y2f += temp * product;
2461       }
2462
2463   for (sum_Xr = sum_X2r = 0., i = 0; i < n_rows; i++)
2464     {
2465       sum_Xr += X[i] * row_tot[i];
2466       sum_X2r += X[i] * X[i] * row_tot[i];
2467     }
2468   Xbar = sum_Xr / W;
2469
2470   for (sum_Yc = sum_Y2c = 0., i = 0; i < n_cols; i++)
2471     {
2472       sum_Yc += Y[i] * col_tot[i];
2473       sum_Y2c += Y[i] * Y[i] * col_tot[i];
2474     }
2475   Ybar = sum_Yc / W;
2476
2477   S = sum_XYf - sum_Xr * sum_Yc / W;
2478   SX = sum_X2r - sum_Xr * sum_Xr / W;
2479   SY = sum_Y2c - sum_Yc * sum_Yc / W;
2480   T = sqrt (SX * SY);
2481   *r = S / T;
2482   *ase_0 = sqrt ((sum_X2Y2f - (sum_XYf * sum_XYf) / W) / (sum_X2r * sum_Y2c));
2483   
2484   {
2485     double s, c, y, t;
2486     
2487     for (s = c = 0., i = 0; i < n_rows; i++)
2488       for (j = 0; j < n_cols; j++)
2489         {
2490           double Xresid, Yresid;
2491           double temp;
2492
2493           Xresid = X[i] - Xbar;
2494           Yresid = Y[j] - Ybar;
2495           temp = (T * Xresid * Yresid
2496                   - ((S / (2. * T))
2497                      * (Xresid * Xresid * SY + Yresid * Yresid * SX)));
2498           y = mat[j + i * n_cols] * temp * temp - c;
2499           t = s + y;
2500           c = (t - s) - y;
2501           s = t;
2502         }
2503     *ase_1 = sqrt (s) / (T * T);
2504   }
2505 }
2506
2507 static double somers_d_v[3];
2508 static double somers_d_ase[3];
2509 static double somers_d_t[3];
2510
2511 /* Calculate symmetric statistics and their asymptotic standard
2512    errors.  Returns 0 if none could be calculated. */
2513 static int
2514 calc_symmetric (double v[N_SYMMETRIC], double ase[N_SYMMETRIC],
2515                 double t[N_SYMMETRIC])
2516 {
2517   int q = min (ns_rows, ns_cols);
2518   
2519   if (q <= 1)
2520     return 0;
2521   
2522   {
2523     int i;
2524
2525     if (v) 
2526       for (i = 0; i < N_SYMMETRIC; i++)
2527         v[i] = ase[i] = t[i] = SYSMIS;
2528   }
2529
2530   /* Phi, Cramer's V, contingency coefficient. */
2531   if (cmd.a_statistics[CRS_ST_PHI] || cmd.a_statistics[CRS_ST_CC])
2532     {
2533       double Xp = 0.;   /* Pearson chi-square. */
2534
2535       {
2536         int r, c;
2537     
2538         for (r = 0; r < n_rows; r++)
2539           for (c = 0; c < n_cols; c++)
2540             {
2541               const double expected = row_tot[r] * col_tot[c] / W;
2542               const double freq = mat[n_cols * r + c];
2543               const double residual = freq - expected;
2544     
2545               if (expected)
2546                 Xp += residual * residual / expected;
2547             }
2548       }
2549
2550       if (cmd.a_statistics[CRS_ST_PHI])
2551         {
2552           v[0] = sqrt (Xp / W);
2553           v[1] = sqrt (Xp / (W * (q - 1)));
2554         }
2555       if (cmd.a_statistics[CRS_ST_CC])
2556         v[2] = sqrt (Xp / (Xp + W));
2557     }
2558   
2559   if (cmd.a_statistics[CRS_ST_BTAU] || cmd.a_statistics[CRS_ST_CTAU]
2560       || cmd.a_statistics[CRS_ST_GAMMA] || cmd.a_statistics[CRS_ST_D])
2561     {
2562       double *cum;
2563       double Dr, Dc;
2564       double P, Q;
2565       double btau_cum, ctau_cum, gamma_cum, d_yx_cum, d_xy_cum;
2566       double btau_var;
2567       
2568       {
2569         int r, c;
2570         
2571         Dr = Dc = W * W;
2572         for (r = 0; r < n_rows; r++)
2573           Dr -= row_tot[r] * row_tot[r];
2574         for (c = 0; c < n_cols; c++)
2575           Dc -= col_tot[c] * col_tot[c];
2576       }
2577       
2578       {
2579         int r, c;
2580
2581         cum = xmalloc (sizeof *cum * n_cols * n_rows);
2582         for (c = 0; c < n_cols; c++)
2583           {
2584             double ct = 0.;
2585             
2586             for (r = 0; r < n_rows; r++)
2587               cum[c + r * n_cols] = ct += mat[c + r * n_cols];
2588           }
2589       }
2590       
2591       /* P and Q. */
2592       {
2593         int i, j;
2594         double Cij, Dij;
2595
2596         P = Q = 0.;
2597         for (i = 0; i < n_rows; i++)
2598           {
2599             Cij = Dij = 0.;
2600
2601             for (j = 1; j < n_cols; j++)
2602               Cij += col_tot[j] - cum[j + i * n_cols];
2603
2604             if (i > 0)
2605               for (j = 1; j < n_cols; j++)
2606                 Dij += cum[j + (i - 1) * n_cols];
2607
2608             for (j = 0;;)
2609               {
2610                 double fij = mat[j + i * n_cols];
2611                 P += fij * Cij;
2612                 Q += fij * Dij;
2613                 
2614                 if (++j == n_cols)
2615                   break;
2616                 assert (j < n_cols);
2617
2618                 Cij -= col_tot[j] - cum[j + i * n_cols];
2619                 Dij += col_tot[j - 1] - cum[j - 1 + i * n_cols];
2620                 
2621                 if (i > 0)
2622                   {
2623                     Cij += cum[j - 1 + (i - 1) * n_cols];
2624                     Dij -= cum[j + (i - 1) * n_cols];
2625                   }
2626               }
2627           }
2628       }
2629
2630       if (cmd.a_statistics[CRS_ST_BTAU])
2631         v[3] = (P - Q) / sqrt (Dr * Dc);
2632       if (cmd.a_statistics[CRS_ST_CTAU])
2633         v[4] = (q * (P - Q)) / ((W * W) * (q - 1));
2634       if (cmd.a_statistics[CRS_ST_GAMMA])
2635         v[5] = (P - Q) / (P + Q);
2636
2637       /* ASE for tau-b, tau-c, gamma.  Calculations could be
2638          eliminated here, at expense of memory.  */
2639       {
2640         int i, j;
2641         double Cij, Dij;
2642
2643         btau_cum = ctau_cum = gamma_cum = d_yx_cum = d_xy_cum = 0.;
2644         for (i = 0; i < n_rows; i++)
2645           {
2646             Cij = Dij = 0.;
2647
2648             for (j = 1; j < n_cols; j++)
2649               Cij += col_tot[j] - cum[j + i * n_cols];
2650
2651             if (i > 0)
2652               for (j = 1; j < n_cols; j++)
2653                 Dij += cum[j + (i - 1) * n_cols];
2654
2655             for (j = 0;;)
2656               {
2657                 double fij = mat[j + i * n_cols];
2658
2659                 if (cmd.a_statistics[CRS_ST_BTAU])
2660                   {
2661                     const double temp = (2. * sqrt (Dr * Dc) * (Cij - Dij)
2662                                          + v[3] * (row_tot[i] * Dc
2663                                                    + col_tot[j] * Dr));
2664                     btau_cum += fij * temp * temp;
2665                   }
2666                 
2667                 {
2668                   const double temp = Cij - Dij;
2669                   ctau_cum += fij * temp * temp;
2670                 }
2671
2672                 if (cmd.a_statistics[CRS_ST_GAMMA])
2673                   {
2674                     const double temp = Q * Cij - P * Dij;
2675                     gamma_cum += fij * temp * temp;
2676                   }
2677
2678                 if (cmd.a_statistics[CRS_ST_D])
2679                   {
2680                     d_yx_cum += fij * sqr (Dr * (Cij - Dij)
2681                                            - (P - Q) * (W - row_tot[i]));
2682                     d_xy_cum += fij * sqr (Dc * (Dij - Cij)
2683                                            - (Q - P) * (W - col_tot[j]));
2684                   }
2685                 
2686                 if (++j == n_cols)
2687                   break;
2688                 assert (j < n_cols);
2689
2690                 Cij -= col_tot[j] - cum[j + i * n_cols];
2691                 Dij += col_tot[j - 1] - cum[j - 1 + i * n_cols];
2692                 
2693                 if (i > 0)
2694                   {
2695                     Cij += cum[j - 1 + (i - 1) * n_cols];
2696                     Dij -= cum[j + (i - 1) * n_cols];
2697                   }
2698               }
2699           }
2700       }
2701
2702       btau_var = ((btau_cum
2703                    - (W * sqr (W * (P - Q) / sqrt (Dr * Dc) * (Dr + Dc))))
2704                   / sqr (Dr * Dc));
2705       if (cmd.a_statistics[CRS_ST_BTAU])
2706         {
2707           ase[3] = sqrt (btau_var);
2708           t[3] = v[3] / (2 * sqrt ((ctau_cum - (P - Q) * (P - Q) / W)
2709                                    / (Dr * Dc)));
2710         }
2711       if (cmd.a_statistics[CRS_ST_CTAU])
2712         {
2713           ase[4] = ((2 * q / ((q - 1) * W * W))
2714                     * sqrt (ctau_cum - (P - Q) * (P - Q) / W));
2715           t[4] = v[4] / ase[4];
2716         }
2717       if (cmd.a_statistics[CRS_ST_GAMMA])
2718         {
2719           ase[5] = ((4. / ((P + Q) * (P + Q))) * sqrt (gamma_cum));
2720           t[5] = v[5] / (2. / (P + Q)
2721                          * sqrt (ctau_cum - (P - Q) * (P - Q) / W));
2722         }
2723       if (cmd.a_statistics[CRS_ST_D])
2724         {
2725           somers_d_v[0] = (P - Q) / (.5 * (Dc + Dr));
2726           somers_d_ase[0] = 2. * btau_var / (Dr + Dc) * sqrt (Dr * Dc);
2727           somers_d_t[0] = (somers_d_v[0]
2728                            / (4 / (Dc + Dr)
2729                               * sqrt (ctau_cum - sqr (P - Q) / W)));
2730           somers_d_v[1] = (P - Q) / Dc;
2731           somers_d_ase[1] = 2. / sqr (Dc) * sqrt (d_xy_cum);
2732           somers_d_t[1] = (somers_d_v[1]
2733                            / (2. / Dc
2734                               * sqrt (ctau_cum - sqr (P - Q) / W)));
2735           somers_d_v[2] = (P - Q) / Dr;
2736           somers_d_ase[2] = 2. / sqr (Dr) * sqrt (d_yx_cum);
2737           somers_d_t[2] = (somers_d_v[2]
2738                            / (2. / Dr
2739                               * sqrt (ctau_cum - sqr (P - Q) / W)));
2740         }
2741
2742       free (cum);
2743     }
2744
2745   /* Spearman correlation, Pearson's r. */
2746   if (cmd.a_statistics[CRS_ST_CORR])
2747     {
2748       double *R = local_alloc (sizeof *R * n_rows);
2749       double *C = local_alloc (sizeof *C * n_cols);
2750       
2751       {
2752         double y, t, c = 0., s = 0.;
2753         int i = 0;
2754         
2755         for (;;)
2756           {
2757             R[i] = s + (row_tot[i] + 1.) / 2.;
2758             y = row_tot[i] - c;
2759             t = s + y;
2760             c = (t - s) - y;
2761             s = t;
2762             if (++i == n_rows)
2763               break;
2764             assert (i < n_rows);
2765           }
2766       }
2767       
2768       {
2769         double y, t, c = 0., s = 0.;
2770         int j = 0;
2771         
2772         for (;;)
2773           {
2774             C[j] = s + (col_tot[j] + 1.) / 2;
2775             y = col_tot[j] - c;
2776             t = s + y;
2777             c = (t - s) - y;
2778             s = t;
2779             if (++j == n_cols)
2780               break;
2781             assert (j < n_cols);
2782           }
2783       }
2784       
2785       calc_r (R, C, &v[6], &t[6], &ase[6]);
2786       t[6] = v[6] / t[6];
2787
2788       local_free (R);
2789       local_free (C);
2790
2791       calc_r ((double *) rows, (double *) cols, &v[7], &t[7], &ase[7]);
2792       t[7] = v[7] / t[7];
2793     }
2794
2795   /* Cohen's kappa. */
2796   if (cmd.a_statistics[CRS_ST_KAPPA] && ns_rows == ns_cols)
2797     {
2798       double sum_fii, sum_rici, sum_fiiri_ci, sum_fijri_ci2, sum_riciri_ci;
2799       int i, j;
2800       
2801       for (sum_fii = sum_rici = sum_fiiri_ci = sum_riciri_ci = 0., i = j = 0;
2802            i < ns_rows; i++, j++)
2803         {
2804           double prod, sum;
2805           
2806           while (col_tot[j] == 0.)
2807             j++;
2808           
2809           prod = row_tot[i] * col_tot[j];
2810           sum = row_tot[i] + col_tot[j];
2811           
2812           sum_fii += mat[j + i * n_cols];
2813           sum_rici += prod;
2814           sum_fiiri_ci += mat[j + i * n_cols] * sum;
2815           sum_riciri_ci += prod * sum;
2816         }
2817       for (sum_fijri_ci2 = 0., i = 0; i < ns_rows; i++)
2818         for (j = 0; j < ns_cols; j++)
2819           {
2820             double sum = row_tot[i] + col_tot[j];
2821             sum_fijri_ci2 += mat[j + i * n_cols] * sum * sum;
2822           }
2823       
2824       v[8] = (W * sum_fii - sum_rici) / (W * W - sum_rici);
2825
2826       ase[8] = sqrt ((W * W * sum_rici
2827                       + sum_rici * sum_rici
2828                       - W * sum_riciri_ci)
2829                      / (W * (W * W - sum_rici) * (W * W - sum_rici)));
2830 #if 0
2831       t[8] = v[8] / sqrt (W * (((sum_fii * (W - sum_fii))
2832                                 / sqr (W * W - sum_rici))
2833                                + ((2. * (W - sum_fii)
2834                                    * (2. * sum_fii * sum_rici
2835                                       - W * sum_fiiri_ci))
2836                                   / cube (W * W - sum_rici))
2837                                + (sqr (W - sum_fii)
2838                                   * (W * sum_fijri_ci2 - 4.
2839                                      * sum_rici * sum_rici)
2840                                   / pow4 (W * W - sum_rici))));
2841 #else
2842       t[8] = v[8] / ase[8];
2843 #endif
2844     }
2845
2846   return 1;
2847 }
2848
2849 /* Calculate risk estimate. */
2850 static int
2851 calc_risk (double *value, double *upper, double *lower, union value *c)
2852 {
2853   double f11, f12, f21, f22;
2854   double v;
2855
2856   {
2857     int i;
2858       
2859     for (i = 0; i < 3; i++)
2860       value[i] = upper[i] = lower[i] = SYSMIS;
2861   }
2862     
2863   if (ns_rows != 2 || ns_cols != 2)
2864     return 0;
2865   
2866   {
2867     int nz_cols[2];
2868     int i, j;
2869
2870     for (i = j = 0; i < n_cols; i++)
2871       if (col_tot[i] != 0.)
2872         {
2873           nz_cols[j++] = i;
2874           if (j == 2)
2875             break;
2876         }
2877
2878     assert (j == 2);
2879
2880     f11 = mat[nz_cols[0]];
2881     f12 = mat[nz_cols[1]];
2882     f21 = mat[nz_cols[0] + n_cols];
2883     f22 = mat[nz_cols[1] + n_cols];
2884
2885     c[0] = cols[nz_cols[0]];
2886     c[1] = cols[nz_cols[1]];
2887   }
2888
2889   value[0] = (f11 * f22) / (f12 * f21);
2890   v = sqrt (1. / f11 + 1. / f12 + 1. / f21 + 1. / f22);
2891   lower[0] = value[0] * exp (-1.960 * v);
2892   upper[0] = value[0] * exp (1.960 * v);
2893
2894   value[1] = (f11 * (f21 + f22)) / (f21 * (f11 + f12));
2895   v = sqrt ((f12 / (f11 * (f11 + f12)))
2896             + (f22 / (f21 * (f21 + f22))));
2897   lower[1] = value[1] * exp (-1.960 * v);
2898   upper[1] = value[1] * exp (1.960 * v);
2899     
2900   value[2] = (f12 * (f21 + f22)) / (f22 * (f11 + f12));
2901   v = sqrt ((f11 / (f12 * (f11 + f12)))
2902             + (f21 / (f22 * (f21 + f22))));
2903   lower[2] = value[2] * exp (-1.960 * v);
2904   upper[2] = value[2] * exp (1.960 * v);
2905
2906   return 1;
2907 }
2908
2909 /* Calculate directional measures. */
2910 static int
2911 calc_directional (double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL],
2912                   double t[N_DIRECTIONAL])
2913 {
2914   {
2915     int i;
2916
2917     for (i = 0; i < N_DIRECTIONAL; i++)
2918       v[i] = ase[i] = t[i] = SYSMIS;
2919   }
2920
2921   /* Lambda. */
2922   if (cmd.a_statistics[CRS_ST_LAMBDA])
2923     {
2924       double *fim = xmalloc (sizeof *fim * n_rows);
2925       int *fim_index = xmalloc (sizeof *fim_index * n_rows);
2926       double *fmj = xmalloc (sizeof *fmj * n_cols);
2927       int *fmj_index = xmalloc (sizeof *fmj_index * n_cols);
2928       double sum_fim, sum_fmj;
2929       double rm, cm;
2930       int rm_index, cm_index;
2931       int i, j;
2932
2933       /* Find maximum for each row and their sum. */
2934       for (sum_fim = 0., i = 0; i < n_rows; i++)
2935         {
2936           double max = mat[i * n_cols];
2937           int index = 0;
2938
2939           for (j = 1; j < n_cols; j++)
2940             if (mat[j + i * n_cols] > max)
2941               {
2942                 max = mat[j + i * n_cols];
2943                 index = j;
2944               }
2945         
2946           sum_fim += fim[i] = max;
2947           fim_index[i] = index;
2948         }
2949
2950       /* Find maximum for each column. */
2951       for (sum_fmj = 0., j = 0; j < n_cols; j++)
2952         {
2953           double max = mat[j];
2954           int index = 0;
2955
2956           for (i = 1; i < n_rows; i++)
2957             if (mat[j + i * n_cols] > max)
2958               {
2959                 max = mat[j + i * n_cols];
2960                 index = i;
2961               }
2962         
2963           sum_fmj += fmj[j] = max;
2964           fmj_index[j] = index;
2965         }
2966
2967       /* Find maximum row total. */
2968       rm = row_tot[0];
2969       rm_index = 0;
2970       for (i = 1; i < n_rows; i++)
2971         if (row_tot[i] > rm)
2972           {
2973             rm = row_tot[i];
2974             rm_index = i;
2975           }
2976
2977       /* Find maximum column total. */
2978       cm = col_tot[0];
2979       cm_index = 0;
2980       for (j = 1; j < n_cols; j++)
2981         if (col_tot[j] > cm)
2982           {
2983             cm = col_tot[j];
2984             cm_index = j;
2985           }
2986
2987       v[0] = (sum_fim + sum_fmj - cm - rm) / (2. * W - rm - cm);
2988       v[1] = (sum_fmj - rm) / (W - rm);
2989       v[2] = (sum_fim - cm) / (W - cm);
2990
2991       /* ASE1 for Y given X. */
2992       {
2993         double accum;
2994
2995         for (accum = 0., i = 0; i < n_rows; i++)
2996           for (j = 0; j < n_cols; j++)
2997             {
2998               const int deltaj = j == cm_index;
2999               accum += (mat[j + i * n_cols]
3000                         * sqr ((j == fim_index[i])
3001                                - deltaj
3002                                + v[0] * deltaj));
3003             }
3004       
3005         ase[2] = sqrt (accum - W * v[0]) / (W - cm);
3006       }
3007
3008       /* ASE0 for Y given X. */
3009       {
3010         double accum;
3011       
3012         for (accum = 0., i = 0; i < n_rows; i++)
3013           if (cm_index != fim_index[i])
3014             accum += (mat[i * n_cols + fim_index[i]]
3015                       + mat[i * n_cols + cm_index]);
3016         t[2] = v[2] / (sqrt (accum - sqr (sum_fim - cm) / W) / (W - cm));
3017       }
3018
3019       /* ASE1 for X given Y. */
3020       {
3021         double accum;
3022
3023         for (accum = 0., i = 0; i < n_rows; i++)
3024           for (j = 0; j < n_cols; j++)
3025             {
3026               const int deltaj = i == rm_index;
3027               accum += (mat[j + i * n_cols]
3028                         * sqr ((i == fmj_index[j])
3029                                - deltaj
3030                                + v[0] * deltaj));
3031             }
3032       
3033         ase[1] = sqrt (accum - W * v[0]) / (W - rm);
3034       }
3035
3036       /* ASE0 for X given Y. */
3037       {
3038         double accum;
3039       
3040         for (accum = 0., j = 0; j < n_cols; j++)
3041           if (rm_index != fmj_index[j])
3042             accum += (mat[j + n_cols * fmj_index[j]]
3043                       + mat[j + n_cols * rm_index]);
3044         t[1] = v[1] / (sqrt (accum - sqr (sum_fmj - rm) / W) / (W - rm));
3045       }
3046
3047       /* Symmetric ASE0 and ASE1. */
3048       {
3049         double accum0;
3050         double accum1;
3051
3052         for (accum0 = accum1 = 0., i = 0; i < n_rows; i++)
3053           for (j = 0; j < n_cols; j++)
3054             {
3055               int temp0 = (fmj_index[j] == i) + (fim_index[i] == j);
3056               int temp1 = (i == rm_index) + (j == cm_index);
3057               accum0 += mat[j + i * n_cols] * sqr (temp0 - temp1);
3058               accum1 += (mat[j + i * n_cols]
3059                          * sqr (temp0 + (v[0] - 1.) * temp1));
3060             }
3061         ase[0] = sqrt (accum1 - 4. * W * v[0] * v[0]) / (2. * W - rm - cm);
3062         t[0] = v[0] / (sqrt (accum0 - sqr ((sum_fim + sum_fmj - cm - rm) / W))
3063                        / (2. * W - rm - cm));
3064       }
3065
3066       free (fim);
3067       free (fim_index);
3068       free (fmj);
3069       free (fmj_index);
3070       
3071       {
3072         double sum_fij2_ri, sum_fij2_ci;
3073         double sum_ri2, sum_cj2;
3074
3075         for (sum_fij2_ri = sum_fij2_ci = 0., i = 0; i < n_rows; i++)
3076           for (j = 0; j < n_cols; j++)
3077             {
3078               double temp = sqr (mat[j + i * n_cols]);
3079               sum_fij2_ri += temp / row_tot[i];
3080               sum_fij2_ci += temp / col_tot[j];
3081             }
3082
3083         for (sum_ri2 = 0., i = 0; i < n_rows; i++)
3084           sum_ri2 += row_tot[i] * row_tot[i];
3085
3086         for (sum_cj2 = 0., j = 0; j < n_cols; j++)
3087           sum_cj2 += col_tot[j] * col_tot[j];
3088
3089         v[3] = (W * sum_fij2_ci - sum_ri2) / (W * W - sum_ri2);
3090         v[4] = (W * sum_fij2_ri - sum_cj2) / (W * W - sum_cj2);
3091       }
3092     }
3093
3094   if (cmd.a_statistics[CRS_ST_UC])
3095     {
3096       double UX, UY, UXY, P;
3097       double ase1_yx, ase1_xy, ase1_sym;
3098       int i, j;
3099
3100       for (UX = 0., i = 0; i < n_rows; i++)
3101         if (row_tot[i] > 0.)
3102           UX -= row_tot[i] / W * log (row_tot[i] / W);
3103       
3104       for (UY = 0., j = 0; j < n_cols; j++)
3105         if (col_tot[j] > 0.)
3106           UY -= col_tot[j] / W * log (col_tot[j] / W);
3107
3108       for (UXY = P = 0., i = 0; i < n_rows; i++)
3109         for (j = 0; j < n_cols; j++)
3110           {
3111             double entry = mat[j + i * n_cols];
3112
3113             if (entry <= 0.)
3114               continue;
3115             
3116             P += entry * sqr (log (col_tot[j] * row_tot[i] / (W * entry)));
3117             UXY -= entry / W * log (entry / W);
3118           }
3119
3120       for (ase1_yx = ase1_xy = ase1_sym = 0., i = 0; i < n_rows; i++)
3121         for (j = 0; j < n_cols; j++)
3122           {
3123             double entry = mat[j + i * n_cols];
3124
3125             if (entry <= 0.)
3126               continue;
3127             
3128             ase1_yx += entry * sqr (UY * log (entry / row_tot[i])
3129                                     + (UX - UXY) * log (col_tot[j] / W));
3130             ase1_xy += entry * sqr (UX * log (entry / col_tot[j])
3131                                     + (UY - UXY) * log (row_tot[i] / W));
3132             ase1_sym += entry * sqr ((UXY
3133                                       * log (row_tot[i] * col_tot[j] / (W * W)))
3134                                      - (UX + UY) * log (entry / W));
3135           }
3136       
3137       v[5] = 2. * ((UX + UY - UXY) / (UX + UY));
3138       ase[5] = (2. / (W * sqr (UX + UY))) * sqrt (ase1_sym);
3139       t[5] = v[5] / ((2. / (W * (UX + UY)))
3140                      * sqrt (P - sqr (UX + UY - UXY) / W));
3141                     
3142       v[6] = (UX + UY - UXY) / UX;
3143       ase[6] = sqrt (ase1_xy) / (W * UX * UX);
3144       t[6] = v[6] / (sqrt (P - W * sqr (UX + UY - UXY)) / (W * UX));
3145       
3146       v[7] = (UX + UY - UXY) / UY;
3147       ase[7] = sqrt (ase1_yx) / (W * UY * UY);
3148       t[7] = v[7] / (sqrt (P - W * sqr (UX + UY - UXY)) / (W * UY));
3149     }
3150
3151   /* Somers' D. */
3152   if (cmd.a_statistics[CRS_ST_D])
3153     {
3154       int i;
3155       
3156       if (!sym)
3157         calc_symmetric (NULL, NULL, NULL);
3158       for (i = 0; i < 3; i++)
3159         {
3160           v[8 + i] = somers_d_v[i];
3161           ase[8 + i] = somers_d_ase[i];
3162           t[8 + i] = somers_d_t[i];
3163         }
3164     }
3165
3166   /* Eta. */
3167   if (cmd.a_statistics[CRS_ST_ETA])
3168     {
3169       {
3170         double sum_Xr, sum_X2r;
3171         double SX, SXW;
3172         int i, j;
3173       
3174         for (sum_Xr = sum_X2r = 0., i = 0; i < n_rows; i++)
3175           {
3176             sum_Xr += rows[i].f * row_tot[i];
3177             sum_X2r += rows[i].f * rows[i].f * row_tot[i];
3178           }
3179         SX = sum_X2r - sum_Xr * sum_Xr / W;
3180       
3181         for (SXW = 0., j = 0; j < n_cols; j++)
3182           {
3183             double cum;
3184
3185             for (cum = 0., i = 0; i < n_rows; i++)
3186               {
3187                 SXW += rows[i].f * rows[i].f * mat[j + i * n_cols];
3188                 cum += rows[i].f * mat[j + i * n_cols];
3189               }
3190
3191             SXW -= cum * cum / col_tot[j];
3192           }
3193         v[11] = sqrt (1. - SXW / SX);
3194       }
3195
3196       {
3197         double sum_Yc, sum_Y2c;
3198         double SY, SYW;
3199         int i, j;
3200
3201         for (sum_Yc = sum_Y2c = 0., i = 0; i < n_cols; i++)
3202           {
3203             sum_Yc += cols[i].f * col_tot[i];
3204             sum_Y2c += cols[i].f * cols[i].f * col_tot[i];
3205           }
3206         SY = sum_Y2c - sum_Yc * sum_Yc / W;
3207
3208         for (SYW = 0., i = 0; i < n_rows; i++)
3209           {
3210             double cum;
3211
3212             for (cum = 0., j = 0; j < n_cols; j++)
3213               {
3214                 SYW += cols[j].f * cols[j].f * mat[j + i * n_cols];
3215                 cum += cols[j].f * mat[j + i * n_cols];
3216               }
3217           
3218             SYW -= cum * cum / row_tot[i];
3219           }
3220         v[12] = sqrt (1. - SYW / SY);
3221       }
3222     }
3223
3224   return 1;
3225 }
3226
3227 /* A wrapper around data_out() that limits string output to short
3228    string width and null terminates the result. */
3229 static void
3230 format_short (char *s, const struct fmt_spec *fp, const union value *v)
3231 {
3232   struct fmt_spec fmt_subst;
3233
3234   /* Limit to short string width. */
3235   if (formats[fp->type].cat & FCAT_STRING) 
3236     {
3237       fmt_subst = *fp;
3238
3239       assert (fmt_subst.type == FMT_A || fmt_subst.type == FMT_AHEX);
3240       if (fmt_subst.type == FMT_A)
3241         fmt_subst.w = min (8, fmt_subst.w);
3242       else
3243         fmt_subst.w = min (16, fmt_subst.w);
3244
3245       fp = &fmt_subst;
3246     }
3247
3248   /* Format. */
3249   data_out (s, fp, v);
3250   
3251   /* Null terminate. */
3252   s[fp->w] = '\0';
3253 }
3254
3255 /* 
3256    Local Variables:
3257    mode: c
3258    End:
3259 */