+ d->next_value_idx = 0;
+ for (i = 0; i < d->var_cnt; )
+ {
+ struct variable *v = d->var[i];
+
+ if (dict_class_from_id (v->name) != DC_SCRATCH)
+ {
+ v->fv = d->next_value_idx;
+ d->next_value_idx += v->nv;
+ i++;
+ }
+ else
+ dict_delete_var (default_dict, v);
+ }
+}
+
+/* Copies values from SRC, which represents a case arranged
+ according to dictionary D, to DST, which represents a case
+ arranged according to the dictionary that will be produced by
+ dict_compact_values(D). */
+void
+dict_compact_case (const struct dictionary *d,
+ struct ccase *dst, const struct ccase *src)
+{
+ size_t i;
+ size_t value_idx;
+
+ value_idx = 0;
+ for (i = 0; i < d->var_cnt; i++)
+ {
+ struct variable *v = d->var[i];
+
+ if (dict_class_from_id (v->name) != DC_SCRATCH)
+ {
+ case_copy (dst, value_idx, src, v->fv, v->nv);
+ value_idx += v->nv;
+ }
+ }
+}
+
+/* Returns the number of values that would be used by a case if
+ dict_compact_values() were called. */
+size_t
+dict_get_compacted_value_cnt (const struct dictionary *d)
+{
+ size_t i;
+ size_t cnt;
+
+ cnt = 0;
+ for (i = 0; i < d->var_cnt; i++)
+ if (dict_class_from_id (d->var[i]->name) != DC_SCRATCH)
+ cnt += d->var[i]->nv;
+ return cnt;
+}
+
+/* Creates and returns an array mapping from a dictionary index
+ to the `fv' that the corresponding variable will have after
+ calling dict_compact_values(). Scratch variables receive -1
+ for `fv' because dict_compact_values() will delete them. */
+int *
+dict_get_compacted_idx_to_fv (const struct dictionary *d)
+{
+ size_t i;
+ size_t next_value_idx;
+ int *idx_to_fv;
+
+ idx_to_fv = xmalloc (d->var_cnt * sizeof *idx_to_fv);
+ next_value_idx = 0;