0b9d1519517b100f6e0376110ab3a91813a44a9d
[pspp] / src / language / stats / crosstabs.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014, 2016 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 /* FIXME:
18
19    - How to calculate significance of some symmetric and directional measures?
20    - How to calculate ASE for symmetric Somers ' d?
21    - How to calculate ASE for Goodman and Kruskal's tau?
22    - How to calculate approx. T of symmetric uncertainty coefficient?
23
24 */
25
26 #include <config.h>
27
28 #include <ctype.h>
29 #include <float.h>
30 #include <gsl/gsl_cdf.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33
34 #include "data/case.h"
35 #include "data/casegrouper.h"
36 #include "data/casereader.h"
37 #include "data/data-out.h"
38 #include "data/dataset.h"
39 #include "data/dictionary.h"
40 #include "data/format.h"
41 #include "data/value-labels.h"
42 #include "data/variable.h"
43 #include "language/command.h"
44 #include "language/stats/freq.h"
45 #include "language/dictionary/split-file.h"
46 #include "language/lexer/lexer.h"
47 #include "language/lexer/variable-parser.h"
48 #include "libpspp/array.h"
49 #include "libpspp/assertion.h"
50 #include "libpspp/compiler.h"
51 #include "libpspp/hash-functions.h"
52 #include "libpspp/hmap.h"
53 #include "libpspp/hmapx.h"
54 #include "libpspp/message.h"
55 #include "libpspp/misc.h"
56 #include "libpspp/pool.h"
57 #include "libpspp/str.h"
58 #include "output/pivot-table.h"
59 #include "output/charts/barchart.h"
60
61 #include "gl/minmax.h"
62 #include "gl/xalloc.h"
63 #include "gl/xsize.h"
64
65 #include "gettext.h"
66 #define _(msgid) gettext (msgid)
67 #define N_(msgid) msgid
68
69 /* Kinds of cells in the crosstabulation. */
70 #define CRS_CELLS                                               \
71     C(COUNT, N_("Count"), PIVOT_RC_COUNT)                       \
72     C(EXPECTED, N_("Expected"), PIVOT_RC_OTHER)                 \
73     C(ROW, N_("Row %"), PIVOT_RC_PERCENT)                       \
74     C(COLUMN, N_("Column %"), PIVOT_RC_PERCENT)                 \
75     C(TOTAL, N_("Total %"), PIVOT_RC_PERCENT)                   \
76     C(RESIDUAL, N_("Residual"), PIVOT_RC_RESIDUAL)              \
77     C(SRESIDUAL, N_("Std. Residual"), PIVOT_RC_RESIDUAL)        \
78     C(ASRESIDUAL, N_("Adjusted Residual"), PIVOT_RC_RESIDUAL)
79 enum crs_cell
80   {
81 #define C(KEYWORD, STRING, RC) CRS_CL_##KEYWORD,
82     CRS_CELLS
83 #undef C
84   };
85 enum {
86 #define C(KEYWORD, STRING, RC) + 1
87   CRS_N_CELLS = CRS_CELLS
88 #undef C
89 };
90 #define CRS_ALL_CELLS ((1u << CRS_N_CELLS) - 1)
91
92 /* Kinds of statistics. */
93 #define CRS_STATISTICS                          \
94     S(CHISQ)                                    \
95     S(PHI)                                      \
96     S(CC)                                       \
97     S(LAMBDA)                                   \
98     S(UC)                                       \
99     S(BTAU)                                     \
100     S(CTAU)                                     \
101     S(RISK)                                     \
102     S(GAMMA)                                    \
103     S(D)                                        \
104     S(KAPPA)                                    \
105     S(ETA)                                      \
106     S(CORR)
107 enum crs_statistic_index {
108 #define S(KEYWORD) CRS_ST_##KEYWORD##_INDEX,
109   CRS_STATISTICS
110 #undef S
111 };
112 enum crs_statistic_bit {
113 #define S(KEYWORD) CRS_ST_##KEYWORD = 1u << CRS_ST_##KEYWORD##_INDEX,
114   CRS_STATISTICS
115 #undef S
116 };
117 enum {
118 #define S(KEYWORD) + 1
119   CRS_N_STATISTICS = CRS_STATISTICS
120 #undef S
121 };
122 #define CRS_ALL_STATISTICS ((1u << CRS_N_STATISTICS) - 1)
123
124 /* Number of chi-square statistics. */
125 #define N_CHISQ 5
126
127 /* Number of symmetric statistics. */
128 #define N_SYMMETRIC 9
129
130 /* Number of directional statistics. */
131 #define N_DIRECTIONAL 13
132
133 /* Indexes into the 'vars' member of struct crosstabulation and
134    struct crosstab member. */
135 enum
136   {
137     ROW_VAR = 0,                /* Row variable. */
138     COL_VAR = 1                 /* Column variable. */
139     /* Higher indexes cause multiple tables to be output. */
140   };
141
142 struct xtab_var
143   {
144     const struct variable *var;
145     union value *values;
146     size_t n_values;
147   };
148
149 /* A crosstabulation of 2 or more variables. */
150 struct crosstabulation
151   {
152     struct crosstabs_proc *proc;
153     struct fmt_spec weight_format; /* Format for weight variable. */
154     double missing;             /* Weight of missing cases. */
155
156     /* Variables (2 or more). */
157     int n_vars;
158     struct xtab_var *vars;
159
160     /* Constants (0 or more). */
161     int n_consts;
162     struct xtab_var *const_vars;
163     size_t *const_indexes;
164
165     /* Data. */
166     struct hmap data;
167     struct freq **entries;
168     size_t n_entries;
169
170     /* Number of statistically interesting columns/rows
171        (columns/rows with data in them). */
172     int ns_cols, ns_rows;
173
174     /* Matrix contents. */
175     double *mat;                /* Matrix proper. */
176     double *row_tot;            /* Row totals. */
177     double *col_tot;            /* Column totals. */
178     double total;               /* Grand total. */
179   };
180
181 /* Integer mode variable info. */
182 struct var_range
183   {
184     struct hmap_node hmap_node; /* In struct crosstabs_proc var_ranges map. */
185     const struct variable *var; /* The variable. */
186     int min;                    /* Minimum value. */
187     int max;                    /* Maximum value + 1. */
188     int count;                  /* max - min. */
189   };
190
191 struct crosstabs_proc
192   {
193     const struct dictionary *dict;
194     enum { INTEGER, GENERAL } mode;
195     enum mv_class exclude;
196     bool barchart;
197     bool bad_warn;
198     struct fmt_spec weight_format;
199
200     /* Variables specifies on VARIABLES. */
201     const struct variable **variables;
202     size_t n_variables;
203     struct hmap var_ranges;
204
205     /* TABLES. */
206     struct crosstabulation *pivots;
207     int n_pivots;
208
209     /* CELLS. */
210     int n_cells;                /* Number of cells requested. */
211     unsigned int cells;         /* Bit k is 1 if cell k is requested. */
212     int a_cells[CRS_N_CELLS];   /* 0...n_cells-1 are the requested cells. */
213
214     /* Rounding of cells. */
215     bool round_case_weights;    /* Round case weights? */
216     bool round_cells;           /* If !round_case_weights, round cells? */
217     bool round_down;            /* Round down? (otherwise to nearest) */
218
219     /* STATISTICS. */
220     unsigned int statistics;    /* Bit k is 1 if statistic k is requested. */
221
222     bool descending;            /* True if descending sort order is requested. */
223   };
224
225 static bool parse_crosstabs_tables (struct lexer *, struct dataset *,
226                                     struct crosstabs_proc *);
227 static bool parse_crosstabs_variables (struct lexer *, struct dataset *,
228                                        struct crosstabs_proc *);
229
230 static const struct var_range *get_var_range (const struct crosstabs_proc *,
231                                               const struct variable *);
232
233 static bool should_tabulate_case (const struct crosstabulation *,
234                                   const struct ccase *, enum mv_class exclude);
235 static void tabulate_general_case (struct crosstabulation *, const struct ccase *,
236                                    double weight);
237 static void tabulate_integer_case (struct crosstabulation *, const struct ccase *,
238                                    double weight);
239 static void postcalc (struct crosstabs_proc *);
240
241 static double
242 round_weight (const struct crosstabs_proc *proc, double weight)
243 {
244   return proc->round_down ? floor (weight) : floor (weight + 0.5);
245 }
246
247 #define FOR_EACH_POPULATED_COLUMN(C, XT) \
248   for (int C = next_populated_column (0, XT); \
249        C < (XT)->vars[COL_VAR].n_values;      \
250        C = next_populated_column (C + 1, XT))
251 static int
252 next_populated_column (int c, const struct crosstabulation *xt)
253 {
254   int n_columns = xt->vars[COL_VAR].n_values;
255   for (; c < n_columns; c++)
256     if (xt->col_tot[c])
257       break;
258   return c;
259 }
260
261 #define FOR_EACH_POPULATED_ROW(R, XT) \
262   for (int R = next_populated_row (0, XT); R < (XT)->vars[ROW_VAR].n_values; \
263        R = next_populated_row (R + 1, XT))
264 static int
265 next_populated_row (int r, const struct crosstabulation *xt)
266 {
267   int n_rows = xt->vars[ROW_VAR].n_values;
268   for (; r < n_rows; r++)
269     if (xt->row_tot[r])
270       break;
271   return r;
272 }
273
274 /* Parses and executes the CROSSTABS procedure. */
275 int
276 cmd_crosstabs (struct lexer *lexer, struct dataset *ds)
277 {
278   int result = CMD_FAILURE;
279
280   struct crosstabs_proc proc = {
281     .dict = dataset_dict (ds),
282     .mode = GENERAL,
283     .exclude = MV_ANY,
284     .barchart = false,
285     .bad_warn = true,
286     .weight_format = *dict_get_weight_format (dataset_dict (ds)),
287
288     .variables = NULL,
289     .n_variables = 0,
290     .var_ranges = HMAP_INITIALIZER (proc.var_ranges),
291
292     .pivots = NULL,
293     .n_pivots = 0,
294
295     .cells = 1u << CRS_CL_COUNT,
296     /* n_cells and a_cells will be filled in later. */
297
298     .round_case_weights = false,
299     .round_cells = false,
300     .round_down = false,
301
302     .statistics = 0,
303
304     .descending = false,
305   };
306   bool show_tables = true;
307   lex_match (lexer, T_SLASH);
308   for (;;)
309     {
310       if (lex_match_id (lexer, "VARIABLES"))
311         {
312           if (!parse_crosstabs_variables (lexer, ds, &proc))
313             goto exit;
314         }
315       else if (lex_match_id (lexer, "MISSING"))
316         {
317           lex_match (lexer, T_EQUALS);
318           if (lex_match_id (lexer, "TABLE"))
319             proc.exclude = MV_ANY;
320           else if (lex_match_id (lexer, "INCLUDE"))
321             proc.exclude = MV_SYSTEM;
322           else if (lex_match_id (lexer, "REPORT"))
323             proc.exclude = MV_NEVER;
324           else
325             {
326               lex_error (lexer, NULL);
327               goto exit;
328             }
329         }
330       else if (lex_match_id (lexer, "COUNT"))
331         {
332           lex_match (lexer, T_EQUALS);
333
334           /* Default is CELL. */
335           proc.round_case_weights = false;
336           proc.round_cells = true;
337
338           while (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)
339             {
340               if (lex_match_id (lexer, "ASIS"))
341                 {
342                   proc.round_case_weights = false;
343                   proc.round_cells = false;
344                 }
345               else if (lex_match_id (lexer, "CASE"))
346                 {
347                   proc.round_case_weights = true;
348                   proc.round_cells = false;
349                 }
350               else if (lex_match_id (lexer, "CELL"))
351                 {
352                   proc.round_case_weights = false;
353                   proc.round_cells = true;
354                 }
355               else if (lex_match_id (lexer, "ROUND"))
356                 proc.round_down = false;
357               else if (lex_match_id (lexer, "TRUNCATE"))
358                 proc.round_down = true;
359               else
360                 {
361                   lex_error (lexer, NULL);
362                   goto exit;
363                 }
364               lex_match (lexer, T_COMMA);
365             }
366         }
367       else if (lex_match_id (lexer, "FORMAT"))
368         {
369           lex_match (lexer, T_EQUALS);
370           while (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)
371             {
372               if (lex_match_id (lexer, "AVALUE"))
373                 proc.descending = false;
374               else if (lex_match_id (lexer, "DVALUE"))
375                 proc.descending = true;
376               else if (lex_match_id (lexer, "TABLES"))
377                 show_tables = true;
378               else if (lex_match_id (lexer, "NOTABLES"))
379                 show_tables = false;
380               else
381                 {
382                   lex_error (lexer, NULL);
383                   goto exit;
384                 }
385               lex_match (lexer, T_COMMA);
386             }
387         }
388       else if (lex_match_id (lexer, "BARCHART"))
389         proc.barchart = true;
390       else if (lex_match_id (lexer, "CELLS"))
391         {
392           lex_match (lexer, T_EQUALS);
393
394           if (lex_match_id (lexer, "NONE"))
395             proc.cells = 0;
396           else if (lex_match (lexer, T_ALL))
397             proc.cells = CRS_ALL_CELLS;
398           else
399             {
400               proc.cells = 0;
401               while (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)
402                 {
403 #define C(KEYWORD, STRING, RC)                                  \
404                   if (lex_match_id (lexer, #KEYWORD))           \
405                     {                                           \
406                       proc.cells |= 1u << CRS_CL_##KEYWORD;     \
407                       continue;                                 \
408                     }
409                   CRS_CELLS
410 #undef C
411                   lex_error (lexer, NULL);
412                   goto exit;
413                 }
414               if (!proc.cells)
415                 proc.cells = ((1u << CRS_CL_COUNT) | (1u << CRS_CL_ROW)
416                               | (1u << CRS_CL_COLUMN) | (1u << CRS_CL_TOTAL));
417             }
418         }
419       else if (lex_match_id (lexer, "STATISTICS"))
420         {
421           lex_match (lexer, T_EQUALS);
422
423           if (lex_match_id (lexer, "NONE"))
424             proc.statistics = 0;
425           else if (lex_match (lexer, T_ALL))
426             proc.statistics = CRS_ALL_STATISTICS;
427           else
428             {
429               proc.statistics = 0;
430               while (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)
431                 {
432 #define S(KEYWORD)                                              \
433                   if (lex_match_id (lexer, #KEYWORD))           \
434                     {                                           \
435                       proc.statistics |= CRS_ST_##KEYWORD;      \
436                       continue;                                 \
437                     }
438                   CRS_STATISTICS
439 #undef S
440                   lex_error (lexer, NULL);
441                   goto exit;
442                 }
443               if (!proc.statistics)
444                 proc.statistics = CRS_ST_CHISQ;
445             }
446         }
447       else if (!parse_crosstabs_tables (lexer, ds, &proc))
448         goto exit;
449
450       if (!lex_match (lexer, T_SLASH))
451         break;
452     }
453   if (!lex_end_of_command (lexer))
454     goto exit;
455
456   if (!proc.n_pivots)
457     {
458       msg (SE, _("At least one crosstabulation must be requested (using "
459                  "the TABLES subcommand)."));
460       goto exit;
461     }
462
463   /* Cells. */
464   if (!show_tables)
465     proc.cells = 0;
466   for (int i = 0; i < CRS_N_CELLS; i++)
467     if (proc.cells & (1u << i))
468       proc.a_cells[proc.n_cells++] = i;
469   assert (proc.n_cells < CRS_N_CELLS);
470
471   /* Missing values. */
472   if (proc.mode == GENERAL && proc.exclude == MV_NEVER)
473     {
474       msg (SE, _("Missing mode %s not allowed in general mode.  "
475                  "Assuming %s."), "REPORT", "MISSING=TABLE");
476       proc.exclude = MV_ANY;
477     }
478
479   struct casereader *input = casereader_create_filter_weight (proc_open (ds),
480                                                               dataset_dict (ds),
481                                                               NULL, NULL);
482   struct casegrouper *grouper = casegrouper_create_splits (input, dataset_dict (ds));
483   struct casereader *group;
484   while (casegrouper_get_next_group (grouper, &group))
485     {
486       struct ccase *c;
487
488       /* Output SPLIT FILE variables. */
489       c = casereader_peek (group, 0);
490       if (c != NULL)
491         {
492           output_split_file_values (ds, c);
493           case_unref (c);
494         }
495
496       /* Initialize hash tables. */
497       for (struct crosstabulation *xt = &proc.pivots[0];
498            xt < &proc.pivots[proc.n_pivots]; xt++)
499         hmap_init (&xt->data);
500
501       /* Tabulate. */
502       for (; (c = casereader_read (group)) != NULL; case_unref (c))
503         for (struct crosstabulation *xt = &proc.pivots[0];
504              xt < &proc.pivots[proc.n_pivots]; xt++)
505           {
506             double weight = dict_get_case_weight (dataset_dict (ds), c,
507                                                   &proc.bad_warn);
508             if (proc.round_case_weights)
509               {
510                 weight = round_weight (&proc, weight);
511                 if (weight == 0.)
512                   continue;
513               }
514             if (should_tabulate_case (xt, c, proc.exclude))
515               {
516                 if (proc.mode == GENERAL)
517                   tabulate_general_case (xt, c, weight);
518                 else
519                   tabulate_integer_case (xt, c, weight);
520               }
521             else
522               xt->missing += weight;
523           }
524       casereader_destroy (group);
525
526       /* Output. */
527       postcalc (&proc);
528     }
529   bool ok = casegrouper_destroy (grouper);
530   ok = proc_commit (ds) && ok;
531
532   result = ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
533
534 exit:
535   free (proc.variables);
536
537   struct var_range *range, *next_range;
538   HMAP_FOR_EACH_SAFE (range, next_range, struct var_range, hmap_node,
539                       &proc.var_ranges)
540     {
541       hmap_delete (&proc.var_ranges, &range->hmap_node);
542       free (range);
543     }
544   for (struct crosstabulation *xt = &proc.pivots[0];
545        xt < &proc.pivots[proc.n_pivots]; xt++)
546     {
547       free (xt->vars);
548       free (xt->const_vars);
549       free (xt->const_indexes);
550     }
551   free (proc.pivots);
552
553   return result;
554 }
555
556 /* Parses the TABLES subcommand. */
557 static bool
558 parse_crosstabs_tables (struct lexer *lexer, struct dataset *ds,
559                         struct crosstabs_proc *proc)
560 {
561   const struct variable ***by = NULL;
562   size_t *by_nvar = NULL;
563   bool ok = false;
564
565   /* Ensure that this is a TABLES subcommand. */
566   if (!lex_match_id (lexer, "TABLES")
567       && (lex_token (lexer) != T_ID ||
568           dict_lookup_var (dataset_dict (ds), lex_tokcstr (lexer)) == NULL)
569       && lex_token (lexer) != T_ALL)
570     {
571       lex_error (lexer, NULL);
572       return false;
573     }
574   lex_match (lexer, T_EQUALS);
575
576   struct const_var_set *var_set
577     = (proc->variables
578        ? const_var_set_create_from_array (proc->variables,
579                                           proc->n_variables)
580        : const_var_set_create_from_dict (dataset_dict (ds)));
581
582   size_t nx = 1;
583   int n_by = 0;
584   for (;;)
585     {
586       by = xnrealloc (by, n_by + 1, sizeof *by);
587       by_nvar = xnrealloc (by_nvar, n_by + 1, sizeof *by_nvar);
588       if (!parse_const_var_set_vars (lexer, var_set, &by[n_by], &by_nvar[n_by],
589                                      PV_NO_DUPLICATE | PV_NO_SCRATCH))
590         goto done;
591       if (xalloc_oversized (nx, by_nvar[n_by]))
592         {
593           msg (SE, _("Too many cross-tabulation variables or dimensions."));
594           goto done;
595         }
596       nx *= by_nvar[n_by];
597       n_by++;
598
599       if (!lex_match (lexer, T_BY))
600         {
601           if (n_by < 2)
602             goto done;
603           else
604             break;
605         }
606     }
607
608   int *by_iter = xcalloc (n_by, sizeof *by_iter);
609   proc->pivots = xnrealloc (proc->pivots,
610                             proc->n_pivots + nx, sizeof *proc->pivots);
611   for (int i = 0; i < nx; i++)
612     {
613       struct crosstabulation *xt = &proc->pivots[proc->n_pivots++];
614
615       *xt = (struct crosstabulation) {
616         .proc = proc,
617         .weight_format = proc->weight_format,
618         .missing = 0.,
619         .n_vars = n_by,
620         .vars = xcalloc (n_by, sizeof *xt->vars),
621         .n_consts = 0,
622         .const_vars = NULL,
623         .const_indexes = NULL,
624       };
625
626       for (int j = 0; j < n_by; j++)
627         xt->vars[j].var = by[j][by_iter[j]];
628
629       for (int j = n_by - 1; j >= 0; j--)
630         {
631           if (++by_iter[j] < by_nvar[j])
632             break;
633           by_iter[j] = 0;
634         }
635     }
636   free (by_iter);
637   ok = true;
638
639 done:
640   /* All return paths lead here. */
641   for (int i = 0; i < n_by; i++)
642     free (by[i]);
643   free (by);
644   free (by_nvar);
645
646   const_var_set_destroy (var_set);
647
648   return ok;
649 }
650
651 /* Parses the VARIABLES subcommand. */
652 static bool
653 parse_crosstabs_variables (struct lexer *lexer, struct dataset *ds,
654                            struct crosstabs_proc *proc)
655 {
656   if (proc->n_pivots)
657     {
658       msg (SE, _("%s must be specified before %s."), "VARIABLES", "TABLES");
659       return false;
660     }
661
662   lex_match (lexer, T_EQUALS);
663
664   for (;;)
665     {
666       size_t orig_nv = proc->n_variables;
667
668       if (!parse_variables_const (lexer, dataset_dict (ds),
669                                   &proc->variables, &proc->n_variables,
670                                   (PV_APPEND | PV_NUMERIC
671                                    | PV_NO_DUPLICATE | PV_NO_SCRATCH)))
672         return false;
673
674       if (!lex_force_match (lexer, T_LPAREN))
675           goto error;
676
677       if (!lex_force_int (lexer))
678         goto error;
679       long min = lex_integer (lexer);
680       lex_get (lexer);
681
682       lex_match (lexer, T_COMMA);
683
684       if (!lex_force_int_range (lexer, NULL, min, LONG_MAX))
685         goto error;
686       long max = lex_integer (lexer);
687       lex_get (lexer);
688
689       if (!lex_force_match (lexer, T_RPAREN))
690         goto error;
691
692       for (size_t i = orig_nv; i < proc->n_variables; i++)
693         {
694           const struct variable *var = proc->variables[i];
695           struct var_range *vr = xmalloc (sizeof *vr);
696
697           vr->var = var;
698           vr->min = min;
699           vr->max = max;
700           vr->count = max - min + 1;
701           hmap_insert (&proc->var_ranges, &vr->hmap_node,
702                        hash_pointer (var, 0));
703         }
704
705       if (lex_token (lexer) == T_SLASH)
706         break;
707     }
708
709   proc->mode = INTEGER;
710   return true;
711
712  error:
713   free (proc->variables);
714   proc->variables = NULL;
715   proc->n_variables = 0;
716   return false;
717 }
718 \f
719 /* Data file processing. */
720
721 static const struct var_range *
722 get_var_range (const struct crosstabs_proc *proc, const struct variable *var)
723 {
724   if (!hmap_is_empty (&proc->var_ranges))
725     {
726       const struct var_range *range;
727
728       HMAP_FOR_EACH_IN_BUCKET (range, struct var_range, hmap_node,
729                                hash_pointer (var, 0), &proc->var_ranges)
730         if (range->var == var)
731           return range;
732     }
733
734   return NULL;
735 }
736
737 static bool
738 should_tabulate_case (const struct crosstabulation *xt, const struct ccase *c,
739                       enum mv_class exclude)
740 {
741   int j;
742   for (j = 0; j < xt->n_vars; j++)
743     {
744       const struct variable *var = xt->vars[j].var;
745       const struct var_range *range = get_var_range (xt->proc, var);
746
747       if (var_is_value_missing (var, case_data (c, var), exclude))
748         return false;
749
750       if (range != NULL)
751         {
752           double num = case_num (c, var);
753           if (num < range->min || num >= range->max + 1.)
754             return false;
755         }
756     }
757   return true;
758 }
759
760 static void
761 tabulate_integer_case (struct crosstabulation *xt, const struct ccase *c,
762                        double weight)
763 {
764   struct freq *te;
765   size_t hash;
766   int j;
767
768   hash = 0;
769   for (j = 0; j < xt->n_vars; j++)
770     {
771       /* Throw away fractional parts of values. */
772       hash = hash_int (case_num (c, xt->vars[j].var), hash);
773     }
774
775   HMAP_FOR_EACH_WITH_HASH (te, struct freq, node, hash, &xt->data)
776     {
777       for (j = 0; j < xt->n_vars; j++)
778         if ((int) case_num (c, xt->vars[j].var) != (int) te->values[j].f)
779           goto no_match;
780
781       /* Found an existing entry. */
782       te->count += weight;
783       return;
784
785     no_match: ;
786     }
787
788   /* No existing entry.  Create a new one. */
789   te = xmalloc (table_entry_size (xt->n_vars));
790   te->count = weight;
791   for (j = 0; j < xt->n_vars; j++)
792     te->values[j].f = (int) case_num (c, xt->vars[j].var);
793   hmap_insert (&xt->data, &te->node, hash);
794 }
795
796 static void
797 tabulate_general_case (struct crosstabulation *xt, const struct ccase *c,
798                        double weight)
799 {
800   struct freq *te;
801   size_t hash;
802   int j;
803
804   hash = 0;
805   for (j = 0; j < xt->n_vars; j++)
806     {
807       const struct variable *var = xt->vars[j].var;
808       hash = value_hash (case_data (c, var), var_get_width (var), hash);
809     }
810
811   HMAP_FOR_EACH_WITH_HASH (te, struct freq, node, hash, &xt->data)
812     {
813       for (j = 0; j < xt->n_vars; j++)
814         {
815           const struct variable *var = xt->vars[j].var;
816           if (!value_equal (case_data (c, var), &te->values[j],
817                             var_get_width (var)))
818             goto no_match;
819         }
820
821       /* Found an existing entry. */
822       te->count += weight;
823       return;
824
825     no_match: ;
826     }
827
828   /* No existing entry.  Create a new one. */
829   te = xmalloc (table_entry_size (xt->n_vars));
830   te->count = weight;
831   for (j = 0; j < xt->n_vars; j++)
832     {
833       const struct variable *var = xt->vars[j].var;
834       value_clone (&te->values[j], case_data (c, var), var_get_width (var));
835     }
836   hmap_insert (&xt->data, &te->node, hash);
837 }
838 \f
839 /* Post-data reading calculations. */
840
841 static int compare_table_entry_vars_3way (const struct freq *a,
842                                           const struct freq *b,
843                                           const struct crosstabulation *xt,
844                                           int idx0, int idx1);
845 static int compare_table_entry_3way (const void *ap_, const void *bp_,
846                                      const void *xt_);
847 static int compare_table_entry_3way_inv (const void *ap_, const void *bp_,
848                                      const void *xt_);
849
850 static void enum_var_values (const struct crosstabulation *, int var_idx,
851                              bool descending);
852 static void free_var_values (const struct crosstabulation *, int var_idx);
853 static void output_crosstabulation (struct crosstabs_proc *,
854                                 struct crosstabulation *);
855 static void make_crosstabulation_subset (struct crosstabulation *xt,
856                                      size_t row0, size_t row1,
857                                      struct crosstabulation *subset);
858 static void make_summary_table (struct crosstabs_proc *);
859 static bool find_crosstab (struct crosstabulation *, size_t *row0p,
860                            size_t *row1p);
861
862 static void
863 postcalc (struct crosstabs_proc *proc)
864 {
865   /* Round hash table entries, if requested
866
867      If this causes any of the cell counts to fall to zero, delete those
868      cells. */
869   if (proc->round_cells)
870     for (struct crosstabulation *xt = proc->pivots;
871          xt < &proc->pivots[proc->n_pivots]; xt++)
872       {
873         struct freq *e, *next;
874         HMAP_FOR_EACH_SAFE (e, next, struct freq, node, &xt->data)
875           {
876             e->count = round_weight (proc, e->count);
877             if (e->count == 0.0)
878               {
879                 hmap_delete (&xt->data, &e->node);
880                 free (e);
881               }
882           }
883       }
884
885   /* Convert hash tables into sorted arrays of entries. */
886   for (struct crosstabulation *xt = proc->pivots;
887        xt < &proc->pivots[proc->n_pivots]; xt++)
888     {
889       struct freq *e;
890
891       xt->n_entries = hmap_count (&xt->data);
892       xt->entries = xnmalloc (xt->n_entries, sizeof *xt->entries);
893       size_t i = 0;
894       HMAP_FOR_EACH (e, struct freq, node, &xt->data)
895         xt->entries[i++] = e;
896       hmap_destroy (&xt->data);
897
898       sort (xt->entries, xt->n_entries, sizeof *xt->entries,
899             proc->descending ? compare_table_entry_3way_inv : compare_table_entry_3way,
900             xt);
901
902     }
903
904   make_summary_table (proc);
905
906   /* Output each pivot table. */
907   for (struct crosstabulation *xt = proc->pivots;
908        xt < &proc->pivots[proc->n_pivots]; xt++)
909     {
910       output_crosstabulation (proc, xt);
911       if (proc->barchart)
912         {
913           int n_vars = (xt->n_vars > 2 ? 2 : xt->n_vars);
914           const struct variable **vars = xcalloc (n_vars, sizeof *vars);
915           for (size_t i = 0; i < n_vars; i++)
916             vars[i] = xt->vars[i].var;
917           chart_submit (barchart_create (vars, n_vars, _("Count"),
918                                          false,
919                                          xt->entries, xt->n_entries));
920           free (vars);
921         }
922     }
923
924   /* Free output and prepare for next split file. */
925   for (struct crosstabulation *xt = proc->pivots;
926        xt < &proc->pivots[proc->n_pivots]; xt++)
927     {
928       xt->missing = 0.0;
929
930       /* Free the members that were allocated in this function(and the values
931          owned by the entries.
932
933          The other pointer members are either both allocated and destroyed at a
934          lower level (in output_crosstabulation), or both allocated and
935          destroyed at a higher level (in crs_custom_tables and free_proc,
936          respectively). */
937       for (size_t i = 0; i < xt->n_vars; i++)
938         {
939           int width = var_get_width (xt->vars[i].var);
940           if (value_needs_init (width))
941             {
942               size_t j;
943
944               for (j = 0; j < xt->n_entries; j++)
945                 value_destroy (&xt->entries[j]->values[i], width);
946             }
947         }
948
949       for (size_t i = 0; i < xt->n_entries; i++)
950         free (xt->entries[i]);
951       free (xt->entries);
952     }
953 }
954
955 static void
956 make_crosstabulation_subset (struct crosstabulation *xt, size_t row0,
957                              size_t row1, struct crosstabulation *subset)
958 {
959   *subset = *xt;
960   if (xt->n_vars > 2)
961     {
962       assert (xt->n_consts == 0);
963       subset->n_vars = 2;
964       subset->vars = xt->vars;
965
966       subset->n_consts = xt->n_vars - 2;
967       subset->const_vars = xt->vars + 2;
968       subset->const_indexes = xcalloc (subset->n_consts,
969                                        sizeof *subset->const_indexes);
970       for (size_t i = 0; i < subset->n_consts; i++)
971         {
972           const union value *value = &xt->entries[row0]->values[2 + i];
973
974           for (size_t j = 0; j < xt->vars[2 + i].n_values; j++)
975             if (value_equal (&xt->vars[2 + i].values[j], value,
976                              var_get_width (xt->vars[2 + i].var)))
977               {
978                 subset->const_indexes[i] = j;
979                 goto found;
980               }
981           NOT_REACHED ();
982         found: ;
983         }
984     }
985   subset->entries = &xt->entries[row0];
986   subset->n_entries = row1 - row0;
987 }
988
989 static int
990 compare_table_entry_var_3way (const struct freq *a,
991                               const struct freq *b,
992                               const struct crosstabulation *xt,
993                               int idx)
994 {
995   return value_compare_3way (&a->values[idx], &b->values[idx],
996                              var_get_width (xt->vars[idx].var));
997 }
998
999 static int
1000 compare_table_entry_vars_3way (const struct freq *a,
1001                                const struct freq *b,
1002                                const struct crosstabulation *xt,
1003                                int idx0, int idx1)
1004 {
1005   int i;
1006
1007   for (i = idx1 - 1; i >= idx0; i--)
1008     {
1009       int cmp = compare_table_entry_var_3way (a, b, xt, i);
1010       if (cmp != 0)
1011         return cmp;
1012     }
1013   return 0;
1014 }
1015
1016 /* Compare the struct freq at *AP to the one at *BP and
1017    return a strcmp()-type result. */
1018 static int
1019 compare_table_entry_3way (const void *ap_, const void *bp_, const void *xt_)
1020 {
1021   const struct freq *const *ap = ap_;
1022   const struct freq *const *bp = bp_;
1023   const struct freq *a = *ap;
1024   const struct freq *b = *bp;
1025   const struct crosstabulation *xt = xt_;
1026   int cmp;
1027
1028   cmp = compare_table_entry_vars_3way (a, b, xt, 2, xt->n_vars);
1029   if (cmp != 0)
1030     return cmp;
1031
1032   cmp = compare_table_entry_var_3way (a, b, xt, ROW_VAR);
1033   if (cmp != 0)
1034     return cmp;
1035
1036   return compare_table_entry_var_3way (a, b, xt, COL_VAR);
1037 }
1038
1039 /* Inverted version of compare_table_entry_3way */
1040 static int
1041 compare_table_entry_3way_inv (const void *ap_, const void *bp_, const void *xt_)
1042 {
1043   return -compare_table_entry_3way (ap_, bp_, xt_);
1044 }
1045
1046 /* Output a table summarizing the cases processed. */
1047 static void
1048 make_summary_table (struct crosstabs_proc *proc)
1049 {
1050   struct pivot_table *table = pivot_table_create (N_("Summary"));
1051   pivot_table_set_weight_var (table, dict_get_weight (proc->dict));
1052
1053   pivot_dimension_create (table, PIVOT_AXIS_COLUMN, N_("Statistics"),
1054                           N_("N"), PIVOT_RC_COUNT,
1055                           N_("Percent"), PIVOT_RC_PERCENT);
1056
1057   struct pivot_dimension *cases = pivot_dimension_create (
1058     table, PIVOT_AXIS_COLUMN, N_("Cases"),
1059     N_("Valid"), N_("Missing"), N_("Total"));
1060   cases->root->show_label = true;
1061
1062   struct pivot_dimension *tables = pivot_dimension_create (
1063     table, PIVOT_AXIS_ROW, N_("Crosstabulation"));
1064   for (struct crosstabulation *xt = &proc->pivots[0];
1065        xt < &proc->pivots[proc->n_pivots]; xt++)
1066     {
1067       struct string name = DS_EMPTY_INITIALIZER;
1068       for (size_t i = 0; i < xt->n_vars; i++)
1069         {
1070           if (i > 0)
1071             ds_put_cstr (&name, " Ã— ");
1072           ds_put_cstr (&name, var_to_string (xt->vars[i].var));
1073         }
1074
1075       int row = pivot_category_create_leaf (
1076         tables->root,
1077         pivot_value_new_user_text_nocopy (ds_steal_cstr (&name)));
1078
1079       double valid = 0.;
1080       for (size_t i = 0; i < xt->n_entries; i++)
1081         valid += xt->entries[i]->count;
1082
1083       double n[3];
1084       n[0] = valid;
1085       n[1] = xt->missing;
1086       n[2] = n[0] + n[1];
1087       for (int i = 0; i < 3; i++)
1088         {
1089           pivot_table_put3 (table, 0, i, row, pivot_value_new_number (n[i]));
1090           pivot_table_put3 (table, 1, i, row,
1091                             pivot_value_new_number (n[i] / n[2] * 100.0));
1092         }
1093     }
1094
1095   pivot_table_submit (table);
1096 }
1097 \f
1098 /* Output. */
1099
1100 static struct pivot_table *create_crosstab_table (
1101   struct crosstabs_proc *, struct crosstabulation *,
1102   size_t crs_leaves[CRS_N_CELLS]);
1103 static struct pivot_table *create_chisq_table (struct crosstabulation *);
1104 static struct pivot_table *create_sym_table (struct crosstabulation *);
1105 static struct pivot_table *create_risk_table (
1106   struct crosstabulation *, struct pivot_dimension **risk_statistics);
1107 static struct pivot_table *create_direct_table (struct crosstabulation *);
1108 static void display_crosstabulation (struct crosstabs_proc *,
1109                                      struct crosstabulation *,
1110                                      struct pivot_table *,
1111                                      size_t crs_leaves[CRS_N_CELLS]);
1112 static void display_chisq (struct crosstabulation *, struct pivot_table *);
1113 static void display_symmetric (struct crosstabs_proc *,
1114                                struct crosstabulation *, struct pivot_table *);
1115 static void display_risk (struct crosstabulation *, struct pivot_table *,
1116                           struct pivot_dimension *risk_statistics);
1117 static void display_directional (struct crosstabs_proc *,
1118                                  struct crosstabulation *,
1119                                  struct pivot_table *);
1120 static void delete_missing (struct crosstabulation *);
1121 static void build_matrix (struct crosstabulation *);
1122
1123 /* Output pivot table XT in the context of PROC. */
1124 static void
1125 output_crosstabulation (struct crosstabs_proc *proc, struct crosstabulation *xt)
1126 {
1127   for (size_t i = 0; i < xt->n_vars; i++)
1128     enum_var_values (xt, i, proc->descending);
1129
1130   if (xt->vars[COL_VAR].n_values == 0)
1131     {
1132       struct string vars;
1133       int i;
1134
1135       ds_init_cstr (&vars, var_to_string (xt->vars[0].var));
1136       for (i = 1; i < xt->n_vars; i++)
1137         ds_put_format (&vars, " Ã— %s", var_to_string (xt->vars[i].var));
1138
1139       /* TRANSLATORS: The %s here describes a crosstabulation.  It takes the
1140          form "var1 * var2 * var3 * ...".  */
1141       msg (SW, _("Crosstabulation %s contained no non-missing cases."),
1142            ds_cstr (&vars));
1143
1144       ds_destroy (&vars);
1145       for (size_t i = 0; i < xt->n_vars; i++)
1146         free_var_values (xt, i);
1147       return;
1148     }
1149
1150   size_t crs_leaves[CRS_N_CELLS];
1151   struct pivot_table *table = (proc->cells
1152                                ? create_crosstab_table (proc, xt, crs_leaves)
1153                                : NULL);
1154   struct pivot_table *chisq = (proc->statistics & CRS_ST_CHISQ
1155                                ? create_chisq_table (xt)
1156                                : NULL);
1157   struct pivot_table *sym
1158     = (proc->statistics & (CRS_ST_PHI | CRS_ST_CC | CRS_ST_BTAU | CRS_ST_CTAU
1159                            | CRS_ST_GAMMA | CRS_ST_CORR | CRS_ST_KAPPA)
1160        ? create_sym_table (xt)
1161        : NULL);
1162   struct pivot_dimension *risk_statistics = NULL;
1163   struct pivot_table *risk = (proc->statistics & CRS_ST_RISK
1164                               ? create_risk_table (xt, &risk_statistics)
1165                               : NULL);
1166   struct pivot_table *direct
1167     = (proc->statistics & (CRS_ST_LAMBDA | CRS_ST_UC | CRS_ST_D | CRS_ST_ETA)
1168        ? create_direct_table (xt)
1169        : NULL);
1170
1171   size_t row0 = 0;
1172   size_t row1 = 0;
1173   while (find_crosstab (xt, &row0, &row1))
1174     {
1175       struct crosstabulation x;
1176
1177       make_crosstabulation_subset (xt, row0, row1, &x);
1178
1179       size_t n_rows = x.vars[ROW_VAR].n_values;
1180       size_t n_cols = x.vars[COL_VAR].n_values;
1181       if (size_overflow_p (xtimes (xtimes (n_rows, n_cols), sizeof (double))))
1182         xalloc_die ();
1183       x.row_tot = xmalloc (n_rows * sizeof *x.row_tot);
1184       x.col_tot = xmalloc (n_cols * sizeof *x.col_tot);
1185       x.mat = xmalloc (n_rows * n_cols * sizeof *x.mat);
1186
1187       build_matrix (&x);
1188
1189       /* Find the first variable that differs from the last subtable. */
1190       if (table)
1191         display_crosstabulation (proc, &x, table, crs_leaves);
1192
1193       if (proc->exclude == MV_NEVER)
1194         delete_missing (&x);
1195
1196       if (chisq)
1197         display_chisq (&x, chisq);
1198
1199       if (sym)
1200         display_symmetric (proc, &x, sym);
1201       if (risk)
1202         display_risk (&x, risk, risk_statistics);
1203       if (direct)
1204         display_directional (proc, &x, direct);
1205
1206       free (x.mat);
1207       free (x.row_tot);
1208       free (x.col_tot);
1209       free (x.const_indexes);
1210     }
1211
1212   if (table)
1213     pivot_table_submit (table);
1214
1215   if (chisq)
1216     pivot_table_submit (chisq);
1217
1218   if (sym)
1219     pivot_table_submit (sym);
1220
1221   if (risk)
1222     {
1223       if (!pivot_table_is_empty (risk))
1224         pivot_table_submit (risk);
1225       else
1226         pivot_table_unref (risk);
1227     }
1228
1229   if (direct)
1230     pivot_table_submit (direct);
1231
1232   for (size_t i = 0; i < xt->n_vars; i++)
1233     free_var_values (xt, i);
1234 }
1235
1236 static void
1237 build_matrix (struct crosstabulation *x)
1238 {
1239   const int col_var_width = var_get_width (x->vars[COL_VAR].var);
1240   const int row_var_width = var_get_width (x->vars[ROW_VAR].var);
1241   size_t n_rows = x->vars[ROW_VAR].n_values;
1242   size_t n_cols = x->vars[COL_VAR].n_values;
1243   int col, row;
1244   double *mp;
1245   struct freq **p;
1246
1247   mp = x->mat;
1248   col = row = 0;
1249   for (p = x->entries; p < &x->entries[x->n_entries]; p++)
1250     {
1251       const struct freq *te = *p;
1252
1253       while (!value_equal (&x->vars[ROW_VAR].values[row],
1254                            &te->values[ROW_VAR], row_var_width))
1255         {
1256           for (; col < n_cols; col++)
1257             *mp++ = 0.0;
1258           col = 0;
1259           row++;
1260         }
1261
1262       while (!value_equal (&x->vars[COL_VAR].values[col],
1263                            &te->values[COL_VAR], col_var_width))
1264         {
1265           *mp++ = 0.0;
1266           col++;
1267         }
1268
1269       *mp++ = te->count;
1270       if (++col >= n_cols)
1271         {
1272           col = 0;
1273           row++;
1274         }
1275     }
1276   while (mp < &x->mat[n_cols * n_rows])
1277     *mp++ = 0.0;
1278   assert (mp == &x->mat[n_cols * n_rows]);
1279
1280   /* Column totals, row totals, ns_rows. */
1281   mp = x->mat;
1282   for (col = 0; col < n_cols; col++)
1283     x->col_tot[col] = 0.0;
1284   for (row = 0; row < n_rows; row++)
1285     x->row_tot[row] = 0.0;
1286   x->ns_rows = 0;
1287   for (row = 0; row < n_rows; row++)
1288     {
1289       bool row_is_empty = true;
1290       for (col = 0; col < n_cols; col++)
1291         {
1292           if (*mp != 0.0)
1293             {
1294               row_is_empty = false;
1295               x->col_tot[col] += *mp;
1296               x->row_tot[row] += *mp;
1297             }
1298           mp++;
1299         }
1300       if (!row_is_empty)
1301         x->ns_rows++;
1302     }
1303   assert (mp == &x->mat[n_cols * n_rows]);
1304
1305   /* ns_cols. */
1306   x->ns_cols = 0;
1307   for (col = 0; col < n_cols; col++)
1308     for (row = 0; row < n_rows; row++)
1309       if (x->mat[col + row * n_cols] != 0.0)
1310         {
1311           x->ns_cols++;
1312           break;
1313         }
1314
1315   /* Grand total. */
1316   x->total = 0.0;
1317   for (col = 0; col < n_cols; col++)
1318     x->total += x->col_tot[col];
1319 }
1320
1321 static void
1322 add_var_dimension (struct pivot_table *table, const struct xtab_var *var,
1323                    enum pivot_axis_type axis_type, bool total)
1324 {
1325   struct pivot_dimension *d = pivot_dimension_create__ (
1326     table, axis_type, pivot_value_new_variable (var->var));
1327
1328   struct pivot_footnote *missing_footnote = pivot_table_create_footnote (
1329     table, pivot_value_new_text (N_("Missing value")));
1330
1331   struct pivot_category *group = pivot_category_create_group__ (
1332     d->root, pivot_value_new_variable (var->var));
1333   for (size_t j = 0; j < var->n_values; j++)
1334     {
1335       struct pivot_value *value = pivot_value_new_var_value (
1336         var->var, &var->values[j]);
1337       if (var_is_value_missing (var->var, &var->values[j], MV_ANY))
1338         pivot_value_add_footnote (value, missing_footnote);
1339       pivot_category_create_leaf (group, value);
1340     }
1341
1342   if (total)
1343     pivot_category_create_leaf (d->root, pivot_value_new_text (N_("Total")));
1344 }
1345
1346 static struct pivot_table *
1347 create_crosstab_table (struct crosstabs_proc *proc, struct crosstabulation *xt,
1348                        size_t crs_leaves[CRS_N_CELLS])
1349 {
1350   /* Title. */
1351   struct string title = DS_EMPTY_INITIALIZER;
1352   for (size_t i = 0; i < xt->n_vars; i++)
1353     {
1354       if (i)
1355         ds_put_cstr (&title, " Ã— ");
1356       ds_put_cstr (&title, var_to_string (xt->vars[i].var));
1357     }
1358   for (size_t i = 0; i < xt->n_consts; i++)
1359     {
1360       const struct variable *var = xt->const_vars[i].var;
1361       const union value *value = &xt->entries[0]->values[2 + i];
1362       char *s;
1363
1364       ds_put_format (&title, ", %s=", var_to_string (var));
1365
1366       /* Insert the formatted value of VAR without any leading spaces. */
1367       s = data_out (value, var_get_encoding (var), var_get_print_format (var),
1368                     settings_get_fmt_settings ());
1369       ds_put_cstr (&title, s + strspn (s, " "));
1370       free (s);
1371     }
1372   struct pivot_table *table = pivot_table_create__ (
1373     pivot_value_new_user_text_nocopy (ds_steal_cstr (&title)),
1374     "Crosstabulation");
1375   pivot_table_set_weight_format (table, &proc->weight_format);
1376
1377   struct pivot_dimension *statistics = pivot_dimension_create (
1378     table, PIVOT_AXIS_ROW, N_("Statistics"));
1379
1380   struct statistic
1381     {
1382       const char *label;
1383       const char *rc;
1384     };
1385   static const struct statistic stats[CRS_N_CELLS] =
1386     {
1387 #define C(KEYWORD, STRING, RC) { STRING, RC },
1388       CRS_CELLS
1389 #undef C
1390     };
1391   for (size_t i = 0; i < CRS_N_CELLS; i++)
1392     if (proc->cells & (1u << i) && stats[i].label)
1393         crs_leaves[i] = pivot_category_create_leaf_rc (
1394           statistics->root, pivot_value_new_text (stats[i].label),
1395           stats[i].rc);
1396
1397   for (size_t i = 0; i < xt->n_vars; i++)
1398     add_var_dimension (table, &xt->vars[i],
1399                        i == COL_VAR ? PIVOT_AXIS_COLUMN : PIVOT_AXIS_ROW,
1400                        true);
1401
1402   return table;
1403 }
1404
1405 static struct pivot_table *
1406 create_chisq_table (struct crosstabulation *xt)
1407 {
1408   struct pivot_table *chisq = pivot_table_create (N_("Chi-Square Tests"));
1409   pivot_table_set_weight_format (chisq, &xt->weight_format);
1410
1411   pivot_dimension_create (
1412     chisq, PIVOT_AXIS_ROW, N_("Statistics"),
1413     N_("Pearson Chi-Square"),
1414     N_("Likelihood Ratio"),
1415     N_("Fisher's Exact Test"),
1416     N_("Continuity Correction"),
1417     N_("Linear-by-Linear Association"),
1418     N_("N of Valid Cases"), PIVOT_RC_COUNT);
1419
1420   pivot_dimension_create (
1421     chisq, PIVOT_AXIS_COLUMN, N_("Statistics"),
1422     N_("Value"), PIVOT_RC_OTHER,
1423     N_("df"), PIVOT_RC_COUNT,
1424     N_("Asymptotic Sig. (2-tailed)"), PIVOT_RC_SIGNIFICANCE,
1425     N_("Exact Sig. (2-tailed)"), PIVOT_RC_SIGNIFICANCE,
1426     N_("Exact Sig. (1-tailed)"), PIVOT_RC_SIGNIFICANCE);
1427
1428   for (size_t i = 2; i < xt->n_vars; i++)
1429     add_var_dimension (chisq, &xt->vars[i], PIVOT_AXIS_ROW, false);
1430
1431   return chisq;
1432 }
1433
1434 /* Symmetric measures. */
1435 static struct pivot_table *
1436 create_sym_table (struct crosstabulation *xt)
1437 {
1438   struct pivot_table *sym = pivot_table_create (N_("Symmetric Measures"));
1439   pivot_table_set_weight_format (sym, &xt->weight_format);
1440
1441   pivot_dimension_create (
1442     sym, PIVOT_AXIS_COLUMN, N_("Values"),
1443     N_("Value"), PIVOT_RC_OTHER,
1444     N_("Asymp. Std. Error"), PIVOT_RC_OTHER,
1445     N_("Approx. T"), PIVOT_RC_OTHER,
1446     N_("Approx. Sig."), PIVOT_RC_SIGNIFICANCE);
1447
1448   struct pivot_dimension *statistics = pivot_dimension_create (
1449     sym, PIVOT_AXIS_ROW, N_("Statistics"));
1450   pivot_category_create_group (
1451     statistics->root, N_("Nominal by Nominal"),
1452     N_("Phi"), N_("Cramer's V"), N_("Contingency Coefficient"));
1453   pivot_category_create_group (
1454     statistics->root, N_("Ordinal by Ordinal"),
1455     N_("Kendall's tau-b"), N_("Kendall's tau-c"),
1456     N_("Gamma"), N_("Spearman Correlation"));
1457   pivot_category_create_group (
1458     statistics->root, N_("Interval by Interval"),
1459     N_("Pearson's R"));
1460   pivot_category_create_group (
1461     statistics->root, N_("Measure of Agreement"),
1462     N_("Kappa"));
1463   pivot_category_create_leaves (statistics->root, N_("N of Valid Cases"),
1464                                 PIVOT_RC_COUNT);
1465
1466   for (size_t i = 2; i < xt->n_vars; i++)
1467     add_var_dimension (sym, &xt->vars[i], PIVOT_AXIS_ROW, false);
1468
1469   return sym;
1470 }
1471
1472 /* Risk estimate. */
1473 static struct pivot_table *
1474 create_risk_table (struct crosstabulation *xt,
1475                    struct pivot_dimension **risk_statistics)
1476 {
1477   struct pivot_table *risk = pivot_table_create (N_("Risk Estimate"));
1478   pivot_table_set_weight_format (risk, &xt->weight_format);
1479
1480   struct pivot_dimension *values = pivot_dimension_create (
1481     risk, PIVOT_AXIS_COLUMN, N_("Values"),
1482     N_("Value"), PIVOT_RC_OTHER);
1483   pivot_category_create_group (
1484   /* xgettext:no-c-format */
1485     values->root, N_("95% Confidence Interval"),
1486     N_("Lower"), PIVOT_RC_OTHER,
1487     N_("Upper"), PIVOT_RC_OTHER);
1488
1489   *risk_statistics = pivot_dimension_create (
1490     risk, PIVOT_AXIS_ROW, N_("Statistics"));
1491
1492   for (size_t i = 2; i < xt->n_vars; i++)
1493     add_var_dimension (risk, &xt->vars[i], PIVOT_AXIS_ROW, false);
1494
1495   return risk;
1496 }
1497
1498 static void
1499 create_direct_stat (struct pivot_category *parent,
1500                     const struct crosstabulation *xt,
1501                     const char *name, bool symmetric)
1502 {
1503   struct pivot_category *group = pivot_category_create_group (
1504     parent, name);
1505   if (symmetric)
1506     pivot_category_create_leaf (group, pivot_value_new_text (N_("Symmetric")));
1507
1508   char *row_label = xasprintf (_("%s Dependent"),
1509                                var_to_string (xt->vars[ROW_VAR].var));
1510   pivot_category_create_leaf (group, pivot_value_new_user_text_nocopy (
1511                                 row_label));
1512
1513   char *col_label = xasprintf (_("%s Dependent"),
1514                                var_to_string (xt->vars[COL_VAR].var));
1515   pivot_category_create_leaf (group, pivot_value_new_user_text_nocopy (
1516                                 col_label));
1517 }
1518
1519 /* Directional measures. */
1520 static struct pivot_table *
1521 create_direct_table (struct crosstabulation *xt)
1522 {
1523   struct pivot_table *direct = pivot_table_create (N_("Directional Measures"));
1524   pivot_table_set_weight_format (direct, &xt->weight_format);
1525
1526   pivot_dimension_create (
1527     direct, PIVOT_AXIS_COLUMN, N_("Values"),
1528     N_("Value"), PIVOT_RC_OTHER,
1529     N_("Asymp. Std. Error"), PIVOT_RC_OTHER,
1530     N_("Approx. T"), PIVOT_RC_OTHER,
1531     N_("Approx. Sig."), PIVOT_RC_SIGNIFICANCE);
1532
1533   struct pivot_dimension *statistics = pivot_dimension_create (
1534     direct, PIVOT_AXIS_ROW, N_("Statistics"));
1535   struct pivot_category *nn = pivot_category_create_group (
1536     statistics->root, N_("Nominal by Nominal"));
1537   create_direct_stat (nn, xt, N_("Lambda"), true);
1538   create_direct_stat (nn, xt, N_("Goodman and Kruskal tau"), false);
1539   create_direct_stat (nn, xt, N_("Uncertainty Coefficient"), true);
1540   struct pivot_category *oo = pivot_category_create_group (
1541     statistics->root, N_("Ordinal by Ordinal"));
1542   create_direct_stat (oo, xt, N_("Somers' d"), true);
1543   struct pivot_category *ni = pivot_category_create_group (
1544     statistics->root, N_("Nominal by Interval"));
1545   create_direct_stat (ni, xt, N_("Eta"), false);
1546
1547   for (size_t i = 2; i < xt->n_vars; i++)
1548     add_var_dimension (direct, &xt->vars[i], PIVOT_AXIS_ROW, false);
1549
1550   return direct;
1551 }
1552
1553 /* Delete missing rows and columns for statistical analysis when
1554    /MISSING=REPORT. */
1555 static void
1556 delete_missing (struct crosstabulation *xt)
1557 {
1558   size_t n_rows = xt->vars[ROW_VAR].n_values;
1559   size_t n_cols = xt->vars[COL_VAR].n_values;
1560   int r, c;
1561
1562   for (r = 0; r < n_rows; r++)
1563     if (var_is_num_missing (xt->vars[ROW_VAR].var,
1564                             xt->vars[ROW_VAR].values[r].f, MV_USER))
1565       {
1566         for (c = 0; c < n_cols; c++)
1567           xt->mat[c + r * n_cols] = 0.;
1568         xt->ns_rows--;
1569       }
1570
1571
1572   for (c = 0; c < n_cols; c++)
1573     if (var_is_num_missing (xt->vars[COL_VAR].var,
1574                             xt->vars[COL_VAR].values[c].f, MV_USER))
1575       {
1576         for (r = 0; r < n_rows; r++)
1577           xt->mat[c + r * n_cols] = 0.;
1578         xt->ns_cols--;
1579       }
1580 }
1581
1582 static bool
1583 find_crosstab (struct crosstabulation *xt, size_t *row0p, size_t *row1p)
1584 {
1585   size_t row0 = *row1p;
1586   size_t row1;
1587
1588   if (row0 >= xt->n_entries)
1589     return false;
1590
1591   for (row1 = row0 + 1; row1 < xt->n_entries; row1++)
1592     {
1593       struct freq *a = xt->entries[row0];
1594       struct freq *b = xt->entries[row1];
1595       if (compare_table_entry_vars_3way (a, b, xt, 2, xt->n_vars) != 0)
1596         break;
1597     }
1598   *row0p = row0;
1599   *row1p = row1;
1600   return true;
1601 }
1602
1603 /* Compares `union value's A_ and B_ and returns a strcmp()-like
1604    result.  WIDTH_ points to an int which is either 0 for a
1605    numeric value or a string width for a string value. */
1606 static int
1607 compare_value_3way (const void *a_, const void *b_, const void *width_)
1608 {
1609   const union value *a = a_;
1610   const union value *b = b_;
1611   const int *width = width_;
1612
1613   return value_compare_3way (a, b, *width);
1614 }
1615
1616 /* Inverted version of the above */
1617 static int
1618 compare_value_3way_inv (const void *a_, const void *b_, const void *width_)
1619 {
1620   return -compare_value_3way (a_, b_, width_);
1621 }
1622
1623
1624 /* Given an array of ENTRY_CNT table_entry structures starting at
1625    ENTRIES, creates a sorted list of the values that the variable
1626    with index VAR_IDX takes on.  Stores the array of the values in
1627    XT->values and the number of values in XT->n_values. */
1628 static void
1629 enum_var_values (const struct crosstabulation *xt, int var_idx,
1630                  bool descending)
1631 {
1632   struct xtab_var *xv = &xt->vars[var_idx];
1633   const struct var_range *range = get_var_range (xt->proc, xv->var);
1634
1635   if (range)
1636     {
1637       xv->values = xnmalloc (range->count, sizeof *xv->values);
1638       xv->n_values = range->count;
1639       for (size_t i = 0; i < range->count; i++)
1640         xv->values[i].f = range->min + i;
1641     }
1642   else
1643     {
1644       int width = var_get_width (xv->var);
1645       struct hmapx_node *node;
1646       const union value *iter;
1647       struct hmapx set;
1648
1649       hmapx_init (&set);
1650       for (size_t i = 0; i < xt->n_entries; i++)
1651         {
1652           const struct freq *te = xt->entries[i];
1653           const union value *value = &te->values[var_idx];
1654           size_t hash = value_hash (value, width, 0);
1655
1656           HMAPX_FOR_EACH_WITH_HASH (iter, node, hash, &set)
1657             if (value_equal (iter, value, width))
1658               goto next_entry;
1659
1660           hmapx_insert (&set, (union value *) value, hash);
1661
1662         next_entry: ;
1663         }
1664
1665       xv->n_values = hmapx_count (&set);
1666       xv->values = xnmalloc (xv->n_values, sizeof *xv->values);
1667       size_t i = 0;
1668       HMAPX_FOR_EACH (iter, node, &set)
1669         xv->values[i++] = *iter;
1670       hmapx_destroy (&set);
1671
1672       sort (xv->values, xv->n_values, sizeof *xv->values,
1673             descending ? compare_value_3way_inv : compare_value_3way,
1674             &width);
1675     }
1676 }
1677
1678 static void
1679 free_var_values (const struct crosstabulation *xt, int var_idx)
1680 {
1681   struct xtab_var *xv = &xt->vars[var_idx];
1682   free (xv->values);
1683   xv->values = NULL;
1684   xv->n_values = 0;
1685 }
1686
1687 /* Displays the crosstabulation table. */
1688 static void
1689 display_crosstabulation (struct crosstabs_proc *proc,
1690                          struct crosstabulation *xt, struct pivot_table *table,
1691                          size_t crs_leaves[CRS_N_CELLS])
1692 {
1693   size_t n_rows = xt->vars[ROW_VAR].n_values;
1694   size_t n_cols = xt->vars[COL_VAR].n_values;
1695
1696   size_t *indexes = xnmalloc (table->n_dimensions, sizeof *indexes);
1697   assert (xt->n_vars == 2);
1698   for (size_t i = 0; i < xt->n_consts; i++)
1699     indexes[i + 3] = xt->const_indexes[i];
1700
1701   /* Put in the actual cells. */
1702   double *mp = xt->mat;
1703   for (size_t r = 0; r < n_rows; r++)
1704     {
1705       if (!xt->row_tot[r] && proc->mode != INTEGER)
1706         continue;
1707
1708       indexes[ROW_VAR + 1] = r;
1709       for (size_t c = 0; c < n_cols; c++)
1710         {
1711           if (!xt->col_tot[c] && proc->mode != INTEGER)
1712             continue;
1713
1714           indexes[COL_VAR + 1] = c;
1715
1716           double expected_value = xt->row_tot[r] * xt->col_tot[c] / xt->total;
1717           double residual = *mp - expected_value;
1718           double sresidual = residual / sqrt (expected_value);
1719           double asresidual = (sresidual
1720                                * (1. - xt->row_tot[r] / xt->total)
1721                                * (1. - xt->col_tot[c] / xt->total));
1722           double entries[CRS_N_CELLS] = {
1723             [CRS_CL_COUNT] = *mp,
1724             [CRS_CL_ROW] = *mp / xt->row_tot[r] * 100.,
1725             [CRS_CL_COLUMN] = *mp / xt->col_tot[c] * 100.,
1726             [CRS_CL_TOTAL] = *mp / xt->total * 100.,
1727             [CRS_CL_EXPECTED] = expected_value,
1728             [CRS_CL_RESIDUAL] = residual,
1729             [CRS_CL_SRESIDUAL] = sresidual,
1730             [CRS_CL_ASRESIDUAL] = asresidual,
1731           };
1732           for (size_t i = 0; i < proc->n_cells; i++)
1733             {
1734               int cell = proc->a_cells[i];
1735               indexes[0] = crs_leaves[cell];
1736               pivot_table_put (table, indexes, table->n_dimensions,
1737                                pivot_value_new_number (entries[cell]));
1738             }
1739
1740           mp++;
1741         }
1742     }
1743
1744   /* Row totals. */
1745   for (size_t r = 0; r < n_rows; r++)
1746     {
1747       if (!xt->row_tot[r] && proc->mode != INTEGER)
1748         continue;
1749
1750       double expected_value = xt->row_tot[r] / xt->total;
1751       double entries[CRS_N_CELLS] = {
1752         [CRS_CL_COUNT] = xt->row_tot[r],
1753         [CRS_CL_ROW] = 100.0,
1754         [CRS_CL_COLUMN] = expected_value * 100.,
1755         [CRS_CL_TOTAL] = expected_value * 100.,
1756         [CRS_CL_EXPECTED] = expected_value,
1757         [CRS_CL_RESIDUAL] = SYSMIS,
1758         [CRS_CL_SRESIDUAL] = SYSMIS,
1759         [CRS_CL_ASRESIDUAL] = SYSMIS,
1760       };
1761       for (size_t i = 0; i < proc->n_cells; i++)
1762         {
1763           int cell = proc->a_cells[i];
1764           double entry = entries[cell];
1765           if (entry != SYSMIS)
1766             {
1767               indexes[ROW_VAR + 1] = r;
1768               indexes[COL_VAR + 1] = n_cols;
1769               indexes[0] = crs_leaves[cell];
1770               pivot_table_put (table, indexes, table->n_dimensions,
1771                                pivot_value_new_number (entry));
1772             }
1773         }
1774     }
1775
1776   for (size_t c = 0; c <= n_cols; c++)
1777     {
1778       if (c < n_cols && !xt->col_tot[c] && proc->mode != INTEGER)
1779         continue;
1780
1781       double ct = c < n_cols ? xt->col_tot[c] : xt->total;
1782       double expected_value = ct / xt->total;
1783       double entries[CRS_N_CELLS] = {
1784         [CRS_CL_COUNT] = ct,
1785         [CRS_CL_ROW] = expected_value * 100.0,
1786         [CRS_CL_COLUMN] = 100.0,
1787         [CRS_CL_TOTAL] = expected_value * 100.,
1788         [CRS_CL_EXPECTED] = expected_value,
1789         [CRS_CL_RESIDUAL] = SYSMIS,
1790         [CRS_CL_SRESIDUAL] = SYSMIS,
1791         [CRS_CL_ASRESIDUAL] = SYSMIS,
1792       };
1793       for (size_t i = 0; i < proc->n_cells; i++)
1794         {
1795           int cell = proc->a_cells[i];
1796           double entry = entries[cell];
1797           if (entry != SYSMIS)
1798             {
1799               indexes[ROW_VAR + 1] = n_rows;
1800               indexes[COL_VAR + 1] = c;
1801               indexes[0] = crs_leaves[cell];
1802               pivot_table_put (table, indexes, table->n_dimensions,
1803                                pivot_value_new_number (entry));
1804             }
1805         }
1806     }
1807
1808   free (indexes);
1809 }
1810
1811 static void calc_r (struct crosstabulation *,
1812                     double *XT, double *Y, double *, double *, double *);
1813 static void calc_chisq (struct crosstabulation *,
1814                         double[N_CHISQ], int[N_CHISQ], double *, double *);
1815
1816 /* Display chi-square statistics. */
1817 static void
1818 display_chisq (struct crosstabulation *xt, struct pivot_table *chisq)
1819 {
1820   double chisq_v[N_CHISQ];
1821   double fisher1, fisher2;
1822   int df[N_CHISQ];
1823   calc_chisq (xt, chisq_v, df, &fisher1, &fisher2);
1824
1825   size_t *indexes = xnmalloc (chisq->n_dimensions, sizeof *indexes);
1826   assert (xt->n_vars == 2);
1827   for (size_t i = 0; i < xt->n_consts; i++)
1828     indexes[i + 2] = xt->const_indexes[i];
1829   for (int i = 0; i < N_CHISQ; i++)
1830     {
1831       indexes[0] = i;
1832
1833       double entries[5] = { SYSMIS, SYSMIS, SYSMIS, SYSMIS, SYSMIS };
1834       if (i == 2)
1835         {
1836           entries[3] = fisher2;
1837           entries[4] = fisher1;
1838         }
1839       else if (chisq_v[i] != SYSMIS)
1840         {
1841           entries[0] = chisq_v[i];
1842           entries[1] = df[i];
1843           entries[2] = gsl_cdf_chisq_Q (chisq_v[i], df[i]);
1844         }
1845
1846       for (size_t j = 0; j < sizeof entries / sizeof *entries; j++)
1847         if (entries[j] != SYSMIS)
1848           {
1849             indexes[1] = j;
1850             pivot_table_put (chisq, indexes, chisq->n_dimensions,
1851                              pivot_value_new_number (entries[j]));
1852         }
1853     }
1854
1855   indexes[0] = 5;
1856   indexes[1] = 0;
1857   pivot_table_put (chisq, indexes, chisq->n_dimensions,
1858                    pivot_value_new_number (xt->total));
1859
1860   free (indexes);
1861 }
1862
1863 static int calc_symmetric (struct crosstabs_proc *, struct crosstabulation *,
1864                            double[N_SYMMETRIC], double[N_SYMMETRIC],
1865                            double[N_SYMMETRIC],
1866                            double[3], double[3], double[3]);
1867
1868 /* Display symmetric measures. */
1869 static void
1870 display_symmetric (struct crosstabs_proc *proc, struct crosstabulation *xt,
1871                    struct pivot_table *sym)
1872 {
1873   double sym_v[N_SYMMETRIC], sym_ase[N_SYMMETRIC], sym_t[N_SYMMETRIC];
1874   double somers_d_v[3], somers_d_ase[3], somers_d_t[3];
1875
1876   if (!calc_symmetric (proc, xt, sym_v, sym_ase, sym_t,
1877                        somers_d_v, somers_d_ase, somers_d_t))
1878     return;
1879
1880   size_t *indexes = xnmalloc (sym->n_dimensions, sizeof *indexes);
1881   assert (xt->n_vars == 2);
1882   for (size_t i = 0; i < xt->n_consts; i++)
1883     indexes[i + 2] = xt->const_indexes[i];
1884
1885   for (int i = 0; i < N_SYMMETRIC; i++)
1886     {
1887       if (sym_v[i] == SYSMIS)
1888         continue;
1889
1890       indexes[1] = i;
1891
1892       double entries[] = { sym_v[i], sym_ase[i], sym_t[i] };
1893       for (size_t j = 0; j < sizeof entries / sizeof *entries; j++)
1894         if (entries[j] != SYSMIS)
1895           {
1896             indexes[0] = j;
1897             pivot_table_put (sym, indexes, sym->n_dimensions,
1898                              pivot_value_new_number (entries[j]));
1899           }
1900     }
1901
1902   indexes[1] = N_SYMMETRIC;
1903   indexes[0] = 0;
1904   struct pivot_value *total = pivot_value_new_number (xt->total);
1905   pivot_value_set_rc (sym, total, PIVOT_RC_COUNT);
1906   pivot_table_put (sym, indexes, sym->n_dimensions, total);
1907
1908   free (indexes);
1909 }
1910
1911 static bool calc_risk (struct crosstabulation *,
1912                        double[], double[], double[], union value *,
1913                        double *);
1914
1915 /* Display risk estimate. */
1916 static void
1917 display_risk (struct crosstabulation *xt, struct pivot_table *risk,
1918               struct pivot_dimension *risk_statistics)
1919 {
1920   double risk_v[3], lower[3], upper[3], n_valid;
1921   union value c[2];
1922   if (!calc_risk (xt, risk_v, upper, lower, c, &n_valid))
1923     return;
1924
1925   size_t *indexes = xnmalloc (risk->n_dimensions, sizeof *indexes);
1926   assert (xt->n_vars == 2);
1927   for (size_t i = 0; i < xt->n_consts; i++)
1928     indexes[i + 2] = xt->const_indexes[i];
1929
1930   for (int i = 0; i < 3; i++)
1931     {
1932       const struct variable *cv = xt->vars[COL_VAR].var;
1933       const struct variable *rv = xt->vars[ROW_VAR].var;
1934
1935       if (risk_v[i] == SYSMIS)
1936         continue;
1937
1938       struct string label = DS_EMPTY_INITIALIZER;
1939       switch (i)
1940         {
1941         case 0:
1942           ds_put_format (&label, _("Odds Ratio for %s"), var_to_string (rv));
1943           ds_put_cstr (&label, " (");
1944           var_append_value_name (rv, &c[0], &label);
1945           ds_put_cstr (&label, " / ");
1946           var_append_value_name (rv, &c[1], &label);
1947           ds_put_cstr (&label, ")");
1948           break;
1949         case 1:
1950         case 2:
1951           ds_put_format (&label, _("For cohort %s = "), var_to_string (cv));
1952           var_append_value_name (cv, &xt->vars[ROW_VAR].values[i - 1], &label);
1953           break;
1954         }
1955
1956       indexes[1] = pivot_category_create_leaf (
1957         risk_statistics->root,
1958         pivot_value_new_user_text_nocopy (ds_steal_cstr (&label)));
1959
1960       double entries[] = { risk_v[i], lower[i], upper[i] };
1961       for (size_t j = 0; j < sizeof entries / sizeof *entries; j++)
1962         {
1963           indexes[0] = j;
1964           pivot_table_put (risk, indexes, risk->n_dimensions,
1965                            pivot_value_new_number (entries[i]));
1966         }
1967     }
1968   indexes[1] = pivot_category_create_leaf (
1969     risk_statistics->root,
1970     pivot_value_new_text (N_("N of Valid Cases")));
1971   indexes[0] = 0;
1972   pivot_table_put (risk, indexes, risk->n_dimensions,
1973                    pivot_value_new_number (n_valid));
1974   free (indexes);
1975 }
1976
1977 static int calc_directional (struct crosstabs_proc *, struct crosstabulation *,
1978                              double[N_DIRECTIONAL], double[N_DIRECTIONAL],
1979                              double[N_DIRECTIONAL], double[N_DIRECTIONAL]);
1980
1981 /* Display directional measures. */
1982 static void
1983 display_directional (struct crosstabs_proc *proc,
1984                      struct crosstabulation *xt, struct pivot_table *direct)
1985 {
1986   double direct_v[N_DIRECTIONAL];
1987   double direct_ase[N_DIRECTIONAL];
1988   double direct_t[N_DIRECTIONAL];
1989   double sig[N_DIRECTIONAL];
1990   if (!calc_directional (proc, xt, direct_v, direct_ase, direct_t, sig))
1991     return;
1992
1993   size_t *indexes = xnmalloc (direct->n_dimensions, sizeof *indexes);
1994   assert (xt->n_vars == 2);
1995   for (size_t i = 0; i < xt->n_consts; i++)
1996     indexes[i + 2] = xt->const_indexes[i];
1997
1998   for (int i = 0; i < N_DIRECTIONAL; i++)
1999     {
2000       if (direct_v[i] == SYSMIS)
2001         continue;
2002
2003       indexes[1] = i;
2004
2005       double entries[] = {
2006         direct_v[i], direct_ase[i], direct_t[i], sig[i],
2007       };
2008       for (size_t j = 0; j < sizeof entries / sizeof *entries; j++)
2009         if (entries[j] != SYSMIS)
2010           {
2011             indexes[0] = j;
2012             pivot_table_put (direct, indexes, direct->n_dimensions,
2013                              pivot_value_new_number (entries[j]));
2014           }
2015     }
2016
2017   free (indexes);
2018 }
2019 \f
2020 /* Statistical calculations. */
2021
2022 /* Returns the value of the logarithm of gamma (factorial) function for an integer
2023    argument XT. */
2024 static double
2025 log_gamma_int (double xt)
2026 {
2027   double r = 0;
2028   int i;
2029
2030   for (i = 2; i < xt; i++)
2031     r += log(i);
2032
2033   return r;
2034 }
2035
2036 /* Calculate P_r as specified in _SPSS Statistical Algorithms_,
2037    Appendix 5. */
2038 static inline double
2039 Pr (int a, int b, int c, int d)
2040 {
2041   return exp (log_gamma_int (a + b + 1.) -  log_gamma_int (a + 1.)
2042             + log_gamma_int (c + d + 1.) - log_gamma_int (b + 1.)
2043             + log_gamma_int (a + c + 1.) - log_gamma_int (c + 1.)
2044             + log_gamma_int (b + d + 1.) - log_gamma_int (d + 1.)
2045             - log_gamma_int (a + b + c + d + 1.));
2046 }
2047
2048 /* Swap the contents of A and B. */
2049 static inline void
2050 swap (int *a, int *b)
2051 {
2052   int t = *a;
2053   *a = *b;
2054   *b = t;
2055 }
2056
2057 /* Calculate significance for Fisher's exact test as specified in
2058    _SPSS Statistical Algorithms_, Appendix 5. */
2059 static void
2060 calc_fisher (int a, int b, int c, int d, double *fisher1, double *fisher2)
2061 {
2062   int xt;
2063   double pn1;
2064
2065   if (MIN (c, d) < MIN (a, b))
2066     swap (&a, &c), swap (&b, &d);
2067   if (MIN (b, d) < MIN (a, c))
2068     swap (&a, &b), swap (&c, &d);
2069   if (b * c < a * d)
2070     {
2071       if (b < c)
2072         swap (&a, &b), swap (&c, &d);
2073       else
2074         swap (&a, &c), swap (&b, &d);
2075     }
2076
2077   pn1 = Pr (a, b, c, d);
2078   *fisher1 = pn1;
2079   for (xt = 1; xt <= a; xt++)
2080     {
2081       *fisher1 += Pr (a - xt, b + xt, c + xt, d - xt);
2082     }
2083
2084   *fisher2 = *fisher1;
2085
2086   for (xt = 1; xt <= b; xt++)
2087     {
2088       double p = Pr (a + xt, b - xt, c - xt, d + xt);
2089       if (p < pn1)
2090         *fisher2 += p;
2091     }
2092 }
2093
2094 /* Calculates chi-squares into CHISQ.  MAT is a matrix with N_COLS
2095    columns with values COLS and N_ROWS rows with values ROWS.  Values
2096    in the matrix sum to xt->total. */
2097 static void
2098 calc_chisq (struct crosstabulation *xt,
2099             double chisq[N_CHISQ], int df[N_CHISQ],
2100             double *fisher1, double *fisher2)
2101 {
2102   chisq[0] = chisq[1] = 0.;
2103   chisq[2] = chisq[3] = chisq[4] = SYSMIS;
2104   *fisher1 = *fisher2 = SYSMIS;
2105
2106   df[0] = df[1] = (xt->ns_cols - 1) * (xt->ns_rows - 1);
2107
2108   if (xt->ns_rows <= 1 || xt->ns_cols <= 1)
2109     {
2110       chisq[0] = chisq[1] = SYSMIS;
2111       return;
2112     }
2113
2114   size_t n_cols = xt->vars[COL_VAR].n_values;
2115   FOR_EACH_POPULATED_ROW (r, xt)
2116     FOR_EACH_POPULATED_COLUMN (c, xt)
2117       {
2118         const double expected = xt->row_tot[r] * xt->col_tot[c] / xt->total;
2119         const double freq = xt->mat[n_cols * r + c];
2120         const double residual = freq - expected;
2121
2122         chisq[0] += residual * residual / expected;
2123         if (freq)
2124           chisq[1] += freq * log (expected / freq);
2125       }
2126
2127   if (chisq[0] == 0.)
2128     chisq[0] = SYSMIS;
2129
2130   if (chisq[1] != 0.)
2131     chisq[1] *= -2.;
2132   else
2133     chisq[1] = SYSMIS;
2134
2135   /* Calculate Yates and Fisher exact test. */
2136   if (xt->ns_cols == 2 && xt->ns_rows == 2)
2137     {
2138       double f11, f12, f21, f22;
2139
2140       {
2141         int nz_cols[2];
2142
2143         int j = 0;
2144         FOR_EACH_POPULATED_COLUMN (c, xt)
2145           {
2146             nz_cols[j++] = c;
2147             if (j == 2)
2148               break;
2149           }
2150         assert (j == 2);
2151
2152         f11 = xt->mat[nz_cols[0]];
2153         f12 = xt->mat[nz_cols[1]];
2154         f21 = xt->mat[nz_cols[0] + n_cols];
2155         f22 = xt->mat[nz_cols[1] + n_cols];
2156       }
2157
2158       /* Yates. */
2159       {
2160         const double xt_ = fabs (f11 * f22 - f12 * f21) - 0.5 * xt->total;
2161
2162         if (xt_ > 0.)
2163           chisq[3] = (xt->total * pow2 (xt_)
2164                       / (f11 + f12) / (f21 + f22)
2165                       / (f11 + f21) / (f12 + f22));
2166         else
2167           chisq[3] = 0.;
2168
2169         df[3] = 1.;
2170       }
2171
2172       /* Fisher. */
2173       calc_fisher (f11 + .5, f12 + .5, f21 + .5, f22 + .5, fisher1, fisher2);
2174     }
2175
2176   /* Calculate Mantel-Haenszel. */
2177   if (var_is_numeric (xt->vars[ROW_VAR].var)
2178       && var_is_numeric (xt->vars[COL_VAR].var))
2179     {
2180       double r, ase_0, ase_1;
2181       calc_r (xt, (double *) xt->vars[ROW_VAR].values,
2182               (double *) xt->vars[COL_VAR].values,
2183               &r, &ase_0, &ase_1);
2184
2185       chisq[4] = (xt->total - 1.) * r * r;
2186       df[4] = 1;
2187     }
2188 }
2189
2190 /* Calculate the value of Pearson's r.  r is stored into R, its T value into
2191    T, and standard error into ERROR.  The row and column values must be
2192    passed in XT and Y. */
2193 static void
2194 calc_r (struct crosstabulation *xt,
2195         double *XT, double *Y, double *r, double *t, double *error)
2196 {
2197   size_t n_rows = xt->vars[ROW_VAR].n_values;
2198   size_t n_cols = xt->vars[COL_VAR].n_values;
2199   double SX, SY, S, T;
2200   double Xbar, Ybar;
2201   double sum_XYf, sum_X2Y2f;
2202   double sum_Xr, sum_X2r;
2203   double sum_Yc, sum_Y2c;
2204   int i, j;
2205
2206   for (sum_X2Y2f = sum_XYf = 0., i = 0; i < n_rows; i++)
2207     for (j = 0; j < n_cols; j++)
2208       {
2209         double fij = xt->mat[j + i * n_cols];
2210         double product = XT[i] * Y[j];
2211         double temp = fij * product;
2212         sum_XYf += temp;
2213         sum_X2Y2f += temp * product;
2214       }
2215
2216   for (sum_Xr = sum_X2r = 0., i = 0; i < n_rows; i++)
2217     {
2218       sum_Xr += XT[i] * xt->row_tot[i];
2219       sum_X2r += pow2 (XT[i]) * xt->row_tot[i];
2220     }
2221   Xbar = sum_Xr / xt->total;
2222
2223   for (sum_Yc = sum_Y2c = 0., i = 0; i < n_cols; i++)
2224     {
2225       sum_Yc += Y[i] * xt->col_tot[i];
2226       sum_Y2c += Y[i] * Y[i] * xt->col_tot[i];
2227     }
2228   Ybar = sum_Yc / xt->total;
2229
2230   S = sum_XYf - sum_Xr * sum_Yc / xt->total;
2231   SX = sum_X2r - pow2 (sum_Xr) / xt->total;
2232   SY = sum_Y2c - pow2 (sum_Yc) / xt->total;
2233   T = sqrt (SX * SY);
2234   *r = S / T;
2235   *t = *r / sqrt (1 - pow2 (*r)) * sqrt (xt->total - 2);
2236
2237   {
2238     double s, c, y, t;
2239
2240     for (s = c = 0., i = 0; i < n_rows; i++)
2241       for (j = 0; j < n_cols; j++)
2242         {
2243           double Xresid, Yresid;
2244           double temp;
2245
2246           Xresid = XT[i] - Xbar;
2247           Yresid = Y[j] - Ybar;
2248           temp = (T * Xresid * Yresid
2249                   - ((S / (2. * T))
2250                      * (Xresid * Xresid * SY + Yresid * Yresid * SX)));
2251           y = xt->mat[j + i * n_cols] * temp * temp - c;
2252           t = s + y;
2253           c = (t - s) - y;
2254           s = t;
2255         }
2256     *error = sqrt (s) / (T * T);
2257   }
2258 }
2259
2260 /* Calculate symmetric statistics and their asymptotic standard
2261    errors.  Returns 0 if none could be calculated. */
2262 static int
2263 calc_symmetric (struct crosstabs_proc *proc, struct crosstabulation *xt,
2264                 double v[N_SYMMETRIC], double ase[N_SYMMETRIC],
2265                 double t[N_SYMMETRIC],
2266                 double somers_d_v[3], double somers_d_ase[3],
2267                 double somers_d_t[3])
2268 {
2269   size_t n_rows = xt->vars[ROW_VAR].n_values;
2270   size_t n_cols = xt->vars[COL_VAR].n_values;
2271   int q, i;
2272
2273   q = MIN (xt->ns_rows, xt->ns_cols);
2274   if (q <= 1)
2275     return 0;
2276
2277   for (i = 0; i < N_SYMMETRIC; i++)
2278     v[i] = ase[i] = t[i] = SYSMIS;
2279
2280   /* Phi, Cramer's V, contingency coefficient. */
2281   if (proc->statistics & (CRS_ST_PHI | CRS_ST_CC))
2282     {
2283       double Xp = 0.;   /* Pearson chi-square. */
2284
2285       FOR_EACH_POPULATED_ROW (r, xt)
2286         FOR_EACH_POPULATED_COLUMN (c, xt)
2287           {
2288             double expected = xt->row_tot[r] * xt->col_tot[c] / xt->total;
2289             double freq = xt->mat[n_cols * r + c];
2290             double residual = freq - expected;
2291
2292             Xp += residual * residual / expected;
2293           }
2294
2295       if (proc->statistics & CRS_ST_PHI)
2296         {
2297           v[0] = sqrt (Xp / xt->total);
2298           v[1] = sqrt (Xp / (xt->total * (q - 1)));
2299         }
2300       if (proc->statistics & CRS_ST_CC)
2301         v[2] = sqrt (Xp / (Xp + xt->total));
2302     }
2303
2304   if (proc->statistics & (CRS_ST_BTAU | CRS_ST_CTAU
2305                           | CRS_ST_GAMMA | CRS_ST_D))
2306     {
2307       double *cum;
2308       double Dr, Dc;
2309       double P, Q;
2310       double btau_cum, ctau_cum, gamma_cum, d_yx_cum, d_xy_cum;
2311       double btau_var;
2312       int r, c;
2313
2314       Dr = Dc = pow2 (xt->total);
2315       for (r = 0; r < n_rows; r++)
2316         Dr -= pow2 (xt->row_tot[r]);
2317       for (c = 0; c < n_cols; c++)
2318         Dc -= pow2 (xt->col_tot[c]);
2319
2320       cum = xnmalloc (n_cols * n_rows, sizeof *cum);
2321       for (c = 0; c < n_cols; c++)
2322         {
2323           double ct = 0.;
2324
2325           for (r = 0; r < n_rows; r++)
2326             cum[c + r * n_cols] = ct += xt->mat[c + r * n_cols];
2327         }
2328
2329       /* P and Q. */
2330       {
2331         int i, j;
2332         double Cij, Dij;
2333
2334         P = Q = 0.;
2335         for (i = 0; i < n_rows; i++)
2336           {
2337             Cij = Dij = 0.;
2338
2339             for (j = 1; j < n_cols; j++)
2340               Cij += xt->col_tot[j] - cum[j + i * n_cols];
2341
2342             if (i > 0)
2343               for (j = 1; j < n_cols; j++)
2344                 Dij += cum[j + (i - 1) * n_cols];
2345
2346             for (j = 0;;)
2347               {
2348                 double fij = xt->mat[j + i * n_cols];
2349                 P += fij * Cij;
2350                 Q += fij * Dij;
2351
2352                 if (++j == n_cols)
2353                   break;
2354                 assert (j < n_cols);
2355
2356                 Cij -= xt->col_tot[j] - cum[j + i * n_cols];
2357                 Dij += xt->col_tot[j - 1] - cum[j - 1 + i * n_cols];
2358
2359                 if (i > 0)
2360                   {
2361                     Cij += cum[j - 1 + (i - 1) * n_cols];
2362                     Dij -= cum[j + (i - 1) * n_cols];
2363                   }
2364               }
2365           }
2366       }
2367
2368       if (proc->statistics & CRS_ST_BTAU)
2369         v[3] = (P - Q) / sqrt (Dr * Dc);
2370       if (proc->statistics & CRS_ST_CTAU)
2371         v[4] = (q * (P - Q)) / (pow2 (xt->total) * (q - 1));
2372       if (proc->statistics & CRS_ST_GAMMA)
2373         v[5] = (P - Q) / (P + Q);
2374
2375       /* ASE for tau-b, tau-c, gamma.  Calculations could be
2376          eliminated here, at expense of memory.  */
2377       {
2378         int i, j;
2379         double Cij, Dij;
2380
2381         btau_cum = ctau_cum = gamma_cum = d_yx_cum = d_xy_cum = 0.;
2382         for (i = 0; i < n_rows; i++)
2383           {
2384             Cij = Dij = 0.;
2385
2386             for (j = 1; j < n_cols; j++)
2387               Cij += xt->col_tot[j] - cum[j + i * n_cols];
2388
2389             if (i > 0)
2390               for (j = 1; j < n_cols; j++)
2391                 Dij += cum[j + (i - 1) * n_cols];
2392
2393             for (j = 0;;)
2394               {
2395                 double fij = xt->mat[j + i * n_cols];
2396
2397                 if (proc->statistics & CRS_ST_BTAU)
2398                   {
2399                     const double temp = (2. * sqrt (Dr * Dc) * (Cij - Dij)
2400                                          + v[3] * (xt->row_tot[i] * Dc
2401                                                    + xt->col_tot[j] * Dr));
2402                     btau_cum += fij * temp * temp;
2403                   }
2404
2405                 {
2406                   const double temp = Cij - Dij;
2407                   ctau_cum += fij * temp * temp;
2408                 }
2409
2410                 if (proc->statistics & CRS_ST_GAMMA)
2411                   {
2412                     const double temp = Q * Cij - P * Dij;
2413                     gamma_cum += fij * temp * temp;
2414                   }
2415
2416                 if (proc->statistics & CRS_ST_D)
2417                   {
2418                     d_yx_cum += fij * pow2 (Dr * (Cij - Dij)
2419                                             - (P - Q) * (xt->total - xt->row_tot[i]));
2420                     d_xy_cum += fij * pow2 (Dc * (Dij - Cij)
2421                                             - (Q - P) * (xt->total - xt->col_tot[j]));
2422                   }
2423
2424                 if (++j == n_cols)
2425                   break;
2426                 assert (j < n_cols);
2427
2428                 Cij -= xt->col_tot[j] - cum[j + i * n_cols];
2429                 Dij += xt->col_tot[j - 1] - cum[j - 1 + i * n_cols];
2430
2431                 if (i > 0)
2432                   {
2433                     Cij += cum[j - 1 + (i - 1) * n_cols];
2434                     Dij -= cum[j + (i - 1) * n_cols];
2435                   }
2436               }
2437           }
2438       }
2439
2440       btau_var = ((btau_cum
2441                    - (xt->total * pow2 (xt->total * (P - Q) / sqrt (Dr * Dc) * (Dr + Dc))))
2442                   / pow2 (Dr * Dc));
2443       if (proc->statistics & CRS_ST_BTAU)
2444         {
2445           ase[3] = sqrt (btau_var);
2446           t[3] = v[3] / (2 * sqrt ((ctau_cum - (P - Q) * (P - Q) / xt->total)
2447                                    / (Dr * Dc)));
2448         }
2449       if (proc->statistics & CRS_ST_CTAU)
2450         {
2451           ase[4] = ((2 * q / ((q - 1) * pow2 (xt->total)))
2452                     * sqrt (ctau_cum - (P - Q) * (P - Q) / xt->total));
2453           t[4] = v[4] / ase[4];
2454         }
2455       if (proc->statistics & CRS_ST_GAMMA)
2456         {
2457           ase[5] = ((4. / ((P + Q) * (P + Q))) * sqrt (gamma_cum));
2458           t[5] = v[5] / (2. / (P + Q)
2459                          * sqrt (ctau_cum - (P - Q) * (P - Q) / xt->total));
2460         }
2461       if (proc->statistics & CRS_ST_D)
2462         {
2463           somers_d_v[0] = (P - Q) / (.5 * (Dc + Dr));
2464           somers_d_ase[0] = SYSMIS;
2465           somers_d_t[0] = (somers_d_v[0]
2466                            / (4 / (Dc + Dr)
2467                               * sqrt (ctau_cum - pow2 (P - Q) / xt->total)));
2468           somers_d_v[1] = (P - Q) / Dc;
2469           somers_d_ase[1] = 2. / pow2 (Dc) * sqrt (d_xy_cum);
2470           somers_d_t[1] = (somers_d_v[1]
2471                            / (2. / Dc
2472                               * sqrt (ctau_cum - pow2 (P - Q) / xt->total)));
2473           somers_d_v[2] = (P - Q) / Dr;
2474           somers_d_ase[2] = 2. / pow2 (Dr) * sqrt (d_yx_cum);
2475           somers_d_t[2] = (somers_d_v[2]
2476                            / (2. / Dr
2477                               * sqrt (ctau_cum - pow2 (P - Q) / xt->total)));
2478         }
2479
2480       free (cum);
2481     }
2482
2483   /* Spearman correlation, Pearson's r. */
2484   if (proc->statistics & CRS_ST_CORR)
2485     {
2486       double *R = xmalloc (sizeof *R * n_rows);
2487       double *C = xmalloc (sizeof *C * n_cols);
2488
2489       {
2490         double y, t, c = 0., s = 0.;
2491         int i = 0;
2492
2493         for (;;)
2494           {
2495             R[i] = s + (xt->row_tot[i] + 1.) / 2.;
2496             y = xt->row_tot[i] - c;
2497             t = s + y;
2498             c = (t - s) - y;
2499             s = t;
2500             if (++i == n_rows)
2501               break;
2502             assert (i < n_rows);
2503           }
2504       }
2505
2506       {
2507         double y, t, c = 0., s = 0.;
2508         int j = 0;
2509
2510         for (;;)
2511           {
2512             C[j] = s + (xt->col_tot[j] + 1.) / 2;
2513             y = xt->col_tot[j] - c;
2514             t = s + y;
2515             c = (t - s) - y;
2516             s = t;
2517             if (++j == n_cols)
2518               break;
2519             assert (j < n_cols);
2520           }
2521       }
2522
2523       calc_r (xt, R, C, &v[6], &t[6], &ase[6]);
2524
2525       free (R);
2526       free (C);
2527
2528       calc_r (xt, (double *) xt->vars[ROW_VAR].values,
2529               (double *) xt->vars[COL_VAR].values,
2530               &v[7], &t[7], &ase[7]);
2531     }
2532
2533   /* Cohen's kappa. */
2534   if (proc->statistics & CRS_ST_KAPPA && xt->ns_rows == xt->ns_cols)
2535     {
2536       double ase_under_h0;
2537       double sum_fii, sum_rici, sum_fiiri_ci, sum_fijri_ci2, sum_riciri_ci;
2538       int i, j;
2539
2540       for (sum_fii = sum_rici = sum_fiiri_ci = sum_riciri_ci = 0., i = j = 0;
2541            i < xt->ns_rows; i++, j++)
2542         {
2543           double prod, sum;
2544
2545           while (xt->col_tot[j] == 0.)
2546             j++;
2547
2548           prod = xt->row_tot[i] * xt->col_tot[j];
2549           sum = xt->row_tot[i] + xt->col_tot[j];
2550
2551           sum_fii += xt->mat[j + i * n_cols];
2552           sum_rici += prod;
2553           sum_fiiri_ci += xt->mat[j + i * n_cols] * sum;
2554           sum_riciri_ci += prod * sum;
2555         }
2556       for (sum_fijri_ci2 = 0., i = 0; i < xt->ns_rows; i++)
2557         for (j = 0; j < xt->ns_cols; j++)
2558           {
2559             double sum = xt->row_tot[i] + xt->col_tot[j];
2560             sum_fijri_ci2 += xt->mat[j + i * n_cols] * sum * sum;
2561           }
2562
2563       v[8] = (xt->total * sum_fii - sum_rici) / (pow2 (xt->total) - sum_rici);
2564
2565       ase_under_h0 = sqrt ((pow2 (xt->total) * sum_rici
2566                             + sum_rici * sum_rici
2567                             - xt->total * sum_riciri_ci)
2568                            / (xt->total * (pow2 (xt->total) - sum_rici) * (pow2 (xt->total) - sum_rici)));
2569
2570       ase[8] = sqrt (xt->total * (((sum_fii * (xt->total - sum_fii))
2571                                 / pow2 (pow2 (xt->total) - sum_rici))
2572                                + ((2. * (xt->total - sum_fii)
2573                                    * (2. * sum_fii * sum_rici
2574                                       - xt->total * sum_fiiri_ci))
2575                                   / pow3 (pow2 (xt->total) - sum_rici))
2576                                + (pow2 (xt->total - sum_fii)
2577                                   * (xt->total * sum_fijri_ci2 - 4.
2578                                      * sum_rici * sum_rici)
2579                                   / pow4 (pow2 (xt->total) - sum_rici))));
2580
2581       t[8] = v[8] / ase_under_h0;
2582     }
2583
2584   return 1;
2585 }
2586
2587 /* Calculate risk estimate. */
2588 static bool
2589 calc_risk (struct crosstabulation *xt,
2590            double *value, double *upper, double *lower, union value *c,
2591            double *n_valid)
2592 {
2593   size_t n_cols = xt->vars[COL_VAR].n_values;
2594   double f11, f12, f21, f22;
2595   double v;
2596
2597   for (int i = 0; i < 3; i++)
2598     value[i] = upper[i] = lower[i] = SYSMIS;
2599
2600   if (xt->ns_rows != 2 || xt->ns_cols != 2)
2601     return false;
2602
2603   {
2604     /* Find populated columns. */
2605     int nz_cols[2];
2606     int n = 0;
2607     FOR_EACH_POPULATED_COLUMN (c, xt)
2608       nz_cols[n++] = c;
2609     assert (n == 2);
2610
2611     /* Find populated rows. */
2612     int nz_rows[2];
2613     n = 0;
2614     FOR_EACH_POPULATED_ROW (r, xt)
2615       nz_rows[n++] = r;
2616     assert (n == 2);
2617
2618     f11 = xt->mat[nz_cols[0] + n_cols * nz_rows[0]];
2619     f12 = xt->mat[nz_cols[1] + n_cols * nz_rows[0]];
2620     f21 = xt->mat[nz_cols[0] + n_cols * nz_rows[1]];
2621     f22 = xt->mat[nz_cols[1] + n_cols * nz_rows[1]];
2622     *n_valid = f11 + f12 + f21 + f22;
2623
2624     c[0] = xt->vars[COL_VAR].values[nz_cols[0]];
2625     c[1] = xt->vars[COL_VAR].values[nz_cols[1]];
2626   }
2627
2628   value[0] = (f11 * f22) / (f12 * f21);
2629   v = sqrt (1. / f11 + 1. / f12 + 1. / f21 + 1. / f22);
2630   lower[0] = value[0] * exp (-1.960 * v);
2631   upper[0] = value[0] * exp (1.960 * v);
2632
2633   value[1] = (f11 * (f21 + f22)) / (f21 * (f11 + f12));
2634   v = sqrt ((f12 / (f11 * (f11 + f12)))
2635             + (f22 / (f21 * (f21 + f22))));
2636   lower[1] = value[1] * exp (-1.960 * v);
2637   upper[1] = value[1] * exp (1.960 * v);
2638
2639   value[2] = (f12 * (f21 + f22)) / (f22 * (f11 + f12));
2640   v = sqrt ((f11 / (f12 * (f11 + f12)))
2641             + (f21 / (f22 * (f21 + f22))));
2642   lower[2] = value[2] * exp (-1.960 * v);
2643   upper[2] = value[2] * exp (1.960 * v);
2644
2645   return true;
2646 }
2647
2648 /* Calculate directional measures. */
2649 static int
2650 calc_directional (struct crosstabs_proc *proc, struct crosstabulation *xt,
2651                   double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL],
2652                   double t[N_DIRECTIONAL], double sig[N_DIRECTIONAL])
2653 {
2654   size_t n_rows = xt->vars[ROW_VAR].n_values;
2655   size_t n_cols = xt->vars[COL_VAR].n_values;
2656   for (int i = 0; i < N_DIRECTIONAL; i++)
2657     v[i] = ase[i] = t[i] = sig[i] = SYSMIS;
2658
2659   /* Lambda. */
2660   if (proc->statistics & CRS_ST_LAMBDA)
2661     {
2662       /* Find maximum for each row and their sum. */
2663       double *fim = xnmalloc (n_rows, sizeof *fim);
2664       int *fim_index = xnmalloc (n_rows, sizeof *fim_index);
2665       double sum_fim = 0.0;
2666       for (int i = 0; i < n_rows; i++)
2667         {
2668           double max = xt->mat[i * n_cols];
2669           int index = 0;
2670
2671           for (int j = 1; j < n_cols; j++)
2672             if (xt->mat[j + i * n_cols] > max)
2673               {
2674                 max = xt->mat[j + i * n_cols];
2675                 index = j;
2676               }
2677
2678           fim[i] = max;
2679           sum_fim += max;
2680           fim_index[i] = index;
2681         }
2682
2683       /* Find maximum for each column. */
2684       double *fmj = xnmalloc (n_cols, sizeof *fmj);
2685       int *fmj_index = xnmalloc (n_cols, sizeof *fmj_index);
2686       double sum_fmj = 0.0;
2687       for (int j = 0; j < n_cols; j++)
2688         {
2689           double max = xt->mat[j];
2690           int index = 0;
2691
2692           for (int i = 1; i < n_rows; i++)
2693             if (xt->mat[j + i * n_cols] > max)
2694               {
2695                 max = xt->mat[j + i * n_cols];
2696                 index = i;
2697               }
2698
2699           fmj[j] = max;
2700           sum_fmj += max;
2701           fmj_index[j] = index;
2702         }
2703
2704       /* Find maximum row total. */
2705       double rm = xt->row_tot[0];
2706       int rm_index = 0;
2707       for (int i = 1; i < n_rows; i++)
2708         if (xt->row_tot[i] > rm)
2709           {
2710             rm = xt->row_tot[i];
2711             rm_index = i;
2712           }
2713
2714       /* Find maximum column total. */
2715       double cm = xt->col_tot[0];
2716       int cm_index = 0;
2717       for (int j = 1; j < n_cols; j++)
2718         if (xt->col_tot[j] > cm)
2719           {
2720             cm = xt->col_tot[j];
2721             cm_index = j;
2722           }
2723
2724       v[0] = (sum_fim + sum_fmj - cm - rm) / (2. * xt->total - rm - cm);
2725       v[1] = (sum_fmj - rm) / (xt->total - rm);
2726       v[2] = (sum_fim - cm) / (xt->total - cm);
2727
2728       /* ASE1 for Y given XT. */
2729       {
2730         double accum = 0.0;
2731         for (int i = 0; i < n_rows; i++)
2732           if (cm_index == fim_index[i])
2733             accum += fim[i];
2734         ase[2] = sqrt ((xt->total - sum_fim) * (sum_fim + cm - 2. * accum)
2735                        / pow3 (xt->total - cm));
2736       }
2737
2738       /* ASE0 for Y given XT. */
2739       {
2740         double accum = 0.0;
2741         for (int i = 0; i < n_rows; i++)
2742           if (cm_index != fim_index[i])
2743             accum += (xt->mat[i * n_cols + fim_index[i]]
2744                       + xt->mat[i * n_cols + cm_index]);
2745         t[2] = v[2] / (sqrt (accum - pow2 (sum_fim - cm) / xt->total) / (xt->total - cm));
2746       }
2747
2748       /* ASE1 for XT given Y. */
2749       {
2750         double accum = 0.0;
2751         for (int j = 0; j < n_cols; j++)
2752           if (rm_index == fmj_index[j])
2753             accum += fmj[j];
2754         ase[1] = sqrt ((xt->total - sum_fmj) * (sum_fmj + rm - 2. * accum)
2755                        / pow3 (xt->total - rm));
2756       }
2757
2758       /* ASE0 for XT given Y. */
2759       {
2760         double accum = 0.0;
2761         for (int j = 0; j < n_cols; j++)
2762           if (rm_index != fmj_index[j])
2763             accum += (xt->mat[j + n_cols * fmj_index[j]]
2764                       + xt->mat[j + n_cols * rm_index]);
2765         t[1] = v[1] / (sqrt (accum - pow2 (sum_fmj - rm) / xt->total) / (xt->total - rm));
2766       }
2767
2768       /* Symmetric ASE0 and ASE1. */
2769       {
2770         double accum0 = 0.0;
2771         double accum1 = 0.0;
2772         for (int i = 0; i < n_rows; i++)
2773           for (int j = 0; j < n_cols; j++)
2774             {
2775               int temp0 = (fmj_index[j] == i) + (fim_index[i] == j);
2776               int temp1 = (i == rm_index) + (j == cm_index);
2777               accum0 += xt->mat[j + i * n_cols] * pow2 (temp0 - temp1);
2778               accum1 += (xt->mat[j + i * n_cols]
2779                          * pow2 (temp0 + (v[0] - 1.) * temp1));
2780             }
2781         ase[0] = sqrt (accum1 - 4. * xt->total * v[0] * v[0]) / (2. * xt->total - rm - cm);
2782         t[0] = v[0] / (sqrt (accum0 - pow2 (sum_fim + sum_fmj - cm - rm) / xt->total)
2783                        / (2. * xt->total - rm - cm));
2784       }
2785
2786       for (int i = 0; i < 3; i++)
2787         sig[i] = 2 * gsl_cdf_ugaussian_Q (t[i]);
2788
2789       free (fim);
2790       free (fim_index);
2791       free (fmj);
2792       free (fmj_index);
2793
2794       /* Tau. */
2795       {
2796         double sum_fij2_ri = 0.0;
2797         double sum_fij2_ci = 0.0;
2798         FOR_EACH_POPULATED_ROW (i, xt)
2799           FOR_EACH_POPULATED_COLUMN (j, xt)
2800             {
2801               double temp = pow2 (xt->mat[j + i * n_cols]);
2802               sum_fij2_ri += temp / xt->row_tot[i];
2803               sum_fij2_ci += temp / xt->col_tot[j];
2804             }
2805
2806         double sum_ri2 = 0.0;
2807         for (int i = 0; i < n_rows; i++)
2808           sum_ri2 += pow2 (xt->row_tot[i]);
2809
2810         double sum_cj2 = 0.0;
2811         for (int j = 0; j < n_cols; j++)
2812           sum_cj2 += pow2 (xt->col_tot[j]);
2813
2814         v[3] = (xt->total * sum_fij2_ci - sum_ri2) / (pow2 (xt->total) - sum_ri2);
2815         v[4] = (xt->total * sum_fij2_ri - sum_cj2) / (pow2 (xt->total) - sum_cj2);
2816       }
2817     }
2818
2819   if (proc->statistics & CRS_ST_UC)
2820     {
2821       double UX = 0.0;
2822       FOR_EACH_POPULATED_ROW (i, xt)
2823         UX -= xt->row_tot[i] / xt->total * log (xt->row_tot[i] / xt->total);
2824
2825       double UY = 0.0;
2826       FOR_EACH_POPULATED_COLUMN (j, xt)
2827         UY -= xt->col_tot[j] / xt->total * log (xt->col_tot[j] / xt->total);
2828
2829       double UXY = 0.0;
2830       double P = 0.0;
2831       for (int i = 0; i < n_rows; i++)
2832         for (int j = 0; j < n_cols; j++)
2833           {
2834             double entry = xt->mat[j + i * n_cols];
2835
2836             if (entry <= 0.)
2837               continue;
2838
2839             P += entry * pow2 (log (xt->col_tot[j] * xt->row_tot[i] / (xt->total * entry)));
2840             UXY -= entry / xt->total * log (entry / xt->total);
2841           }
2842
2843       double ase1_yx = 0.0;
2844       double ase1_xy = 0.0;
2845       double ase1_sym = 0.0;
2846       for (int i = 0; i < n_rows; i++)
2847         for (int j = 0; j < n_cols; j++)
2848           {
2849             double entry = xt->mat[j + i * n_cols];
2850
2851             if (entry <= 0.)
2852               continue;
2853
2854             ase1_yx += entry * pow2 (UY * log (entry / xt->row_tot[i])
2855                                     + (UX - UXY) * log (xt->col_tot[j] / xt->total));
2856             ase1_xy += entry * pow2 (UX * log (entry / xt->col_tot[j])
2857                                     + (UY - UXY) * log (xt->row_tot[i] / xt->total));
2858             ase1_sym += entry * pow2 ((UXY
2859                                       * log (xt->row_tot[i] * xt->col_tot[j] / pow2 (xt->total)))
2860                                      - (UX + UY) * log (entry / xt->total));
2861           }
2862
2863       v[5] = 2. * ((UX + UY - UXY) / (UX + UY));
2864       ase[5] = (2. / (xt->total * pow2 (UX + UY))) * sqrt (ase1_sym);
2865       t[5] = SYSMIS;
2866
2867       v[6] = (UX + UY - UXY) / UX;
2868       ase[6] = sqrt (ase1_xy) / (xt->total * UX * UX);
2869       t[6] = v[6] / (sqrt (P - xt->total * pow2 (UX + UY - UXY)) / (xt->total * UX));
2870
2871       v[7] = (UX + UY - UXY) / UY;
2872       ase[7] = sqrt (ase1_yx) / (xt->total * UY * UY);
2873       t[7] = v[7] / (sqrt (P - xt->total * pow2 (UX + UY - UXY)) / (xt->total * UY));
2874     }
2875
2876   /* Somers' D. */
2877   if (proc->statistics & CRS_ST_D)
2878     {
2879       double v_dummy[N_SYMMETRIC];
2880       double ase_dummy[N_SYMMETRIC];
2881       double t_dummy[N_SYMMETRIC];
2882       double somers_d_v[3];
2883       double somers_d_ase[3];
2884       double somers_d_t[3];
2885
2886       if (calc_symmetric (proc, xt, v_dummy, ase_dummy, t_dummy,
2887                           somers_d_v, somers_d_ase, somers_d_t))
2888         {
2889           for (int i = 0; i < 3; i++)
2890             {
2891               v[8 + i] = somers_d_v[i];
2892               ase[8 + i] = somers_d_ase[i];
2893               t[8 + i] = somers_d_t[i];
2894               sig[8 + i] = 2 * gsl_cdf_ugaussian_Q (fabs (somers_d_t[i]));
2895             }
2896         }
2897     }
2898
2899   /* Eta. */
2900   if (proc->statistics & CRS_ST_ETA)
2901     {
2902       /* X dependent. */
2903       double sum_Xr = 0.0;
2904       double sum_X2r = 0.0;
2905       for (int i = 0; i < n_rows; i++)
2906         {
2907           sum_Xr += xt->vars[ROW_VAR].values[i].f * xt->row_tot[i];
2908           sum_X2r += pow2 (xt->vars[ROW_VAR].values[i].f) * xt->row_tot[i];
2909         }
2910       double SX = sum_X2r - pow2 (sum_Xr) / xt->total;
2911
2912       double SXW = 0.0;
2913       FOR_EACH_POPULATED_COLUMN (j, xt)
2914         {
2915           double cum = 0.0;
2916
2917           for (int i = 0; i < n_rows; i++)
2918             {
2919               SXW += (pow2 (xt->vars[ROW_VAR].values[i].f)
2920                       * xt->mat[j + i * n_cols]);
2921               cum += (xt->vars[ROW_VAR].values[i].f
2922                       * xt->mat[j + i * n_cols]);
2923             }
2924
2925           SXW -= cum * cum / xt->col_tot[j];
2926         }
2927       v[11] = sqrt (1. - SXW / SX);
2928
2929       /* Y dependent. */
2930       double sum_Yc = 0.0;
2931       double sum_Y2c = 0.0;
2932       for (int i = 0; i < n_cols; i++)
2933         {
2934           sum_Yc += xt->vars[COL_VAR].values[i].f * xt->col_tot[i];
2935           sum_Y2c += pow2 (xt->vars[COL_VAR].values[i].f) * xt->col_tot[i];
2936         }
2937       double SY = sum_Y2c - pow2 (sum_Yc) / xt->total;
2938
2939       double SYW = 0.0;
2940       FOR_EACH_POPULATED_ROW (i, xt)
2941         {
2942           double cum = 0.0;
2943           for (int j = 0; j < n_cols; j++)
2944             {
2945               SYW += (pow2 (xt->vars[COL_VAR].values[j].f)
2946                       * xt->mat[j + i * n_cols]);
2947               cum += (xt->vars[COL_VAR].values[j].f
2948                       * xt->mat[j + i * n_cols]);
2949             }
2950
2951           SYW -= cum * cum / xt->row_tot[i];
2952         }
2953       v[12] = sqrt (1. - SYW / SY);
2954     }
2955
2956   return 1;
2957 }
2958
2959 /*
2960    Local Variables:
2961    mode: c
2962    End:
2963 */