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