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