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