+
+ /* If ALL the members of X were also found in Y, then this must be a subset */
+ if (n >= x->n_vars)
+ return true;
+
+ return false;
+}
+
+
+
+
+void
+interaction_dump (const struct interaction *i)
+{
+ int v = 0;
+ if ( i->n_vars == 0)
+ {
+ printf ("(empty)\n");
+ return;
+ }
+ printf ("%s", var_get_name (i->vars[v]));
+ for (v = 1; v < i->n_vars; ++v)
+ printf (" * %s", var_get_name (i->vars[v]));
+ printf ("\n");
+}
+
+/* Appends STR with a representation of the interaction, suitable for user
+ display.
+
+ STR must have been initialised prior to calling this function.
+*/
+void
+interaction_to_string (const struct interaction *iact, struct string *str)
+{
+ int v = 0;
+ if ( iact->n_vars == 0)
+ return;
+ ds_put_cstr (str, var_to_string (iact->vars[v]));
+ for (v = 1; v < iact->n_vars; ++v)
+ {
+ ds_put_cstr (str, " * ");
+ ds_put_cstr (str, var_to_string (iact->vars[v]));
+ }
+}
+
+unsigned int
+interaction_case_hash (const struct interaction *iact, const struct ccase *c, unsigned int base)
+{
+ int i;
+ size_t hash = base;
+ for (i = 0; i < iact->n_vars; ++i)
+ {
+ const struct variable *var = iact->vars[i];
+ const union value *val = case_data (c, var);
+ hash = value_hash (val, var_get_width (var), hash);
+ }
+ return hash;
+}
+
+bool
+interaction_case_equal (const struct interaction *iact, const struct ccase *c1, const struct ccase *c2)
+{
+ int i;
+ bool same = true;
+
+ for (i = 0; i < iact->n_vars; ++i)
+ {
+ const struct variable *var = iact->vars[i];
+ if ( ! value_equal (case_data (c1, var), case_data (c2, var), var_get_width (var)))
+ {
+ same = false;
+ break;
+ }
+ }
+
+ return same;
+}
+
+
+int
+interaction_case_cmp_3way (const struct interaction *iact, const struct ccase *c1, const struct ccase *c2)
+{
+ int i;
+ int result = 0;
+
+ for (i = 0; i < iact->n_vars; ++i)
+ {
+ const struct variable *var = iact->vars[i];
+ result = value_compare_3way (case_data (c1, var), case_data (c2, var), var_get_width (var));
+ if (result != 0)
+ break;
+ }
+