Add casereader_create_append_numeric function.
authorJohn Darrington <john@marilyn.intra>
Thu, 4 Sep 2008 12:28:45 +0000 (20:28 +0800)
committerJohn Darrington <john@marilyn.intra>
Thu, 4 Sep 2008 12:28:45 +0000 (20:28 +0800)
This change provides a new casereader translator which
appends a numeric value to casereader; the value to be
determined by a user supplied function.

src/data/casereader-filter.c
src/data/casereader-translator.c
src/data/casereader.h

index b4275254fa24db01a182a66bf5000c48646b001e..5c46ed50dba436d1584a320e134be8fefc5e5de0 100644 (file)
@@ -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,
index 229dac2e54944c8df81088080c1032330c0cd84e..0557b65e8d6336452b4b88c4881d901fc289c7f2 100644 (file)
@@ -110,58 +110,104 @@ static const struct casereader_class casereader_translator_class =
     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);
+}
+
index ffbd17323ffc32274c69ce8c41f7598170a08d16..f7e885e64412d8ffbbe5b8e5258258109814d997 100644 (file)
@@ -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);