NULL,
NULL,
};
+
\f
-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;
}
+
+\f
+
+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);
+}
+