X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdictionary.c;h=f1c5f462f3a437170d216822c9de865ccf24f25b;hb=5156fa5a8323a16f6b4bbc8950221cdc1d0e023d;hp=0f7133ecf59dd5c5e716cd21aa0515b8a18292be;hpb=312ad23d59e643e0c72e7ad684b00f3432461dee;p=pspp-builds.git diff --git a/src/dictionary.c b/src/dictionary.c index 0f7133ec..f1c5f462 100644 --- a/src/dictionary.c +++ b/src/dictionary.c @@ -18,10 +18,12 @@ 02111-1307, USA. */ #include -#include +#include "dictionary.h" #include #include "algorithm.h" #include "alloc.h" +#include "case.h" +#include "error.h" #include "hash.h" #include "misc.h" #include "str.h" @@ -123,6 +125,7 @@ dict_clear (struct dictionary *d) for (i = 0; i < d->var_cnt; i++) { struct variable *v = d->var[i]; + var_clear_aux (v); val_labs_destroy (v->val_labs); free (v->label); free (v); @@ -145,6 +148,19 @@ dict_clear (struct dictionary *d) dict_clear_vectors (d); } +/* Destroys the aux data for every variable in D, by calling + var_clear_aux() for each variable. */ +void +dict_clear_aux (struct dictionary *d) +{ + int i; + + assert (d != NULL); + + for (i = 0; i < d->var_cnt; i++) + var_clear_aux (d->var[i]); +} + /* Clears a dictionary and destroys it. */ void dict_destroy (struct dictionary *d) @@ -236,7 +252,7 @@ dict_create_var (struct dictionary *d, const char *name, int width) 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) { @@ -250,8 +266,11 @@ dict_create_var (struct dictionary *d, const char *name, int width) v->print.w = v->width; v->print.d = 0; } + v->write = v->print; v->val_labs = val_labs_create (v->width); v->label = NULL; + v->aux = NULL; + v->aux_dtor = NULL; /* Update dictionary. */ if (d->var_cnt >= d->var_cap) @@ -320,6 +339,7 @@ dict_rename_var (struct dictionary *d, struct variable *v, 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; @@ -366,7 +386,7 @@ dict_contains_var (const struct dictionary *d, const struct variable *v) 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 @@ -407,7 +427,10 @@ dict_delete_var (struct dictionary *d, struct variable *v) assert (dict_contains_var (d, v)); assert (d->var[v->index] == v); - /* Remove v from splits, weight, filter variables. */ + /* Delete aux data. */ + var_clear_aux (v); + + /* Remove V from splits, weight, filter variables. */ d->split_cnt = remove_equal (d->split, d->split_cnt, sizeof *d->split, &v, compare_variable_dblptrs, NULL); @@ -417,7 +440,7 @@ dict_delete_var (struct dictionary *d, struct variable *v) d->filter = NULL; dict_clear_vectors (d); - /* Remove v from var array. */ + /* Remove V from var array. */ d->var_cnt--; memmove (d->var + v->index, d->var + v->index + 1, (d->var_cnt - v->index) * sizeof *d->var); @@ -556,11 +579,14 @@ dict_get_weight (const struct dictionary *d) 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); @@ -569,9 +595,15 @@ dict_get_case_weight (const struct dictionary *d, const struct ccase *c) 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; } } @@ -652,21 +684,70 @@ dict_get_case_size (const struct dictionary *d) 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