mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
0.2.4 randomHelpers
This commit is contained in:
parent
82ed8ed86f
commit
ce8965b227
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/randomHelpers.git"
|
||||
},
|
||||
"version": "0.2.3",
|
||||
"version": "0.2.4",
|
||||
"license": "MIT",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=randomHelpers
|
||||
version=0.2.3
|
||||
version=0.2.4
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library with helper function for faster random bits
|
||||
|
238
libraries/randomHelpers/randomHelpers.cpp
Normal file
238
libraries/randomHelpers/randomHelpers.cpp
Normal file
@ -0,0 +1,238 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: randomHelpers.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.2.4
|
||||
// PURPOSE: Arduino library with helper function for faster random bits
|
||||
// URL: https://github.com/RobTillaart/randomHelpers
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.2.4 2022-04-15 fix #4 split .h in .h and .cpp
|
||||
// 0.2.3 2021-12-27 update library.json, license, minor edits
|
||||
// 0.2.2 2021-11-15 update Arduino-CI, readme.md badges
|
||||
// add seedMarsaglia(uint32_t a, uint32_t b)
|
||||
// fix randomDice()
|
||||
// 0.2.1 2021-01-07 Arduino-CI
|
||||
// 0.2.0 2020-07-01 rewrite.
|
||||
// 0.1.01 2015-08-18 bug fixes and further optimizations.
|
||||
// 0.1.00 2015-08-17 initial version.
|
||||
|
||||
|
||||
#include "randomHelpers.h"
|
||||
|
||||
|
||||
// the idea is to have one buffer ( __randomBuffer) which holds 32 random bits.
|
||||
// Every call fetches bits from that buffer and if it does not hold enough
|
||||
// bits any more it fills the buffer first. This way the relative expensive
|
||||
// calls to random() which produces a 32 bit number are minimized in an
|
||||
// efficient way.
|
||||
//
|
||||
// TBD: put it in a class ?
|
||||
|
||||
uint32_t __randomBuffer = 0;
|
||||
uint8_t __randomIdx = 0;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// An example of a simple pseudo-random number generator is the
|
||||
// Multiply-with-carry method invented by George Marsaglia.
|
||||
// it has two initializers (not zero) which can be changed
|
||||
// to seed the generator.
|
||||
//
|
||||
uint32_t m_w = 1;
|
||||
uint32_t m_z = 2;
|
||||
|
||||
|
||||
uint32_t Marsaglia()
|
||||
{
|
||||
m_z = 36969L * (m_z & 65535L) + (m_z >> 16);
|
||||
m_w = 18000L * (m_w & 65535L) + (m_w >> 16);
|
||||
return (m_z << 16) + m_w; /* 32-bit result */
|
||||
}
|
||||
|
||||
|
||||
bool seedMarsaglia(uint32_t a, uint32_t b)
|
||||
{
|
||||
if (a == 0 || b == 0) return false;
|
||||
m_w = a;
|
||||
m_z = b;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint32_t getRandom32()
|
||||
{
|
||||
// return random(0xFFFFFFFF); // use the built in
|
||||
return Marsaglia();
|
||||
}
|
||||
|
||||
|
||||
bool getRandom1()
|
||||
{
|
||||
if (__randomIdx < 1)
|
||||
{
|
||||
__randomBuffer = getRandom32();
|
||||
__randomIdx = 32;
|
||||
}
|
||||
bool rv = __randomBuffer & 0x01;
|
||||
__randomBuffer >>= 1;
|
||||
__randomIdx--;
|
||||
return rv;
|
||||
}
|
||||
|
||||
// typical use
|
||||
bool inline flipCoin()
|
||||
{
|
||||
return getRandom1();
|
||||
};
|
||||
|
||||
|
||||
uint8_t getRandom4()
|
||||
{
|
||||
if (__randomIdx < 4)
|
||||
{
|
||||
__randomBuffer = getRandom32();
|
||||
__randomIdx = 32;
|
||||
}
|
||||
uint8_t rv = __randomBuffer & 0x0F;
|
||||
__randomBuffer >>= 4;
|
||||
__randomIdx -= 4;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
uint8_t getRandom5()
|
||||
{
|
||||
if (__randomIdx < 5)
|
||||
{
|
||||
__randomBuffer = getRandom32();
|
||||
__randomIdx = 32;
|
||||
}
|
||||
uint8_t rv = __randomBuffer & 0x1F;
|
||||
__randomBuffer >>= 5;
|
||||
__randomIdx -= 5;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
uint8_t getRandom6()
|
||||
{
|
||||
if (__randomIdx < 6)
|
||||
{
|
||||
__randomBuffer = getRandom32();
|
||||
__randomIdx = 32;
|
||||
}
|
||||
uint8_t rv = __randomBuffer & 0x3F;
|
||||
__randomBuffer >>= 6;
|
||||
__randomIdx -= 6;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// typical use
|
||||
uint8_t throwDice()
|
||||
{
|
||||
if (__randomIdx < 16)
|
||||
{
|
||||
__randomBuffer = getRandom32();
|
||||
__randomIdx = 32;
|
||||
}
|
||||
uint16_t rv = __randomBuffer % 6 + 1;
|
||||
__randomBuffer >>= 3;
|
||||
__randomIdx -= 3;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
uint8_t getRandom8()
|
||||
{
|
||||
if (__randomIdx < 8)
|
||||
{
|
||||
__randomBuffer = getRandom32();
|
||||
__randomIdx = 32;
|
||||
}
|
||||
uint8_t rv = __randomBuffer & 0xFF;
|
||||
__randomBuffer >>= 8;
|
||||
__randomIdx -= 8;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
uint16_t getRandom16()
|
||||
{
|
||||
if (__randomIdx < 16)
|
||||
{
|
||||
__randomBuffer = getRandom32();
|
||||
__randomIdx = 32;
|
||||
}
|
||||
uint16_t rv = __randomBuffer & 0xFFFF;
|
||||
__randomBuffer >>= 16;
|
||||
__randomIdx -= 16;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
uint32_t getRandom24()
|
||||
{
|
||||
return getRandom32() & 0xFFFFFF;
|
||||
}
|
||||
|
||||
|
||||
uint64_t getRandom64()
|
||||
{
|
||||
uint64_t rv = getRandom32();
|
||||
rv <<= 32;
|
||||
rv |= getRandom32();
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
// works well for 1..16; but above it is worse
|
||||
uint32_t getRandomBits(uint8_t n)
|
||||
{
|
||||
if (__randomIdx < n)
|
||||
{
|
||||
__randomBuffer = getRandom32();
|
||||
__randomIdx = 32;
|
||||
}
|
||||
uint32_t rv = __randomBuffer & ((1UL << n) - 1);
|
||||
__randomBuffer >>= n;
|
||||
__randomIdx -= n;
|
||||
return rv;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// n = 1..31
|
||||
// TODO: performance gain too low for n > 16
|
||||
uint32_t getRandomBits(uint8_t n)
|
||||
{
|
||||
uint32_t rv = 0;
|
||||
|
||||
// for large values of n the more straightforward approach is faster (UNO).
|
||||
if (n > 32) n = 32;
|
||||
if (n >= 20) return getRandom32() >> (32 - n);
|
||||
|
||||
if (n >= __randomIdx)
|
||||
{
|
||||
if (__randomIdx > 0)
|
||||
{
|
||||
n -= __randomIdx;
|
||||
rv = __randomBuffer << n;
|
||||
}
|
||||
__randomBuffer = getRandom32();
|
||||
__randomIdx = 32;
|
||||
}
|
||||
if (n > 0) // more bits needed?
|
||||
{
|
||||
rv |= __randomBuffer & ((1UL << n) - 1);
|
||||
__randomBuffer >>= n;
|
||||
__randomIdx -= n;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -1,26 +1,15 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: randomHelpers.h
|
||||
// AUTHOR: Rob dot Tillaart at gmail dot com
|
||||
// VERSION: 0.2.3
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.2.4
|
||||
// PURPOSE: Arduino library with helper function for faster random bits
|
||||
// URL: https://github.com/RobTillaart/randomHelpers
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.2.3 2021-12-27 update library.json, license, minor edits
|
||||
// 0.2.2 2021-11-15 update Arduino-CI, readme.md badges
|
||||
// add seedMarsaglia(uint32_t a, uint32_t b)
|
||||
// fix randomDice()
|
||||
// 0.2.1 2021-01-07 Arduino-CI
|
||||
// 0.2.0 2020-07-01 rewrite.
|
||||
// 0.1.01 2015-08-18 bug fixes and further optimizations.
|
||||
// 0.1.00 2015-08-17 initial version.
|
||||
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#define RANDOM_HELPERS_VERSION (F("0.2.3"))
|
||||
#define RANDOM_HELPERS_VERSION (F("0.2.4"))
|
||||
|
||||
|
||||
// the idea is to have one buffer ( __randomBuffer) which holds 32 random bits.
|
||||
@ -31,9 +20,6 @@
|
||||
//
|
||||
// TBD: put it in a class ?
|
||||
|
||||
uint32_t __randomBuffer = 0;
|
||||
uint8_t __randomIdx = 0;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@ -42,152 +28,34 @@ uint8_t __randomIdx = 0;
|
||||
// it has two initializers (not zero) which can be changed
|
||||
// to seed the generator.
|
||||
//
|
||||
uint32_t m_w = 1;
|
||||
uint32_t m_z = 2;
|
||||
|
||||
uint32_t Marsaglia();
|
||||
|
||||
uint32_t Marsaglia()
|
||||
{
|
||||
m_z = 36969L * (m_z & 65535L) + (m_z >> 16);
|
||||
m_w = 18000L * (m_w & 65535L) + (m_w >> 16);
|
||||
return (m_z << 16) + m_w; /* 32-bit result */
|
||||
}
|
||||
bool seedMarsaglia(uint32_t a, uint32_t b);
|
||||
|
||||
uint32_t getRandom32();
|
||||
|
||||
bool seedMarsaglia(uint32_t a, uint32_t b)
|
||||
{
|
||||
if (a == 0 || b == 0) return false;
|
||||
m_w = a;
|
||||
m_z = b;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint32_t getRandom32()
|
||||
{
|
||||
// return random(0xFFFFFFFF); // use the built in
|
||||
return Marsaglia();
|
||||
}
|
||||
|
||||
|
||||
bool getRandom1()
|
||||
{
|
||||
if (__randomIdx < 1)
|
||||
{
|
||||
__randomBuffer = getRandom32();
|
||||
__randomIdx = 32;
|
||||
}
|
||||
bool rv = __randomBuffer & 0x01;
|
||||
__randomBuffer >>= 1;
|
||||
__randomIdx--;
|
||||
return rv;
|
||||
}
|
||||
bool getRandom1();
|
||||
|
||||
// typical use
|
||||
bool inline flipCoin()
|
||||
{
|
||||
return getRandom1();
|
||||
};
|
||||
bool inline flipCoin();
|
||||
|
||||
uint8_t getRandom4();
|
||||
|
||||
uint8_t getRandom4()
|
||||
{
|
||||
if (__randomIdx < 4)
|
||||
{
|
||||
__randomBuffer = getRandom32();
|
||||
__randomIdx = 32;
|
||||
}
|
||||
uint8_t rv = __randomBuffer & 0x0F;
|
||||
__randomBuffer >>= 4;
|
||||
__randomIdx -= 4;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
uint8_t getRandom5()
|
||||
{
|
||||
if (__randomIdx < 5)
|
||||
{
|
||||
__randomBuffer = getRandom32();
|
||||
__randomIdx = 32;
|
||||
}
|
||||
uint8_t rv = __randomBuffer & 0x1F;
|
||||
__randomBuffer >>= 5;
|
||||
__randomIdx -= 5;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
uint8_t getRandom6()
|
||||
{
|
||||
if (__randomIdx < 6)
|
||||
{
|
||||
__randomBuffer = getRandom32();
|
||||
__randomIdx = 32;
|
||||
}
|
||||
uint8_t rv = __randomBuffer & 0x3F;
|
||||
__randomBuffer >>= 6;
|
||||
__randomIdx -= 6;
|
||||
return rv;
|
||||
}
|
||||
uint8_t getRandom5();
|
||||
|
||||
uint8_t getRandom6();
|
||||
|
||||
// typical use
|
||||
uint8_t throwDice()
|
||||
{
|
||||
if (__randomIdx < 16)
|
||||
{
|
||||
__randomBuffer = getRandom32();
|
||||
__randomIdx = 32;
|
||||
}
|
||||
uint16_t rv = __randomBuffer % 6 + 1;
|
||||
__randomBuffer >>= 3;
|
||||
__randomIdx -= 3;
|
||||
return rv;
|
||||
}
|
||||
uint8_t throwDice();
|
||||
|
||||
uint8_t getRandom8();
|
||||
|
||||
uint8_t getRandom8()
|
||||
{
|
||||
if (__randomIdx < 8)
|
||||
{
|
||||
__randomBuffer = getRandom32();
|
||||
__randomIdx = 32;
|
||||
}
|
||||
uint8_t rv = __randomBuffer & 0xFF;
|
||||
__randomBuffer >>= 8;
|
||||
__randomIdx -= 8;
|
||||
return rv;
|
||||
}
|
||||
uint16_t getRandom16();
|
||||
|
||||
uint32_t getRandom24();
|
||||
|
||||
uint16_t getRandom16()
|
||||
{
|
||||
if (__randomIdx < 16)
|
||||
{
|
||||
__randomBuffer = getRandom32();
|
||||
__randomIdx = 32;
|
||||
}
|
||||
uint16_t rv = __randomBuffer & 0xFFFF;
|
||||
__randomBuffer >>= 16;
|
||||
__randomIdx -= 16;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
uint32_t getRandom24()
|
||||
{
|
||||
return getRandom32() & 0xFFFFFF;
|
||||
}
|
||||
|
||||
|
||||
uint64_t getRandom64()
|
||||
{
|
||||
uint64_t rv = getRandom32();
|
||||
rv <<= 32;
|
||||
rv |= getRandom32();
|
||||
return rv;
|
||||
}
|
||||
uint64_t getRandom64();
|
||||
|
||||
/*
|
||||
// works well for 1..16; but above it is worse
|
||||
@ -208,32 +76,8 @@ uint32_t getRandomBits(uint8_t n)
|
||||
|
||||
// n = 1..31
|
||||
// TODO: performance gain too low for n > 16
|
||||
uint32_t getRandomBits(uint8_t n)
|
||||
{
|
||||
uint32_t rv = 0;
|
||||
uint32_t getRandomBits(uint8_t n);
|
||||
|
||||
// for large values of n the more straightforward approach is faster (UNO).
|
||||
if (n > 32) n = 32;
|
||||
if (n >= 20) return getRandom32() >> (32 - n);
|
||||
|
||||
if (n >= __randomIdx)
|
||||
{
|
||||
if (__randomIdx > 0)
|
||||
{
|
||||
n -= __randomIdx;
|
||||
rv = __randomBuffer << n;
|
||||
}
|
||||
__randomBuffer = getRandom32();
|
||||
__randomIdx = 32;
|
||||
}
|
||||
if (n > 0) // more bits needed?
|
||||
{
|
||||
rv |= __randomBuffer & ((1UL << n) - 1);
|
||||
__randomBuffer >>= n;
|
||||
__randomIdx -= n;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
Loading…
Reference in New Issue
Block a user