diff --git a/libraries/Gauss/CHANGELOG.md b/libraries/Gauss/CHANGELOG.md index 3634037e9..79a2930c6 100644 --- a/libraries/Gauss/CHANGELOG.md +++ b/libraries/Gauss/CHANGELOG.md @@ -6,6 +6,21 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.2.0] - 2023-07-10 +- improve performance => faster lookup. + - removed __z[] saves 136 bytes RAM +- remove MultiMap dependency. +- - remove **\_stddev** as **\_reciprokeSD** holds same information. +- add **float P_outside(float f, float g)** + - returns **P(x < f) + P(g < x)** under condition (f < g). +- add **float denormalize(float value)** (reverse normalize). +- add examples DS18B20 and HX711 and BMI +- update readme.md +- minor edits. + + +---- + ## [0.1.1] - 2023-07-07 - improve performance => reciprokeSD = 1.0/stddev - update readme.md @@ -19,8 +34,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - add **float getStdDev()** convenience function. - clean up a bit - - ## [0.1.0] - 2023-07-06 - initial version diff --git a/libraries/Gauss/Gauss.cpp b/libraries/Gauss/Gauss.cpp index 0bff0615b..408b1e759 100644 --- a/libraries/Gauss/Gauss.cpp +++ b/libraries/Gauss/Gauss.cpp @@ -1,7 +1,7 @@ // // FILE: Gauss.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.1.1 +// VERSION: 0.2.0 // PURPOSE: Library for the Gauss probability math. // DATE: 2023-07-06 diff --git a/libraries/Gauss/Gauss.h b/libraries/Gauss/Gauss.h index c66c990f1..8d37682b2 100644 --- a/libraries/Gauss/Gauss.h +++ b/libraries/Gauss/Gauss.h @@ -2,15 +2,14 @@ // // FILE: Gauss.h // AUTHOR: Rob Tillaart -// VERSION: 0.1.1 +// VERSION: 0.2.0 // PURPOSE: Library for the Gauss probability math. // DATE: 2023-07-06 #include "Arduino.h" -#include "MultiMap.h" -#define GAUSS_LIB_VERSION (F("0.1.1")) +#define GAUSS_LIB_VERSION (F("0.2.0")) class Gauss @@ -19,7 +18,6 @@ class Gauss Gauss() { _mean = 0; - _stddev = 1; _reciprokeSD = 1; } @@ -27,8 +25,8 @@ class Gauss bool begin(float mean = 0, float stddev = 1) { _mean = mean; - _stddev = stddev; // should be positive - _reciprokeSD = 1.0 / _stddev; + if (stddev == 0) _reciprokeSD = NAN; + else _reciprokeSD = 1.0 / stddev; return (stddev > 0); } @@ -41,14 +39,13 @@ class Gauss float getStdDev() { - return _stddev; + return 1.0 / _reciprokeSD; } float P_smaller(float value) { - if (_stddev == 0) return NAN; - // normalize(value) + if (_reciprokeSD == NAN) return NAN; return _P_smaller((value - _mean) * _reciprokeSD); } @@ -61,18 +58,25 @@ class Gauss float P_between(float p, float q) { - if (_stddev == 0) return NAN; + if (_reciprokeSD == NAN) return NAN; if (p >= q) return 0; return P_smaller(q) - P_smaller(p); } + float P_outside(float p, float q) + { + return 1.0 - P_between(p, q); + } + + float P_equal(float value) { - if (_stddev == 0) return NAN; + if (_reciprokeSD == NAN) return NAN; float n = (value - _mean) * _reciprokeSD; + // gain of ~10% if we allocate a global var for 'constant' c float c = _reciprokeSD * (1.0 / sqrt(TWO_PI)); - return c * exp(-0.5 * n * n); + return c * exp(-0.5 * (n * n)); } @@ -88,18 +92,32 @@ class Gauss } + float denormalize(float value) + { + return value / _reciprokeSD + _mean; + } + + float bellCurve(float value) { return P_equal(value); } + float CDF(float value) + { + return P_smaller(value); + } + + private: float _P_smaller(float x) { // NORM.DIST(mean, stddev, x, true) + // these points correspond with + // 0.0 .. 3.0 in steps of 0.1 followed by 4.0, 5.0 and 6.0 float __gauss[] = { 0.50000000, 0.53982784, 0.57925971, 0.61791142, 0.65542174, 0.69146246, 0.72574688, 0.75803635, @@ -112,24 +130,37 @@ class Gauss 0.99999971, 1.00000000 }; - // 0..60000 uint16_t = 68 bytes less - float __z[] = { - 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, - 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, - 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, - 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0, 4,0, - 5.0, 6.0 - }; - - // a dedicated MultiMap could exploit the fact that - // the __z[] array is largely equidistant. - // that could remove the __z[] array (almost) completely. - if (x < 0) return 1.0 - multiMap(-x, __z, __gauss, 34); - return multiMap(x, __z, __gauss, 34); + bool neg = false; + if (x < 0) + { + neg = true; + x = -x; + } + + if (x >= 6.0) + { + if (neg) return 0.0; + return 1.0; + } + + if (x <= 3.0) + { + int idx = x * 10; + float rv = __gauss[idx] + ((x * 10) - idx) * (__gauss[idx+1] - __gauss[idx]); + if (neg) return 1.0 - rv; + return rv; + } + + // 3.0 .. 6.0 + int xint = x; + int idx = 27 + xint; + float rv = __gauss[idx] + (x - xint) * (__gauss[idx+1] - __gauss[idx]); + if (neg) return 1.0 - rv; + return rv; } float _mean = 0; - float _stddev = 1; // not needed as _reciprokeSD holds same info? + // reciprokeSD = 1.0 / stddev is faster in most math (MUL vs DIV) float _reciprokeSD = 1; }; diff --git a/libraries/Gauss/README.md b/libraries/Gauss/README.md index 17f94eb2e..3477b1a66 100644 --- a/libraries/Gauss/README.md +++ b/libraries/Gauss/README.md @@ -8,7 +8,7 @@ # Gauss -Library for the Gauss probability math. +Library for the Gauss probability math. (Normal Distribution). ## Description @@ -17,31 +17,47 @@ Gauss is an experimental Arduino library to approximate the probability that a v smaller or larger than a given value. These under the premises of a Gaussian distribution with parameters **mean** and **stddev** (a.k.a. average / mu / µ and standard deviation / sigma / σ). -If these parameters are not given, 0 and 1 are used by default (normalized Gaussian distribution). +If these parameters are not given, mean == 0 and stddev == 1 are used by default. +This is the normalized Gaussian distribution. -The values are approximated with **MultiMap()** using a 32 points interpolated lookup. -Therefore the **MultiMap** library need to be downloaded too (see related below). -The number of lookup points might chance in the future. +The values of the functions are approximated with a **MultiMap()** based lookup +using a 34 points interpolated lookup. +- Version 0.1.x used the **MultiMap** library need to be downloaded too (see related below). +- Version 0.2.0 and above embeds an optimized version, so no need to use **MultiMap**. -Return values are given as floats, if one needs percentages, just multiply by 100.0. +Note: The number of lookup points might chance in the future, keeping a balance between +accuracy and footprint. -#### Accuracy +#### Accuracy / precision -The lookup table has 34 points with 8 decimals. +The version 0.2.0 lookup table has 34 points with 8 decimals. This matches the precision of float data type. -Do not expect a very high accuracy / precision as interpolation is linear. -For many applications this accuracy is sufficient. +Do not expect an 8 decimals accuracy / precision as interpolation is linear. -Values of the table are calculated with ```NORM.DIST(mean, stddev, x, true)```. +A first investigation (part 0.0 - 1.3) shows: +- maximum error ~ 0.0003016 <= 0.031% +- average error ~ 0.0001433 <= 0.015% + +I expect that for many applications this accuracy is probably sufficient. + +The 34 points are in a (mostly) equidistant table. +Searching the interpolation points is optimized in version 0.2.0. +The table uses the symmetry of the distribution to reduce the number of points. + +Values of the table are calculated with ```NORM.DIST(x, mean, stddev, true)``` +spreadsheet function. Note: 0.1.0 was 32 points 4 decimals. Need to investigate reduction of points. + #### Applications -- use as a filter? do not allow > 3 sigma -- compare historic data to current data -- compare population data with individual +- use as a filter e.g. detect above N1 sigma and under N2 sigma +- compare historic data to current data e.g. temperature. + - transforming to sigma makes it scale C / F / K independent. +- fill a bag (etc) until a certain weight is reached (+- N sigma) +- compare population data with individual, e.g. Body Mass Index (BMI). #### Character @@ -50,6 +66,7 @@ Note: 0.1.0 was 32 points 4 decimals. Need to investigate reduction of points. |:-----------:|:------:|:----------:|:-----:| | mean | mu | ALT-230 | µ | | stddev | sigma | ALT-229 | σ | +| CDF | phi | ALT-232 | Φ | ALT-237 for lower case - https://altcodesguru.com/greek-alt-codes.html @@ -74,38 +91,51 @@ Note: 0.1.0 was 32 points 4 decimals. Need to investigate reduction of points. - **Gauss()** constructor. Uses mean = 0 and stddev = 1 by default. - **bool begin(float mean = 0, float stddev = 1)** set the mean and stddev. Returns true if stddev > 0 which should be so. -Returns false if stddev <= 0, which could be a user choice. +Returns false if stddev <= 0, however it could be a user choice to use this. Note that if ```stddev == 0```, probabilities cannot be calculated as the distribution is not Gaussian. -The default values (0,1) gives the normalized Gaussian distribution. -**begin()** can be called at any time to change the mean or stddev. +The default values (0, 1) gives the normalized Gaussian distribution. +**begin()** can be called at any time to change the mean and/or stddev. - **float getMean()** returns current mean. - **float getStddev()** returns current stddev. #### Probability -Probability functions return NAN if stddev == 0. +Probability functions return NAN if stddev == 0. +Return values are given as a float 0.0 .. 1.0. +Multiply probabilities by 100.0 to get the value as a percentage. - **float P_smaller(float f)** returns probability **P(x < f)**. -Multiply by 100.0 to get the value as a percentage. A.k.a. **CDF()** Cumulative Distribution Function. - **float P_larger(float f)** returns probability **P(x > f)**. -Multiply by 100.0 to get the value as a percentage. As the distribution is continuous **P_larger(f) == 1 - P_smaller(f)**. - **float P_between(float f, float g)** returns probability **P(f < x < g)**. -Multiply by 100.0 to get the value as a percentage. + - if f >= g ==> returns 1.0 - **float P_equal(float f)** returns probability **P(x == f)**. This uses the bell curve formula. +- **float P_outside(float f, float g)** returns probability **P(x < f) + P(g < x)**. + - note that f should be smaller or equal to g + - **P_outside() = 1 - P_between()** -#### Other +#### Normalize - **float normalize(float f)** normalize a value to normalized distribution. +E.g if mean == 50 and stddev == 14, then 71 ==> +1.5 sigma. Is equal to number of **stddevs()**. +- **float denormalize(float f)** reverses normalize(). +What value would have a deviation of 1.73 stddev. - **float stddevs(float f)** returns the number of stddevs from the mean. -E.g if mean == 50 and stddev == 14, then 71 ==> +1.5 sigma. +Identical to **normalize()**. + + +#### Other + +wrapper functions: + - **float bellCurve(float f)** returns probability **P(x == f)**. +- **float CDF(float f)** returns probability **P(x < f)**. ## Performance @@ -114,26 +144,26 @@ Indicative numbers for 1000 calls, timing in micros. Arduino UNO, 16 MHz, IDE 1.8.19 -| function | 0.1.0 | 0.1.1 | notes | -|:--------------|:--------:|:--------:|:--------| -| P_smaller | 375396 | 365964 | -| P_larger | 384368 | 375032 | -| P_between | 265624 | 269176 | -| normalize | 44172 | 23024 | -| bellCurve | 255728 | 205460 | -| approx.bell | 764028 | 719184 | see examples +| function | 0.1.0 | 0.1.1 | 0.2.0 | notes | +|:--------------|:--------:|:--------:|:--------:|:--------| +| P_smaller | 375396 | 365964 | 159536 | +| P_larger | 384368 | 375032 | 169056 | +| P_between | 265624 | 269176 | 150148 | +| normalize | 44172 | 23024 | 23024 | +| bellCurve | 255728 | 205460 | 192524 | +| approx.bell | 764028 | 719184 | 333172 | see examples ESP32, 240 MHz, IDE 1.8.19 -| function | 0.1.0 | 0.1.1 | notes | -|:--------------|:--------:|:--------:|:--------| -| P_smaller | - | 4046 | -| P_larger | - | 4043 | -| P_between | - | 3023 | -| normalize | - | 592 | -| bellCurve | - | 13522 | -| approx.bell | - | 7300 | +| function | 0.1.0 | 0.1.1 | 0.2.0 | notes | +|:--------------|:--------:|:--------:|:--------:|:--------| +| P_smaller | - | 4046 | 1498 | +| P_larger | - | 4043 | 1516 | +| P_between | - | 3023 | 1569 | +| normalize | - | 592 | 585 | +| bellCurve | - | 13522 | 13133 | +| approx.bell | - | 7300 | 2494 | ## Future @@ -141,33 +171,19 @@ ESP32, 240 MHz, IDE 1.8.19 #### Must - documentation - +- test test test #### Should -- optimize accuracy - - revisit lookup of MultiMap - - (-10 .. 0) might be more accurate (significant digits)? - - double instead of floats? (good table?) - - make use of equidistant \_\_z\[] table - #### Could - add examples - - e.g. temperature (DS18B20 or DHT22) - - e.g. loadcell (HX711) -- embed MultiMap hardcoded instead of library dependency - add unit tests -- remove **\_stddev** as **\_reciprokeSD** holds same information. -- reverse normalization - - G(100,25) which value has stddev 0.735? - **VAL(probability = 0.75)** ==> 134 whatever - - Returns the value of the distribution for which the **CDF()** is at least probability. - - Inverse of **P_smaller()** -- **float P_outside(float f, float g)** returns probability **P(x < f) + P(g < x)**. - - assuming no overlap. Use **P_outside() = 1 - P_between()** - + - Returns the value for which the **CDF()** is at least probability. + - Inverse of **P_smaller()** (how? binary search) + #### Won't (unless requested) @@ -177,5 +193,5 @@ ESP32, 240 MHz, IDE 1.8.19 - move code to .cpp file? (rather small lib). - **void setMean(float f)** can be done with begin() - **void setStddev(float f)** can be done with begin() - - +- optimize accuracy + - (-6 .. 0) might be more accurate (significant digits)? diff --git a/libraries/Gauss/examples/Gauss_BMI/Gauss_BMI.ino b/libraries/Gauss/examples/Gauss_BMI/Gauss_BMI.ino new file mode 100644 index 000000000..e151b6175 --- /dev/null +++ b/libraries/Gauss/examples/Gauss_BMI/Gauss_BMI.ino @@ -0,0 +1,74 @@ +// +// FILE: Gauss_BMI.ino +// AUTHOR: Rob Tillaart +// PURPOSE: demo - not a medical program + +#include "Gauss.h" + +Gauss G; + + +void setup(void) +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("GAUSS_LIB_VERSION:\t"); + Serial.println(GAUSS_LIB_VERSION); + Serial.println(); + + // BMI - adjust to your local situation + // https://en.wikipedia.org/wiki/List_of_sovereign_states_by_body_mass_index + // stddev is assumption. + G.begin(25.0, 2.5); +} + + +void loop(void) +{ + // flush + while (Serial.available()) Serial.read(); + + Serial.println("Enter your weight in kg: "); + while (!Serial.available()); + float weight = Serial.parseFloat(); + if (weight == 0) return; + + while (Serial.available()) Serial.read(); + Serial.println("Enter your length in cm: "); + while (!Serial.available()); + float length = Serial.parseFloat(); + if (length == 0) return; + + float BMI = (10000.0 * weight) / (length * length); + + float stddev = G.normalize(BMI); + Serial.print("\tWeight:\t\t"); + Serial.println(weight); + + Serial.print("\tLength:\t\t"); + Serial.println(length); + + Serial.print("\tBMI:\t\t"); + Serial.println(BMI); + + Serial.print("\tStddev:\t\t"); + if (stddev >= 0) Serial.print('+'); + Serial.println(stddev, 2); + + Serial.print("\tSmaller:\t"); + Serial.print(100.0 * G.P_smaller(BMI)); + Serial.println("%"); + + Serial.print("\tLarger:\t\t"); + Serial.print(100.0 * G.P_larger(BMI)); + Serial.println("%"); + + Serial.print("\tSame:\t\t"); + Serial.print(100.0 * G.P_between(BMI - 0.1, BMI + 0.1)); + Serial.print("%"); + Serial.println(); + Serial.println(); +} + + +// -- END OF FILE -- diff --git a/libraries/Gauss/examples/Gauss_DS18B20/.arduino-ci.yml b/libraries/Gauss/examples/Gauss_DS18B20/.arduino-ci.yml new file mode 100644 index 000000000..da1d68905 --- /dev/null +++ b/libraries/Gauss/examples/Gauss_DS18B20/.arduino-ci.yml @@ -0,0 +1,35 @@ +platforms: + rpipico: + board: rp2040:rp2040:rpipico + package: rp2040:rp2040 + gcc: + features: + defines: + - ARDUINO_ARCH_RP2040 + warnings: + flags: + +packages: + rp2040:rp2040: + url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json + +compile: + # Choosing to run compilation tests on 2 different Arduino platforms + platforms: + - uno + # - due + # - zero + # - leonardo + - m4 + #- esp32 + - esp8266 + # - mega2560 + - rpipico + libraries: + - MultiMap + - DS18B20_RT + +unittest: + # These dependent libraries will be installed + libraries: + - MultiMap \ No newline at end of file diff --git a/libraries/Gauss/examples/Gauss_DS18B20/Gauss_DS18B20.ino b/libraries/Gauss/examples/Gauss_DS18B20/Gauss_DS18B20.ino new file mode 100644 index 000000000..c9d691906 --- /dev/null +++ b/libraries/Gauss/examples/Gauss_DS18B20/Gauss_DS18B20.ino @@ -0,0 +1,59 @@ +// +// FILE: Gauss_DS18B20.ino +// AUTHOR: Rob Tillaart +// PURPOSE: demo +// +// can be used with plotter + + +#include "DS18B20.h" +#include "Gauss.h" + +#define ONE_WIRE_BUS 2 + +OneWire oneWire(ONE_WIRE_BUS); +DS18B20 sensor(&oneWire); + +Gauss G; + + +void setup(void) +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("GAUSS_LIB_VERSION:\t"); + Serial.println(GAUSS_LIB_VERSION); + Serial.print("DS18B20_LIB_VERSION:\t"); + Serial.println(DS18B20_LIB_VERSION); + Serial.println(); + + // default temperature + stddev + // adjust to your local situation + G.begin(26.00, 0.2); + sensor.begin(); + sensor.setResolution(12); + + Serial.println("\ndone..."); +} + + +void loop(void) +{ + // simulation + // float temp = 18 + random(800) * 0.01; + + sensor.requestTemperatures(); + while (!sensor.isConversionComplete()); + float temp = sensor.getTempC(); + float stddev = G.normalize(temp); + + Serial.print("TEMP: "); + Serial.print(temp, 2); + Serial.print("\tSTDDEV: "); + if (stddev >= 0) Serial.print('+'); + Serial.print(stddev, 2); + Serial.println(); +} + + +// -- END OF FILE -- diff --git a/libraries/Gauss/examples/Gauss_HX711/.arduino-ci.yml b/libraries/Gauss/examples/Gauss_HX711/.arduino-ci.yml new file mode 100644 index 000000000..e8c93c7f7 --- /dev/null +++ b/libraries/Gauss/examples/Gauss_HX711/.arduino-ci.yml @@ -0,0 +1,35 @@ +platforms: + rpipico: + board: rp2040:rp2040:rpipico + package: rp2040:rp2040 + gcc: + features: + defines: + - ARDUINO_ARCH_RP2040 + warnings: + flags: + +packages: + rp2040:rp2040: + url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json + +compile: + # Choosing to run compilation tests on 2 different Arduino platforms + platforms: + - uno + # - due + # - zero + # - leonardo + - m4 + - esp32 + - esp8266 + # - mega2560 + - rpipico + libraries: + - MultiMap + - HX711 + +unittest: + # These dependent libraries will be installed + libraries: + - MultiMap \ No newline at end of file diff --git a/libraries/Gauss/examples/Gauss_HX711/Gauss_HX711.ino b/libraries/Gauss/examples/Gauss_HX711/Gauss_HX711.ino new file mode 100644 index 000000000..67d8a0cf5 --- /dev/null +++ b/libraries/Gauss/examples/Gauss_HX711/Gauss_HX711.ino @@ -0,0 +1,69 @@ +// +// FILE: Gauss_HX711.ino +// AUTHOR: Rob Tillaart +// PURPOSE: demo +// +// can be used with plotter + + +#include "HX711.h" +#include "Gauss.h" + +HX711 scale; +uint8_t dataPin = 6; +uint8_t clockPin = 7; + +Gauss G; + + +void setup(void) +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("GAUSS_LIB_VERSION:\t"); + Serial.println(GAUSS_LIB_VERSION); + Serial.print("HX711_LIB_VERSION:\t"); + Serial.println(HX711_LIB_VERSION); + Serial.println(); + + // default weight in grams + stddev + // adjust to your local situation + G.begin(100.0, 0.75); + + scale.begin(dataPin, clockPin); + + // load cell factor 5 KG + // TODO: calibrate the load cell. + scale.set_scale(420.0983); + + // reset the scale to zero = 0 + scale.tare(); + + Serial.println("you may now add weights."); +} + + +void loop(void) +{ + // simulation + // float weight = 249 + random(20) * 0.1; + + float weight = scale.get_units(5); + float stddev = G.normalize(weight); + + Serial.print("WEIGHT: "); + Serial.print(weight, 1); + Serial.print("\tSTDDEV: "); + if (stddev >= 0) Serial.print('+'); + Serial.print(stddev, 2); + Serial.print("\t"); + if (stddev < -1) Serial.print("LOW."); // TOO LOW + else if (stddev > 1) Serial.print("HIGH."); + else Serial.print("OK."); + Serial.println(); + + delay(1000); +} + + +// -- END OF FILE -- diff --git a/libraries/Gauss/examples/Gauss_performance/Gauss_performance.ino b/libraries/Gauss/examples/Gauss_performance/Gauss_performance.ino index 31aa37b4f..3785b47dd 100644 --- a/libraries/Gauss/examples/Gauss_performance/Gauss_performance.ino +++ b/libraries/Gauss/examples/Gauss_performance/Gauss_performance.ino @@ -150,5 +150,4 @@ void test_6() } - // -- END OF FILE -- diff --git a/libraries/Gauss/examples/Gauss_performance/performance_0.2.0.txt b/libraries/Gauss/examples/Gauss_performance/performance_0.2.0.txt new file mode 100644 index 000000000..3a3aa58ce --- /dev/null +++ b/libraries/Gauss/examples/Gauss_performance/performance_0.2.0.txt @@ -0,0 +1,17 @@ +Arduino UNO +IDE 1.8.19 + +Gauss_performance.ino +GAUSS_LIB_VERSION: 0.2.0 + +Timing in micros (1000 calls) + +P_smaller: 159536 +P_larger: 169056 +P_between: 150148 +normalize: 23024 +bellCurve: 192524 +approx.bell: 333172 + +done... + diff --git a/libraries/Gauss/examples/Gauss_test/Gauss_test.ino b/libraries/Gauss/examples/Gauss_test/Gauss_test.ino index 80217334e..e93279a51 100644 --- a/libraries/Gauss/examples/Gauss_test/Gauss_test.ino +++ b/libraries/Gauss/examples/Gauss_test/Gauss_test.ino @@ -17,9 +17,9 @@ void setup(void) Serial.println(); test_1(); -// test_2(); -// test_3(); -// test_4(); + test_2(); + test_3(); + test_4(); Serial.println("\ndone..."); } diff --git a/libraries/Gauss/examples/Gauss_test_bell_curve/Gauss_test_bell_curve.ino b/libraries/Gauss/examples/Gauss_test_bell_curve/Gauss_test_bell_curve.ino index 86c80fa5c..2fa5651ed 100644 --- a/libraries/Gauss/examples/Gauss_test_bell_curve/Gauss_test_bell_curve.ino +++ b/libraries/Gauss/examples/Gauss_test_bell_curve/Gauss_test_bell_curve.ino @@ -2,7 +2,8 @@ // FILE: Gauss_test_bell_curve.ino // AUTHOR: Rob Tillaart // PURPOSE: demo - +// +// use plotter to create the graph in two ways #include "Gauss.h" @@ -42,6 +43,7 @@ void get_bell_curve() } +// approximation of the bell curve void approximate() { G.begin(0, 1); @@ -49,8 +51,9 @@ void approximate() for (float f = -5.0; f <= 5.0; f += 0.01) { // width == 2x 0.5233 == 1.0466 - // 0.0466 heuristic correction factor to match peak of bellCurve() - // not exact match but almost perfect + // 0.0466 heuristic correction factor to match peak of the bell curve() + // not an exact match but almost perfect + // cf found with separate function below float cf = 0.52330751; float a = G.P_smaller(f - cf); float b = G.P_smaller(f + cf); @@ -60,7 +63,7 @@ void approximate() } -// find the correction factor for the appoximate function +// find the correction factor for the approximate function // so the peak matches the bell curve function. // ==> 0.52330751 void find_correction_factor() diff --git a/libraries/Gauss/library.json b/libraries/Gauss/library.json index 5ae12fce1..0da44d0e8 100644 --- a/libraries/Gauss/library.json +++ b/libraries/Gauss/library.json @@ -15,15 +15,7 @@ "type": "git", "url": "https://github.com/RobTillaart/Gauss.git" }, - "dependencies": - [ - { - "owner": "Rob Tillaart", - "name": "MultiMap", - "version": "^0.1.7" - } - ], - "version": "0.1.1", + "version": "0.2.0", "license": "MIT", "frameworks": "arduino", "platforms": "*", diff --git a/libraries/Gauss/library.properties b/libraries/Gauss/library.properties index 7473aff72..e9869a33a 100644 --- a/libraries/Gauss/library.properties +++ b/libraries/Gauss/library.properties @@ -1,5 +1,5 @@ name=Gauss -version=0.1.1 +version=0.2.0 author=Rob Tillaart maintainer=Rob Tillaart sentence=Library for the Gauss probability math. @@ -8,5 +8,5 @@ category=Data Processing url=https://github.com/RobTillaart/Gauss architectures=* includes=Gauss.h -depends=MultiMap +depends= diff --git a/libraries/Gauss/test/unit_test_001.cpp b/libraries/Gauss/test/unit_test_001.cpp index 528d0fe5c..dd936ccff 100644 --- a/libraries/Gauss/test/unit_test_001.cpp +++ b/libraries/Gauss/test/unit_test_001.cpp @@ -103,6 +103,22 @@ unittest(test_P_between) } +unittest(test_P_outside) +{ + Gauss G; + + G.begin(0, 1); + + assertEqualFloat(0.5013, G.P_outside(-3.0, 0.0), 0.0001); + assertEqualFloat(0.5228, G.P_outside(-2.0, 0.0), 0.0001); + assertEqualFloat(0.6587, G.P_outside(-1.0, 0.0), 0.0001); + assertEqualFloat(1.0000, G.P_outside(0.0, 0.0), 0.0001); + assertEqualFloat(0.6587, G.P_outside(0.0, 1.0), 0.0001); + assertEqualFloat(0.5228, G.P_outside(0.0, 2.0), 0.0001); + assertEqualFloat(0.5013, G.P_outside(0.0, 3.0), 0.0001); +} + + unittest(test_P_equal) { Gauss G; @@ -132,6 +148,14 @@ unittest(test_normailze) assertEqualFloat(1.0, G.normalize(125), 0.0001); assertEqualFloat(2.0, G.normalize(150), 0.0001); assertEqualFloat(3.0, G.normalize(175), 0.0001); + + assertEqualFloat(25, G.denormalize(-3.0), 0.0001); + assertEqualFloat(50, G.denormalize(-2.0), 0.0001); + assertEqualFloat(75, G.denormalize(-1.0), 0.0001); + assertEqualFloat(100, G.denormalize(0.0), 0.0001); + assertEqualFloat(125, G.denormalize(1.0), 0.0001); + assertEqualFloat(150, G.denormalize(2.0), 0.0001); + assertEqualFloat(175, G.denormalize(3.0), 0.0001); }