-/* PSPP - a program for statistical analysis.
- Copyright (C) 2011, 2012, 2013, 2019 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 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.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include <config.h>
-
-#include "data/case.h"
-#include "data/format.h"
-#include "data/variable.h"
-
-#include "libpspp/bt.h"
-#include "libpspp/hmap.h"
-#include "libpspp/misc.h"
-#include "libpspp/pool.h"
-
-#include "math/moments.h"
-
-#include <math.h>
-
-#include "means.h"
-
-#include "gettext.h"
-#define _(msgid) gettext (msgid)
-#define N_(msgid) (msgid)
-
-struct per_var_data
-{
-};
-
-struct per_var_data_simple
-{
- struct per_var_data parent;
- double acc;
-};
-
-struct per_var_data_moment
-{
- struct per_var_data parent;
- struct moments1 *mom;
-};
-
-static struct per_var_data *
-default_create (struct pool *pool)
-{
- struct per_var_data_moment *pvd = pool_alloc (pool, sizeof *pvd);
-
- pvd->mom = moments1_create (MOMENT_KURTOSIS);
-
- return (struct per_var_data *) pvd;
-}
-
-static void
-default_update (struct per_var_data *stat, double w, double x)
-{
- struct per_var_data_moment *pvd = (struct per_var_data_moment *)stat;
-
- moments1_add (pvd->mom, x, w);
-}
-
-\f
-
-/* HARMONIC MEAN: The reciprocal of the sum of the reciprocals:
- 1 / ( 1/(x_0) + 1/(x_1) + ... + 1/(x_{n-1}) ) */
-
-struct harmonic_mean
-{
- struct per_var_data parent;
- double rsum;
- double n;
-};
-
-static struct per_var_data *
-harmonic_create (struct pool *pool)
-{
- struct harmonic_mean *hm = pool_alloc (pool, sizeof *hm);
-
- hm->rsum = 0;
- hm->n = 0;
-
- return (struct per_var_data *) hm;
-}
-
-
-static void
-harmonic_update (struct per_var_data *stat, double w, double x)
-{
- struct harmonic_mean *hm = (struct harmonic_mean *)stat;
- hm->rsum += w / x;
- hm->n += w;
-}
-
-
-static double
-harmonic_get (const struct per_var_data *pvd)
-{
- const struct harmonic_mean *hm = (const struct harmonic_mean *) pvd;
-
- return hm->n / hm->rsum;
-}
-
-\f
-
-/* GEOMETRIC MEAN: The nth root of the product of all n observations
- pow ((x_0 * x_1 * ... x_{n - 1}), 1/n) */
-struct geometric_mean
-{
- struct per_var_data parent;
- double prod;
- double n;
-};
-
-static struct per_var_data *
-geometric_create (struct pool *pool)
-{
- struct geometric_mean *gm = pool_alloc (pool, sizeof *gm);
-
- gm->prod = 1.0;
- gm->n = 0;
-
- return (struct per_var_data *) gm;
-}
-
-static void
-geometric_update (struct per_var_data *pvd, double w, double x)
-{
- struct geometric_mean *gm = (struct geometric_mean *)pvd;
- gm->prod *= pow (x, w);
- gm->n += w;
-}
-
-
-static double
-geometric_get (const struct per_var_data *pvd)
-{
- const struct geometric_mean *gm = (const struct geometric_mean *)pvd;
- return pow (gm->prod, 1.0 / gm->n);
-}
-
-\f
-
-static double
-sum_get (const struct per_var_data *pvd)
-{
- double n, mean;
-
- moments1_calculate (((struct per_var_data_moment *)pvd)->mom, &n, &mean, 0, 0, 0);
-
- return mean * n;
-}
-
-
-static double
-n_get (const struct per_var_data *pvd)
-{
- double n;
-
- moments1_calculate (((struct per_var_data_moment *)pvd)->mom, &n, 0, 0, 0, 0);
-
- return n;
-}
-
-static double
-arithmean_get (const struct per_var_data *pvd)
-{
- double n, mean;
-
- moments1_calculate (((struct per_var_data_moment *)pvd)->mom, &n, &mean, 0, 0, 0);
-
- return mean;
-}
-
-static double
-variance_get (const struct per_var_data *pvd)
-{
- double n, mean, variance;
-
- moments1_calculate (((struct per_var_data_moment *)pvd)->mom, &n, &mean, &variance, 0, 0);
-
- return variance;
-}
-
-
-static double
-stddev_get (const struct per_var_data *pvd)
-{
- return sqrt (variance_get (pvd));
-}
-
-
-\f
-
-static double
-skew_get (const struct per_var_data *pvd)
-{
- double skew;
-
- moments1_calculate (((struct per_var_data_moment *)pvd)->mom, NULL, NULL, NULL, &skew, 0);
-
- return skew;
-}
-
-static double
-sekurt_get (const struct per_var_data *pvd)
-{
- double n;
-
- moments1_calculate (((struct per_var_data_moment *)pvd)->mom, &n, NULL, NULL, NULL, NULL);
-
- return calc_sekurt (n);
-}
-
-static double
-seskew_get (const struct per_var_data *pvd)
-{
- double n;
-
- moments1_calculate (((struct per_var_data_moment *)pvd)->mom, &n, NULL, NULL, NULL, NULL);
-
- return calc_seskew (n);
-}
-
-static double
-kurt_get (const struct per_var_data *pvd)
-{
- double kurt;
-
- moments1_calculate (((struct per_var_data_moment *)pvd)->mom, NULL, NULL, NULL, NULL, &kurt);
-
- return kurt;
-}
-
-static double
-semean_get (const struct per_var_data *pvd)
-{
- double n, var;
-
- moments1_calculate (((struct per_var_data_moment *)pvd)->mom, &n, NULL, &var, NULL, NULL);
-
- return sqrt (var / n);
-}
-
-\f
-
-/* MIN: The smallest (closest to minus infinity) value. */
-
-static struct per_var_data *
-min_create (struct pool *pool)
-{
- struct per_var_data_simple *pvd = pool_alloc (pool, sizeof *pvd);
-
- pvd->acc = DBL_MAX;
-
- return (struct per_var_data *) pvd;
-}
-
-static void
-min_update (struct per_var_data *pvd, double w UNUSED, double x)
-{
- double *r = &((struct per_var_data_simple *)pvd)->acc;
-
- if (x < *r)
- *r = x;
-}
-
-static double
-min_get (const struct per_var_data *pvd)
-{
- double *r = &((struct per_var_data_simple *)pvd)->acc;
-
- return *r;
-}
-
-/* MAX: The largest (closest to plus infinity) value. */
-
-static struct per_var_data *
-max_create (struct pool *pool)
-{
- struct per_var_data_simple *pvd = pool_alloc (pool, sizeof *pvd);
-
- pvd->acc = -DBL_MAX;
-
- return (struct per_var_data *) pvd;
-}
-
-static void
-max_update (struct per_var_data *pvd, double w UNUSED, double x)
-{
- double *r = &((struct per_var_data_simple *)pvd)->acc;
-
- if (x > *r)
- *r = x;
-}
-
-static double
-max_get (const struct per_var_data *pvd)
-{
- double *r = &((struct per_var_data_simple *)pvd)->acc;
-
- return *r;
-}
-
-\f
-
-struct range
-{
- struct per_var_data parent;
- double min;
- double max;
-};
-
-static struct per_var_data *
-range_create (struct pool *pool)
-{
- struct range *r = pool_alloc (pool, sizeof *r);
-
- r->min = DBL_MAX;
- r->max = -DBL_MAX;
-
- return (struct per_var_data *) r;
-}
-
-static void
-range_update (struct per_var_data *pvd, double w UNUSED, double x)
-{
- struct range *r = (struct range *) pvd;
-
- if (x > r->max)
- r->max = x;
-
- if (x < r->min)
- r->min = x;
-}
-
-static double
-range_get (const struct per_var_data *pvd)
-{
- const struct range *r = (struct range *) pvd;
-
- return r->max - r->min;
-}
-
-\f
-
-/* LAST: The last value (the one closest to the end of the file). */
-
-static struct per_var_data *
-last_create (struct pool *pool)
-{
- struct per_var_data_simple *pvd = pool_alloc (pool, sizeof *pvd);
-
- return (struct per_var_data *) pvd;
-}
-
-static void
-last_update (struct per_var_data *pvd, double w UNUSED, double x)
-{
- struct per_var_data_simple *stat = (struct per_var_data_simple *) pvd;
-
- stat->acc = x;
-}
-
-static double
-last_get (const struct per_var_data *pvd)
-{
- const struct per_var_data_simple *stat = (struct per_var_data_simple *) pvd;
-
- return stat->acc;
-}
-
-/* FIRST: The first value (the one closest to the start of the file). */
-
-static struct per_var_data *
-first_create (struct pool *pool)
-{
- struct per_var_data_simple *pvd = pool_alloc (pool, sizeof *pvd);
-
- pvd->acc = SYSMIS;
-
- return (struct per_var_data *) pvd;
-}
-
-static void
-first_update (struct per_var_data *pvd, double w UNUSED, double x)
-{
- struct per_var_data_simple *stat = (struct per_var_data_simple *) pvd;
-
- if (stat->acc == SYSMIS)
- stat->acc = x;
-}
-
-static double
-first_get (const struct per_var_data *pvd)
-{
- const struct per_var_data_simple *stat = (struct per_var_data_simple *) pvd;
-
- return stat->acc;
-}
-
-/* Table of cell_specs */
-const struct cell_spec cell_spec[n_MEANS_STATISTICS] = {
- {N_("Mean"), "MEAN", default_create, default_update, arithmean_get},
- {N_("N"), "COUNT", default_create, default_update, n_get},
- {N_("Std. Deviation"), "STDDEV", default_create, default_update, stddev_get},
-#if 0
- {N_("Median"), "MEDIAN", default_create, default_update, NULL},
- {N_("Group Median"), "GMEDIAN", default_create, default_update, NULL},
-#endif
- {N_("S.E. Mean"), "SEMEAN", default_create, default_update, semean_get},
- {N_("Sum"), "SUM", default_create, default_update, sum_get},
- {N_("Minimum"), "MIN", min_create, min_update, min_get},
- {N_("Maximum"), "MAX", max_create, max_update, max_get},
- {N_("Range"), "RANGE", range_create, range_update, range_get},
- {N_("Variance"), "VARIANCE", default_create, default_update, variance_get},
- {N_("Kurtosis"), "KURT", default_create, default_update, kurt_get},
- {N_("S.E. Kurt"), "SEKURT", default_create, default_update, sekurt_get},
- {N_("Skewness"), "SKEW", default_create, default_update, skew_get},
- {N_("S.E. Skew"), "SESKEW", default_create, default_update, seskew_get},
- {N_("First"), "FIRST", first_create, first_update, first_get},
- {N_("Last"), "LAST", last_create, last_update, last_get},
-#if 0
- {N_("Percent N"), "NPCT", default_create, default_update, NULL},
- {N_("Percent Sum"), "SPCT", default_create, default_update, NULL},
-#endif
- {N_("Harmonic Mean"), "HARMONIC", harmonic_create, harmonic_update, harmonic_get},
- {N_("Geom. Mean"), "GEOMETRIC", geometric_create, geometric_update, geometric_get}
-};