random: use more robust seeding strategy
This commit is contained in:
parent
cdac2dcbc2
commit
a90ce0920f
33
random.hpp
33
random.hpp
@ -18,18 +18,49 @@
|
|||||||
#define CRUFT_UTIL_RANDOM_HPP
|
#define CRUFT_UTIL_RANDOM_HPP
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
|
||||||
namespace util::random {
|
namespace util::random {
|
||||||
|
template <typename T>
|
||||||
|
struct state_size;
|
||||||
|
|
||||||
|
template <
|
||||||
|
class UIntType,
|
||||||
|
size_t w, size_t n, size_t m, size_t r,
|
||||||
|
UIntType a, size_t u, UIntType d, size_t s,
|
||||||
|
UIntType b, size_t t,
|
||||||
|
UIntType c, size_t l, UIntType f
|
||||||
|
> struct state_size<std::mersenne_twister_engine<UIntType,w,n,m,r,a,u,d,s,b,t,c,l,f>> {
|
||||||
|
static constexpr auto value = n * sizeof (UIntType);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename UIntType, UIntType a, UIntType c, UIntType m>
|
||||||
|
struct state_size<std::linear_congruential_engine<UIntType,a,c,m>> {
|
||||||
|
static constexpr auto value = sizeof (UIntType);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr auto state_size_v = state_size<T>::value;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
/// return correctly initialised thread-local generator of an unspecified,
|
/// return correctly initialised thread-local generator of an unspecified,
|
||||||
/// but not entirely useless, type. ie, not LCG.
|
/// but not entirely useless, type. ie, not LCG.
|
||||||
inline auto&
|
inline auto&
|
||||||
generator (void)
|
generator (void)
|
||||||
{
|
{
|
||||||
static thread_local std::default_random_engine gen { std::random_device {}() };
|
using generator_t = std::default_random_engine;
|
||||||
|
|
||||||
|
static thread_local generator_t gen = [] () {
|
||||||
|
std::array<int,state_size_v<generator_t> / 4> seed;
|
||||||
|
std::generate (seed.begin (), seed.end (), std::random_device ());
|
||||||
|
|
||||||
|
std::seed_seq seq (seed.begin (), seed.end ());
|
||||||
|
return generator_t (seq);
|
||||||
|
} ();
|
||||||
|
|
||||||
return gen;
|
return gen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user