parent
593d1780c2
commit
5cbc9c0651
9 changed files with 192 additions and 57 deletions
7
.arduino-ci.yml
Normal file
7
.arduino-ci.yml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
compile:
|
||||||
|
# Choosing to run compilation tests on 2 different Arduino platforms
|
||||||
|
platforms:
|
||||||
|
- uno
|
||||||
|
- leonardo
|
||||||
|
- due
|
||||||
|
- zero
|
13
.github/workflows/arduino_test_runner.yml
vendored
Normal file
13
.github/workflows/arduino_test_runner.yml
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
name: Arduino CI
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
arduino_ci:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: Arduino-CI/action@master
|
||||||
|
# Arduino-CI/action@v0.1.1
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2010-2020 Rob Tillaart
|
Copyright (c) 2010-2021 Rob Tillaart
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
56
README.md
56
README.md
|
@ -1,44 +1,55 @@
|
||||||
|
|
||||||
|
[](https://github.com/marketplace/actions/arduino_ci)
|
||||||
|
[](https://github.com/RobTillaart/Statistic/blob/master/LICENSE)
|
||||||
|
[](https://github.com/RobTillaart/Statistic/releases)
|
||||||
|
|
||||||
|
|
||||||
# Statistic
|
# Statistic
|
||||||
|
|
||||||
Statistic library for Arduino includes sum, average, variance and std deviation
|
Statistic library for Arduino includes sum, average, variance and std deviation
|
||||||
|
|
||||||
# Description
|
|
||||||
|
## Description
|
||||||
|
|
||||||
The statistic library is made to get basic statistical information from a
|
The statistic library is made to get basic statistical information from a
|
||||||
one dimensional set of data, e.g. a stream of values of a sensor.
|
one dimensional set of data, e.g. a stream of values of a sensor.
|
||||||
|
|
||||||
The stability of the formulas is improved by the help of Gil Ross (Thanks!)
|
The stability of the formulas is improved by the help of Gil Ross (Thanks!)
|
||||||
|
|
||||||
The functions implemented are:
|
## Interface
|
||||||
|
|
||||||
* **clear(useStdDev)**
|
- **Statistic(bool useStdDev = true)** Constructor, default use the standard deviation
|
||||||
* **add(value)**
|
functions. Setting this flag to **false** reduces math so slight increase of performance.
|
||||||
* **count()** returns zero if count == zero (of course)
|
- **void clear(bool useStdDev = true)** resets all variables.
|
||||||
* **sum()** returns zero if count == zero
|
- **void add(float value)**
|
||||||
* **minimum()** returns zero if count == zero
|
- **uint32_t count()** returns zero if count == zero (of course)
|
||||||
* **maximum()** returns zero if count == zero
|
- **float sum()** returns zero if count == zero
|
||||||
* **average()** returns NAN if count == zero
|
- **float minimum()** returns zero if count == zero
|
||||||
|
- **float maximum()** returns zero if count == zero
|
||||||
|
- **float average()** returns NAN if count == zero
|
||||||
|
|
||||||
These three functions only work id useStdDev == true:
|
These three functions only work if **useStdDev == true**
|
||||||
|
|
||||||
* **variance()** returns NAN if count == zero
|
- **variance()** returns NAN if count == zero
|
||||||
* **pop_stdev()** population stdev, returns NAN if count == zero
|
- **pop_stdev()** population stdev, returns NAN if count == zero
|
||||||
* **unbiased_stdev()** returnsNAN if count == zero
|
- **unbiased_stdev()** returnsNAN if count == zero
|
||||||
|
|
||||||
|
|
||||||
# Operational
|
## Operational
|
||||||
|
|
||||||
See examples
|
See examples
|
||||||
|
|
||||||
# FAQ
|
## FAQ
|
||||||
|
|
||||||
|
#### Q: Are individual samples still available?
|
||||||
|
|
||||||
### Q: Are individual samples still available?
|
|
||||||
The values added to the library are not stored in the lib as it would use lots
|
The values added to the library are not stored in the lib as it would use lots
|
||||||
of memory quite fast. Instead a few calculated values are kept to be able to
|
of memory quite fast. Instead a few calculated values are kept to be able to
|
||||||
calculate the most important statistics.
|
calculate the most important statistics.
|
||||||
|
|
||||||
|
|
||||||
### Q: How many samples can the lib hold? (internal variables and overflow)
|
#### Q: How many samples can the lib hold? (internal variables and overflow)
|
||||||
|
|
||||||
The counter of samples is an **uint32_t**, implying a maximum of about **4 billion** samples.
|
The counter of samples is an **uint32_t**, implying a maximum of about **4 billion** samples.
|
||||||
In practice 'strange' things might happen before this number is reached.
|
In practice 'strange' things might happen before this number is reached.
|
||||||
There are two internal variables, **_sum** which is the sum of the values and **_ssq**
|
There are two internal variables, **_sum** which is the sum of the values and **_ssq**
|
||||||
|
@ -52,10 +63,11 @@ This workaround has no influence on the standard deviation.
|
||||||
|
|
||||||
!! Do not forget to add the expected average to the calculated average.
|
!! Do not forget to add the expected average to the calculated average.
|
||||||
|
|
||||||
*(Q: should this subtraction trick be build into the lib?)*
|
- Q: should this subtraction trick be build into the lib?
|
||||||
|
|
||||||
|
|
||||||
### Q: How about the precision of the library?
|
#### Q: How about the precision of the library?
|
||||||
|
|
||||||
The precision of the internal variables is restricted due to the fact
|
The precision of the internal variables is restricted due to the fact
|
||||||
that they are 32 bit float (IEEE754). If the internal variable **_sum** has
|
that they are 32 bit float (IEEE754). If the internal variable **_sum** has
|
||||||
a large value, adding relative small values to the dataset wouldn't
|
a large value, adding relative small values to the dataset wouldn't
|
||||||
|
@ -69,11 +81,13 @@ but it works only if the samples are available and the they may be added
|
||||||
in the sorted increasing order.
|
in the sorted increasing order.
|
||||||
|
|
||||||
|
|
||||||
### Q: When will internal var's overflow? esp. squared sum
|
#### Q: When will internal var's overflow? esp. squared sum
|
||||||
|
|
||||||
IEEE754 floats have a max value of about **+-3.4028235E+38**
|
IEEE754 floats have a max value of about **+-3.4028235E+38**
|
||||||
|
|
||||||
|
|
||||||
### Q: Why are there two functions for stdev?
|
#### Q: Why are there two functions for stdev?
|
||||||
|
|
||||||
There are two stdev functions the population stdev and the unbiased stdev.
|
There are two stdev functions the population stdev and the unbiased stdev.
|
||||||
See Wikipedia for an elaborate description of the difference between these two.
|
See Wikipedia for an elaborate description of the difference between these two.
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// FILE: Statistic.cpp
|
// FILE: Statistic.cpp
|
||||||
// AUTHOR: Rob dot Tillaart at gmail dot com
|
// AUTHOR: Rob dot Tillaart at gmail dot com
|
||||||
// modified at 0.3 by Gil Ross at physics dot org
|
// modified at 0.3 by Gil Ross at physics dot org
|
||||||
// VERSION: 0.4.1
|
// VERSION: 0.4.2
|
||||||
// PURPOSE: Recursive statistical library for Arduino
|
// PURPOSE: Recursive statistical library for Arduino
|
||||||
//
|
//
|
||||||
// NOTE: 2011-01-07 Gill Ross
|
// NOTE: 2011-01-07 Gill Ross
|
||||||
|
@ -53,15 +53,18 @@
|
||||||
// refactor
|
// refactor
|
||||||
// Added flag to switch on the use of stdDev runtime. [idea marc.recksiedl]
|
// Added flag to switch on the use of stdDev runtime. [idea marc.recksiedl]
|
||||||
// 0.4.1 2020-06-19 fix library.json
|
// 0.4.1 2020-06-19 fix library.json
|
||||||
//
|
// 0.4.2 2021-01-08 add Arduino-CI + unit tests
|
||||||
|
|
||||||
|
|
||||||
#include "Statistic.h"
|
#include "Statistic.h"
|
||||||
|
|
||||||
|
|
||||||
Statistic::Statistic(bool useStdDev)
|
Statistic::Statistic(bool useStdDev)
|
||||||
{
|
{
|
||||||
clear(useStdDev);
|
clear(useStdDev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Statistic::clear(bool useStdDev) // useStdDev default true.
|
void Statistic::clear(bool useStdDev) // useStdDev default true.
|
||||||
{
|
{
|
||||||
_cnt = 0;
|
_cnt = 0;
|
||||||
|
@ -74,6 +77,7 @@ void Statistic::clear(bool useStdDev) // useStdDev default true.
|
||||||
// which is SUM(from i = 1 to N) of f(i)-_ave_N)**2
|
// which is SUM(from i = 1 to N) of f(i)-_ave_N)**2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// adds a new value to the data-set
|
// adds a new value to the data-set
|
||||||
void Statistic::add(const float value)
|
void Statistic::add(const float value)
|
||||||
{
|
{
|
||||||
|
@ -102,6 +106,7 @@ void Statistic::add(const float value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// returns the average of the data-set added sofar
|
// returns the average of the data-set added sofar
|
||||||
float Statistic::average() const
|
float Statistic::average() const
|
||||||
{
|
{
|
||||||
|
@ -109,6 +114,7 @@ float Statistic::average() const
|
||||||
return _sum / _cnt;
|
return _sum / _cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Population standard deviation = s = sqrt [ S ( Xi - µ )2 / N ]
|
// Population standard deviation = s = sqrt [ S ( Xi - µ )2 / N ]
|
||||||
// http://www.suite101.com/content/how-is-standard-deviation-used-a99084
|
// http://www.suite101.com/content/how-is-standard-deviation-used-a99084
|
||||||
float Statistic::variance() const
|
float Statistic::variance() const
|
||||||
|
@ -118,6 +124,7 @@ float Statistic::variance() const
|
||||||
return _ssqdif / _cnt;
|
return _ssqdif / _cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float Statistic::pop_stdev() const
|
float Statistic::pop_stdev() const
|
||||||
{
|
{
|
||||||
if (!_useStdDev) return NAN;
|
if (!_useStdDev) return NAN;
|
||||||
|
@ -125,6 +132,7 @@ float Statistic::pop_stdev() const
|
||||||
return sqrt( _ssqdif / _cnt);
|
return sqrt( _ssqdif / _cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float Statistic::unbiased_stdev() const
|
float Statistic::unbiased_stdev() const
|
||||||
{
|
{
|
||||||
if (!_useStdDev) return NAN;
|
if (!_useStdDev) return NAN;
|
||||||
|
|
|
@ -3,15 +3,17 @@
|
||||||
// FILE: Statistic.h
|
// FILE: Statistic.h
|
||||||
// AUTHOR: Rob dot Tillaart at gmail dot com
|
// AUTHOR: Rob dot Tillaart at gmail dot com
|
||||||
// modified at 0.3 by Gil Ross at physics dot org
|
// modified at 0.3 by Gil Ross at physics dot org
|
||||||
// VERSION: 0.4.1
|
// VERSION: 0.4.2
|
||||||
// PURPOSE: Recursive Statistical library for Arduino
|
// PURPOSE: Recursive Statistical library for Arduino
|
||||||
// HISTORY: See Statistic.cpp
|
// HISTORY: See Statistic.cpp
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#define STATISTIC_LIB_VERSION "0.4.1"
|
|
||||||
|
#define STATISTIC_LIB_VERSION (F("0.4.2"))
|
||||||
|
|
||||||
class Statistic
|
class Statistic
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/RobTillaart/Statistic.git"
|
"url": "https://github.com/RobTillaart/Statistic.git"
|
||||||
},
|
},
|
||||||
"version":"0.4.1",
|
"version":"0.4.2",
|
||||||
"frameworks": "arduino",
|
"frameworks": "arduino",
|
||||||
"platforms": "*"
|
"platforms": "*"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
name=Statistic
|
name=Statistic
|
||||||
version=0.4.1
|
version=0.4.2
|
||||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||||
sentence=Library with basic statistical functions for Arduino.
|
sentence=Library with basic statistical functions for Arduino.
|
||||||
|
|
91
test/unit_test_001.cpp
Normal file
91
test/unit_test_001.cpp
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
//
|
||||||
|
// FILE: unit_test_001.cpp
|
||||||
|
// AUTHOR: Rob Tillaart
|
||||||
|
// DATE: 2021-01-08
|
||||||
|
// PURPOSE: unit tests for the Statistic library
|
||||||
|
// https://github.com/RobTillaart/Statistic
|
||||||
|
// https://github.com/Arduino-CI/arduino_ci/blob/master/REFERENCE.md
|
||||||
|
//
|
||||||
|
|
||||||
|
// supported assertions
|
||||||
|
// ----------------------------
|
||||||
|
// assertEqual(expected, actual); // a == b
|
||||||
|
// assertNotEqual(unwanted, actual); // a != b
|
||||||
|
// assertComparativeEquivalent(expected, actual); // abs(a - b) == 0 or (!(a > b) && !(a < b))
|
||||||
|
// assertComparativeNotEquivalent(unwanted, actual); // abs(a - b) > 0 or ((a > b) || (a < b))
|
||||||
|
// assertLess(upperBound, actual); // a < b
|
||||||
|
// assertMore(lowerBound, actual); // a > b
|
||||||
|
// assertLessOrEqual(upperBound, actual); // a <= b
|
||||||
|
// assertMoreOrEqual(lowerBound, actual); // a >= b
|
||||||
|
// assertTrue(actual);
|
||||||
|
// assertFalse(actual);
|
||||||
|
// assertNull(actual);
|
||||||
|
|
||||||
|
// // special cases for floats
|
||||||
|
// assertEqualFloat(expected, actual, epsilon); // fabs(a - b) <= epsilon
|
||||||
|
// assertNotEqualFloat(unwanted, actual, epsilon); // fabs(a - b) >= epsilon
|
||||||
|
// assertInfinity(actual); // isinf(a)
|
||||||
|
// assertNotInfinity(actual); // !isinf(a)
|
||||||
|
// assertNAN(arg); // isnan(a)
|
||||||
|
// assertNotNAN(arg); // !isnan(a)
|
||||||
|
|
||||||
|
#include <ArduinoUnitTests.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "Statistic.h"
|
||||||
|
|
||||||
|
|
||||||
|
unittest_setup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest_teardown()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unittest(test_constructor)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "VERSION: %s\n", STATISTIC_LIB_VERSION);
|
||||||
|
|
||||||
|
Statistic myStats;
|
||||||
|
assertEqual(0, myStats.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unittest(test_basic)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "VERSION: %s\n", STATISTIC_LIB_VERSION);
|
||||||
|
|
||||||
|
Statistic myStats;
|
||||||
|
|
||||||
|
for (int i = 1; i < 100; i++) myStats.add(i);
|
||||||
|
assertEqual(99, myStats.count());
|
||||||
|
assertEqualFloat(4950, myStats.sum(), 0.0001);
|
||||||
|
assertEqualFloat(1, myStats.minimum(), 0.0001);
|
||||||
|
assertEqualFloat(50, myStats.average(), 0.0001);
|
||||||
|
assertEqualFloat(99, myStats.maximum(), 0.0001);
|
||||||
|
assertEqualFloat(816.667, myStats.variance(), 0.001); // note 1 digit less
|
||||||
|
assertEqualFloat(28.5774, myStats.pop_stdev(), 0.0001);
|
||||||
|
assertEqualFloat(28.7228, myStats.unbiased_stdev(), 0.0001);
|
||||||
|
|
||||||
|
myStats.clear();
|
||||||
|
assertEqualFloat(0, myStats.sum(), 0.0001);
|
||||||
|
assertEqualFloat(0, myStats.minimum(), 0.0001);
|
||||||
|
assertEqualFloat(0, myStats.average(), 0.0001);
|
||||||
|
assertEqualFloat(0, myStats.maximum(), 0.0001);
|
||||||
|
assertEqualFloat(0, myStats.variance(), 0.0001);
|
||||||
|
assertEqualFloat(0, myStats.pop_stdev(), 0.0001);
|
||||||
|
assertEqualFloat(0, myStats.unbiased_stdev(), 0.0001);
|
||||||
|
|
||||||
|
assertEqual(0, myStats.count());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unittest_main()
|
||||||
|
|
||||||
|
// --------
|
Loading…
Reference in a new issue