X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fcasereader-translator.c;h=0557b65e8d6336452b4b88c4881d901fc289c7f2;hb=b65cf0519aa1db140d30c878978f29b1e23c9cd0;hp=f41dbb56fbc331af8adab5c6b93b472f09325158;hpb=ed88deded6a59254dd55883308c4c20966efc77e;p=pspp-builds.git diff --git a/src/data/casereader-translator.c b/src/data/casereader-translator.c index f41dbb56..0557b65e 100644 --- a/src/data/casereader-translator.c +++ b/src/data/casereader-translator.c @@ -1,20 +1,18 @@ -/* PSPP - computes sample statistics. +/* PSPP - a program for statistical analysis. Copyright (C) 2007 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with this program. If not, see . */ #include @@ -27,26 +25,41 @@ #include "xalloc.h" +/* Casereader that applies a user-supplied function to translate + each case into another in an arbitrary fashion. */ + +/* A translating casereader. */ struct casereader_translator { - struct casereader *subreader; + struct casereader *subreader; /* Source of input cases. */ - void (*translate) (const struct ccase *input, struct ccase *output, - void *aux); + void (*translate) (struct ccase *input, struct ccase *output, void *aux); bool (*destroy) (void *aux); void *aux; }; -static struct casereader_class casereader_translator_class; +static const struct casereader_class casereader_translator_class; + +/* Creates and returns a new casereader whose cases are produced + by reading from SUBREADER and passing through TRANSLATE, which + must create case OUTPUT, with OUTPUT_VALUE_CNT values, and + populate it based on INPUT and auxiliary data AUX. TRANSLATE + must also destroy INPUT. + When the translating casereader is destroyed, DESTROY will be + called to allow any state maintained by TRANSLATE to be freed. + + 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_translator (struct casereader *subreader, size_t output_value_cnt, - void (*translate) (const struct ccase *input, + void (*translate) (struct ccase *input, struct ccase *output, void *aux), bool (*destroy) (void *aux), - void *aux) + void *aux) { struct casereader_translator *ct = xmalloc (sizeof *ct); struct casereader *reader; @@ -62,24 +75,26 @@ casereader_create_translator (struct casereader *subreader, return reader; } +/* Internal read function for translating casereader. */ static bool casereader_translator_read (struct casereader *reader UNUSED, - void *ct_, struct ccase *c) + void *ct_, struct ccase *c) { struct casereader_translator *ct = ct_; struct ccase tmp; - if (casereader_read (ct->subreader, &tmp)) + if (casereader_read (ct->subreader, &tmp)) { ct->translate (&tmp, c, ct->aux); - return true; + return true; } else return false; } +/* Internal destroy function for translating casereader. */ static void -casereader_translator_destroy (struct casereader *reader UNUSED, void *ct_) +casereader_translator_destroy (struct casereader *reader UNUSED, void *ct_) { struct casereader_translator *ct = ct_; casereader_destroy (ct->subreader); @@ -87,10 +102,112 @@ casereader_translator_destroy (struct casereader *reader UNUSED, void *ct_) free (ct); } -static struct casereader_class casereader_translator_class = +/* Casereader class for translating casereader. */ +static const struct casereader_class casereader_translator_class = { casereader_translator_read, casereader_translator_destroy, NULL, NULL, }; + + + +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, + 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_append_numeric (struct casereader *subreader, + new_value_func func, void *aux, + void (*destroy) (void *aux)) +{ + 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 +can_translate (struct ccase *input, struct ccase *output, void *can_) +{ + 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, can->value_ofs + 1); + case_data_rw_idx (output, can->value_ofs)->f = new_value; +} + +static bool +can_destroy (void *can_) +{ + 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); +} +