Elementa v8.0.0
Minimalistic library for any C++ application (C++11 and up)
Loading...
Searching...
No Matches
statistic.h
Go to the documentation of this file.
1
3#include "elementa/license.inc"
4#include "elementa/checks.inc"
5
6#ifndef ELEMENTA_MATH_STATS_STATISTIC_H
7#define ELEMENTA_MATH_STATS_STATISTIC_H
8
9#include <limits>
10#include <type_traits>
11#include <string>
12#include <cmath>
13#include <vector>
14#include <functional>
16
17namespace elementa
18{
19
20namespace math
21{
22
23namespace stats
24{
25
27/* *************************************************************************/
43/* ***************************************************************************
44*
45* Types: SampleSize, StaDatum, GetStaDatumFun
46* Constexpr: getstadatum_direct
47*
48***************************************************************************** */
49
51using SampleSize = size_t;
52
54using StaDatum = double;
55
57template <class DatumIterator>
58using GetStaDatumFun = std::function< StaDatum(const DatumIterator &) >;
59
61template <class DatumIterator>
62constexpr StaDatum getstadatum_direct(const DatumIterator & ti)
63 { return(static_cast<StaDatum>(*ti)); }
64
65
66/* *****************************************************************************
67*
68* Base policy class: StatPol_BaseOnInc
69* Policy classes: StaPol_Min, StaPol_Max, StaPol_Mean, StaPol_Var
70*
71*******************************************************************************/
72
73// forward declaration
74template <class Policy>
75class Statistic;
76
77
79
82{
83 public:
84
85 template <class TIt>
86 StaDatum calc(const TIt & first, const TIt & pastend, SampleSize & n,
87 const GetStaDatumFun<TIt> & getdatum =
88 getstadatum_direct<TIt>);
89
90 virtual StaDatum incCalc(StaDatum prev, StaDatum v, SampleSize n) = 0;
91};
92
93
95
98{
99 public:
100
101 StaDatum incCalc(StaDatum prev, StaDatum v, SampleSize n)
102 { return(v < prev ? v : prev); }
103};
104
105
107
110{
111 public:
112
113 StaDatum incCalc(StaDatum prev, StaDatum v, SampleSize n)
114 { return(v > prev ? v : prev); }
115};
116
117
119
122{
123 public:
124
125 template <class TIt>
126 StaDatum calc(const TIt & first, const TIt & pastend, SampleSize & n,
127 const GetStaDatumFun<TIt> & getdatum =
128 getstadatum_direct<TIt>);
129
130 StaDatum incCalc(StaDatum prev, StaDatum v, SampleSize n)
131 { // here n is from 0 to N-1, but we need from 1 to N, thus we add 1
132 ++n; return(1.0/static_cast<StaDatum>(n) *
133 (v + static_cast<StaDatum>(n-1) * prev)); }
134};
135
136
138
143{
144 public:
145
147
148 StaPol_Var(Statistic<StaPol_Mean> & meanstat):meanstat_{&meanstat} {}
149
150
151 template <class TIt>
152 StaDatum calc(const TIt & first, const TIt & pastend, SampleSize & n,
153 const GetStaDatumFun<TIt> & getdatum =
154 getstadatum_direct<TIt>);
155
156 StaDatum incCalc(StaDatum prev, StaDatum v, SampleSize n);
157
158 private:
159
160 Statistic<StaPol_Mean> * meanstat_;
161 StaDatum prev_;
162};
163
164
165/* *****************************************************************************
166*
167* Template class: Statistic
168*
169*******************************************************************************/
170
172
192template <class Calc >
194{
195 public:
196
198 Statistic(const Calc c):calculator_{c} { reset(); }
199
200
202 void reset(void) { calculated_ = false; domsize_ = 0; }
203
205 bool calculated(void) const noexcept { return(calculated_); }
206
208 StaDatum value(void) const { checkCalculated(); return(value_); }
209
211
213 StaDatum previous(void) const;
214
216
217 SampleSize domainSize(void) const noexcept { return(domsize_); }
218
220 template <class TIt>
221 StaDatum calculate(const TIt & first, const TIt & pastend,
222 const GetStaDatumFun<TIt> & getdatum =
223 getstadatum_direct<TIt>);
224
226
228
229
230 private:
231
232 Calc calculator_;
233 bool calculated_;
234 StaDatum value_,prev_;
235 SampleSize domsize_;
236
237 void checkCalculated(void) const
238 { if (!calculated_) ELE_CODE_INVSTATE("Statistic not calculated yet"); }
239};
240
241
242/* *****************************************************************************
243*
244* Classes: StaGroup_MinMax, StaGroup_MeanVar, StaGroup_MinMaxMeanVar
245*
246*******************************************************************************/
247
249
252{
253 public:
254
257
259 template <class TIt>
260 void calculate(const TIt & first, const TIt & pastend,
261 const GetStaDatumFun<TIt> & getdatum =
262 getstadatum_direct<TIt>)
263 { stamin.calculate(first,pastend,getdatum);
264 stamax.calculate(first,pastend,getdatum); }
265
267 void update(StaDatum v) { stamin.update(v); stamax.update(v); }
268
270 void reset(void) { stamin.reset(); stamax.reset(); }
271};
272
273
275
278{
279 public:
280
283
285 template <class TIt>
286 void calculate(const TIt & first, const TIt & pastend,
287 const GetStaDatumFun<TIt> & getdatum =
288 getstadatum_direct<TIt>)
289 { stamean.calculate(first,pastend,getdatum);
290 stavar.calculate(first,pastend,getdatum); }
291
293 void update(StaDatum v) { stamean.update(v); stavar.update(v); }
294
296 void reset(void) { stamean.reset(); stavar.reset(); }
297};
298
299
301
304{
305 public:
306
311
313 template <class TIt>
314 void calculate(const TIt & first, const TIt & pastend,
315 const GetStaDatumFun<TIt> & getdatum =
316 getstadatum_direct<TIt>)
317 { stamin.calculate(first,pastend,getdatum);
318 stamax.calculate(first,pastend,getdatum);
319 stamean.calculate(first,pastend,getdatum);
320 stavar.calculate(first,pastend,getdatum); }
321
324 { stamin.update(v); stamax.update(v);
325 stamean.update(v); stavar.update(v); }
326
328 void reset(void)
329 { stamin.reset(); stamax.reset();
330 stamean.reset(); stavar.reset(); }
331};
332
333
334
335/* ===========================================================================
336
337 ========== IMPLEMENTATION OF TEMPLATES ==========
338
339============================================================================= */
340
341
342/* *****************************************************************************
343*
344* Template class: Statistic
345*
346*******************************************************************************/
347
348template <class Calc >
350{
351 checkCalculated();
352 if (domsize_ < 2) ELE_CODE_INVSTATE("No previous value");
353 return(prev_);
354}
355
356template <class Calc>
357template <class TIt>
358StaDatum Statistic<Calc>::calculate(const TIt & first, const TIt & pastend,
359 const GetStaDatumFun<TIt> & getdatum)
360{
361 if (first == pastend) ELE_CODE_INVARG("Cannot calculate statistic on empty "
362 "sample");
363 value_ = calculator_.calc(first,pastend,domsize_,getdatum);
364 prev_ = value_;
365 calculated_ = true;
366 return(value_);
367}
368
369template <class Calc>
371{
372 if (domsize_ == std::numeric_limits<SampleSize>::max())
373 ELE_CODE_INVSTATE("Maximum size of sample reached");
374 if (domsize_ == 0)
375 {
376 value_ = v;
377 prev_ = value_;
378 }
379 else
380 {
381 prev_ = value_;
382 value_= calculator_.incCalc(prev_,v,domsize_);
383 }
384 ++domsize_;
385 calculated_ = true;
386 return(value_);
387}
388
389
390/* *****************************************************************************
391*
392* Base policy class: StatPol_BaseOnInc
393*
394*******************************************************************************/
395
396template <class TIt>
397StaDatum StaPol_BaseOnInc::calc(const TIt & first, const TIt & pastend,
398 SampleSize & n,
399 const GetStaDatumFun<TIt> & getdatum)
400{
401 StaDatum v = getdatum(first);
402 auto it{first};
403 ++it;
404 n = 1;
405 while (it != pastend)
406 {
407 v = incCalc(v,getdatum(it),n);
408 ++n;
409 ++it;
410 }
411 return(v);
412}
413
414
415/* *****************************************************************************
416*
417* Policy class: StaPol_Mean
418*
419*******************************************************************************/
420
421template <class TIt>
422StaDatum StaPol_Mean::calc(const TIt & first, const TIt & pastend,
423 SampleSize & n, const GetStaDatumFun<TIt> & getdatum)
424{
425 StaDatum s{getdatum(first)};
426 n = 1;
427 auto it{first};
428 ++it;
429 while (it != pastend)
430 {
431 s += getdatum(it);
432 ++it;
433 ++n;
434 }
435 return(s / static_cast<StaDatum>(n));
436}
437
438
439/* *****************************************************************************
440*
441* Policy class: StaPol_Var
442*
443*******************************************************************************/
444
445template <class TIt>
446StaDatum StaPol_Var::calc(const TIt & first, const TIt & pastend,
447 SampleSize & n, const GetStaDatumFun<TIt> & getdatum)
448{
449 n = meanstat_->domainSize();
450 if (n < 2) return(0); // no variance
451 StaDatum mu = meanstat_->value();
452 auto it0{first};
453 StaDatum s{getdatum(it0) - mu},aux;
454 s *= s;
455 ++it0;
456 while (it0 != pastend)
457 {
458 aux = getdatum(it0) - mu;
459 s += aux*aux;
460 ++it0;
461 }
462 prev_ = s / static_cast<StaDatum>(n-1); return(prev_);
463}
464
465
466
469} // end stats namespace
470
471} // end math namespace
472
473} // end elementa namespace
474
475
476#endif
477
478
#define ELE_CODE_INVSTATE(expl)
To throw an invalid-state exception with an explanation.
Definition: exceptions.h:306
#define ELE_CODE_INVARG(expl)
To throw an invalid-argument exception with an explanation.
Definition: exceptions.h:310
A group of statistics consisting of mean and var.
Definition: statistic.h:278
A group of statistics consisting of min and max.
Definition: statistic.h:252
A group of statistics consisting of min, max, mean and var.
Definition: statistic.h:304
An incomplete base policy for Statistic that uses incCalc() to do calcs.
Definition: statistic.h:82
Policy for Statistic that calculates the maximum.
Definition: statistic.h:110
Policy for Statistic that calculates the mean.
Definition: statistic.h:122
Policy for Statistic that calculates the minimum.
Definition: statistic.h:98
Policy for Statistic that calculates the variance.
Definition: statistic.h:143
A statistic, i.e., a numerical function of a sample of data.
Definition: statistic.h:194
Statistic< StaPol_Max > stamax
The max statistic.
Definition: statistic.h:308
Statistic< StaPol_Var > stavar
The var statistic.
Definition: statistic.h:310
Statistic(const Calc c)
Constructor: a statistic not calculated ever.
Definition: statistic.h:198
void update(StaDatum v)
Update statistic on all members of the group at once.
Definition: statistic.h:293
StaDatum update(StaDatum v)
Calculate the statistic incrementally from its previous value.
Definition: statistic.h:370
size_t SampleSize
The number of elements in a sample.
Definition: statistic.h:51
void calculate(const TIt &first, const TIt &pastend, const GetStaDatumFun< TIt > &getdatum=getstadatum_direct< TIt >)
Calculate the statistic on all members of the group at once.
Definition: statistic.h:314
Statistic< StaPol_Mean > stamean
The mean statistic.
Definition: statistic.h:281
void update(StaDatum v)
Update statistic on all members of the group at once.
Definition: statistic.h:267
void reset(void)
Set the statistic to the previous-to-calculated state.
Definition: statistic.h:202
Statistic< StaPol_Max > stamax
The max statistic.
Definition: statistic.h:256
void calculate(const TIt &first, const TIt &pastend, const GetStaDatumFun< TIt > &getdatum=getstadatum_direct< TIt >)
Calculate the statistic on all members of the group at once.
Definition: statistic.h:260
void reset(void)
Reset all statistics.
Definition: statistic.h:296
StaDatum calculate(const TIt &first, const TIt &pastend, const GetStaDatumFun< TIt > &getdatum=getstadatum_direct< TIt >)
Calculate the statistic on a sample and return its value.
Definition: statistic.h:358
StaDatum previous(void) const
Return the value of the statistic previous to the current one.
Definition: statistic.h:349
SampleSize domainSize(void) const noexcept
Return the number of data that has produced the current value.
Definition: statistic.h:217
Statistic< StaPol_Min > stamin
The min statistic.
Definition: statistic.h:307
StaDatum value(void) const
Return its current calculated value, or throw if none.
Definition: statistic.h:208
Statistic< StaPol_Var > stavar
The var statistic.
Definition: statistic.h:282
Statistic< StaPol_Mean > stamean
The mean statistic.
Definition: statistic.h:309
bool calculated(void) const noexcept
Return whether the statistic has been calculated.
Definition: statistic.h:205
constexpr StaDatum getstadatum_direct(const DatumIterator &ti)
A simple GetStaDatumFun that gets directly the datum from the iterator.
Definition: statistic.h:62
std::function< StaDatum(const DatumIterator &) > GetStaDatumFun
A function type that gets a datum from an iterator.
Definition: statistic.h:58
void calculate(const TIt &first, const TIt &pastend, const GetStaDatumFun< TIt > &getdatum=getstadatum_direct< TIt >)
Calculate the statistic on all members of the group at once.
Definition: statistic.h:286
double StaDatum
Type of data to allow for statistic calculation.
Definition: statistic.h:54
void reset(void)
Reset all statistics.
Definition: statistic.h:328
void reset(void)
Reset all statistics.
Definition: statistic.h:270
StaPol_Var(Statistic< StaPol_Mean > &meanstat)
Construct the policy for using incremental calculations.
Definition: statistic.h:148
void update(StaDatum v)
Update statistic on all members of the group at once.
Definition: statistic.h:323
Statistic< StaPol_Min > stamin
The min statistic.
Definition: statistic.h:255