diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/common/mptRandom.h | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/common/mptRandom.h')
-rw-r--r-- | Src/external_dependencies/openmpt-trunk/common/mptRandom.h | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/common/mptRandom.h b/Src/external_dependencies/openmpt-trunk/common/mptRandom.h new file mode 100644 index 00000000..905d1839 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/common/mptRandom.h @@ -0,0 +1,140 @@ +/* + * mptRandom.h + * ----------- + * Purpose: PRNG + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#pragma once + +#include "openmpt/all/BuildSettings.hpp" + +#include "mpt/base/bit.hpp" +#include "mpt/mutex/mutex.hpp" +#ifdef MODPLUG_TRACKER +#include "mpt/random/crand.hpp" +#endif // MODPLUG_TRACKER +#include "mpt/random/default_engines.hpp" +#include "mpt/random/device.hpp" +#include "mpt/random/engine.hpp" +#include "mpt/random/engine_lcg.hpp" +#include "mpt/random/seed.hpp" + +#include <limits> +#include <random> + + + +OPENMPT_NAMESPACE_BEGIN + + +// NOTE: +// We implement our own PRNG and distribution functions as the implementations +// of std::uniform_int_distribution is either wrong (not uniform in MSVC2010) or +// not guaranteed to be livelock-free for bad PRNGs (in GCC, Clang, boost). +// We resort to a simpler implementation with only power-of-2 result ranges for +// both the underlying PRNG and our interface function. This saves us from +// complicated code having to deal with partial bits of entropy. +// Our interface still somewhat follows the mindset of C++11 <random> (with the +// addition of a simple wrapper function mpt::random which saves the caller from +// instantiating distribution objects for the common uniform distribution case. +// We are still using std::random_device for initial seeding when avalable and +// after working around its set of problems. + + +namespace mpt +{ + + + +template <typename Trng> +class thread_safe_prng + : private Trng +{ +private: + mpt::mutex m; +public: + typedef typename Trng::result_type result_type; +public: + template <typename Trd> + explicit thread_safe_prng(Trd & rd) + : Trng(mpt::make_prng<Trng>(rd)) + { + return; + } + thread_safe_prng(Trng rng) + : Trng(rng) + { + return; + } +public: + static MPT_CONSTEXPRINLINE typename engine_traits<Trng>::result_type min() + { + return Trng::min(); + } + static MPT_CONSTEXPRINLINE typename engine_traits<Trng>::result_type max() + { + return Trng::max(); + } + static MPT_CONSTEXPRINLINE int result_bits() + { + return engine_traits<Trng>::result_bits(); + } +public: + typename engine_traits<Trng>::result_type operator()() + { + mpt::lock_guard<mpt::mutex> l(m); + return Trng::operator()(); + } +}; + + +#ifdef MPT_BUILD_FUZZER + +// Use deterministic seeding +using random_device = deterministc_random_device; + +#else // !MPT_BUILD_FUZZER + +// mpt::random_device always generates 32 bits of entropy +using random_device = mpt::sane_random_device; + +#endif // MPT_BUILD_FUZZER + + +#ifdef MPT_BUILD_FUZZER + +// Use fast PRNGs in order to not waste time fuzzing more complex PRNG +// implementations. +using fast_prng = deterministic_fast_engine; +using good_prng = deterministic_good_engine; + +#else // !MPT_BUILD_FUZZER + +// We cannot use std::minstd_rand here because it has not a power-of-2 sized +// output domain which we rely upon. +using fast_prng = fast_engine; // about 3 ALU operations, ~32bit of state, suited for inner loops +using good_prng = good_engine; + +#endif // MPT_BUILD_FUZZER + + +using default_prng = mpt::good_prng; + + +mpt::random_device & global_random_device(); +mpt::thread_safe_prng<mpt::default_prng> & global_prng(); + +#if defined(MODPLUG_TRACKER) && !defined(MPT_BUILD_WINESUPPORT) +void set_global_random_device(mpt::random_device *rd); +void set_global_prng(mpt::thread_safe_prng<mpt::default_prng> *rng); +#endif // MODPLUG_TRACKER && !MPT_BUILD_WINESUPPORT + + +} // namespace mpt + + +OPENMPT_NAMESPACE_END |