math: Make 'accumulate' a feature of order statistics, not all stats.
[pspp] / src / math / order-stats.h
index 581bb11455eb9ba5291f87c549e6057ef96ae3db..4bb69383fb7944a22b12f0ce3d8328e2d27abfff 100644 (file)
 
 /* Support for order statistics.
 
-   This data structure supplies infrastructure for higher-level statistics that
-   rely on order statistics.  It is a kind of "abstract base class" that is not
-   useful on its own.  The common pattern for using the statistics based on it
+   The kth order statistic of a statistical sample is equal to its kth-smallest
+   value.  The minimum is the first order statistic and the maximum is the
+   largest.  This code and data structure supplies infrastructure for
+   higher-level statistics that rely on order statistics.  It is a kind of
+   "abstract base class" that is not useful on its own.
+
+   This is implemented here as a kind of "partial frequency table".  The
+   order_stats_accumulate() and order_stats_accumulate_idx() functions
+   effectively generate all of the frequency table entries for the variable,
+   one by one, and pass them to the "accumulate" function, if any.  They can
+   also record pairs of frequency tables entries surrounding desired target
+   cumulative weights in 'k' data structures.
+
+   Client use
+   ==========
+
+   The common pattern for clients to use statistics based on order statistics
    is this:
 
    - Create the higher-level statistic with, for example, percentile_create().
 struct casereader;
 struct variable;
 
-/*
-  cc <= tc < cc_p1
+/* A pair of adjacent frequency table entries.
+
+   cc <= tc < cc_p1
 */
 struct k
 {
+  /* Target cumulative weight.
+     Set by the client before invoking order_stats_accumulate{,_idx}. */
   double tc;
-  double cc;
-  double cc_p1;
-  double c;
-  double c_p1;
-  double y;
-  double y_p1;
+
+  /* Lower order statistics. */
+  double cc;                    /* Largest cumulative weight <= tc. */
+  double c;                     /* Weight for data values equal to 'y'. */
+  double y;                     /* Data value. */
+
+  /* Upper order statistics. */
+  double cc_p1;                 /* Smallest cumulative weight > tc. */
+  double c_p1;                  /* Weight for data values equal to 'y_p1'. */
+  double y_p1;                  /* Data value. */
 };
 
 /* Order statistics calculation data structure.  See the comment at the top of
@@ -62,10 +83,11 @@ struct k
 struct order_stats
 {
   struct statistic parent;
-  int n_k;
-  struct k *k;
 
-  double cc;
+  void (*accumulate) (struct statistic *, const struct ccase *, double c, double cc, double y);
+
+  struct k *k;
+  size_t n_k;
 };
 
 void order_stats_accumulate_idx (struct order_stats **os, size_t n_os,