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