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
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
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 library for Arduino includes sum, average, variance and std deviation
 | 
			
		||||
 | 
			
		||||
# Description
 | 
			
		||||
 | 
			
		||||
## Description
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
The stability of the formulas is improved by the help of Gil Ross (Thanks!)
 | 
			
		||||
 | 
			
		||||
The functions implemented are:
 | 
			
		||||
## Interface
 | 
			
		||||
 | 
			
		||||
* **clear(useStdDev)**
 | 
			
		||||
* **add(value)**
 | 
			
		||||
* **count()**   returns zero if count == zero (of course)
 | 
			
		||||
* **sum()**     returns zero if count == zero
 | 
			
		||||
* **minimum()** returns zero if count == zero
 | 
			
		||||
* **maximum()** returns zero if count == zero
 | 
			
		||||
* **average()** returns NAN if count == zero
 | 
			
		||||
- **Statistic(bool useStdDev = true)** Constructor, default use the standard deviation
 | 
			
		||||
functions. Setting this flag to **false** reduces math so slight increase of performance.
 | 
			
		||||
- **void clear(bool useStdDev = true)** resets all variables.
 | 
			
		||||
- **void add(float value)**
 | 
			
		||||
- **uint32_t count()** returns zero if count == zero (of course)
 | 
			
		||||
- **float sum()**      returns zero 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
 | 
			
		||||
* **pop_stdev()**        population stdev, returns NAN if count == zero
 | 
			
		||||
* **unbiased_stdev()**   returnsNAN if count == zero
 | 
			
		||||
- **variance()**         returns NAN if count == zero
 | 
			
		||||
- **pop_stdev()**        population stdev, returns NAN if count == zero
 | 
			
		||||
- **unbiased_stdev()**   returnsNAN if count == zero
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Operational
 | 
			
		||||
## Operational
 | 
			
		||||
 | 
			
		||||
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 
 | 
			
		||||
of memory quite fast. Instead a few calculated values are kept to be able to 
 | 
			
		||||
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. 
 | 
			
		||||
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** 
 | 
			
		||||
| 
						 | 
				
			
			@ -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.
 | 
			
		||||
 | 
			
		||||
*(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 
 | 
			
		||||
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 
 | 
			
		||||
| 
						 | 
				
			
			@ -69,11 +81,13 @@ but it works only if the samples are available and the they may be added
 | 
			
		|||
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**
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 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. 
 | 
			
		||||
See Wikipedia for an elaborate description of the difference between these two.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
//    FILE: Statistic.cpp
 | 
			
		||||
//  AUTHOR: Rob dot Tillaart at gmail dot com
 | 
			
		||||
//          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
 | 
			
		||||
//
 | 
			
		||||
// NOTE: 2011-01-07 Gill Ross
 | 
			
		||||
| 
						 | 
				
			
			@ -28,40 +28,43 @@
 | 
			
		|||
// unbiassed SE.
 | 
			
		||||
// -------------
 | 
			
		||||
//
 | 
			
		||||
// HISTORY:
 | 
			
		||||
// 0.1     2010-10-29 initial version
 | 
			
		||||
// 0.2     2010-10-29 stripped to minimal functionality
 | 
			
		||||
// 0.2.01  2010-10-30
 | 
			
		||||
//         added minimim, maximum, unbiased stdev,
 | 
			
		||||
//         changed counter to long -> int overflows @32K samples
 | 
			
		||||
// 0.3     2011-01-07
 | 
			
		||||
//         branched from 0.2.01 version of Rob Tillaart's code
 | 
			
		||||
// 0.3.1   2012-11-10 minor edits
 | 
			
		||||
// 0.3.2   2012-11-10 minor edits
 | 
			
		||||
//         changed count -> unsigned long allows for 2^32 samples
 | 
			
		||||
//         added variance()
 | 
			
		||||
// 0.3.3   2015-03-07
 | 
			
		||||
//         float -> double to support ARM (compiles)
 | 
			
		||||
//          moved count() sum() min() max() to .h; for optimizing compiler
 | 
			
		||||
// 0.3.4   2017-07-31
 | 
			
		||||
//         Refactored const in many places
 | 
			
		||||
//         [reverted] double to float on request as float is 99.99% of the cases
 | 
			
		||||
//         good enough and float(32 bit) is supported in HW for some processors.
 | 
			
		||||
// 0.3.5   2017-09-27
 | 
			
		||||
//         Added #include <Arduino.h> to fix uint32_t bug
 | 
			
		||||
// 0.4.0   2020-05-13
 | 
			
		||||
//         refactor
 | 
			
		||||
//         Added flag to switch on the use of stdDev runtime. [idea marc.recksiedl]
 | 
			
		||||
// 0.4.1   2020-06-19 fix library.json
 | 
			
		||||
//
 | 
			
		||||
//  HISTORY:
 | 
			
		||||
//  0.1     2010-10-29 initial version
 | 
			
		||||
//  0.2     2010-10-29 stripped to minimal functionality
 | 
			
		||||
//  0.2.01  2010-10-30
 | 
			
		||||
//          added minimim, maximum, unbiased stdev,
 | 
			
		||||
//          changed counter to long -> int overflows @32K samples
 | 
			
		||||
//  0.3     2011-01-07
 | 
			
		||||
//          branched from 0.2.01 version of Rob Tillaart's code
 | 
			
		||||
//  0.3.1   2012-11-10 minor edits
 | 
			
		||||
//  0.3.2   2012-11-10 minor edits
 | 
			
		||||
//          changed count -> unsigned long allows for 2^32 samples
 | 
			
		||||
//          added variance()
 | 
			
		||||
//  0.3.3   2015-03-07
 | 
			
		||||
//          float -> double to support ARM (compiles)
 | 
			
		||||
//           moved count() sum() min() max() to .h; for optimizing compiler
 | 
			
		||||
//  0.3.4   2017-07-31
 | 
			
		||||
//          Refactored const in many places
 | 
			
		||||
//          [reverted] double to float on request as float is 99.99% of the cases
 | 
			
		||||
//          good enough and float(32 bit) is supported in HW for some processors.
 | 
			
		||||
//  0.3.5   2017-09-27
 | 
			
		||||
//          Added #include <Arduino.h> to fix uint32_t bug
 | 
			
		||||
//  0.4.0   2020-05-13
 | 
			
		||||
//          refactor
 | 
			
		||||
//          Added flag to switch on the use of stdDev runtime. [idea marc.recksiedl]
 | 
			
		||||
//  0.4.1   2020-06-19  fix library.json
 | 
			
		||||
//  0.4.2   2021-01-08  add Arduino-CI + unit tests
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "Statistic.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Statistic::Statistic(bool useStdDev)
 | 
			
		||||
{
 | 
			
		||||
    clear(useStdDev);
 | 
			
		||||
  clear(useStdDev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void Statistic::clear(bool useStdDev)	// useStdDev default true.
 | 
			
		||||
{
 | 
			
		||||
    _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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// adds a new value to the data-set
 | 
			
		||||
void Statistic::add(const float value)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -96,12 +100,13 @@ void Statistic::add(const float value)
 | 
			
		|||
        // ~10% faster but limits the amount of samples to 65K as _cnt*_cnt overflows
 | 
			
		||||
        // float _store = _sum - _cnt * value;
 | 
			
		||||
        // _ssqdif = _ssqdif + _store * _store / (_cnt*_cnt - _cnt);
 | 
			
		||||
		//
 | 
			
		||||
		// solution:  TODO verify
 | 
			
		||||
		// _ssqdif = _ssqdif + (_store * _store / _cnt) / (_cnt - 1);
 | 
			
		||||
        //
 | 
			
		||||
        // solution:  TODO verify
 | 
			
		||||
        // _ssqdif = _ssqdif + (_store * _store / _cnt) / (_cnt - 1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// returns the average of the data-set added sofar
 | 
			
		||||
float Statistic::average() const
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -109,6 +114,7 @@ float Statistic::average() const
 | 
			
		|||
    return _sum / _cnt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Population standard deviation = s = sqrt [ S ( Xi - µ )2 / N ]
 | 
			
		||||
// http://www.suite101.com/content/how-is-standard-deviation-used-a99084
 | 
			
		||||
float Statistic::variance() const
 | 
			
		||||
| 
						 | 
				
			
			@ -118,6 +124,7 @@ float Statistic::variance() const
 | 
			
		|||
    return _ssqdif / _cnt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
float Statistic::pop_stdev() const
 | 
			
		||||
{
 | 
			
		||||
    if (!_useStdDev) return NAN;
 | 
			
		||||
| 
						 | 
				
			
			@ -125,6 +132,7 @@ float Statistic::pop_stdev() const
 | 
			
		|||
    return sqrt( _ssqdif / _cnt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
float Statistic::unbiased_stdev() const
 | 
			
		||||
{
 | 
			
		||||
    if (!_useStdDev) return NAN;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,15 +3,17 @@
 | 
			
		|||
//    FILE: Statistic.h
 | 
			
		||||
//  AUTHOR: Rob dot Tillaart at gmail dot com
 | 
			
		||||
//          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
 | 
			
		||||
// HISTORY: See Statistic.cpp
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <Arduino.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
#define STATISTIC_LIB_VERSION "0.4.1"
 | 
			
		||||
 | 
			
		||||
#define STATISTIC_LIB_VERSION       (F("0.4.2"))
 | 
			
		||||
 | 
			
		||||
class Statistic
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,7 @@
 | 
			
		|||
    "type": "git",
 | 
			
		||||
    "url": "https://github.com/RobTillaart/Statistic.git"
 | 
			
		||||
  },
 | 
			
		||||
  "version":"0.4.1",
 | 
			
		||||
  "version":"0.4.2",
 | 
			
		||||
  "frameworks": "arduino",
 | 
			
		||||
  "platforms": "*"
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
name=Statistic
 | 
			
		||||
version=0.4.1
 | 
			
		||||
version=0.4.2
 | 
			
		||||
author=Rob Tillaart <rob.tillaart@gmail.com>
 | 
			
		||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
 | 
			
		||||
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