0.1.4 statHelpers

This commit is contained in:
rob tillaart 2021-12-28 15:37:03 +01:00
parent 3e810b9c7f
commit 8b91a1df78
19 changed files with 132 additions and 82 deletions

View File

@ -2,9 +2,13 @@ compile:
# Choosing to run compilation tests on 2 different Arduino platforms
platforms:
- uno
- leonardo
- due
- zero
- leonardo
- m4
- esp32
- esp8266
- mega2560
libraries:
- "printHelpers"

View File

@ -4,10 +4,14 @@ name: Arduino CI
on: [push, pull_request]
jobs:
arduino_ci:
runTest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: Arduino-CI/action@master
# Arduino-CI/action@v0.1.1
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6
- run: |
gem install arduino_ci
arduino_ci.rb

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2010-2021 Rob Tillaart
Copyright (c) 2010-2022 Rob Tillaart
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,12 +1,16 @@
[![Arduino CI](https://github.com/RobTillaart/statHelpers/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
[![Arduino-lint](https://github.com/RobTillaart/statHelpers/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/statHelpers/actions/workflows/arduino-lint.yml)
[![JSON check](https://github.com/RobTillaart/statHelpers/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/statHelpers/actions/workflows/jsoncheck.yml)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/statHelpers/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/statHelpers.svg?maxAge=3600)](https://github.com/RobTillaart/statHelpers/releases)
# statHelpers
Arduino library with a number of statistic helper functions.
## Description
This library contains functions that have the goal to help with
@ -17,17 +21,17 @@ some basic statistical calculations.
### Permutation
returns how many different ways one can choose a set of k elements
from a set of n. The order does matter.
Returns how many different ways one can choose a set of k elements from a set of n.
The order does matter so (1, 2) is not equal to (2, 1).
The limits mentioned is the n for which all k still work.
- **uint32_t permutations(n, k)** exact up to 12
- **uint64_t permutations64(n, k)** exact up to 20
- **double dpermutations(n, k)** not exact up to 34 (4 byte) or 170 (8 byte)
- **uint32_t permutations(n, k)** exact up to n = 12
- **uint64_t permutations64(n, k)** exact up to n = 20
- **double dpermutations(n, k)** not exact up to n = 34 (4 byte) or n = 170 (8 byte)
If you need a larger n but k is near 0 the functions will still work, but
to which k differs per value for n. (no formula found, and an overflow
detection takes overhead).
If you need a larger n but k is near 0 the functions will still work.
To which value of k the formulas work differs per value for n.
No formula found, and build in an overflow detection takes overhead, so that is not done.
- **nextPermutation<Type>(array, size)** given an array of type T it finds the next permutation
@ -38,10 +42,10 @@ other same code examples exist.
### Factorial
- **uint32_t factorial(n)** exact up to 12!
- **uint64_t factorial64(n)** exact up to 20! (Print 64 bit ints with my printHelpers)
- **double dfactorial(n)** not exact up to 34! (4 byte) or 170! (8 byte)
- **double stirling(n)** approximation function for factorial (right magnitude)
- **uint32_t factorial(n)** exact up to n = 12.
- **uint64_t factorial64(n)** exact up to n = 20. (Print 64 bit ints with my printHelpers)
- **double dfactorial(n)** not exact up to n = 34 (4 byte) or n = 170 (8 byte).
- **double stirling(n)** approximation function for factorial (right magnitude).
**dfactorial()** is quite accurate over the whole range.
**stirling()** is up to 3x faster for large n (> 100),
@ -64,64 +68,83 @@ Notes:
### Combinations
returns how many different ways one can choose a set of k elements
from a set of n. The order does not matter.
Returns how many different ways one can choose a set of k elements from a set of n.
The order does **not** matter so (1, 2) is equal to (2, 1).
The number of combinations grows fast so n is limited per function.
The limits mentioned is the n for which all k still work.
- **uint32_t combinations(n, k)** n = 0 .. 30 (iterative version)
- **uint64_t combinations64(n, k)** n = 0 .. 61 (iterative version)
- **uint32_t combinations(n, k)** n = 0 .. 30 (iterative version)
- **uint64_t combinations64(n, k)** n = 0 .. 61 (iterative version)
- **uint32_t rcombinations(n, k)** n = 0 .. 30 (recursive version, slightly slower)
- **uint64_t rcombinations64(n, k)** n = 0 .. 61 (recursive version, slightly slower)
- **double dcombinations(n, k)** n = 0 .. 125 (4bit) n = 0 .. 1020 (8 bit)
- **double dcombinations(n, k)** n = 0 .. 125 (4bit) n = 0 .. 1020 (8 bit)
If you need a larger n but k is near 0 or near n the functions will still work,
but for which k differs per value for n. (no formula found, and an overflow
detection takes overhead).
If you need a larger n but k is near 0 the functions will still work.
To which value of k the formulas work differs per value for n.
No formula found, and build in an overflow detection takes overhead, so that is not done.
- **combPascal(n, k)** n = 0 .. 30 but due to double recursion per iteration it takes
time and a lot of it for larger values. Added for recreational purposes, limited tested.
Uses Pascal's triangle.
## Notes
- **perm1** is a sketch in the examples that shows a recursive permutation
algorithm. It generates all permutations of a given char string.
- **perm1** is a sketch in the examples that shows a recursive permutation algorithm.
It generates all permutations of a given char string.
It allows you to process every instance.
It is added to this library as it fits in the context.
### Experimental - large numbers
- **void bigFactorial(uint32_t n, double &mantissa, uint32_t &exponent)** returns a double mantissa between 0 and 10, and an integer exponent.
- **void bigPermutation(uint32_t n, uint32_t k, double &mantissa, uint32_t &exponent)** returns a double mantissa between 0 and 10, and an integer exponent.
- **void bigCombination(uint32_t n, uint32_t k, double &mantissa, uint32_t &exponent)** returns a double mantissa between 0 and 10, and an integer exponent.
An experimental **bigFactorial(n)** calculation to get an idea of the big numbers. it can calculate factorials up to an exponent of 4294967295 max. 100.000.000! can be done in 38 minutes on an ESP32 @240 Mhz. Maximum value for n is **518678059! == 2.1718890e4294967292** a number that took ~10 hrs to calculate.
- **void bigFactorial(uint32_t n, double &mantissa, uint32_t &exponent)**
returns a double mantissa between 0 and 10, and an integer exponent.
- **void bigPermutation(uint32_t n, uint32_t k, double &mantissa, uint32_t &exponent)**
returns a double mantissa between 0 and 10, and an integer exponent.
- **void bigCombination(uint32_t n, uint32_t k, double &mantissa, uint32_t &exponent)**
returns a double mantissa between 0 and 10, and an integer exponent.
An experimental **bigPermutation(n, k)** calculation, to handle big numbers too. Maximum value for n is **518678059** to have full range support. For small(er) values of k, n can even be much larger, but not larger than 4294967295 max.
An experimental **bigFactorial(n)** calculation to get an idea of the big numbers.
it can calculate factorials up to an exponent of 4294967295 max. 100.000.000! can be
done in 38 minutes on an ESP32 at 240 MHz.
Maximum value for n is **518678059! == 2.1718890e4294967292** a number that took ~10 hrs to calculate.
An experimental **bigCombination(n, k)** calculation for big numbers. Not investigated what its maximum value is, but it should be higher than **518678059** as the number of combinations is always smaller than number of permutations.
An experimental **bigPermutation(n, k)** calculation, to handle big numbers too.
Maximum value for n is **518678059** to have full range support. For small(er)
values of k, n can even be much larger, but not larger than 4294967295 max.
An experimental **bigCombination(n, k)** calculation for big numbers.
Not investigated what its maximum value is, but it should be higher than **518678059** as the number
of combinations is always smaller than number of permutations.
#### Experimental - not investigated yet
To have support for huge numbers one could upgrade the code to use uint64_t as parameter and internally but calculating these values could take a lot of time, although **bigPermutations64(n, k)** and **bigCombinations64(n, k)** would work fast for small values of k.
To have support for huge numbers one could upgrade the code to use uint64_t as parameter and
internally but calculating these values could take a lot of time, although **bigPermutations64(n, k)**
and **bigCombinations64(n, k)** would work fast for small values of k.
- **void bigFactorial64(uint64_t n, double &mantissa, uint64_t &exponent)** returns a double mantissa between 0 and 10, and an integer exponent.
- **void bigPermutation64(uint64_t n, uint64_t k, double &mantissa, uint64_t &exponent)** returns a double mantissa between 0 and 10, and an integer exponent.
- **void bigCombination64(uint64_t n, uint64_t k, double &mantissa, uint64_t &exponent)** returns a double mantissa between 0 and 10, and an integer exponent.
- **void bigFactorial64(uint64_t n, double &mantissa, uint64_t &exponent)**
returns a double mantissa between 0 and 10, and an integer exponent.
- **void bigPermutation64(uint64_t n, uint64_t k, double &mantissa, uint64_t &exponent)**
returns a double mantissa between 0 and 10, and an integer exponent.
- **void bigCombination64(uint64_t n, uint64_t k, double &mantissa, uint64_t &exponent)**
returns a double mantissa between 0 and 10, and an integer exponent.
## Operation
See examples
## Future
- code & example for get Nth Permutation
- investigate valid range detection for a given (n, k) for combinations and permutations.
- investigate a bigFloat class to do math for permutations and combinations to substantially larger values.
- Look for optimizations
- Look for ways to extend the scope
## Operation
See examples

View File

@ -1,7 +1,6 @@
//
// FILE: bigCombinations.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo
// DATE: 2021-08-06
// URL: https://github.com/RobTillaart/statHelpers
@ -14,6 +13,7 @@
uint32_t start, duration1;
volatile uint32_t x;
void setup()
{
Serial.begin(115200);
@ -72,8 +72,11 @@ void setup()
Serial.println("\nDone...");
}
void loop()
{
}
// -- END OF FILE --

View File

@ -1,7 +1,6 @@
//
// FILE: bigFactorial.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo
// DATE: 2021-08-05
// URL: https://github.com/RobTillaart/statHelpers
@ -72,8 +71,11 @@ void setup()
Serial.println("\n Done...");
}
void loop()
{
}
// -- END OF FILE --

View File

@ -1,7 +1,6 @@
//
// FILE: permutations.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo
// DATE: 2021-08-06
// URL: https://github.com/RobTillaart/statHelpers
@ -14,6 +13,7 @@
uint32_t start, duration1, duration2;
volatile uint32_t x;
void setup()
{
Serial.begin(115200);
@ -135,9 +135,11 @@ void setup()
Serial.println("\nDone...");
}
void loop()
{
}
// -- END OF FILE --

View File

@ -1,7 +1,6 @@
//
// FILE: combinations.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo
// DATE: 2020-07-01
// URL: https://github.com/RobTillaart/statHelpers
@ -14,6 +13,7 @@
uint32_t start, duration1;
volatile uint32_t x;
void setup()
{
Serial.begin(115200);
@ -135,8 +135,11 @@ void setup()
Serial.println("\nDone...");
}
void loop()
{
}
// -- END OF FILE --

View File

@ -1,7 +1,6 @@
//
// FILE: factorial.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo
// DATE: 2020-07-01
// URL: https://github.com/RobTillaart/statHelpers
@ -38,7 +37,6 @@ void setup()
}
Serial.println();
Serial.println("PERFORMANCE");
Serial.println("n\tdfactorial,stirling usec\t values");
delay(100);
@ -90,8 +88,11 @@ void setup()
Serial.println("\n Done...");
}
void loop()
{
}
// -- END OF FILE --

View File

@ -1,7 +1,6 @@
//
// FILE: factorial_performance.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo
// DATE: 2020-07-01
// URL: https://github.com/RobTillaart/statHelpers
@ -62,8 +61,11 @@ void setup()
Serial.println("\n Done...");
}
void loop()
{
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -1,7 +1,6 @@
//
// FILE: nextPermutation.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo
// DATE: 2020-07-01
// URL: https://github.com/RobTillaart/statHelpers
@ -65,7 +64,11 @@ void setup()
Serial.println("\nDone...");
}
void loop()
{
}
// -- END OF FILE --

View File

@ -2,23 +2,21 @@
// FILE: perm1.ino
// AUTHOR: Rob Tillaart
// DATE: 2010-11-23
//
// PUPROSE: demo permutations
//
//
// WARNING TAKES LONG
// ====================================================================
// ESP32 @ 240 MHz string len 8 ==> ~8100 millis(mostly printing!!
// UNO no printing string len 8 ==> ~431 millis
// UNO no printing string len 10 ==> ~38763 millis
// ========================================================================
// ESP32 @ 240 MHz string length 8 ==> ~8100 milliseconds => printing!!
// UNO no printing string length 8 ==> ~431 milliseconds
// UNO no printing string length 10 ==> ~38763 milliseconds
char permstring[12] = "0123456789"; // can be made slightly longer
uint32_t start, stop;
void permutate(char * array, uint8_t n)
{
if (n == 0) // end reached print the string
@ -44,6 +42,7 @@ void permutate(char * array, uint8_t n)
}
}
void setup()
{
Serial.begin(500000);
@ -60,8 +59,11 @@ void setup()
Serial.println(stop - start);
}
void loop()
{
}
// -- END OF FILE --

View File

@ -1,7 +1,6 @@
//
// FILE: permutations.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo
// DATE: 2020-07-02
// URL: https://github.com/RobTillaart/statHelpers
@ -14,6 +13,7 @@
uint32_t start, duration1, duration2;
volatile uint32_t x;
void setup()
{
Serial.begin(115200);
@ -89,9 +89,11 @@ void setup()
Serial.println("\nDone...");
}
void loop()
{
}
// -- END OF FILE --

View File

@ -1,7 +1,6 @@
//
// FILE: semiFactorial.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo
// DATE: 2021-08-05
// URL: https://github.com/RobTillaart/statHelpers
@ -69,8 +68,11 @@ void setup()
Serial.println("\n Done...");
}
void loop()
{
}
// -- END OF FILE --

View File

@ -4,7 +4,7 @@ As the formula for combinations is symmetrical one knows that:
- if it works for (N, 0..k) it will also work for (N, n-k..n)
- if it works for (N, 0..k) it will also work for (N-1, 0..k)
- (n, 0) = 1; (n, 1) = n; (n, 2) = n * (n+1) / 2;
- (n, 0) = 1; (n, 1) = n; (n, 2) = n \* (n+1) / 2;
- from the latter a rule of thumb states that nCr(n,k) < n^k
assume nCr(n,k) > MAXVAL && nCr(n,k-1) <= MAXVAL

View File

@ -15,8 +15,9 @@
"type": "git",
"url": "https://github.com/RobTillaart/statHelpers.git"
},
"version": "0.1.3",
"version": "0.1.4",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*"
"platforms": "*",
"headers": "statHelpers.h"
}

View File

@ -1,5 +1,5 @@
name=statHelpers
version=0.1.3
version=0.1.4
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library with a number of statistic helper functions.

View File

@ -2,7 +2,7 @@
//
// FILE: statHelpers.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.3
// VERSION: 0.1.4
// PURPOSE: Arduino library with a number of statistic helper functions.
// DATE: 2020-07-01
// URL: https://github.com/RobTillaart/statHelpers
@ -11,12 +11,7 @@
#include "Arduino.h"
#define STATHELPERS_LIB_VERSION (F("0.1.3"))
// TODO
// Look for optimizations
// Look for ways to extend the scope
#define STATHELPERS_LIB_VERSION (F("0.1.4"))
///////////////////////////////////////////////////////////////////////////
@ -57,7 +52,9 @@ As an example consider finding the next permutation of:
The longest monotonically decreasing tail is 666411, and the corresponding head is 8342.
8342 666411
666411 is, by definition, reverse-ordered, and cannot be increased by permuting its elements. To find the next permutation, we must increase the head; a matter of finding the smallest tail element larger than the heads final 2.
666411 is, by definition, reverse-ordered, and cannot be increased by permuting its elements.
To find the next permutation, we must increase the head; a matter of finding the smallest tail
element larger than the heads final 2.
8342 666411
Walking back from the end of tail, the first element greater than 2 is 4.
@ -66,7 +63,8 @@ Walking back from the end of tail, the first element greater than 2 is 4.
Swap the 2 and the 4
8344 666211
Since head has increased, we now have a greater permutation. To reduce to the next permutation, we reverse tail, putting it into increasing order.
Since head has increased, we now have a greater permutation. To reduce to the next permutation,
we reverse tail, putting it into increasing order.
8344 112666
Join the head and tail back together. The permutation one greater than 8342666411 is 8344112666.
@ -545,3 +543,4 @@ void bigCombinations64(uint64_t n, uint64_t k, double &mantissa, uint64_t &expon
// -- END OF FILE --

View File

@ -29,6 +29,7 @@
// assertNAN(arg); // isnan(a)
// assertNotNAN(arg); // !isnan(a)
#include <ArduinoUnitTests.h>
@ -39,8 +40,10 @@
unittest_setup()
{
fprintf(stderr, "\nSTATHELPERS_LIB_VERSION: %s\n", (char *) STATHELPERS_LIB_VERSION);
}
unittest_teardown()
{
}
@ -48,8 +51,6 @@ unittest_teardown()
unittest(test_permutations)
{
fprintf(stderr, "\nVERSION: %s\n", STATHELPERS_LIB_VERSION);
fprintf(stderr, "\n\tpermutations(12, k)\n");
for (int k = 0; k <= 12; k++)
{
@ -87,8 +88,6 @@ unittest(test_permutations)
unittest(test_factorial)
{
fprintf(stderr, "\nVERSION: %s\n", STATHELPERS_LIB_VERSION);
fprintf(stderr, "\n\tfactorial(n)\n");
for (int n = 0; n <= 12; n++)
{
@ -115,8 +114,6 @@ unittest(test_factorial)
unittest(test_combinations)
{
fprintf(stderr, "\nVERSION: %s\n", STATHELPERS_LIB_VERSION);
fprintf(stderr, "\n\tcombinations(30, k)\n");
for (int k = 0; k <= 30; k++)
{