random: separate the generator initialisation code

This commit is contained in:
Danny Robson 2019-02-21 20:53:32 +11:00
parent 8f88569f61
commit 6142f7fb1d

View File

@ -3,7 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2016-2018 Danny Robson <danny@nerdcruft.net>
* Copyright 2016-2019 Danny Robson <danny@nerdcruft.net>
*/
#pragma once
@ -18,37 +18,19 @@
namespace cruft::random {
/// A trait describing the internal state size of a given Generator.
///
/// The structure must be specialised.
///
/// \tparam GeneratorT The generator to query
///////////////////////////////////////////////////////////////////////////
/// Initialise and return a generator using random_device.
template <typename GeneratorT>
struct state_size;
GeneratorT
initialise (void)
{
// Approximate the state size of the generator by its size in bytes.
std::array<unsigned,sizeof (GeneratorT) / sizeof (unsigned) + 1> seed;
std::generate (seed.begin (), seed.end (), std::random_device ());
//-------------------------------------------------------------------------
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;
std::seed_seq seq (seed.begin (), seed.end ());
return GeneratorT (seq);
}
///////////////////////////////////////////////////////////////////////////
@ -60,15 +42,7 @@ namespace cruft::random {
generator (void)
{
using generator_t = std::mt19937_64;
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);
} ();
static thread_local auto gen = initialise<generator_t> ();
return gen;
}