Containers (STL-compatible) StateMachines MessageBus and more for Embedded Systems. See www.etlcpp.com
Diff: random.cpp
- Revision:
- 0:b47c2a7920c2
diff -r 000000000000 -r b47c2a7920c2 random.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/random.cpp Fri Mar 16 16:34:18 2018 +0000 @@ -0,0 +1,353 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +http://www.etlcpp.com + +Copyright(c) 2017 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "platform.h" +#include "random.h" + +namespace etl +{ + //*************************************************************************** + // XOR Shift + //*************************************************************************** + + //*************************************************************************** + /// Default constructor. + /// Attempts to come up with a unique non-zero seed. + //*************************************************************************** + random_xorshift::random_xorshift() + { + // An attempt to come up with a unique non-zero seed, + // based on the address of the instance. + uintptr_t n = reinterpret_cast<uintptr_t>(this); + uint32_t seed = static_cast<uint32_t>(n); + initialise(seed); + } + + //*************************************************************************** + /// Constructor with seed value. + ///\param seed The new seed value. + //*************************************************************************** + random_xorshift::random_xorshift(uint32_t seed) + { + initialise(seed); + } + + //*************************************************************************** + /// Initialises the sequence with a new seed value. + ///\param seed The new seed value. + //*************************************************************************** + void random_xorshift::initialise(uint32_t seed) + { + // Add the first four primes to ensure that the seed isn't zero. + state[0] = seed + 3; + state[1] = seed + 5; + state[2] = seed + 7; + state[3] = seed + 11; + } + + //*************************************************************************** + /// Get the next random_xorshift number. + //*************************************************************************** + uint32_t random_xorshift::operator()() + { + uint32_t n = state[3]; + n ^= n << 11; + n ^= n >> 8; + state[3] = state[2]; + state[2] = state[1]; + state[1] = state[0]; + n ^= state[0]; + n ^= state[0] >> 19; + state[0] = n; + + return n; + } + + //*************************************************************************** + /// Get the next random_xorshift number in a specified inclusive range. + //*************************************************************************** + uint32_t random_xorshift::range(uint32_t low, uint32_t high) + { + uint32_t r = high - low + 1; + uint32_t n = operator()(); + n %= r; + n += low; + + return n; + } + + //*************************************************************************** + // Linear Congruential Generator + //*************************************************************************** + + //*************************************************************************** + /// Default constructor. + /// Attempts to come up with a unique non-zero seed. + //*************************************************************************** + random_lcg::random_lcg() + { + // An attempt to come up with a unique non-zero seed, + // based on the address of the instance. + uintptr_t n = reinterpret_cast<uintptr_t>(this); + uint32_t seed = static_cast<uint32_t>(n); + initialise(seed); + } + + //*************************************************************************** + /// Constructor with seed value. + ///\param seed The new seed value. + //*************************************************************************** + random_lcg::random_lcg(uint32_t seed) + { + initialise(seed); + } + + //*************************************************************************** + /// Initialises the sequence with a new seed value. + ///\param seed The new seed value. + //*************************************************************************** + void random_lcg::initialise(uint32_t seed) + { + seed = (seed == 0) ? 1 : seed; + value = (seed > m) ? m : seed; + } + + //*************************************************************************** + /// Get the next random_clcg number. + //*************************************************************************** + uint32_t random_lcg::operator()() + { + value = (a * value) % m; + + return value; + } + + //*************************************************************************** + /// Get the next random_clcg number in a specified inclusive range. + //*************************************************************************** + uint32_t random_lcg::range(uint32_t low, uint32_t high) + { + uint32_t r = high - low + 1; + uint32_t n = operator()(); + n %= r; + n += low; + + return n; + } + + //*************************************************************************** + // Combined Linear Congruential Generator + //*************************************************************************** + + //*************************************************************************** + /// Default constructor. + /// Attempts to come up with a unique non-zero seed. + //*************************************************************************** + random_clcg::random_clcg() + { + // An attempt to come up with a unique non-zero seed, + // based on the address of the instance. + uintptr_t n = reinterpret_cast<uintptr_t>(this); + uint32_t seed = static_cast<uint32_t>(n); + initialise(seed); + } + + //*************************************************************************** + /// Constructor with seed value. + ///\param seed The new seed value. + //*************************************************************************** + random_clcg::random_clcg(uint32_t seed) + { + initialise(seed); + } + + //*************************************************************************** + /// Initialises the sequence with a new seed value. + ///\param seed The new seed value. + //*************************************************************************** + void random_clcg::initialise(uint32_t seed) + { + seed = (seed == 0) ? 1 : seed; + value1 = (seed > m1) ? m1 : seed; + value2 = (seed > m1) ? m1 : seed; + } + + //*************************************************************************** + /// Get the next random_clcg number. + //*************************************************************************** + uint32_t random_clcg::operator()() + { + static const uint32_t m = ((m1 > m2) ? m1 : m2); + + value1 = (a1 * value1) % m1; + value2 = (a2 * value2) % m2; + + return (value1 + value2) % m; + } + + //*************************************************************************** + /// Get the next random_clcg number in a specified inclusive range. + //*************************************************************************** + uint32_t random_clcg::range(uint32_t low, uint32_t high) + { + uint32_t r = high - low + 1; + uint32_t n = operator()(); + n %= r; + n += low; + + return n; + } + + //*************************************************************************** + // Linear Shift Feedback Register + //*************************************************************************** + + //*************************************************************************** + /// Default constructor. + /// Attempts to come up with a unique non-zero seed. + //*************************************************************************** + random_lsfr::random_lsfr() + { + // An attempt to come up with a unique non-zero seed, + // based on the address of the instance. + uintptr_t n = reinterpret_cast<uintptr_t>(this); + uint32_t seed = static_cast<uint32_t>(n); + initialise(seed); + } + + //*************************************************************************** + /// Constructor with seed value. + ///\param seed The new seed value. + //*************************************************************************** + random_lsfr::random_lsfr(uint32_t seed) + { + initialise(seed); + } + + //*************************************************************************** + /// Initialises the sequence with a new seed value. + ///\param seed The new seed value. + //*************************************************************************** + void random_lsfr::initialise(uint32_t seed) + { + value = seed; + } + + //*************************************************************************** + /// Get the next random_lsfr number. + //*************************************************************************** + uint32_t random_lsfr::operator()() + { + static const uint32_t polynomial = 0x80200003; + + value >>= 1; + + if ((value & 1) == 1) + { + value ^= polynomial; + } + + return value; + } + + //*************************************************************************** + /// Get the next random_lsfr number in a specified inclusive range. + //*************************************************************************** + uint32_t random_lsfr::range(uint32_t low, uint32_t high) + { + uint32_t r = high - low + 1; + uint32_t n = operator()(); + n %= r; + n += low; + + return n; + } + + //*************************************************************************** + // Multiply with carry random number generator. + //*************************************************************************** + + //*************************************************************************** + /// Default constructor. + /// Attempts to come up with a unique non-zero seed. + //*************************************************************************** + random_mwc::random_mwc() + { + // An attempt to come up with a unique non-zero seed, + // based on the address of the instance. + uintptr_t n = reinterpret_cast<uintptr_t>(this); + uint32_t seed = static_cast<uint32_t>(n); + initialise(seed); + } + + //*************************************************************************** + /// Constructor with seed value. + ///\param seed The new seed value. + //*************************************************************************** + random_mwc::random_mwc(uint32_t seed) + { + initialise(seed); + } + + //*************************************************************************** + /// Initialises the sequence with a new seed value. + ///\param seed The new seed value. + //*************************************************************************** + void random_mwc::initialise(uint32_t seed) + { + value1 = seed; + value2 = seed; + } + + //*************************************************************************** + /// Get the next random_lsfr number. + //*************************************************************************** + uint32_t random_mwc::operator()() + { + value1 = 36969 * (value1 & 0xFFFF) + (value1 >> 16); + value2 = 18000 * (value2 & 0xFFFF) + (value2 >> 16); + + return (value1 << 16) + value2; + } + + //*************************************************************************** + /// Get the next random_lsfr number in a specified inclusive range. + //*************************************************************************** + uint32_t random_mwc::range(uint32_t low, uint32_t high) + { + uint32_t r = high - low + 1; + uint32_t n = operator()(); + n %= r; + n += low; + + return n; + } +} +