1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2011, 2012, 2013, 2019 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include "data/case.h"
20 #include "data/format.h"
21 #include "data/variable.h"
23 #include "libpspp/bt.h"
24 #include "libpspp/hmap.h"
25 #include "libpspp/misc.h"
26 #include "libpspp/pool.h"
28 #include "math/moments.h"
35 #define _(msgid) gettext (msgid)
36 #define N_(msgid) (msgid)
42 struct per_var_data_simple
44 struct per_var_data parent;
48 struct per_var_data_moment
50 struct per_var_data parent;
54 static struct per_var_data *
55 default_create (struct pool *pool)
57 struct per_var_data_moment *pvd = pool_alloc (pool, sizeof *pvd);
59 pvd->mom = moments1_create (MOMENT_KURTOSIS);
61 return (struct per_var_data *) pvd;
65 default_update (struct per_var_data *stat, double w, double x)
67 struct per_var_data_moment *pvd = (struct per_var_data_moment *)stat;
69 moments1_add (pvd->mom, x, w);
74 /* HARMONIC MEAN: The reciprocal of the sum of the reciprocals:
75 1 / ( 1/(x_0) + 1/(x_1) + ... + 1/(x_{n-1}) ) */
79 struct per_var_data parent;
84 static struct per_var_data *
85 harmonic_create (struct pool *pool)
87 struct harmonic_mean *hm = pool_alloc (pool, sizeof *hm);
92 return (struct per_var_data *) hm;
97 harmonic_update (struct per_var_data *stat, double w, double x)
99 struct harmonic_mean *hm = (struct harmonic_mean *)stat;
106 harmonic_get (const struct per_var_data *pvd)
108 const struct harmonic_mean *hm = (const struct harmonic_mean *) pvd;
110 return hm->n / hm->rsum;
115 /* GEOMETRIC MEAN: The nth root of the product of all n observations
116 pow ((x_0 * x_1 * ... x_{n - 1}), 1/n) */
117 struct geometric_mean
119 struct per_var_data parent;
124 static struct per_var_data *
125 geometric_create (struct pool *pool)
127 struct geometric_mean *gm = pool_alloc (pool, sizeof *gm);
132 return (struct per_var_data *) gm;
136 geometric_update (struct per_var_data *pvd, double w, double x)
138 struct geometric_mean *gm = (struct geometric_mean *)pvd;
139 gm->prod *= pow (x, w);
145 geometric_get (const struct per_var_data *pvd)
147 const struct geometric_mean *gm = (const struct geometric_mean *)pvd;
148 return pow (gm->prod, 1.0 / gm->n);
154 sum_get (const struct per_var_data *pvd)
158 moments1_calculate (((struct per_var_data_moment *)pvd)->mom, &n, &mean, 0, 0, 0);
165 n_get (const struct per_var_data *pvd)
169 moments1_calculate (((struct per_var_data_moment *)pvd)->mom, &n, 0, 0, 0, 0);
175 arithmean_get (const struct per_var_data *pvd)
179 moments1_calculate (((struct per_var_data_moment *)pvd)->mom, &n, &mean, 0, 0, 0);
185 variance_get (const struct per_var_data *pvd)
187 double n, mean, variance;
189 moments1_calculate (((struct per_var_data_moment *)pvd)->mom, &n, &mean, &variance, 0, 0);
196 stddev_get (const struct per_var_data *pvd)
198 return sqrt (variance_get (pvd));
205 skew_get (const struct per_var_data *pvd)
209 moments1_calculate (((struct per_var_data_moment *)pvd)->mom, NULL, NULL, NULL, &skew, 0);
215 sekurt_get (const struct per_var_data *pvd)
219 moments1_calculate (((struct per_var_data_moment *)pvd)->mom, &n, NULL, NULL, NULL, NULL);
221 return calc_sekurt (n);
225 seskew_get (const struct per_var_data *pvd)
229 moments1_calculate (((struct per_var_data_moment *)pvd)->mom, &n, NULL, NULL, NULL, NULL);
231 return calc_seskew (n);
235 kurt_get (const struct per_var_data *pvd)
239 moments1_calculate (((struct per_var_data_moment *)pvd)->mom, NULL, NULL, NULL, NULL, &kurt);
245 semean_get (const struct per_var_data *pvd)
249 moments1_calculate (((struct per_var_data_moment *)pvd)->mom, &n, NULL, &var, NULL, NULL);
251 return sqrt (var / n);
256 /* MIN: The smallest (closest to minus infinity) value. */
258 static struct per_var_data *
259 min_create (struct pool *pool)
261 struct per_var_data_simple *pvd = pool_alloc (pool, sizeof *pvd);
265 return (struct per_var_data *) pvd;
269 min_update (struct per_var_data *pvd, double w UNUSED, double x)
271 double *r = &((struct per_var_data_simple *)pvd)->acc;
278 min_get (const struct per_var_data *pvd)
280 double *r = &((struct per_var_data_simple *)pvd)->acc;
285 /* MAX: The largest (closest to plus infinity) value. */
287 static struct per_var_data *
288 max_create (struct pool *pool)
290 struct per_var_data_simple *pvd = pool_alloc (pool, sizeof *pvd);
294 return (struct per_var_data *) pvd;
298 max_update (struct per_var_data *pvd, double w UNUSED, double x)
300 double *r = &((struct per_var_data_simple *)pvd)->acc;
307 max_get (const struct per_var_data *pvd)
309 double *r = &((struct per_var_data_simple *)pvd)->acc;
318 struct per_var_data parent;
323 static struct per_var_data *
324 range_create (struct pool *pool)
326 struct range *r = pool_alloc (pool, sizeof *r);
331 return (struct per_var_data *) r;
335 range_update (struct per_var_data *pvd, double w UNUSED, double x)
337 struct range *r = (struct range *) pvd;
347 range_get (const struct per_var_data *pvd)
349 const struct range *r = (struct range *) pvd;
351 return r->max - r->min;
356 /* LAST: The last value (the one closest to the end of the file). */
358 static struct per_var_data *
359 last_create (struct pool *pool)
361 struct per_var_data_simple *pvd = pool_alloc (pool, sizeof *pvd);
363 return (struct per_var_data *) pvd;
367 last_update (struct per_var_data *pvd, double w UNUSED, double x)
369 struct per_var_data_simple *stat = (struct per_var_data_simple *) pvd;
375 last_get (const struct per_var_data *pvd)
377 const struct per_var_data_simple *stat = (struct per_var_data_simple *) pvd;
382 /* FIRST: The first value (the one closest to the start of the file). */
384 static struct per_var_data *
385 first_create (struct pool *pool)
387 struct per_var_data_simple *pvd = pool_alloc (pool, sizeof *pvd);
391 return (struct per_var_data *) pvd;
395 first_update (struct per_var_data *pvd, double w UNUSED, double x)
397 struct per_var_data_simple *stat = (struct per_var_data_simple *) pvd;
399 if (stat->acc == SYSMIS)
404 first_get (const struct per_var_data *pvd)
406 const struct per_var_data_simple *stat = (struct per_var_data_simple *) pvd;
411 /* Table of cell_specs */
412 const struct cell_spec cell_spec[n_MEANS_STATISTICS] = {
413 {N_("Mean"), "MEAN", default_create, default_update, arithmean_get},
414 {N_("N"), "COUNT", default_create, default_update, n_get},
415 {N_("Std. Deviation"), "STDDEV", default_create, default_update, stddev_get},
417 {N_("Median"), "MEDIAN", default_create, default_update, NULL},
418 {N_("Group Median"), "GMEDIAN", default_create, default_update, NULL},
420 {N_("S.E. Mean"), "SEMEAN", default_create, default_update, semean_get},
421 {N_("Sum"), "SUM", default_create, default_update, sum_get},
422 {N_("Minimum"), "MIN", min_create, min_update, min_get},
423 {N_("Maximum"), "MAX", max_create, max_update, max_get},
424 {N_("Range"), "RANGE", range_create, range_update, range_get},
425 {N_("Variance"), "VARIANCE", default_create, default_update, variance_get},
426 {N_("Kurtosis"), "KURT", default_create, default_update, kurt_get},
427 {N_("S.E. Kurt"), "SEKURT", default_create, default_update, sekurt_get},
428 {N_("Skewness"), "SKEW", default_create, default_update, skew_get},
429 {N_("S.E. Skew"), "SESKEW", default_create, default_update, seskew_get},
430 {N_("First"), "FIRST", first_create, first_update, first_get},
431 {N_("Last"), "LAST", last_create, last_update, last_get},
433 {N_("Percent N"), "NPCT", default_create, default_update, NULL},
434 {N_("Percent Sum"), "SPCT", default_create, default_update, NULL},
436 {N_("Harmonic Mean"), "HARMONIC", harmonic_create, harmonic_update, harmonic_get},
437 {N_("Geom. Mean"), "GEOMETRIC", geometric_create, geometric_update, geometric_get}