From 36622eca96573ab7ef6540f4904580f1fd759e38 Mon Sep 17 00:00:00 2001 From: couriersud Date: Sun, 3 May 2020 08:56:22 +0200 Subject: [PATCH] netlist: Adding prandom.h (nw) --- src/lib/netlist/plib/prandom.h | 125 +++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 src/lib/netlist/plib/prandom.h diff --git a/src/lib/netlist/plib/prandom.h b/src/lib/netlist/plib/prandom.h new file mode 100644 index 00000000000..5e26ef4997d --- /dev/null +++ b/src/lib/netlist/plib/prandom.h @@ -0,0 +1,125 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud + +#ifndef PRANDOM_H_ +#define PRANDOM_H_ + +/// +/// \file pmath.h +/// + +#include "pconfig.h" +#include "ptypes.h" + +//#include +//#include +//#include +#include + +namespace plib +{ + + /// \brief Mersenne Twister implementation which is state saveable + /// + /// This is a Mersenne Twister implementation which is state saveable. + /// It has been written following this wikipedia entry: + /// + /// https://en.wikipedia.org/wiki/Mersenne_Twister + /// + /// The implementation has basic support for the interface described here + /// + /// https://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine + /// + /// so that it can be used with the C++11 random environment + /// + template + class mersenne_twister_t + { + public: + mersenne_twister_t() + : index(N+1) + { + seed(5489); + } + + static constexpr T min() noexcept { return static_cast(0); } + static constexpr T max() noexcept { return ~T(0) >> (sizeof(T)*8 - w); } + + void seed(T val) noexcept + { + const T lowest_w(~T(0) >> (sizeof(T)*8 - w)); + index = N; + mt[0] = val; + for (std::size_t i=1; i< N; i++) + mt[i] = (f * (mt[i-1] ^ (mt[i-1] >> (w-2))) + i) & lowest_w; + } + + T operator()() noexcept + { + const T lowest_w(~T(0) >> (sizeof(T)*8 - w)); + if (index >= N) + twist(); + + T y = mt[index++]; + y = y ^ ((y >> u) & d); + y = y ^ ((y << s) & b); + y = y ^ ((y << t) & c); + y = y ^ (y >> l); + + return y & lowest_w; + } + + void discard(std::size_t v) noexcept + { + if (v > N - index) + { + v -= N - index; + twist(); + } + while (v > N) + { + v -= N; + twist(); + } + index += v; + } + + private: + void twist() + { + const T lowest_w(~T(0) >> (sizeof(T)*8 - w)); + const T lower_mask((static_cast(1) << r) - 1); // That is, the binary number of r 1's + const T upper_mask((~lower_mask) & lowest_w); + + for (std::size_t i=0; i> 1) ^ ((x & 1) ? a : 0)); + mt[i] = mt[(i + m) % N] ^ xA; + } + index = 0; + } + + std::array mt; + std::size_t index; + }; + + using mt19937_64 = mersenne_twister_t< + uint_fast64_t, + 64, 312, 156, 31, + 0xb5026f5aa96619e9ULL, + 29, 0x5555555555555555ULL, + 17, 0x71d67fffeda60000ULL, + 37, 0xfff7eee000000000ULL, + 43, + 6364136223846793005ULL>; + +} // namespace plib + +#endif // PRANDOM_H_