├── .arduino-ci.yml ├── .github ├── FUNDING.yml └── workflows │ ├── arduino-lint.yml │ ├── arduino_test_runner.yml │ └── jsoncheck.yml ├── CHANGELOG.md ├── FAQ.md ├── LICENSE ├── README.md ├── Statistic.h ├── examples ├── Average │ ├── Average.ino │ ├── performance.0.3.4.txt │ ├── performance.0.4.0.txt │ ├── performance.0.4.3.txt │ └── performance.1.0.5.txt ├── StatisticArray │ └── StatisticArray.ino ├── TimingTest │ ├── TimingTest.ino │ ├── performance_0.4.0.txt │ ├── performance_0.4.4.txt │ └── performance_1.0.0.txt ├── statistic_add_overflow │ └── statistic_add_overflow.ino ├── statistic_range_middle │ ├── output_1.0.5.txt │ └── statistic_range_middle.ino └── statistic_test │ └── statistic_test.ino ├── keywords.txt ├── library.json ├── library.properties └── test └── unit_test_001.cpp /.arduino-ci.yml: -------------------------------------------------------------------------------- 1 | platforms: 2 | rpipico: 3 | board: rp2040:rp2040:rpipico 4 | package: rp2040:rp2040 5 | gcc: 6 | features: 7 | defines: 8 | - ARDUINO_ARCH_RP2040 9 | warnings: 10 | flags: 11 | 12 | packages: 13 | rp2040:rp2040: 14 | url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json 15 | 16 | compile: 17 | # Choosing to run compilation tests on 2 different Arduino platforms 18 | platforms: 19 | - uno 20 | - due 21 | - zero 22 | - leonardo 23 | - m4 24 | - esp32 25 | - esp8266 26 | - mega2560 27 | - rpipico 28 | 29 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: RobTillaart 4 | custom: "https://www.paypal.me/robtillaart" 5 | -------------------------------------------------------------------------------- /.github/workflows/arduino-lint.yml: -------------------------------------------------------------------------------- 1 | name: Arduino-lint 2 | 3 | on: [push, pull_request] 4 | jobs: 5 | lint: 6 | runs-on: ubuntu-latest 7 | timeout-minutes: 5 8 | steps: 9 | - uses: actions/checkout@v4 10 | - uses: arduino/arduino-lint-action@v1 11 | with: 12 | library-manager: update 13 | compliance: strict -------------------------------------------------------------------------------- /.github/workflows/arduino_test_runner.yml: -------------------------------------------------------------------------------- 1 | name: Arduino CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | runTest: 7 | runs-on: ubuntu-latest 8 | timeout-minutes: 20 9 | 10 | steps: 11 | - uses: actions/checkout@v4 12 | - uses: ruby/setup-ruby@v1 13 | with: 14 | ruby-version: 2.6 15 | - run: | 16 | gem install arduino_ci 17 | arduino_ci.rb 18 | -------------------------------------------------------------------------------- /.github/workflows/jsoncheck.yml: -------------------------------------------------------------------------------- 1 | name: JSON check 2 | 3 | on: 4 | push: 5 | paths: 6 | - '**.json' 7 | pull_request: 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | timeout-minutes: 5 13 | steps: 14 | - uses: actions/checkout@v4 15 | - name: json-syntax-check 16 | uses: limitusus/json-syntax-check@v2 17 | with: 18 | pattern: "\\.json$" -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/) 5 | and this project adheres to [Semantic Versioning](http://semver.org/). 6 | 7 | 8 | ## [1.0.8] - 2024-08-27 9 | - Merged #23, compilation error on C++17 or later (kudos to toge) 10 | 11 | ## [1.0.7] - 2024-08-20 12 | - Fix #21, add **getCoefficientOfVariation()** 13 | - update readme.md 14 | - update keywords.txt 15 | 16 | ## [1.0.6] - 2023-11-22 17 | - update readme.md 18 | 19 | ## [1.0.5] - 2023-06-29 20 | - fix #18 add **range()** and **middle()** 21 | - fast first order functions, based on minimum() and maximum() 22 | - statistic value is (very) limited. 23 | - add example. 24 | - update readme.md 25 | 26 | ## [1.0.4] - 2023-05-09 27 | - fix #16 => defined(__AVR__) to catch all ARCH_AVR 28 | 29 | ## [1.0.3] - 2023-05-09 30 | - fix #13 **sqrtf()** missing 31 | - prep more correct NaN when \_cnt == 0; 32 | 33 | ## [1.0.2] - 2023-03-14 34 | - update readme.md 35 | - update FAQ.md 36 | - update GitHub actions 37 | - update license 2023 38 | - minor edits 39 | 40 | ## [1.0.1] - 2022-11-25 41 | - simplified changelog.md 42 | 43 | ## [1.0.0] - 2022-03-09 44 | - CHANGELOG.md: moved history in Statistic.cpp to this file. 45 | - Turned this into a header-only library to make use of compiler 46 | inline optimizations. 47 | - Turned this into a class template to reduce dead code at compile 48 | time and allow for the use of other floating point formats (double, 49 | long double for example). 50 | - Replaced `#include ` with `#include ` to find 51 | the proper location of `uint32_t`. This also allows one to use the 52 | library in non-Arduino environments. 53 | 54 | ---- 55 | 56 | ## [0.4.4] - 2021-12-28 57 | - update library.json, readme, license, minor edits 58 | 59 | ## [0.4.3] - 2021-01-20 60 | - add() returns how much was actually added. 61 | 62 | ## [0.4.2] - 2021-01-08 63 | - add Arduino-CI + unit tests 64 | 65 | ## [0.4.1] - 2020-06-19 66 | - fix library.json 67 | 68 | ## [0.4.0] - 2020-05-13 69 | - refactor 70 | - Added flag to switch on the use of `stdDev` runtime. [idea marc.recksiedl] 71 | 72 | ---- 73 | 74 | ## [0.3.5] - 2017-09-27 75 | - Added `#include ` to fix `uint32_t` bug 76 | 77 | ## [0.3.4] - 2017-07-31 78 | - Refactored const in many places 79 | - reverted double to float on request as float is 99.99% of the 80 | cases good enough and float(32 bit) is supported in HW for some 81 | processors (e.g. Teensy). 82 | 83 | ## [0.3.3] - 2015-03-07 84 | - float -> double to support ARM (compiles) 85 | - moved count() sum() min() max() to .h; for optimizing compiler 86 | 87 | ## [0.3.2] - 2012-11-10 88 | - minor edits 89 | - added variance() 90 | - changed count -> unsigned long allows for 2^32 samples 91 | 92 | ## [0.3.1] - 2012-11-10 93 | - minor edits 94 | 95 | ## [0.3.0] - 2011-01-07 96 | - branched from 0.2.01 version of Rob Tillaart's code 97 | 98 | ---- 99 | 100 | ## [0.2.01] - 2010-10-30 101 | - added minimum(), maximum(), unbiased stdev(). 102 | - changed counter to long -> int overflows @32K samples 103 | 104 | ## [0.2.0] - 2010-10-29 105 | - stripped to minimal functionality 106 | 107 | ---- 108 | 109 | ## [0.1.0] - 2010-10-29 110 | - initial version 111 | -------------------------------------------------------------------------------- /FAQ.md: -------------------------------------------------------------------------------- 1 | ## FAQ 2 | 3 | #### Q: Are individual samples still available? 4 | 5 | The values added to the library are not stored in the lib as it would use lots 6 | of memory quite fast. Instead a few calculated values are kept to be able to 7 | calculate the most important statistics. 8 | 9 | 10 | #### Q: How many samples can the lib hold? Part 1: internal variables and overflow 11 | 12 | Since version 1.0.0 the user can define the ` value type` and the `count type` in the constructor. 13 | So one can use double (64) and uint64_t to improve precision at the price of performance. 14 | 15 | The (default) counter of samples is an **uint32_t**, implying a maximum of about **4 billion** samples. 16 | In practice many 'strange' things might happen before this number is reached. 17 | There are two internal variables, **\_sum** which is the sum of the values and **\_ssq** 18 | which is the sum of the squared values. Both can overflow especially **\_ssq** 19 | can and probably will grow fast. The library does not protect against it. 20 | 21 | **Estimated Average** 22 | There is a workaround for this (to some extend) if one knows the approx 23 | average of the samples before. Before adding values to the lib subtract 24 | the expected average. The sum of the samples would move to around zero. 25 | This workaround has no influence on the standard deviation. 26 | 27 | !! Do not forget to add the expected average to the calculated average. 28 | 29 | - Q: should this subtraction trick be build into the lib? 30 | 31 | 32 | #### Q: How many samples can the lib hold? Part 2: order of magnitude floats 33 | 34 | Since version 1.0.0 the user can define the ` value type` and the `count type` in the constructor. 35 | So one can use double (64) and uint64_t to improve precision at the price of performance. 36 | 37 | The samples are added in the internal variable **\_sum** and counted in **\_cnt**. 38 | In time **\_sum** will outgrow the added values in order of magnitude. 39 | As **\_sum** is a float with 23 bite = ~7 digits precision this problem starts 40 | to become significant between 1 and 10 million calls to **add()**. 41 | The assumption here is that what's added is always in the same order of magnitude 42 | (+- 1) e.g. an analogRead. 10 million looks like a lot but an analogRead takes only 43 | ~0.1 millisecond on a slow device like an UNO. 44 | 45 | Beyond the point that values aren't added any more, and the count still growing, 46 | one will see that the average will go down (very) slowly, but down. 47 | 48 | There are 2 ways to detect this problem: 49 | - check **count()** and decide after 100K samples to call **clear()**. 50 | - (since 0.4.3) Check the return value of **add()** to see what value is actually 51 | added to the internal **\_sum**. If this substantial different, it might be time 52 | to call **clear()** too. 53 | 54 | For applications that need to have an average of large streams of data there also 55 | exists a **runningAverage** library. This holds the last N (< 256) samples and take the 56 | average of them. This will often be the better tool. 57 | 58 | Also a consideration is to make less samples if possible. When temperature does 59 | not change more than 1x per minute, it makes no sense to sample it 2x per second. 60 | 61 | 62 | #### Q: How about the precision of the library? 63 | 64 | Since version 1.0.0 the user can define the ` value type` and the `count type` in the constructor. 65 | So one can use double (64) and uint64_t to improve precision at the price of performance. 66 | 67 | The precision of the internal variables is restricted due to the fact 68 | that they are 32 bit float (IEEE754). If the internal variable **\_sum** has 69 | a large value, adding relative small values to the dataset wouldn't 70 | change its value any more. Same is true for **\_ssq**. One might argue that 71 | statistically speaking these values are less significant, but in fact it is wrong. 72 | 73 | **Sorting values** 74 | There is a workaround for this (to some extend). If one has the samples in an 75 | array or on disk, one can sort the samples in increasing order (abs value) 76 | and add them from this sorted list. This will minimize the error, 77 | but it works only if the samples are available and they may be added 78 | in the sorted, increasing order. 79 | 80 | **Estimated Average** 81 | Another workaround is if one knows the EA = Estimated Average. 82 | By subtracting the EA from every value added, the sum will move roughly around zero. 83 | And the average will therefore also move around zero. 84 | The stdev is not affected and stays the same. 85 | The library does not support this "trick" 86 | - Note one need to correct the sum() with ```sum = _sum + AE * count```. 87 | - Note one need to correct the average() with ```average = _average + AE```. 88 | 89 | 90 | #### Q: When will internal var's overflow? esp. squared sum 91 | 92 | Since version 1.0.0 the user can define the ` value type` and the `count type` in the constructor. 93 | So one can use double (64) and uint64_t to improve precision at the price of performance. 94 | 95 | Single 96 | - https://en.wikipedia.org/wiki/Single-precision_floating-point_format 97 | - IEEE754 floats have a minimum value of about **+-1.17549435E-38** 98 | - IEEE754 floats have a maximum value of about **+-3.40282347E+38** 99 | 100 | Double 101 | - https://en.wikipedia.org/wiki/Double-precision_floating-point_format 102 | - IEEE754 doubles have a minimum value of about **+-2.225073858507201E-308** 103 | - IEEE754 doubles have a maximum value of about **+-1.797693134862315E+308** 104 | 105 | 106 | #### Q: Why are there two functions for stdev? 107 | 108 | There are two standard deviation (stdev) functions the population stdev and the unbiased stdev. 109 | See Wikipedia for an elaborate description of the difference between these two. 110 | - https://en.wikipedia.org/wiki/Standard_deviation 111 | 112 | 113 | #### Q: Missing a question? 114 | 115 | Please file an issue! 116 | 117 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2010-2024 Rob Tillaart 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [![Arduino CI](https://github.com/RobTillaart/Statistic/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci) 3 | [![Arduino-lint](https://github.com/RobTillaart/Statistic/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/Statistic/actions/workflows/arduino-lint.yml) 4 | [![JSON check](https://github.com/RobTillaart/Statistic/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/Statistic/actions/workflows/jsoncheck.yml) 5 | [![GitHub issues](https://img.shields.io/github/issues/RobTillaart/Statistic.svg)](https://github.com/RobTillaart/Statistic/issues) 6 | 7 | [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/Statistic/blob/master/LICENSE) 8 | [![GitHub release](https://img.shields.io/github/release/RobTillaart/Statistic.svg?maxAge=3600)](https://github.com/RobTillaart/Statistic/releases) 9 | [![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/Statistic.svg)](https://registry.platformio.org/libraries/robtillaart/Statistic) 10 | 11 | 12 | # Statistic 13 | 14 | Header-only statistic library for Arduino includes sum, average, variance and standard deviation. 15 | 16 | The `statistic::Statistic` class template accepts 3 arguments: 17 | 18 | * **`typename T`:** The floating point type used to represent the statistics. 19 | * **`typename C`:** The unsigned integer type to store the number of values. 20 | * **`typename _useStdDev`:** Compile-time flag for using variance and standard deviation. 21 | 22 | To maintain backwards compatibility with API <= 0.4.4, the `Statistic` 23 | class implementation has been moved to the `statistic` namespace and a 24 | `typedef statistic::Statistic Statistic` type 25 | definition has been created at global scope. 26 | 27 | The `useStdDev` boolean was moved from a run-time to a compile-time 28 | option for two reasons. First, the compile-time option allows the 29 | optimizer to eliminate dead code (calculating standard deviation and 30 | variances) for a slightly smaller code size. Second, it was observed 31 | in uses of the library that the `useStdDev` boolean was set once in 32 | the class constructor and was never modified at run-time. 33 | 34 | 35 | ## Description 36 | 37 | The statistic library is made to get basic statistical information from a 38 | one dimensional set of data, e.g. a stream of values of a sensor. 39 | 40 | The stability of the formulas is improved by the help of Gil Ross (Thanks!). 41 | 42 | The template version (1.0.0) is created by Glen Cornell (Thanks!). 43 | 44 | 45 | #### Related 46 | 47 | - https://github.com/RobTillaart/Correlation 48 | - https://github.com/RobTillaart/GST - Golden standard test metrics 49 | - https://github.com/RobTillaart/Histogram 50 | - https://github.com/RobTillaart/RunningAngle 51 | - https://github.com/RobTillaart/RunningAverage 52 | - https://github.com/RobTillaart/RunningMedian 53 | - https://github.com/RobTillaart/statHelpers - combinations & permutations 54 | - https://github.com/RobTillaart/Statistic 55 | - https://github.com/RobTillaart/Student 56 | 57 | 58 | ## Interface 59 | 60 | ```cpp 61 | #include "Statistic.h" 62 | ``` 63 | 64 | #### Constructor 65 | 66 | - **Statistic(void)** Default constructor. 67 | - **statistic::Statistic** Constructor, with value type, count type, and standard deviation flag. 68 | The types mentioned are the defaults of the template. 69 | You can override e.g. **statistic::Statistic** for many high precision values. 70 | (assumes double >> float). 71 | - **void clear()** resets all internal variables and counters. 72 | 73 | 74 | #### Core 75 | 76 | - **typename T add(const typename T value)** returns value actually added to internal sum. 77 | If this differs from what should have been added, or even zero, the internal administration is running out of precision. 78 | If this happens after a lot of **add()** calls, it might become time to call **clear()**. 79 | Alternatively one need to define the statistic object with a more precise data type (typical double instead of float). 80 | - **typename C count()** returns zero if count == zero (of course). Must be checked to interpret other values. 81 | - **typename T sum()** returns zero if count == zero. 82 | - **typename T minimum()** returns zero if count == zero. 83 | - **typename T maximum()** returns zero if count == zero. 84 | - **typename T range()** returns maximum - minimum. 85 | - **typename T middle()** returns (minimum + maximum)/2. If T is an integer type rounding errors are possible. 86 | - **typename T average()** returns NAN if count == zero. 87 | 88 | These three functions only work if **useStdDev == true** (in the template). 89 | 90 | - **typename T variance()** returns NAN if count == zero. 91 | - **typename T pop_stdev()** returns NAN if count == zero. 92 | pop_stdev = population standard deviation, 93 | - **typename T unbiased_stdev()** returns NAN if count == zero. 94 | - **typename T getCoefficientOfVariation()** returns coefficient of variation. 95 | This is defined as standardDeviation / Average. 96 | It indicates if the distribution is relative small ( < 1) or relative wide ( > 1). 97 | Note it has no meaning when the average is zero (or close to zero). 98 | 99 | 100 | #### Deprecated methods 101 | 102 | - **Statistic(bool)** Constructor previously used to enable/disable the standard deviation functions. 103 | This argument now has no effect. It is recommended to migrate your code to the default constructor 104 | (which now also implicitly calls `clear()`). 105 | - **void clear(bool)** resets all variables. The boolean argument is ignored. 106 | It is recommended to migrate your code to `clear()` (with no arguments). 107 | 108 | 109 | #### Range() and middle() 110 | 111 | **Range()** and **middle()** are fast functions with limited statistical value. 112 | Still they have their uses. 113 | 114 | Given enough samples (e.g. 100+) and a normal distribution of the samples the **range()** is expected 115 | to be 3 to 4 times the **pop_stdev()**. 116 | If the range is larger than 4 standard deviations one might have added one or more outliers. 117 | 118 | Given enough samples (e.g. 100+) and a normal distribution, the **middle()** and **average()** are 119 | expected to be close to each other. 120 | Note: outliers can disrupt the **middle()**, Several non-normal distributions do too. 121 | 122 | 123 | ## Operational 124 | 125 | See examples. 126 | 127 | 128 | ## Faq 129 | 130 | See https://github.com/RobTillaart/Statistic/blob/master/FAQ.md 131 | 132 | 133 | ## Future 134 | 135 | #### Must 136 | 137 | - update documentation 138 | - links that explain statistics in more depth 139 | 140 | #### Should 141 | 142 | - remove deprecated methods. (1.1.0) 143 | 144 | #### Could 145 | 146 | - add **expected average EA** compensation trick 147 | - every add will subtract EA before added to sum, 148 | - this will keep the **\_sum** to around zero. 149 | - this will move **average()** to around zero. 150 | - do not forget to add **EA** to average. 151 | - do not forget to add **EA** times count for sum. 152 | - does not affect the **std_dev()** 153 | - all functions will become slightly slower. 154 | - maybe in a derived class? 155 | - **lastTimeAdd()** convenience, user can track timestamp 156 | - **largestDelta()** largest difference between two consecutive additions. 157 | - need lastValue + delta so far. 158 | 159 | #### Wont 160 | 161 | - return values of **sum(), minimum(), maximum()** when **count()** == zero 162 | - should these be NaN, which is technically more correct? 163 | - does it exist for all value types? => No! 164 | - user responsibility to check **count()** first. 165 | 166 | 167 | ## Support 168 | 169 | If you appreciate my libraries, you can support the development and maintenance. 170 | Improve the quality of the libraries by providing issues and Pull Requests, or 171 | donate through PayPal or GitHub sponsors. 172 | 173 | Thank you, 174 | 175 | -------------------------------------------------------------------------------- /Statistic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // 3 | // FILE: Statistic.h 4 | // AUTHOR: Rob Tillaart 5 | // modified at 0.3 by Gil Ross at physics dot org 6 | // template version 1.0.0 by Glen Cornell 7 | // VERSION: 1.0.8 8 | // PURPOSE: Recursive Statistical library for Arduino 9 | // HISTORY: See CHANGELOG.md 10 | // 11 | // NOTE: 2011-01-07 Gill Ross 12 | // Rob Tillaart's Statistic library uses one-pass of the data (allowing 13 | // each value to be discarded), but expands the Sum of Squares Differences to 14 | // difference the Sum of Squares and the Average Squared. This is susceptible 15 | // to bit length precision errors with the float type (only 5 or 6 digits 16 | // absolute precision) so for long runs and high ratios of 17 | // the average value to standard deviation the estimate of the 18 | // standard error (deviation) becomes the difference of two large 19 | // numbers and will tend to zero. 20 | // 21 | // For small numbers of iterations and small Average/SE the original code is 22 | // likely to work fine. 23 | // It should also be recognised that for very large samples, questions 24 | // of stability of the sample assume greater importance than the 25 | // correctness of the asymptotic estimators. 26 | // 27 | // This recursive algorithm, which takes slightly more computation per 28 | // iteration is numerically stable. 29 | // It updates the number, mean, max, min and SumOfSquaresDiff each step to 30 | // deliver max min average, population standard error (standard deviation) and 31 | // unbiased SE. 32 | 33 | // Toolchains for some platforms don't have the stdc++ library, so 34 | // we'll make substitutions for features that we use. If your 35 | // platform isn't specified here and fails to compile, then you can 36 | // explicitly override the HAVE_STDCXX_TYPE_TRAITS, HAVE_STDCXX_CMATH, 37 | // and HAVE_STDCXX_CSTDINT feature macros in your build environment. 38 | 39 | 40 | #define STATISTIC_LIB_VERSION (F("1.0.8")) 41 | 42 | 43 | #if defined(__AVR__) 44 | #define HAVE_STDCXX_TYPE_TRAITS 0 45 | #define HAVE_STDCXX_CMATH 0 46 | #define HAVE_STDCXX_CSTDINT 0 47 | #else 48 | #ifndef HAVE_STDCXX_TYPE_TRAITS 49 | #define HAVE_STDCXX_TYPE_TRAITS 1 50 | #endif 51 | #ifndef HAVE_STDCXX_CMATH 52 | #define HAVE_STDCXX_CMATH 1 53 | #endif 54 | #ifndef HAVE_STDCXX_CSTDINT 55 | #define HAVE_STDCXX_CSTDINT 1 56 | #endif 57 | #endif 58 | 59 | 60 | #if HAVE_STDCXX_TYPE_TRAITS || defined(_GLIBCXX_TYPE_TRAITS) 61 | #include 62 | #else 63 | namespace std { 64 | // substitute for std::conditional if not in your tool chain 65 | template 66 | struct conditional { typedef T type; }; 67 | template 68 | struct conditional { typedef F type; }; 69 | }; 70 | #endif /* HAVE_STDCXX_TYPE_TRAITS */ 71 | 72 | 73 | #if HAVE_STDCXX_CMATH || defined(_GLIBCXX_CMATH) 74 | #include 75 | #if not defined(__cplusplus) || __cplusplus < 201703L 76 | // substitute for std::sqrtf function, patch for issue #13 77 | #undef sqrtf 78 | namespace std { 79 | inline float sqrtf(float n) { return __builtin_sqrtf(n); } 80 | }; 81 | #endif 82 | #else 83 | #include 84 | // substitute for std::sqrt functions if not in your tool chain 85 | #undef sqrt 86 | namespace std { 87 | inline float sqrt(float n) { return __builtin_sqrtf(n); } 88 | inline double sqrt(double n) { return __builtin_sqrt(n); } 89 | inline long double sqrt(long double n) { return __builtin_sqrtl(n); } 90 | }; 91 | #endif /* HAVE_STDCXX_CMATH */ 92 | 93 | 94 | #if HAVE_STDCXX_CSTDINT || defined(_GLIBCXX_CSTDINT) 95 | #include 96 | #else 97 | #include // uint32_t, etc. 98 | #endif /* HAVE_STDCXX_CSTDINT */ 99 | 100 | 101 | #if HAVE_STDCXX_LIMITS || defined(_GLIBCXX_NUMERIC_LIMITS) 102 | #include 103 | #else 104 | namespace std { 105 | template 106 | struct numeric_limits { 107 | static constexpr T 108 | quiet_NaN() { return T(); } 109 | }; 110 | template<> 111 | struct numeric_limits { 112 | static constexpr float 113 | quiet_NaN() { return __builtin_nanf(""); } 114 | }; 115 | template<> 116 | struct numeric_limits { 117 | static constexpr double 118 | quiet_NaN() { return __builtin_nan(""); } 119 | }; 120 | template<> 121 | struct numeric_limits { 122 | static constexpr long double 123 | quiet_NaN() { return __builtin_nanl(""); } 124 | }; 125 | }; 126 | #endif /* HAVE_STDCXX_LIMITS */ 127 | 128 | 129 | /////////////////////////////////////////////////////////////////////////////// 130 | // 131 | // STATISTICS CLASS 132 | // 133 | 134 | namespace statistic { 135 | 136 | template 137 | class Statistic 138 | { 139 | public: 140 | typedef T value_type; 141 | typedef C count_type; 142 | 143 | static constexpr value_type NaN { std::numeric_limits::quiet_NaN() }; 144 | 145 | Statistic() = default; 146 | 147 | 148 | void clear() { 149 | _cnt = 0; 150 | _sum = 0; // NaN; 151 | _min = 0; // NaN; 152 | _max = 0; // NaN; 153 | _extra.clear(); 154 | // NOTE: _extra "guards" the conditional code e.g. ssqdiff 155 | // NOTE: ssqdiff = not _ssq but sum of square differences 156 | // which is SUM(from i = 1 to N) of f(i)-_ave_N)**2 157 | } 158 | 159 | 160 | // returns value actually added 161 | value_type add(const value_type value) { 162 | value_type previousSum = _sum; 163 | if (_cnt == 0) 164 | { 165 | _min = value; 166 | _max = value; 167 | } else { 168 | if (value < _min) _min = value; 169 | else if (value > _max) _max = value; 170 | } 171 | _sum += value; 172 | _cnt++; 173 | 174 | if (_useStdDev && (_cnt > 1)) 175 | { 176 | value_type _store = (_sum / _cnt - value); 177 | _extra.ssqdif(_extra.ssqdif() + _cnt * _store * _store / (_cnt - 1)); 178 | 179 | // NOTE: pre 1.0.0 code 180 | // ~10% faster but limits the amount of samples to 65K as _cnt*_cnt overflows 181 | // value_type _store = _sum - _cnt * value; 182 | // _ssqdif = _ssqdif + _store * _store / (_cnt*_cnt - _cnt); 183 | // 184 | // solution: TODO verify 185 | // _ssqdif = _ssqdif + (_store * _store / _cnt) / (_cnt - 1); 186 | } 187 | return _sum - previousSum; 188 | } 189 | 190 | 191 | // returns the number of values added 192 | count_type count() const { return _cnt; }; // zero if count == zero 193 | value_type sum() const { return _sum; }; // zero if count == zero 194 | value_type minimum() const { return _min; }; // zero if count == zero 195 | value_type maximum() const { return _max; }; // zero if count == zero 196 | value_type range() const { return _max - _min; }; // zero if count == zero 197 | value_type middle() const 198 | { 199 | // prevent over- or underflow if value_type is an int type 200 | double mid = _max * 0.5 + _min * 0.5; 201 | return (value_type) mid; 202 | }; // zero if count == zero 203 | 204 | 205 | // NAN if count == zero 206 | value_type average() const { 207 | if (_cnt == 0) return NaN; // prevent DIV0 error 208 | return _sum / _cnt; 209 | } 210 | 211 | 212 | // useStdDev must be true to use next three 213 | // all return NAN if count == zero 214 | value_type variance() const { 215 | if (!_useStdDev) return NaN; 216 | if (_cnt == 0) return NaN; // prevent DIV0 error 217 | return _extra.ssqdif() / _cnt; 218 | } 219 | 220 | 221 | // Population standard deviation 222 | value_type pop_stdev() const { 223 | if (!_useStdDev) return NaN; 224 | if (_cnt == 0) return NaN; // prevent DIV0 error 225 | return std::sqrt( _extra.ssqdif() / _cnt); 226 | } 227 | 228 | 229 | value_type unbiased_stdev() const { 230 | if (!_useStdDev) return NaN; 231 | if (_cnt < 2) return NaN; // prevent DIV0 error 232 | return std::sqrt( _extra.ssqdif() / (_cnt - 1)); 233 | } 234 | 235 | value_type getCoefficientOfVariation() const { 236 | if (_sum == 0) return NaN; 237 | value_type temp = pop_stdev(); // as all samples are available 238 | if (temp == NaN) return NaN; 239 | // return standard deviation / average 240 | value_type cv = temp * _cnt / _sum; 241 | return cv; 242 | } 243 | 244 | // deprecated methods: 245 | Statistic(bool) { 246 | } __attribute__ ((deprecated ("use default constructor instead"))); 247 | void clear(bool) { 248 | clear(); 249 | } __attribute__ ((deprecated ("use Statistic::clear(void) instead"))); 250 | 251 | 252 | protected: 253 | count_type _cnt { 0 }; 254 | value_type _sum { 0.0 }; // NaN; 255 | value_type _min { 0.0 }; // NaN; 256 | value_type _max { 0.0 }; // NaN; 257 | 258 | 259 | // Conditionally compile to reduce dead code if not used 260 | struct Empty { 261 | void clear() { } 262 | value_type ssqdif() const { return NaN; } 263 | void ssqdif(value_type v) { } 264 | }; 265 | 266 | 267 | struct StdDev { 268 | value_type _ssqdif { 0.0 }; // sum of squares difference 269 | void clear() { _ssqdif = 0.0; } 270 | value_type ssqdif() const { return _ssqdif; } 271 | void ssqdif(value_type v) { _ssqdif = v; } 272 | }; 273 | 274 | 275 | typename std::conditional<_useStdDev, StdDev, Empty>::type _extra; 276 | }; 277 | 278 | } // namespace statistic 279 | 280 | 281 | // This typedef maintains backwards API compatibility with library 282 | // versions <= 0.4.4. 283 | typedef statistic::Statistic Statistic; 284 | 285 | 286 | // NOTE: Do not issue 'using statistic;' in your code because the 287 | // compiler will not be able to distinguish between the template 288 | // '::Statistic' and the typedef 'statistic::Statistic' 289 | 290 | 291 | // -- END OF FILE -- 292 | 293 | -------------------------------------------------------------------------------- /examples/Average/Average.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: Average.ino 3 | // AUTHOR: Rob Tillaart 4 | // PURPOSE: Sample sketch for statistic library Arduino 5 | 6 | 7 | #include "Statistic.h" 8 | 9 | statistic::Statistic myStats; 10 | // Statistic myStats; // pre 1.0.0 declaration 11 | 12 | uint32_t start; 13 | uint32_t stop; 14 | 15 | 16 | void setup(void) 17 | { 18 | Serial.begin(115200); 19 | Serial.println(__FILE__); 20 | Serial.print("Demo Statistics lib "); 21 | Serial.println(STATISTIC_LIB_VERSION); 22 | myStats.clear(); //explicitly start clean 23 | start = millis(); 24 | } 25 | 26 | 27 | void loop(void) 28 | { 29 | long rn = random(0, 9999); 30 | myStats.add(rn / 100.0 + 1); 31 | if (myStats.count() == 10000) 32 | { 33 | stop = millis(); 34 | Serial.print(" Count: "); 35 | Serial.println(myStats.count()); 36 | Serial.print(" Min: "); 37 | Serial.println(myStats.minimum(), 4); 38 | Serial.print(" Max: "); 39 | Serial.println(myStats.maximum(), 4); 40 | Serial.print(" Average: "); 41 | Serial.println(myStats.average(), 4); 42 | Serial.print(" variance: "); 43 | Serial.println(myStats.variance(), 4); 44 | Serial.print(" pop stdev: "); 45 | Serial.println(myStats.pop_stdev(), 4); 46 | Serial.print(" unbias stdev: "); 47 | Serial.println(myStats.unbiased_stdev(), 4); 48 | Serial.print(" time(ms): "); 49 | Serial.println(stop - start); 50 | Serial.println("====================================="); 51 | myStats.clear(); 52 | delay(1000); 53 | start = millis(); 54 | } 55 | } 56 | 57 | 58 | // -- END OF FILE -- 59 | 60 | -------------------------------------------------------------------------------- /examples/Average/performance.0.3.4.txt: -------------------------------------------------------------------------------- 1 | C:\Users\Rob\Desktop\WORK\Arduino\libraries\Statistic\examples\Average\Average.ino 2 | Demo Statistics lib 0.3.4 3 | Count: 10000 4 | Min: 1.0100 5 | Max: 100.9600 6 | Average: 50.9408 7 | variance: 835.0057 8 | pop stdev: 28.8965 9 | unbias stdev: 28.8979 10 | time(ms): 2547 11 | ===================================== 12 | Count: 10000 13 | Min: 1.0000 14 | Max: 100.9800 15 | Average: 51.4161 16 | variance: 839.9565 17 | pop stdev: 28.9820 18 | unbias stdev: 28.9835 19 | time(ms): 2548 20 | ===================================== 21 | Count: 10000 22 | Min: 1.0000 23 | Max: 100.9800 24 | Average: 50.9561 25 | variance: 833.2212 26 | pop stdev: 28.8656 27 | unbias stdev: 28.8670 28 | time(ms): 2547 29 | ===================================== 30 | Count: 10000 31 | Min: 1.0000 32 | Max: 100.9700 33 | Average: 51.4648 34 | variance: 849.5839 35 | pop stdev: 29.1476 36 | unbias stdev: 29.1491 37 | time(ms): 2549 38 | ===================================== 39 | Count: 10000 40 | Min: 1.0000 41 | Max: 100.9800 42 | Average: 50.8610 43 | variance: 842.0071 44 | pop stdev: 29.0174 45 | unbias stdev: 29.0188 46 | time(ms): 2548 47 | ===================================== 48 | Count: 10000 49 | Min: 1.0000 50 | Max: 100.9800 51 | Average: 51.2327 52 | variance: 816.5170 53 | pop stdev: 28.5748 54 | unbias stdev: 28.5762 55 | time(ms): 2548 56 | ===================================== 57 | Count: 10000 58 | Min: 1.0000 59 | Max: 100.9800 60 | Average: 50.8115 61 | variance: 835.1608 62 | pop stdev: 28.8991 63 | unbias stdev: 28.9006 64 | time(ms): 2547 65 | ===================================== 66 | Count: 10000 67 | Min: 1.0000 68 | Max: 100.9800 69 | Average: 50.7948 70 | variance: 842.5279 71 | pop stdev: 29.0263 72 | unbias stdev: 29.0278 73 | time(ms): 2548 74 | ===================================== 75 | Count: 10000 76 | Min: 1.0000 77 | Max: 100.9500 78 | Average: 51.0943 79 | variance: 831.8248 80 | pop stdev: 28.8414 81 | unbias stdev: 28.8428 82 | time(ms): 2547 83 | ===================================== 84 | Count: 10000 85 | Min: 1.0000 86 | Max: 100.9700 87 | Average: 50.8915 88 | variance: 836.6669 89 | pop stdev: 28.9252 90 | unbias stdev: 28.9266 91 | time(ms): 2546 92 | ===================================== 93 | Count: 10000 94 | Min: 1.0100 95 | Max: 100.9800 96 | Average: 50.8437 97 | variance: 825.5516 98 | pop stdev: 28.7324 99 | unbias stdev: 28.7339 100 | time(ms): 2548 101 | ===================================== 102 | -------------------------------------------------------------------------------- /examples/Average/performance.0.4.0.txt: -------------------------------------------------------------------------------- 1 | C:\Users\Rob\AppData\Local\Temp\arduino_modified_sketch_796772\Average.ino 2 | Demo Statistics lib 0.4.0 3 | Count: 10000 4 | Min: 1.0100 5 | Max: 100.9600 6 | Average: 50.9408 7 | variance: 835.0057 8 | pop stdev: 28.8965 9 | unbias stdev: 28.8979 10 | time(ms): 2537 11 | ===================================== 12 | Count: 10000 13 | Min: 1.0000 14 | Max: 100.9800 15 | Average: 51.4161 16 | variance: 839.9565 17 | pop stdev: 28.9820 18 | unbias stdev: 28.9835 19 | time(ms): 2538 20 | ===================================== 21 | Count: 10000 22 | Min: 1.0000 23 | Max: 100.9800 24 | Average: 50.9561 25 | variance: 833.2212 26 | pop stdev: 28.8656 27 | unbias stdev: 28.8670 28 | time(ms): 2538 29 | ===================================== 30 | Count: 10000 31 | Min: 1.0000 32 | Max: 100.9700 33 | Average: 51.4648 34 | variance: 849.5839 35 | pop stdev: 29.1476 36 | unbias stdev: 29.1491 37 | time(ms): 2539 38 | ===================================== 39 | Count: 10000 40 | Min: 1.0000 41 | Max: 100.9800 42 | Average: 50.8610 43 | variance: 842.0071 44 | pop stdev: 29.0174 45 | unbias stdev: 29.0188 46 | time(ms): 2538 47 | ===================================== 48 | Count: 10000 49 | Min: 1.0000 50 | Max: 100.9800 51 | Average: 51.2327 52 | variance: 816.5170 53 | pop stdev: 28.5748 54 | unbias stdev: 28.5762 55 | time(ms): 2537 56 | ===================================== 57 | Count: 10000 58 | Min: 1.0000 59 | Max: 100.9800 60 | Average: 50.8115 61 | variance: 835.1608 62 | pop stdev: 28.8991 63 | unbias stdev: 28.9006 64 | time(ms): 2538 65 | ===================================== 66 | Count: 10000 67 | Min: 1.0000 68 | Max: 100.9800 69 | Average: 50.7948 70 | variance: 842.5279 71 | pop stdev: 29.0263 72 | unbias stdev: 29.0278 73 | time(ms): 2538 74 | ===================================== 75 | Count: 10000 76 | Min: 1.0000 77 | Max: 100.9500 78 | Average: 51.0943 79 | variance: 831.8248 80 | pop stdev: 28.8414 81 | unbias stdev: 28.8428 82 | time(ms): 2537 83 | ===================================== 84 | Count: 10000 85 | Min: 1.0000 86 | Max: 100.9700 87 | Average: 50.8915 88 | variance: 836.6669 89 | pop stdev: 28.9252 90 | unbias stdev: 28.9266 91 | time(ms): 2537 92 | ===================================== 93 | Count: 10000 94 | Min: 1.0100 95 | Max: 100.9800 96 | Average: 50.8437 97 | variance: 825.5516 98 | pop stdev: 28.7324 99 | unbias stdev: 28.7339 100 | time(ms): 2537 101 | ===================================== 102 | -------------------------------------------------------------------------------- /examples/Average/performance.0.4.3.txt: -------------------------------------------------------------------------------- 1 | D:\Rob\WORK\Arduino\libraries\Statistic\examples\Average\Average.ino 2 | Demo Statistics lib 0.4.3 3 | Count: 10000 4 | Min: 1.0100 5 | Max: 100.9600 6 | Average: 50.9408 7 | variance: 835.0057 8 | pop stdev: 28.8965 9 | unbias stdev: 28.8979 10 | time(ms): 2539 11 | ===================================== 12 | Count: 10000 13 | Min: 1.0000 14 | Max: 100.9800 15 | Average: 51.4161 16 | variance: 839.9565 17 | pop stdev: 28.9820 18 | unbias stdev: 28.9835 19 | time(ms): 2539 20 | ===================================== 21 | Count: 10000 22 | Min: 1.0000 23 | Max: 100.9800 24 | Average: 50.9561 25 | variance: 833.2212 26 | pop stdev: 28.8656 27 | unbias stdev: 28.8670 28 | time(ms): 2539 29 | ===================================== 30 | Count: 10000 31 | Min: 1.0000 32 | Max: 100.9700 33 | Average: 51.4648 34 | variance: 849.5839 35 | pop stdev: 29.1476 36 | unbias stdev: 29.1491 37 | time(ms): 2541 38 | ===================================== 39 | Count: 10000 40 | Min: 1.0000 41 | Max: 100.9800 42 | Average: 50.8610 43 | variance: 842.0071 44 | pop stdev: 29.0174 45 | unbias stdev: 29.0188 46 | time(ms): 2539 47 | ===================================== 48 | Count: 10000 49 | Min: 1.0000 50 | Max: 100.9800 51 | Average: 51.2327 52 | variance: 816.5170 53 | pop stdev: 28.5748 54 | unbias stdev: 28.5762 55 | time(ms): 2538 56 | ===================================== 57 | Count: 10000 58 | Min: 1.0000 59 | Max: 100.9800 60 | Average: 50.8115 61 | variance: 835.1608 62 | pop stdev: 28.8991 63 | unbias stdev: 28.9006 64 | time(ms): 2539 65 | ===================================== 66 | Count: 10000 67 | Min: 1.0000 68 | Max: 100.9800 69 | Average: 50.7948 70 | variance: 842.5279 71 | pop stdev: 29.0263 72 | unbias stdev: 29.0278 73 | time(ms): 2540 74 | ===================================== 75 | Count: 10000 76 | Min: 1.0000 77 | Max: 100.9500 78 | Average: 51.0943 79 | variance: 831.8248 80 | pop stdev: 28.8414 81 | unbias stdev: 28.8428 82 | time(ms): 2537 83 | ===================================== 84 | Count: 10000 85 | Min: 1.0000 86 | Max: 100.9700 87 | Average: 50.8915 88 | variance: 836.6669 89 | pop stdev: 28.9252 90 | unbias stdev: 28.9266 91 | time(ms): 2539 92 | ===================================== 93 | Count: 10000 94 | Min: 1.0100 95 | Max: 100.9800 96 | Average: 50.8437 97 | variance: 825.5516 98 | pop stdev: 28.7324 99 | unbias stdev: 28.7339 100 | time(ms): 2539 101 | ===================================== 102 | -------------------------------------------------------------------------------- /examples/Average/performance.1.0.5.txt: -------------------------------------------------------------------------------- 1 | D:\Rob\WORK\Arduino\libraries\Statistic\examples\Average\Average.ino 2 | Demo Statistics lib 1.0.5 3 | Count: 10000 4 | Min: 1.0100 5 | Max: 100.9600 6 | Average: 50.9408 7 | variance: 835.0057 8 | pop stdev: 28.8965 9 | unbias stdev: 28.8979 10 | time(ms): 2536 11 | ===================================== 12 | Count: 10000 13 | Min: 1.0000 14 | Max: 100.9800 15 | Average: 51.4161 16 | variance: 839.9565 17 | pop stdev: 28.9820 18 | unbias stdev: 28.9835 19 | time(ms): 2535 20 | ===================================== 21 | Count: 10000 22 | Min: 1.0000 23 | Max: 100.9800 24 | Average: 50.9561 25 | variance: 833.2212 26 | pop stdev: 28.8656 27 | unbias stdev: 28.8670 28 | time(ms): 2536 29 | ===================================== 30 | Count: 10000 31 | Min: 1.0000 32 | Max: 100.9700 33 | Average: 51.4648 34 | variance: 849.5839 35 | pop stdev: 29.1476 36 | unbias stdev: 29.1491 37 | time(ms): 2537 38 | ===================================== 39 | Count: 10000 40 | Min: 1.0000 41 | Max: 100.9800 42 | Average: 50.8610 43 | variance: 842.0071 44 | pop stdev: 29.0174 45 | unbias stdev: 29.0188 46 | time(ms): 2537 47 | ===================================== 48 | Count: 10000 49 | Min: 1.0000 50 | Max: 100.9800 51 | Average: 51.2327 52 | variance: 816.5170 53 | pop stdev: 28.5748 54 | unbias stdev: 28.5762 55 | time(ms): 2535 56 | ===================================== 57 | Count: 10000 58 | Min: 1.0000 59 | Max: 100.9800 60 | Average: 50.8115 61 | variance: 835.1608 62 | pop stdev: 28.8991 63 | unbias stdev: 28.9006 64 | time(ms): 2536 65 | ===================================== 66 | Count: 10000 67 | Min: 1.0000 68 | Max: 100.9800 69 | Average: 50.7948 70 | variance: 842.5279 71 | pop stdev: 29.0263 72 | unbias stdev: 29.0278 73 | time(ms): 2535 74 | ===================================== 75 | Count: 10000 76 | Min: 1.0000 77 | Max: 100.9500 78 | Average: 51.0943 79 | variance: 831.8248 80 | pop stdev: 28.8414 81 | unbias stdev: 28.8428 82 | time(ms): 2536 83 | ===================================== 84 | Count: 10000 85 | Min: 1.0000 86 | Max: 100.9700 87 | Average: 50.8915 88 | variance: 836.6669 89 | pop stdev: 28.9252 90 | unbias stdev: 28.9266 91 | time(ms): 2536 92 | ===================================== 93 | Count: 10000 94 | Min: 1.0100 95 | Max: 100.9800 96 | Average: 50.8437 97 | variance: 825.5516 98 | pop stdev: 28.7324 99 | unbias stdev: 28.7339 100 | time(ms): 2536 101 | ===================================== 102 | -------------------------------------------------------------------------------- /examples/StatisticArray/StatisticArray.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: StatisticArray.ino 3 | // AUTHOR: Rob Tillaart 4 | // PURPOSE: Sample sketch for statistic library Arduino 5 | 6 | 7 | #include "Statistic.h" 8 | 9 | Statistic stats[4]; 10 | 11 | 12 | void setup(void) 13 | { 14 | Serial.begin(115200); 15 | Serial.println(__FILE__); 16 | Serial.print("Demo Statistics lib "); 17 | Serial.println(STATISTIC_LIB_VERSION); 18 | for (int i=0; i<4; i++) 19 | { 20 | stats[i].clear(); //explicitly start clean 21 | } 22 | } 23 | 24 | 25 | void loop(void) 26 | { 27 | long rn = random(0, 9999); 28 | int idx = random(0, 4); 29 | stats[idx].add(rn / 100.0 + 1); 30 | 31 | if (stats[idx].count() == 10000) 32 | { 33 | Serial.print("IDX: "); 34 | Serial.println(idx); 35 | Serial.print(" Count: "); 36 | Serial.println(stats[idx].count()); 37 | Serial.print(" Min: "); 38 | Serial.println(stats[idx].minimum(), 4); 39 | Serial.print(" Max: "); 40 | Serial.println(stats[idx].maximum(), 4); 41 | Serial.print(" Average: "); 42 | Serial.println(stats[idx].average(), 4); 43 | Serial.println("====================================="); 44 | stats[idx].clear(); 45 | } 46 | } 47 | 48 | 49 | // -- END OF FILE -- 50 | 51 | -------------------------------------------------------------------------------- /examples/TimingTest/TimingTest.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: TimingTest.ino 3 | // AUTHOR: Rob Tillaart 4 | // PURPOSE: measure time difference for runtime stddev toggle. 5 | // add is 1024 milliseconds faster for 10K adds ==> ~ 100uSec per add faster. 6 | 7 | 8 | #include "Statistic.h" 9 | 10 | Statistic myStats; 11 | 12 | uint32_t start; 13 | uint32_t stop; 14 | 15 | bool useStdDev = true; 16 | 17 | 18 | void setup(void) 19 | { 20 | Serial.begin(115200); 21 | Serial.println(__FILE__); 22 | Serial.print("Demo Statistics lib "); 23 | Serial.println(STATISTIC_LIB_VERSION); 24 | myStats.clear(useStdDev); 25 | start = millis(); 26 | } 27 | 28 | 29 | void loop(void) 30 | { 31 | long rn = random(0, 9999); 32 | myStats.add(rn / 100.0 + 1); 33 | if (myStats.count() == 10000) 34 | { 35 | stop = millis(); 36 | Serial.print(" Count: "); 37 | Serial.println(myStats.count()); 38 | Serial.print(" Min: "); 39 | Serial.println(myStats.minimum(), 4); 40 | Serial.print(" Max: "); 41 | Serial.println(myStats.maximum(), 4); 42 | Serial.print(" Average: "); 43 | Serial.println(myStats.average(), 4); 44 | if (useStdDev) 45 | { 46 | Serial.print(" variance: "); 47 | Serial.println(myStats.variance(), 4); 48 | Serial.print(" pop stdev: "); 49 | Serial.println(myStats.pop_stdev(), 4); 50 | Serial.print(" unbias stdev: "); 51 | Serial.println(myStats.unbiased_stdev(), 4); 52 | } 53 | Serial.print(" time(ms): "); 54 | Serial.println(stop - start); 55 | Serial.println("====================================="); 56 | useStdDev = !useStdDev; 57 | myStats.clear(useStdDev); 58 | start = millis(); 59 | } 60 | } 61 | 62 | 63 | // -- END OF FILE -- 64 | 65 | -------------------------------------------------------------------------------- /examples/TimingTest/performance_0.4.0.txt: -------------------------------------------------------------------------------- 1 | TimingTest.ino 2 | Demo Statistics lib 0.4.0 3 | Count: 10000 4 | Min: 1.0100 5 | Max: 100.9600 6 | Average: 50.9408 7 | variance: 835.0057 8 | pop stdev: 28.8965 9 | unbias stdev: 28.8979 10 | time(ms): 2537 11 | ===================================== 12 | Count: 10000 13 | Min: 1.0000 14 | Max: 100.9800 15 | Average: 51.4161 16 | time(ms): 1514 17 | ===================================== 18 | Count: 10000 19 | Min: 1.0000 20 | Max: 100.9800 21 | Average: 50.9561 22 | variance: 833.2212 23 | pop stdev: 28.8656 24 | unbias stdev: 28.8670 25 | time(ms): 2538 26 | ===================================== 27 | Count: 10000 28 | Min: 1.0000 29 | Max: 100.9700 30 | Average: 51.4648 31 | time(ms): 1513 32 | ===================================== 33 | Count: 10000 34 | Min: 1.0000 35 | Max: 100.9800 36 | Average: 50.8610 37 | variance: 842.0071 38 | pop stdev: 29.0174 39 | unbias stdev: 29.0188 40 | time(ms): 2538 41 | ===================================== 42 | Count: 10000 43 | Min: 1.0000 44 | Max: 100.9800 45 | Average: 51.2327 46 | time(ms): 1515 47 | ===================================== 48 | Count: 10000 49 | Min: 1.0000 50 | Max: 100.9800 51 | Average: 50.8115 52 | variance: 835.1608 53 | pop stdev: 28.8991 54 | unbias stdev: 28.9006 55 | time(ms): 2538 56 | ===================================== 57 | Count: 10000 58 | Min: 1.0000 59 | Max: 100.9800 60 | Average: 50.7948 61 | time(ms): 1514 62 | ===================================== 63 | Count: 10000 64 | Min: 1.0000 65 | Max: 100.9500 66 | Average: 51.0943 67 | variance: 831.8248 68 | pop stdev: 28.8414 69 | unbias stdev: 28.8428 70 | time(ms): 2538 71 | ===================================== 72 | Count: 10000 73 | Min: 1.0000 74 | Max: 100.9700 75 | Average: 50.8915 76 | time(ms): 1514 77 | ===================================== 78 | -------------------------------------------------------------------------------- /examples/TimingTest/performance_0.4.4.txt: -------------------------------------------------------------------------------- 1 | TimingTest.ino 2 | Demo Statistics lib 0.4.4 3 | Count: 10000 4 | Min: 1.0100 5 | Max: 100.9600 6 | Average: 50.9408 7 | variance: 835.0057 8 | pop stdev: 28.8965 9 | unbias stdev: 28.8979 10 | time(ms): 2538 11 | ===================================== 12 | Count: 10000 13 | Min: 1.0000 14 | Max: 100.9800 15 | Average: 51.4161 16 | time(ms): 1515 17 | ===================================== 18 | Count: 10000 19 | Min: 1.0000 20 | Max: 100.9800 21 | Average: 50.9561 22 | variance: 833.2212 23 | pop stdev: 28.8656 24 | unbias stdev: 28.8670 25 | time(ms): 2540 26 | ===================================== 27 | Count: 10000 28 | Min: 1.0000 29 | Max: 100.9700 30 | Average: 51.4648 31 | time(ms): 1515 32 | ===================================== 33 | Count: 10000 34 | Min: 1.0000 35 | Max: 100.9800 36 | Average: 50.8610 37 | variance: 842.0071 38 | pop stdev: 29.0174 39 | unbias stdev: 29.0188 40 | time(ms): 2540 41 | ===================================== 42 | Count: 10000 43 | Min: 1.0000 44 | Max: 100.9800 45 | Average: 51.2327 46 | time(ms): 1516 47 | ===================================== 48 | Count: 10000 49 | Min: 1.0000 50 | Max: 100.9800 51 | Average: 50.8115 52 | variance: 835.1608 53 | pop stdev: 28.8991 54 | unbias stdev: 28.9006 55 | time(ms): 2540 56 | ===================================== 57 | Count: 10000 58 | Min: 1.0000 59 | Max: 100.9800 60 | Average: 50.7948 61 | time(ms): 1515 62 | ===================================== 63 | -------------------------------------------------------------------------------- /examples/TimingTest/performance_1.0.0.txt: -------------------------------------------------------------------------------- 1 | Demo Statistics lib 1.0.0 2 | Count: 10000 3 | Min: 1.0100 4 | Max: 100.9600 5 | Average: 50.9408 6 | variance: 835.0057 7 | pop stdev: 28.8965 8 | unbias stdev: 28.8979 9 | time(ms): 2535 10 | ===================================== 11 | Count: 10000 12 | Min: 1.0000 13 | Max: 100.9800 14 | Average: 51.4161 15 | time(ms): 2537 16 | ===================================== 17 | Count: 10000 18 | Min: 1.0000 19 | Max: 100.9800 20 | Average: 50.9561 21 | variance: 833.2212 22 | pop stdev: 28.8656 23 | unbias stdev: 28.8670 24 | time(ms): 2536 25 | ===================================== 26 | Count: 10000 27 | Min: 1.0000 28 | Max: 100.9700 29 | Average: 51.4648 30 | time(ms): 2537 31 | ===================================== 32 | Count: 10000 33 | Min: 1.0000 34 | Max: 100.9800 35 | Average: 50.8610 36 | variance: 842.0071 37 | pop stdev: 29.0174 38 | unbias stdev: 29.0188 39 | time(ms): 2537 40 | ===================================== 41 | Count: 10000 42 | Min: 1.0000 43 | Max: 100.9800 44 | Average: 51.2327 45 | time(ms): 2536 46 | ===================================== 47 | Count: 10000 48 | Min: 1.0000 49 | Max: 100.9800 50 | Average: 50.8115 51 | variance: 835.1608 52 | pop stdev: 28.8991 53 | unbias stdev: 28.9006 54 | time(ms): 2535 55 | ===================================== 56 | Count: 10000 57 | Min: 1.0000 58 | Max: 100.9800 59 | Average: 50.7948 60 | time(ms): 2536 61 | ===================================== 62 | Count: 10000 63 | Min: 1.0000 64 | Max: 100.9500 65 | Average: 51.0943 66 | variance: 831.8248 67 | pop stdev: 28.8414 68 | unbias stdev: 28.8428 69 | time(ms): 2536 70 | ===================================== 71 | Count: 10000 72 | Min: 1.0000 73 | Max: 100.9700 74 | Average: 50.8915 75 | time(ms): 2535 76 | ===================================== 77 | Count: 10000 78 | Min: 1.0100 79 | Max: 100.9800 80 | Average: 50.8437 81 | variance: 825.5516 82 | pop stdev: 28.7324 83 | unbias stdev: 28.7339 84 | time(ms): 2536 85 | ===================================== 86 | Count: 10000 87 | Min: 1.0000 88 | Max: 100.9800 89 | Average: 51.3439 90 | time(ms): 2537 91 | ===================================== 92 | Count: 10000 93 | Min: 1.0400 94 | Max: 100.9800 95 | Average: 50.9124 96 | variance: 833.6501 97 | pop stdev: 28.8730 98 | unbias stdev: 28.8744 99 | time(ms): 2536 100 | ===================================== 101 | Count: 10000 102 | Min: 1.0000 103 | Max: 100.9500 104 | Average: 50.7144 105 | time(ms): 2534 106 | ===================================== 107 | Count: 10000 108 | Min: 1.0000 109 | Max: 100.9800 110 | Average: 50.8693 111 | variance: 832.8941 112 | pop stdev: 28.8599 113 | unbias stdev: 28.8613 114 | time(ms): 2536 115 | ===================================== 116 | Count: 10000 117 | Min: 1.0100 118 | Max: 100.9800 119 | Average: 50.4681 120 | time(ms): 2536 121 | ===================================== 122 | Count: 10000 123 | Min: 1.0000 124 | Max: 100.9700 125 | Average: 50.8079 126 | variance: 830.4100 127 | pop stdev: 28.8168 128 | unbias stdev: 28.8183 129 | time(ms): 2536 130 | ===================================== 131 | Count: 10000 132 | Min: 1.0000 133 | Max: 100.9800 134 | Average: 50.9519 135 | time(ms): 2536 136 | ===================================== 137 | Count: 10000 138 | Min: 1.0100 139 | Max: 100.9500 140 | Average: 51.1545 141 | variance: 842.0332 142 | pop stdev: 29.0178 143 | unbias stdev: 29.0193 144 | time(ms): 2535 145 | ===================================== 146 | Count: 10000 147 | Min: 1.0000 148 | Max: 100.9800 149 | Average: 51.2756 150 | time(ms): 2535 151 | ===================================== 152 | Count: 10000 153 | Min: 1.0000 154 | Max: 100.9600 155 | Average: 51.0082 156 | variance: 836.6192 157 | pop stdev: 28.9244 158 | unbias stdev: 28.9258 159 | time(ms): 2536 160 | ===================================== 161 | Count: 10000 162 | Min: 1.0000 163 | Max: 100.9500 164 | Average: 51.4703 165 | time(ms): 2538 166 | ===================================== 167 | -------------------------------------------------------------------------------- /examples/statistic_add_overflow/statistic_add_overflow.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: statistic_add_overflow.ino 3 | // AUTHOR: Rob Tillaart 4 | // PURPOSE: this sketch shows a known (rounding) problem when the 5 | // internal sum is orders of magnitude larger than the added value. 6 | 7 | 8 | #include "Statistic.h" 9 | 10 | Statistic myStats; 11 | 12 | 13 | void setup(void) 14 | { 15 | Serial.begin(115200); 16 | Serial.println(__FILE__); 17 | Serial.print("STATISTIC_LIB_VERSION: "); 18 | Serial.println(STATISTIC_LIB_VERSION); 19 | 20 | myStats.clear(); 21 | 22 | Serial.println("\nCOUNT\tVALUE\tACTUAL\tRATIO"); 23 | for (float value = 1e8; value > 1; value *= 0.1) 24 | { 25 | float actual = myStats.add(value); 26 | float ratio = actual / value; 27 | 28 | Serial.print(myStats.count()); 29 | Serial.print('\t'); 30 | Serial.print(value); 31 | Serial.print('\t'); 32 | Serial.print(actual); 33 | Serial.print('\t'); 34 | Serial.print(ratio); 35 | Serial.print('\n'); 36 | } 37 | 38 | for (float value = 10; value > 0.1; value -= 1) 39 | { 40 | float actual = myStats.add(value); 41 | float ratio = actual / value; 42 | 43 | Serial.print(myStats.count()); 44 | Serial.print('\t'); 45 | Serial.print(value); 46 | Serial.print('\t'); 47 | Serial.print(actual); 48 | Serial.print('\t'); 49 | Serial.print(ratio); 50 | Serial.print('\n'); 51 | } 52 | 53 | Serial.print("\nQED..."); 54 | } 55 | 56 | 57 | void loop(void) 58 | { 59 | } 60 | 61 | 62 | // -- END OF FILE -- 63 | 64 | -------------------------------------------------------------------------------- /examples/statistic_range_middle/output_1.0.5.txt: -------------------------------------------------------------------------------- 1 | D:\Rob\WORK\Arduino\libraries\Statiop stdev: 28.8965 2 | range/stddev: 3.4589 3 | ===================================== 4 | D:\Rob\WORK\Arduino\libraries\Statistic\examples\statistic_range_middle\statistic_range_middle.ino 5 | STATISTIC_LIB_VERSION: 1.0.5 6 | Count: 10000 7 | Min: 1.0100 8 | Max: 100.9600 9 | Range: 99.9500 10 | Middle: 50.9850 11 | Average: 50.9408 12 | middle - avg: 0.0442 13 | variance: 835.0057 14 | pop stdev: 28.8965 15 | range/stddev: 3.4589 16 | ===================================== 17 | Count: 10000 18 | Min: 1.0000 19 | Max: 100.9800 20 | Range: 99.9800 21 | Middle: 50.9900 22 | Average: 51.4161 23 | middle - avg: -0.4261 24 | variance: 839.9565 25 | pop stdev: 28.9820 26 | range/stddev: 3.4497 27 | ===================================== 28 | Count: 10000 29 | Min: 1.0000 30 | Max: 100.9800 31 | Range: 99.9800 32 | Middle: 50.9900 33 | Average: 50.9561 34 | middle - avg: 0.0339 35 | variance: 833.2212 36 | pop stdev: 28.8656 37 | range/stddev: 3.4636 38 | ===================================== 39 | Count: 10000 40 | Min: 1.0000 41 | Max: 100.9700 42 | Range: 99.9700 43 | Middle: 50.9850 44 | Average: 51.4648 45 | middle - avg: -0.4798 46 | variance: 849.5839 47 | pop stdev: 29.1476 48 | range/stddev: 3.4298 49 | ===================================== 50 | Count: 10000 51 | Min: 1.0000 52 | Max: 100.9800 53 | Range: 99.9800 54 | Middle: 50.9900 55 | Average: 50.8610 56 | middle - avg: 0.1290 57 | variance: 842.0071 58 | pop stdev: 29.0174 59 | range/stddev: 3.4455 60 | ===================================== 61 | Count: 10000 62 | Min: 1.0000 63 | Max: 100.9800 64 | Range: 99.9800 65 | Middle: 50.9900 66 | Average: 51.2327 67 | middle - avg: -0.2427 68 | variance: 816.5170 69 | pop stdev: 28.5748 70 | range/stddev: 3.4989 71 | ===================================== 72 | Count: 10000 73 | Min: 1.0000 74 | Max: 100.9800 75 | Range: 99.9800 76 | Middle: 50.9900 77 | Average: 50.8115 78 | middle - avg: 0.1785 79 | variance: 835.1608 80 | pop stdev: 28.8991 81 | range/stddev: 3.4596 82 | ===================================== 83 | Count: 10000 84 | Min: 1.0000 85 | Max: 100.9800 86 | Range: 99.9800 87 | Middle: 50.9900 88 | Average: 50.7948 89 | middle - avg: 0.1952 90 | variance: 842.5279 91 | pop stdev: 29.0263 92 | range/stddev: 3.4445 93 | ===================================== 94 | Count: 10000 95 | Min: 1.0000 96 | Max: 100.9500 97 | Range: 99.9500 98 | Middle: 50.9750 99 | Average: 51.0943 100 | middle - avg: -0.1193 101 | variance: 831.8248 102 | pop stdev: 28.8414 103 | range/stddev: 3.4655 104 | ===================================== 105 | -------------------------------------------------------------------------------- /examples/statistic_range_middle/statistic_range_middle.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: statistic_range_middle.ino 3 | // AUTHOR: Rob Tillaart 4 | // PURPOSE: Sample sketch for statistic library Arduino 5 | 6 | 7 | #include "Statistic.h" 8 | 9 | statistic::Statistic myStats; 10 | // Statistic myStats; // pre 1.0.0 declaration 11 | 12 | 13 | void setup(void) 14 | { 15 | Serial.begin(115200); 16 | Serial.println(__FILE__); 17 | Serial.print("STATISTIC_LIB_VERSION: "); 18 | Serial.println(STATISTIC_LIB_VERSION); 19 | myStats.clear(); // explicitly start clean 20 | } 21 | 22 | 23 | void loop(void) 24 | { 25 | long rn = random(0, 9999); 26 | myStats.add(rn / 100.0 + 1); 27 | if (myStats.count() == 10000) 28 | { 29 | Serial.print(" Count: "); 30 | Serial.println(myStats.count()); 31 | Serial.print(" Min: "); 32 | Serial.println(myStats.minimum(), 4); 33 | Serial.print(" Max: "); 34 | Serial.println(myStats.maximum(), 4); 35 | Serial.print(" Range: "); 36 | Serial.println(myStats.range(), 4); 37 | Serial.print(" Middle: "); 38 | Serial.println(myStats.middle(), 4); 39 | Serial.print(" Average: "); 40 | Serial.println(myStats.average(), 4); 41 | Serial.print(" middle - avg: "); 42 | Serial.println(myStats.middle() - myStats.average(), 4); 43 | Serial.print(" variance: "); 44 | Serial.println(myStats.variance(), 4); 45 | Serial.print(" pop stdev: "); 46 | Serial.println(myStats.pop_stdev(), 4); 47 | Serial.print(" range/stddev: "); 48 | Serial.println(myStats.range() / myStats.pop_stdev(), 4); 49 | Serial.println("====================================="); 50 | myStats.clear(); 51 | delay(1000); 52 | } 53 | } 54 | 55 | 56 | // -- END OF FILE -- 57 | -------------------------------------------------------------------------------- /examples/statistic_test/statistic_test.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: statistic_test.ino 3 | // AUTHOR: Rob Tillaart 4 | // PURPOSE: test sketch 5 | 6 | 7 | #include "Statistic.h" 8 | 9 | statistic::Statistic myStats; 10 | // Statistic myStats; // pre 1.0.0 declaration 11 | 12 | 13 | void setup(void) 14 | { 15 | Serial.begin(115200); 16 | Serial.println(__FILE__); 17 | Serial.print("Demo Statistics lib "); 18 | Serial.println(STATISTIC_LIB_VERSION); 19 | 20 | myStats.clear(); // explicitly start clean 21 | 22 | 23 | for (int i = 0; i < 10; i++) 24 | { 25 | myStats.add(i * 0.01 + 1); // add 10 elements 26 | } 27 | Serial.print(" Count: "); 28 | Serial.println(myStats.count()); 29 | Serial.print(" Min: "); 30 | Serial.println(myStats.minimum(), 4); 31 | Serial.print(" Max: "); 32 | Serial.println(myStats.maximum(), 4); 33 | Serial.print(" Average: "); 34 | Serial.println(myStats.average(), 4); 35 | Serial.print(" variance: "); 36 | Serial.println(myStats.variance(), 4); 37 | Serial.print(" pop stdev: "); 38 | Serial.println(myStats.pop_stdev(), 4); 39 | Serial.print(" unbias stdev: "); 40 | Serial.println(myStats.unbiased_stdev(), 4); 41 | Serial.print("CoefVariation: "); 42 | Serial.println(myStats.getCoefficientOfVariation(), 4); 43 | } 44 | 45 | 46 | void loop(void) 47 | { 48 | } 49 | 50 | 51 | // -- END OF FILE -- 52 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | # Syntax Colouring Map For Statistic 2 | 3 | # Data types (KEYWORD1) 4 | Statistic KEYWORD1 5 | 6 | 7 | # Methods and Functions (KEYWORD2) 8 | clear KEYWORD2 9 | add KEYWORD2 10 | count KEYWORD2 11 | sum KEYWORD2 12 | 13 | minimum KEYWORD2 14 | maximum KEYWORD2 15 | average KEYWORD2 16 | 17 | variance KEYWORD2 18 | pop_stdev KEYWORD2 19 | unbiased_stdev KEYWORD2 20 | getCoefficientOfVariation KEYWORD2 21 | 22 | range KEYWORD2 23 | middle KEYWORD2 24 | 25 | 26 | # Instances (KEYWORD2) 27 | 28 | # Constants (LITERAL1) 29 | STATISTIC_LIB_VERSION LITERAL1 30 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Statistic", 3 | "keywords": "Statistic,sum,min,max,average,variance,standard,deviation,population,unbiased", 4 | "description": "Library with basic statistical functions for Arduino.", 5 | "authors": 6 | [ 7 | { 8 | "name": "Rob Tillaart", 9 | "email": "Rob.Tillaart@gmail.com", 10 | "maintainer": true 11 | }, 12 | { 13 | "name": "Gil Ross" 14 | }, 15 | { 16 | "name": "Glen Cornell" 17 | } 18 | ], 19 | "repository": 20 | { 21 | "type": "git", 22 | "url": "https://github.com/RobTillaart/Statistic.git" 23 | }, 24 | "version": "1.0.8", 25 | "license": "MIT", 26 | "frameworks": "*", 27 | "platforms": "*", 28 | "headers": "Statistic.h" 29 | } 30 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Statistic 2 | version=1.0.8 3 | author=Rob Tillaart 4 | maintainer=Rob Tillaart 5 | sentence=Library with basic statistical functions for Arduino. 6 | paragraph=Supports count, sum, minimum, maximum, average, variance, standard deviation, population and unbiased. 7 | category=Data Processing 8 | url=https://github.com/RobTillaart/Statistic 9 | architectures=* 10 | includes=Statistic.h 11 | depends= 12 | -------------------------------------------------------------------------------- /test/unit_test_001.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: unit_test_001.cpp 3 | // AUTHOR: Rob Tillaart 4 | // DATE: 2021-01-08 5 | // PURPOSE: unit tests for the Statistic library 6 | // https://github.com/RobTillaart/Statistic 7 | // https://github.com/Arduino-CI/arduino_ci/blob/master/REFERENCE.md 8 | // 9 | 10 | // supported assertions 11 | // ---------------------------- 12 | // assertEqual(expected, actual); // a == b 13 | // assertNotEqual(unwanted, actual); // a != b 14 | // assertComparativeEquivalent(expected, actual); // abs(a - b) == 0 or (!(a > b) && !(a < b)) 15 | // assertComparativeNotEquivalent(unwanted, actual); // abs(a - b) > 0 or ((a > b) || (a < b)) 16 | // assertLess(upperBound, actual); // a < b 17 | // assertMore(lowerBound, actual); // a > b 18 | // assertLessOrEqual(upperBound, actual); // a <= b 19 | // assertMoreOrEqual(lowerBound, actual); // a >= b 20 | // assertTrue(actual); 21 | // assertFalse(actual); 22 | // assertNull(actual); 23 | 24 | // // special cases for floats 25 | // assertEqualFloat(expected, actual, epsilon); // fabs(a - b) <= epsilon 26 | // assertNotEqualFloat(unwanted, actual, epsilon); // fabs(a - b) >= epsilon 27 | // assertInfinity(actual); // isinf(a) 28 | // assertNotInfinity(actual); // !isinf(a) 29 | // assertNAN(arg); // isnan(a) 30 | // assertNotNAN(arg); // !isnan(a) 31 | 32 | 33 | #include 34 | 35 | 36 | #include "Arduino.h" 37 | #include "Statistic.h" 38 | 39 | 40 | unittest_setup() 41 | { 42 | fprintf(stderr, "\nSTATISTIC_LIB_VERSION: %s\n", (char *) STATISTIC_LIB_VERSION); 43 | } 44 | 45 | unittest_teardown() 46 | { 47 | } 48 | 49 | 50 | unittest(test_constructor) 51 | { 52 | Statistic myStats; 53 | assertEqual(0, myStats.count()); 54 | } 55 | 56 | 57 | unittest(test_basic) 58 | { 59 | Statistic myStats; 60 | 61 | for (int i = 1; i < 100; i++) myStats.add(i); 62 | assertEqual(99, myStats.count()); 63 | assertEqualFloat(4950, myStats.sum(), 0.0001); 64 | assertEqualFloat(1, myStats.minimum(), 0.0001); 65 | assertEqualFloat(50, myStats.average(), 0.0001); 66 | assertEqualFloat(99, myStats.maximum(), 0.0001); 67 | assertEqualFloat(816.667, myStats.variance(), 0.001); // note 1 digit less 68 | assertEqualFloat(28.5774, myStats.pop_stdev(), 0.0001); 69 | assertEqualFloat(28.7228, myStats.unbiased_stdev(), 0.0001); 70 | 71 | myStats.clear(); 72 | assertEqualFloat(0, myStats.sum(), 0.0001); 73 | assertEqualFloat(0, myStats.minimum(), 0.0001); 74 | assertEqualFloat(0, myStats.average(), 0.0001); 75 | assertEqualFloat(0, myStats.maximum(), 0.0001); 76 | assertEqualFloat(0, myStats.variance(), 0.0001); 77 | assertEqualFloat(0, myStats.pop_stdev(), 0.0001); 78 | assertEqualFloat(0, myStats.unbiased_stdev(), 0.0001); 79 | 80 | assertEqual(0, myStats.count()); 81 | } 82 | 83 | 84 | unittest_main() 85 | 86 | 87 | // -- END OF FILE -- 88 | 89 | --------------------------------------------------------------------------------