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