diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
commit | 6352e8e3196f78388b6c771073f9e03eaa612673 (patch) | |
tree | e23772f79a7fbc41bc9108951e9e136857484bf4 /source/core/StarStaticRandom.hpp | |
parent | 6741a057e5639280d85d0f88ba26f000baa58f61 (diff) |
everything everywhere
all at once
Diffstat (limited to 'source/core/StarStaticRandom.hpp')
-rw-r--r-- | source/core/StarStaticRandom.hpp | 131 |
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 |