Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/core/StarStaticRandom.hpp
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
commit6352e8e3196f78388b6c771073f9e03eaa612673 (patch)
treee23772f79a7fbc41bc9108951e9e136857484bf4 /source/core/StarStaticRandom.hpp
parent6741a057e5639280d85d0f88ba26f000baa58f61 (diff)
everything everywhere
all at once
Diffstat (limited to 'source/core/StarStaticRandom.hpp')
-rw-r--r--source/core/StarStaticRandom.hpp131
1 files changed, 131 insertions, 0 deletions
diff --git a/source/core/StarStaticRandom.hpp b/source/core/StarStaticRandom.hpp
new file mode 100644
index 0000000..97cfdef
--- /dev/null
+++ b/source/core/StarStaticRandom.hpp
@@ -0,0 +1,131 @@
+#ifndef STAR_STATIC_RANDOM_HPP
+#define STAR_STATIC_RANDOM_HPP
+
+#include "StarString.hpp"
+#include "StarXXHash.hpp"
+
+namespace Star {
+
+// Cross-platform, predictable random number generators based on XXHash.
+// Supports primitive types as well as strings for input data.
+
+inline void staticRandomHash32Iter(XXHash32&) {}
+
+template <typename T, typename... TL>
+void staticRandomHash32Iter(XXHash32& hash, T const& v, TL const&... rest) {
+ xxHash32Push(hash, v);
+ staticRandomHash32Iter(hash, rest...);
+}
+
+template <typename T, typename... TL>
+uint32_t staticRandomHash32(T const& v, TL const&... rest) {
+ XXHash32 hash(2938728349u);
+ staticRandomHash32Iter(hash, v, rest...);
+ return hash.digest();
+}
+
+inline void staticRandomHash64Iter(XXHash64&) {}
+
+template <typename T, typename... TL>
+void staticRandomHash64Iter(XXHash64& hash, T const& v, TL const&... rest) {
+ xxHash64Push(hash, v);
+ staticRandomHash64Iter(hash, rest...);
+}
+
+template <typename T, typename... TL>
+uint64_t staticRandomHash64(T const& v, TL const&... rest) {
+ XXHash64 hash(1997293021376312589);
+ staticRandomHash64Iter(hash, v, rest...);
+ return hash.digest();
+}
+
+template <typename T, typename... TL>
+uint32_t staticRandomU32(T const& d, TL const&... rest) {
+ return staticRandomHash32(d, rest...);
+}
+
+template <typename T, typename... TL>
+uint64_t staticRandomU64(T const& d, TL const&... rest) {
+ return staticRandomHash64(d, rest...);
+}
+
+template <typename T, typename... TL>
+int32_t staticRandomI32(T const& d, TL const&... rest) {
+ return (int32_t)staticRandomU32(d, rest...);
+}
+
+template <typename T, typename... TL>
+int32_t staticRandomI32Range(int32_t min, int32_t max, T const& d, TL const&... rest) {
+ uint64_t denom = (uint64_t)(-1) / ((uint64_t)(max - min) + 1);
+ return (int32_t)(staticRandomU64(d, rest...) / denom + min);
+}
+
+template <typename T, typename... TL>
+uint32_t staticRandomU32Range(uint32_t min, uint32_t max, T const& d, TL const&... rest) {
+ uint64_t denom = (uint64_t)(-1) / ((uint64_t)(max - min) + 1);
+ return staticRandomU64(d, rest...) / denom + min;
+}
+
+template <typename T, typename... TL>
+int64_t staticRandomI64(T const& d, TL const&... rest) {
+ return (int64_t)staticRandomU64(d, rest...);
+}
+
+// Generates values in the range [0.0, 1.0]
+template <typename T, typename... TL>
+float staticRandomFloat(T const& d, TL const&... rest) {
+ return (staticRandomU32(d, rest...) & 0x7fffffff) / 2147483648.0;
+}
+
+template <typename T, typename... TL>
+float staticRandomFloatRange(float min, float max, T const& d, TL const&... rest) {
+ return staticRandomFloat(d, rest...) * (max - min) + min;
+}
+
+// Generates values in the range [0.0, 1.0]
+template <typename T, typename... TL>
+double staticRandomDouble(T const& d, TL const&... rest) {
+ return (staticRandomU64(d, rest...) & 0x7fffffffffffffff) / 9223372036854775808.0;
+}
+
+template <typename T, typename... TL>
+double staticRandomDoubleRange(double min, double max, T const& d, TL const&... rest) {
+ return staticRandomDouble(d, rest...) * (max - min) + min;
+}
+
+template <typename Container, typename T, typename... TL>
+typename Container::value_type& staticRandomFrom(Container& container, T const& d, TL const&... rest) {
+ auto i = container.begin();
+ std::advance(i, staticRandomI32Range(0, container.size() - 1, d, rest...));
+ return *i;
+}
+
+template <typename Container, typename T, typename... TL>
+typename Container::value_type const& staticRandomFrom(Container const& container, T const& d, TL const&... rest) {
+ auto i = container.begin();
+ std::advance(i, staticRandomI32Range(0, container.size() - 1, d, rest...));
+ return *i;
+}
+
+template <typename Container, typename T, typename... TL>
+typename Container::value_type staticRandomValueFrom(Container const& container, T const& d, TL const&... rest) {
+ if (container.empty()) {
+ return {};
+ } else {
+ auto i = container.begin();
+ std::advance(i, staticRandomI32Range(0, container.size() - 1, d, rest...));
+ return *i;
+ }
+}
+
+template <typename Container, typename T, typename... TL>
+void staticRandomShuffle(Container& container, T const& d, TL const&... rest) {
+ int mix = 0;
+ std::random_shuffle(container.begin(),
+ container.end(),
+ [&](size_t max) { return staticRandomU32Range(0, max - 1, ++mix, d, rest...); });
+}
+
+}
+
+#endif