random: remove generator choice from easy API

it's supposed to be an easy replacement for std::rand, we don't need to
let the user choose their generator.
This commit is contained in:
Danny Robson 2017-08-28 14:12:36 +10:00
parent 31afd9dcfd
commit 107947899c
2 changed files with 37 additions and 21 deletions

View File

@ -48,7 +48,7 @@ tmpname (std::string &str, size_t length)
str.resize (length); str.resize (length);
std::generate_n (str.begin (), length, [&] (void) { std::generate_n (str.begin (), length, [&] (void) {
return util::rand::choose (alphanum); return util::random::choose (alphanum);
}); });
} }

View File

@ -14,36 +14,52 @@
* Copyright 2016 Danny Robson <danny@nerdcruft.net> * Copyright 2016 Danny Robson <danny@nerdcruft.net>
*/ */
#ifndef __UTIL_RANDOM_HPP #ifndef CRUFT_UTIL_RANDOM_HPP
#define __UTIL_RANDOM_HPP #define CRUFT_UTIL_RANDOM_HPP
#include <random> #include <random>
/////////////////////////////////////////////////////////////////////////////// namespace util::random {
namespace util::rand { ///////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------- /// return correctly initialised thread-local generator of an unspecified,
using default_generator = std::minstd_rand; /// but not entirely useless, type. ie, not LCG.
auto&
generator (void)
//-------------------------------------------------------------------------
template <typename Generator = default_generator>
Generator&
thread_engine (void)
{ {
std::random_device rd; static thread_local std::mt19937_64 gen { std::random_device {}() };
thread_local Generator gen (rd ());
return gen; return gen;
} }
//------------------------------------------------------------------------- ///////////////////////////////////////////////////////////////////////////
template <typename Generator = default_generator, typename T, size_t N> /// select a value uniformly from the range [lo, hi)
T& template <typename T>
choose (T (&t)[N], Generator gen = thread_engine<Generator> ()) std::enable_if_t<std::is_floating_point_v<T>,T>
uniform (T lo, T hi)
{ {
std::uniform_int_distribution<size_t> dist (0, N-1); return std::uniform_real_distribution { lo, hi } (generator ());
return t[dist (gen)]; }
//-------------------------------------------------------------------------
/// select a value uniformly from the range [lo, hi)
template <typename T>
std::enable_if_t<std::is_integral_v<T>,T>
uniform (T lo, T hi)
{
return std::uniform_int_distribution { lo, hi } (generator ());
}
///////////////////////////////////////////////////////////////////////////
/// choose a value at random from an array
template <typename T, size_t N>
T&
choose (T (&t)[N])
{
std::uniform_int_distribution<size_t> dist (0, N - 1);
return t[dist (generator ())];
} }
} }