From: John Darrington Date: Thu, 4 Sep 2008 12:28:45 +0000 (+0800) Subject: Add casereader_create_append_numeric function. X-Git-Tag: v0.7.1~50^2~76 X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b65cf0519aa1db140d30c878978f29b1e23c9cd0;p=pspp-builds.git Add casereader_create_append_numeric function. This change provides a new casereader translator which appends a numeric value to casereader; the value to be determined by a user supplied function. --- diff --git a/src/data/casereader-filter.c b/src/data/casereader-filter.c index b4275254..5c46ed50 100644 --- a/src/data/casereader-filter.c +++ b/src/data/casereader-filter.c @@ -285,7 +285,8 @@ casereader_create_filter_missing (struct casereader *reader, cfm->var_cnt = var_cnt; cfm->class = class; cfm->n_missing = n_missing; - if (n_missing) *n_missing = 0; + if (n_missing) + *n_missing = 0; return casereader_create_filter_func (reader, casereader_filter_missing_include, casereader_filter_missing_destroy, diff --git a/src/data/casereader-translator.c b/src/data/casereader-translator.c index 229dac2e..0557b65e 100644 --- a/src/data/casereader-translator.c +++ b/src/data/casereader-translator.c @@ -110,58 +110,104 @@ static const struct casereader_class casereader_translator_class = NULL, NULL, }; + -struct casereader_arithmetic_sequence - { - int value_ofs; - double first; - double increment; - casenumber n; - }; -static void cas_translate (struct ccase *input, struct ccase *output, - void *aux); -static bool cas_destroy (void *aux); +struct casereader_append_numeric +{ + int value_ofs; + casenumber n; + new_value_func *func; + void *aux; + void (*destroy) (void *aux); +}; + +static bool can_destroy (void *can_); + +static void can_translate (struct ccase *input, struct ccase *output, + void *can_); /* Creates and returns a new casereader whose cases are produced by reading from SUBREADER and appending an additional value, - which takes the value FIRST in the first case, FIRST + - INCREMENT in the second case, FIRST + INCREMENT * 2 in the - third case, and so on. + generated by FUNC. AUX is an optional parameter which + gets passed to FUNC. FUNC will also receive N as it, which is + the ordinal number of the case in the reader. DESTROY is an + optional parameter used to destroy AUX. After this function is called, SUBREADER must not ever again be referenced directly. It will be destroyed automatically when the translating casereader is destroyed. */ struct casereader * -casereader_create_arithmetic_sequence (struct casereader *subreader, - double first, double increment) +casereader_create_append_numeric (struct casereader *subreader, + new_value_func func, void *aux, + void (*destroy) (void *aux)) { - /* This could be implemented with a great deal more efficiency - and generality. However, this implementation is easy. */ - struct casereader_arithmetic_sequence *cas = xmalloc (sizeof *cas); - cas->value_ofs = casereader_get_value_cnt (subreader); - cas->first = first; - cas->increment = increment; - cas->n = 0; - return casereader_create_translator (subreader, cas->value_ofs + 1, - cas_translate, cas_destroy, cas); + struct casereader_append_numeric *can = xmalloc (sizeof *can); + can->value_ofs = casereader_get_value_cnt (subreader); + can->n = 0; + can->aux = aux; + can->func = func; + can->destroy = destroy; + return casereader_create_translator (subreader, can->value_ofs + 1, + can_translate, can_destroy, can); } + static void -cas_translate (struct ccase *input, struct ccase *output, void *cas_) +can_translate (struct ccase *input, struct ccase *output, void *can_) { - struct casereader_arithmetic_sequence *cas = cas_; + struct casereader_append_numeric *can = can_; + double new_value = can->func (input, can->n++, can->aux); case_nullify (output); case_move (output, input); - case_resize (output, cas->value_ofs + 1); - case_data_rw_idx (output, cas->value_ofs)->f - = cas->first + cas->increment * cas->n++; + case_resize (output, can->value_ofs + 1); + case_data_rw_idx (output, can->value_ofs)->f = new_value; } static bool -cas_destroy (void *cas_) +can_destroy (void *can_) { - struct casereader_arithmetic_sequence *cas = cas_; - free (cas); + struct casereader_append_numeric *can = can_; + if (can->destroy) + can->destroy (can->aux); + free (can); return true; } + + + +struct arithmetic_sequence +{ + double first; + double increment; +}; + +static double +next_arithmetic (const struct ccase *c UNUSED, + casenumber n, + void *aux) +{ + struct arithmetic_sequence *as = aux; + return n * as->increment + as->first; +} + +/* Creates and returns a new casereader whose cases are produced + by reading from SUBREADER and appending an additional value, + which takes the value FIRST in the first case, FIRST + + INCREMENT in the second case, FIRST + INCREMENT * 2 in the + third case, and so on. + + After this function is called, SUBREADER must not ever again + be referenced directly. It will be destroyed automatically + when the translating casereader is destroyed. */ +struct casereader * +casereader_create_arithmetic_sequence (struct casereader *subreader, + double first, double increment) +{ + struct arithmetic_sequence *as = xzalloc (sizeof *as); + as->first = first; + as->increment = increment; + return casereader_create_append_numeric (subreader, next_arithmetic, + as, free); +} + diff --git a/src/data/casereader.h b/src/data/casereader.h index ffbd1732..f7e885e6 100644 --- a/src/data/casereader.h +++ b/src/data/casereader.h @@ -113,6 +113,14 @@ casereader_create_translator (struct casereader *, size_t output_value_cnt, bool (*destroy) (void *aux), void *aux); +/* A function which creates a numberic value from an existing case */ +typedef double new_value_func (const struct ccase *, casenumber, void *); + +struct casereader * +casereader_create_append_numeric (struct casereader *subreader, + new_value_func func, void *aux, + void (*destroy) (void *aux)); + struct casereader * casereader_create_arithmetic_sequence (struct casereader *, double first, double increment);