+
+ if (NULL == cat)
+ return;
+
+ cat->df_sum = 0;
+ cat->n_cats_total = 0;
+
+ /* Calculate the degrees of freedom, and the number of categories */
+ for (i = 0 ; i < cat->n_iap; ++i)
+ {
+ int df = 1;
+ const struct interaction *iact = cat->iap[i].iact;
+
+ cat->iap[i].df_prod = iact->n_vars ? xcalloc (iact->n_vars, sizeof (int)) : NULL;
+
+ cat->iap[i].n_cats = 1;
+
+ for (v = 0 ; v < iact->n_vars; ++v)
+ {
+ int x;
+ const struct variable *var = iact->vars[v];
+
+ struct variable_node *vn = lookup_variable (&cat->varmap, var, hash_pointer (var, 0));
+
+ struct value_node *valnd = NULL;
+ struct value_node **array ;
+
+ assert (vn->n_vals == hmap_count (&vn->valmap));
+
+ if (vn->n_vals == 0)
+ {
+ cat->sane = false;
+ return;
+ }
+
+ /* Sort the VALMAP here */
+ array = xcalloc (sizeof *array, vn->n_vals);
+ x = 0;
+ HMAP_FOR_EACH (valnd, struct value_node, node, &vn->valmap)
+ {
+ /* Note: This loop is probably superfluous, it could be done in the
+ update stage (at the expense of a realloc) */
+ array[x++] = valnd;
+ }
+
+ sort (array, vn->n_vals, sizeof (*array),
+ compare_value_node_3way, vn);
+
+ for (x = 0; x < vn->n_vals; ++x)
+ {
+ struct value_node *vvv = array[x];
+ vvv->index = x;
+ }
+ free (array);
+
+ cat->iap[i].df_prod[v] = df * (vn->n_vals - 1);
+ df = cat->iap[i].df_prod[v];
+
+ cat->iap[i].n_cats *= vn->n_vals;
+ }
+
+ if (v > 0)
+ cat->df_sum += cat->iap[i].df_prod [v - 1];
+
+ cat->n_cats_total += cat->iap[i].n_cats;
+ }
+
+