Arduino ci (#3)

* add Arduino-ci
* add unit test
This commit is contained in:
Rob Tillaart 2021-01-08 15:14:13 +01:00 committed by GitHub
parent 593d1780c2
commit 5cbc9c0651
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 192 additions and 57 deletions

7
.arduino-ci.yml Normal file
View file

@ -0,0 +1,7 @@
compile:
# Choosing to run compilation tests on 2 different Arduino platforms
platforms:
- uno
- leonardo
- due
- zero

View 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

View file

@ -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

View file

@ -1,44 +1,55 @@
[![Arduino CI](https://github.com/RobTillaart/Statistic/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/Statistic/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/Statistic.svg?maxAge=3600)](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.

View file

@ -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;

View file

@ -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
{

View file

@ -18,7 +18,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/Statistic.git"
},
"version":"0.4.1",
"version":"0.4.2",
"frameworks": "arduino",
"platforms": "*"
}

View file

@ -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
View 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()
// --------