02111-1307, USA. */
#include <config.h>
-#include <assert.h>
+#include "error.h"
#include <stdlib.h>
#include "algorithm.h"
#include "alloc.h"
+#include "case.h"
#include "hash.h"
#include "misc.h"
#include "str.h"
v->fv = d->next_value_idx;
v->nv = width == 0 ? 1 : DIV_RND_UP (width, 8);
v->init = 1;
- v->reinit = name[0] != '#';
+ v->reinit = dict_class_from_id (name) != DC_SCRATCH;
v->miss_type = MISSING_NONE;
if (v->type == NUMERIC)
{
assert (v != NULL);
assert (new_name != NULL);
assert (strlen (new_name) >= 1 && strlen (new_name) <= 8);
+ assert (dict_contains_var (d, v));
if (!strcmp (v->name, new_name))
return;
assert (d != NULL);
assert (v != NULL);
- return dict_lookup_var (d, v->name) == v;
+ return v->index >= 0 && v->index < d->var_cnt && d->var[v->index] == v;
}
/* Compares two double pointers to variables, which should point
return d->weight;
}
-/* Returns the value of D's weighting variable in case C, except
- that a negative weight is returned as 0. Returns 1 if the
- dictionary is unweighted. */
+/* Returns the value of D's weighting variable in case C, except that a
+ negative weight is returned as 0. Returns 1 if the dictionary is
+ unweighted. Will warn about missing, negative, or zero values if
+ warn_on_invalid is nonzero. The function will set warn_on_invalid to zero
+ if an invalid weight is found. */
double
-dict_get_case_weight (const struct dictionary *d, const struct ccase *c)
+dict_get_case_weight (const struct dictionary *d, const struct ccase *c,
+ int *warn_on_invalid)
{
assert (d != NULL);
assert (c != NULL);
return 1.0;
else
{
- double w = c->data[d->weight->fv].f;
- if (w < 0.0)
+ double w = case_num (c, d->weight->fv);
+ if ( w < 0.0 || w == SYSMIS || is_num_user_missing(w, d->weight) )
w = 0.0;
+ if ( w == 0.0 && *warn_on_invalid ) {
+ *warn_on_invalid = 0;
+ msg (SW, _("At least one case in the data file had a weight value "
+ "that was user-missing, system-missing, zero, or "
+ "negative. These case(s) were ignored."));
+ }
return w;
}
}
return sizeof (union value) * dict_get_next_value_idx (d);
}
-/* Reassigns values in dictionary D so that fragmentation is
- eliminated. */
+/* Deletes scratch variables in dictionary D and reassigns values
+ so that fragmentation is eliminated. */
void
dict_compact_values (struct dictionary *d)
{
size_t i;
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);
+ }
+}
+
+/* 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;
for (i = 0; i < d->var_cnt; i++)
{
struct variable *v = d->var[i];
- v->fv = d->next_value_idx;
- d->next_value_idx += v->nv;
+ if (dict_class_from_id (v->name) != DC_SCRATCH)
+ {
+ idx_to_fv[i] = next_value_idx;
+ next_value_idx += v->nv;
+ }
+ else
+ idx_to_fv[i] = -1;
}
+ return idx_to_fv;
}
/* Returns the SPLIT FILE vars (see cmd_split_file()). Call