X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdictionary.c;h=99ea5b8bcbec501a1cd3c57fa3252351b7d0fb17;hb=6ccbd384363db2e304ffe8cc51fcd2eac0a5349a;hp=6db18670f5ed3c352f182f901261a40355195cf9;hpb=205ac3afa4c2b19c85819d8695abf3975bb11807;p=pspp-builds.git diff --git a/src/dictionary.c b/src/dictionary.c index 6db18670..99ea5b8b 100644 --- a/src/dictionary.c +++ b/src/dictionary.c @@ -18,10 +18,12 @@ 02111-1307, USA. */ #include -#include "error.h" +#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" @@ -54,7 +56,7 @@ dict_create (void) d->var = NULL; d->var_cnt = d->var_cap = 0; - d->name_tab = hsh_create (8, compare_variables, hash_variable, NULL, NULL); + d->name_tab = hsh_create (8, compare_var_names, hash_var_name, NULL, NULL); d->next_value_idx = 0; d->split = NULL; d->split_cnt = 0; @@ -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) @@ -253,6 +269,8 @@ dict_create_var (struct dictionary *d, const char *name, int width) 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) @@ -374,17 +392,12 @@ dict_contains_var (const struct dictionary *d, const struct variable *v) /* Compares two double pointers to variables, which should point to elements of a struct dictionary's `var' member array. */ static int -compare_variable_dblptrs (const void *a_, const void *b_, void *aux UNUSED) +compare_var_ptrs (const void *a_, const void *b_, void *aux UNUSED) { struct variable *const *a = a_; struct variable *const *b = b_; - if (a > b) - return 1; - else if (a < b) - return -1; - else - return 0; + return *a < *b ? -1 : *a > *b; } /* Deletes variable V from dictionary D and frees V. @@ -409,20 +422,21 @@ 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); + &v, compare_var_ptrs, NULL); if (d->weight == v) d->weight = NULL; if (d->filter == v) d->filter = NULL; dict_clear_vectors (d); - /* Remove v from var array. */ + /* Remove V from var array. */ + remove_element (d->var, d->var_cnt, sizeof *d->var, v->index); d->var_cnt--; - memmove (d->var + v->index, d->var + v->index + 1, - (d->var_cnt - v->index) * sizeof *d->var); /* Update index. */ for (i = v->index; i < d->var_cnt; i++) @@ -558,11 +572,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); @@ -571,9 +588,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; } } @@ -661,6 +684,7 @@ 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]; @@ -676,6 +700,30 @@ dict_compact_values (struct dictionary *d) } } +/* 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