aboutsummaryrefslogtreecommitdiff
path: root/Src/external_dependencies/openmpt-trunk/common/mptRandom.h
diff options
context:
space:
mode:
authorJean-Francois Mauguit <jfmauguit@mac.com>2024-09-24 09:03:25 -0400
committerGitHub <noreply@github.com>2024-09-24 09:03:25 -0400
commitbab614c421ed7ae329d26bf028c4a3b1d2450f5a (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/common/mptRandom.h
parent4bde6044fddf053f31795b9eaccdd2a5a527d21f (diff)
parent20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (diff)
downloadwinamp-bab614c421ed7ae329d26bf028c4a3b1d2450f5a.tar.gz
Merge pull request #5 from WinampDesktop/community
Merge to main
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/common/mptRandom.h')
-rw-r--r--Src/external_dependencies/openmpt-trunk/common/mptRandom.h140
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