131 lines
3.9 KiB
C++
131 lines
3.9 KiB
C++
/*
|
|
RANDOM.hpp - support for random number generation with controlled seed
|
|
|
|
Copyright (C) Lumiera.org
|
|
2024, Hermann Vosseler <Ichthyostega@web.de>
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of
|
|
the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
|
|
/** @file random.hpp
|
|
** Generating (pseudo) random numbers with controlled seed.
|
|
** As an extension on top of the [C++ random number framework], several instances
|
|
** of random number sequence generators can be easily created with a controlled seed.
|
|
** For simplified usage, two default instances are exposed as global variable
|
|
** - lib::defaultGen uses fixed seeding (planned: make this configurable)
|
|
** - lib::entropyGen always uses true randomness as seed value.
|
|
** [C++ random number framework]: https://en.cppreference.com/w/cpp/numeric/random
|
|
** @see Random_test
|
|
*/
|
|
|
|
|
|
#ifndef LIB_RANDOM_H
|
|
#define LIB_RANDOM_H
|
|
|
|
|
|
#include "lib/integral.hpp"
|
|
#include "lib/nocopy.hpp"
|
|
|
|
#include <random>
|
|
|
|
|
|
namespace lib {
|
|
|
|
/** Establishes a seed point for any instance or performance. */
|
|
class SeedNucleus
|
|
{
|
|
public:
|
|
virtual ~SeedNucleus(); ///< this is an interface
|
|
virtual uint64_t getSeed() =0;
|
|
};
|
|
|
|
/**
|
|
* Access point to a selection of random number sources.
|
|
* For each kind of performance or usage, a common execution scheme
|
|
* is established to initiate generated number sequences, allowing
|
|
* for seemingly random yet reproducible behaviour — or for actually
|
|
* contingent behaviour when necessary. Client code should rely on
|
|
* [Dependency-Injection](\ref lib::Depend) or the static accessors.
|
|
*/
|
|
template<class GEN>
|
|
class RandomSequencer
|
|
: util::NonCopyable
|
|
{
|
|
std::uniform_int_distribution<int> uniformI_;
|
|
std::uniform_int_distribution<uint64_t> uniformU_;
|
|
std::uniform_real_distribution<double> uniformD_;
|
|
|
|
GEN generator_;
|
|
|
|
public:
|
|
/** Random instances are created as part of an execution scheme */
|
|
RandomSequencer(SeedNucleus&);
|
|
|
|
int i32() { return uniformI_(generator_); }
|
|
uint64_t u64() { return uniformU_(generator_); }
|
|
double uni() { return uniformD_(generator_); }
|
|
|
|
/** inject controlled randomisation */
|
|
void randomise(SeedNucleus&);
|
|
};
|
|
|
|
/**
|
|
* PRNG engine to use by default: 64bit mersenne twister.
|
|
*/
|
|
using Random = RandomSequencer<std::mt19937_64>;
|
|
|
|
|
|
/** a global default RandomSequencer for mundane purposes */
|
|
extern Random defaultGen;
|
|
|
|
/** a global RandomSequencer seeded with real entropy */
|
|
extern Random entropyGen;
|
|
|
|
|
|
/* ===== convenience accessors ===== */
|
|
|
|
inline int rani() { return defaultGen.i32(); }
|
|
inline uint64_t ranu() { return defaultGen.u64(); }
|
|
inline double runi() { return defaultGen.uni(); }
|
|
|
|
|
|
/** inject true randomness into the #defaultGen */
|
|
void randomiseRandomness();
|
|
|
|
|
|
/* ===== Implementation details ===== */
|
|
|
|
template<class GEN>
|
|
inline
|
|
RandomSequencer<GEN>::RandomSequencer (SeedNucleus& nucleus)
|
|
: uniformI_{0}
|
|
, uniformU_{0}
|
|
, uniformD_{}
|
|
, generator_{nucleus.getSeed()}
|
|
{ }
|
|
|
|
|
|
template<class GEN>
|
|
inline void
|
|
RandomSequencer<GEN>::randomise (SeedNucleus& nucleus)
|
|
{
|
|
generator_.discard (nucleus.getSeed() % 55555);
|
|
}
|
|
|
|
|
|
} // namespace lib
|
|
#endif /*LIB_RANDOM_H*/
|