diff options
author | Marcus Müller <mmueller@gnuradio.org> | 2021-03-22 00:37:47 +0100 |
---|---|---|
committer | mormj <34754695+mormj@users.noreply.github.com> | 2021-04-06 07:37:17 -0400 |
commit | eb91fb04b3d0ca8124b9bea375e3bf72963fa172 (patch) | |
tree | dcf96c9e232b7019a7d81cd16901a95bda8b5471 /gnuradio-runtime/include/gnuradio/random.h | |
parent | 42349ff2855c1bb0148c8191339189b0a4cee675 (diff) |
runtime: fix gr::random API to be fixed-width 64 bit, use XOROSHIRO128+
Seeding being inconsistent between gr::random and things like fastnoise
source is an outstanding issue (#1559).
Fix that by fixing the API, and pivoting to our built-in XOROSHIRO128+,
which is also substantially faster than MT19937.
For that purpose, introduce, and python-bind, a wrapper class that can
be used with STL distribution shapers.
Add a unit test for the (P)RNG.
Signed-off-by: Marcus Müller <mmueller@gnuradio.org>
Diffstat (limited to 'gnuradio-runtime/include/gnuradio/random.h')
-rw-r--r-- | gnuradio-runtime/include/gnuradio/random.h | 55 |
1 files changed, 47 insertions, 8 deletions
diff --git a/gnuradio-runtime/include/gnuradio/random.h b/gnuradio-runtime/include/gnuradio/random.h index 504b36a933..ba216f3117 100644 --- a/gnuradio-runtime/include/gnuradio/random.h +++ b/gnuradio-runtime/include/gnuradio/random.h @@ -13,14 +13,53 @@ #include <gnuradio/api.h> #include <gnuradio/gr_complex.h> +#include <gnuradio/xoroshiro128p.h> -#include <cstdlib> -#include <ctime> +#include <limits> #include <random> namespace gr { /*! + * \brief wrapper for XOROSHIRO128+ PRNG for use in std::distributions + * Fulfills C++ named requirements for UniformRandomBitGenerator + * \ingroup math_blk + */ +class GR_RUNTIME_API xoroshiro128p_prng +{ +public: + using result_type = uint64_t; //! \brief value type is uint64 + +private: + result_type state[2]; + +public: + /*! + * \brief minimum value + */ + static constexpr result_type min() { return std::numeric_limits<result_type>::min(); } + /*! + * \brief maximum value + */ + static constexpr result_type max() { return std::numeric_limits<result_type>::max(); } + + /*! + * \brief constructor. Expects a seed. + */ + xoroshiro128p_prng(uint64_t init) { seed(init); } + + + /*! + * \brief yield a random value and advance state + */ + result_type operator()() { return xoroshiro128p_next(state); } + + /*! + * \brief set new seed + */ + void seed(uint64_t seed) { xoroshiro128p_seed(state, seed); } +}; +/*! * \brief pseudo random number generator * \ingroup math_blk */ @@ -31,32 +70,32 @@ protected: bool d_gauss_stored; float d_gauss_value; - std::mt19937 d_rng; // mersenne twister as random number generator + xoroshiro128p_prng d_rng; // mersenne twister as random number generator std::uniform_real_distribution<float> d_uniform; // choose uniform distribution, default is [0,1) - std::uniform_int_distribution<> d_integer_dis; + std::uniform_int_distribution<int64_t> d_integer_dis; public: - random(unsigned int seed = 0, int min_integer = 0, int max_integer = 2); + random(uint64_t seed = 0, int64_t min_integer = 0, int64_t max_integer = 2); ~random(); /*! * \brief Change the seed for the initialized number generator. seed = 0 initializes * the random number generator with the system time. */ - void reseed(unsigned int seed); + void reseed(uint64_t seed); /*! * set minimum and maximum for integer random number generator. * Limits are [minimum, maximum) * Default: [0, std::numeric_limits< IntType >::max)] */ - void set_integer_limits(const int minimum, const int maximum); + void set_integer_limits(int64_t minimum, int64_t maximum); /*! * Uniform random integers in the range set by 'set_integer_limits' [min, max). */ - int ran_int(); + int64_t ran_int(); /*! * \brief Uniform random numbers in the range [0.0, 1.0) |