+
+ stat_create *sc;
+ stat_update *su;
+ stat_get *sd;
+};
+
+struct harmonic_mean
+{
+ double rsum;
+ double n;
+};
+
+static void *
+harmonic_create (struct pool *pool)
+{
+ struct harmonic_mean *hm = pool_alloc (pool, sizeof *hm);
+
+ hm->rsum = 0;
+ hm->n = 0;
+
+ return hm;
+}
+
+
+static void
+harmonic_update (void *stat, double w, double x)
+{
+ struct harmonic_mean *hm = stat;
+ hm->rsum += w / x;
+ hm->n += w;
+}
+
+
+static double
+harmonic_get (const struct per_var_data *pvd UNUSED, void *stat)
+{
+ struct harmonic_mean *hm = stat;
+
+ return hm->n / hm->rsum;
+}
+
+\f
+
+struct geometric_mean
+{
+ double prod;
+ double n;
+};
+
+
+static void *
+geometric_create (struct pool *pool)
+{
+ struct geometric_mean *gm = pool_alloc (pool, sizeof *gm);
+
+ gm->prod = 1.0;
+ gm->n = 0;
+
+ return gm;
+}
+
+
+static void
+geometric_update (void *stat, double w, double x)
+{
+ struct geometric_mean *gm = stat;
+ gm->prod *= pow (x, w);
+ gm->n += w;
+}
+
+
+static double
+geometric_get (const struct per_var_data *pvd UNUSED, void *stat)
+{
+ struct geometric_mean *gm = stat;
+
+ return pow (gm->prod, 1.0 / gm->n);
+}
+
+\f
+
+static double
+sum_get (const struct per_var_data *pvd, void *stat UNUSED)
+{
+ double n, mean;
+
+ moments1_calculate (pvd->mom, &n, &mean, 0, 0, 0);
+
+ return mean * n;
+}
+
+
+static double
+n_get (const struct per_var_data *pvd, void *stat UNUSED)
+{
+ double n;
+
+ moments1_calculate (pvd->mom, &n, 0, 0, 0, 0);
+
+ return n;
+}
+
+static double
+arithmean_get (const struct per_var_data *pvd, void *stat UNUSED)
+{
+ double n, mean;
+
+ moments1_calculate (pvd->mom, &n, &mean, 0, 0, 0);
+
+ return mean;
+}
+
+static double
+variance_get (const struct per_var_data *pvd, void *stat UNUSED)
+{
+ double n, mean, variance;
+
+ moments1_calculate (pvd->mom, &n, &mean, &variance, 0, 0);
+
+ return variance;
+}
+
+
+static double
+stddev_get (const struct per_var_data *pvd, void *stat)
+{
+ return sqrt (variance_get (pvd, stat));
+}
+
+
+\f
+
+static double
+skew_get (const struct per_var_data *pvd, void *stat UNUSED)
+{
+ double skew;
+
+ moments1_calculate (pvd->mom, NULL, NULL, NULL, &skew, 0);
+
+ return skew;
+}
+
+static double
+sekurt_get (const struct per_var_data *pvd, void *stat UNUSED)
+{
+ double n;
+
+ moments1_calculate (pvd->mom, &n, NULL, NULL, NULL, NULL);
+
+ return calc_sekurt (n);
+}
+
+static double
+seskew_get (const struct per_var_data *pvd, void *stat UNUSED)
+{
+ double n;
+
+ moments1_calculate (pvd->mom, &n, NULL, NULL, NULL, NULL);
+
+ return calc_seskew (n);
+}
+
+static double
+kurt_get (const struct per_var_data *pvd, void *stat UNUSED)
+{
+ double kurt;
+
+ moments1_calculate (pvd->mom, NULL, NULL, NULL, NULL, &kurt);
+
+ return kurt;
+}
+
+static double
+semean_get (const struct per_var_data *pvd, void *stat UNUSED)
+{
+ double n, var;
+
+ moments1_calculate (pvd->mom, &n, NULL, &var, NULL, NULL);
+
+ return sqrt (var / n);
+}
+
+\f
+
+static void *
+min_create (struct pool *pool)
+{
+ double *r = pool_alloc (pool, sizeof *r);
+
+ *r = DBL_MAX;
+
+ return r;
+}
+
+static void
+min_update (void *stat, double w UNUSED, double x)
+{
+ double *r = stat;
+
+ if (x < *r)
+ *r = x;
+}
+
+static double
+min_get (const struct per_var_data *pvd UNUSED, void *stat)
+{
+ double *r = stat;
+
+ return *r;
+}
+
+static void *
+max_create (struct pool *pool)
+{
+ double *r = pool_alloc (pool, sizeof *r);
+
+ *r = -DBL_MAX;
+
+ return r;
+}
+
+static void
+max_update (void *stat, double w UNUSED, double x)
+{
+ double *r = stat;
+
+ if (x > *r)
+ *r = x;
+}
+
+static double
+max_get (const struct per_var_data *pvd UNUSED, void *stat)
+{
+ double *r = stat;
+
+ return *r;
+}
+
+\f
+
+struct range
+{
+ double min;
+ double max;