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