libdonut  2.3.2
Application framework for cross-platform game development in C++20
random.hpp
Go to the documentation of this file.
1 #ifndef DONUT_RANDOM_HPP
2 #define DONUT_RANDOM_HPP
3 
4 #include <algorithm> // std::generate
5 #include <array> // std::array
6 #include <bit> // std::rotl
7 #include <cstdint> // std::uint64_t
8 #include <istream> // std::basic_istream
9 #include <limits> // std::numeric_limits
10 #include <ostream> // std::basic_ostream
11 
12 namespace donut::random {
13 
29 public:
30  using result_type = std::uint64_t;
31 
32  static constexpr result_type default_seed = 0;
33 
34  [[nodiscard]] static constexpr result_type min() {
35  return 0;
36  }
37 
38  [[nodiscard]] static constexpr result_type max() {
39  return std::numeric_limits<result_type>::max();
40  }
41 
42  constexpr SplitMix64Engine() noexcept
44 
45  constexpr explicit SplitMix64Engine(result_type value) noexcept
46  : state(value) {}
47 
48  constexpr void seed(result_type value = default_seed) noexcept {
49  state = value;
50  }
51 
52  constexpr result_type operator()() noexcept {
53  state += 0x9E3779B97F4A7C15ull;
54  std::uint64_t z = state;
55  z = (z ^ (z >> 30)) * 0xBF58476D1CE4E5B9ull;
56  z = (z ^ (z >> 27)) * 0x94D049BB133111EBull;
57  return z ^ (z >> 31);
58  }
59 
60  constexpr void discard(unsigned long long z) noexcept {
61  while (z-- > 0) {
62  (*this)();
63  }
64  }
65 
66  [[nodiscard]] constexpr bool operator==(const SplitMix64Engine& other) const noexcept {
67  return state == other.state;
68  }
69 
70  template <typename CharT, typename Traits>
71  friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& stream, const SplitMix64Engine& engine) {
72  return stream << engine.state;
73  }
74 
75  template <typename CharT, typename Traits>
76  friend std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& stream, SplitMix64Engine& engine) {
77  return stream >> engine.state;
78  }
79 
80 private:
81  std::uint64_t state;
82 };
83 
99 public:
100  using result_type = std::uint64_t;
101 
103 
104  [[nodiscard]] static constexpr result_type min() {
105  return 0;
106  }
107 
108  [[nodiscard]] static constexpr result_type max() {
109  return std::numeric_limits<result_type>::max();
110  }
111 
112  constexpr Xoroshiro128PlusPlusEngine() noexcept
114 
115  constexpr explicit Xoroshiro128PlusPlusEngine(result_type value) noexcept {
116  seed(value);
117  }
118 
119  constexpr void seed(result_type value = default_seed) noexcept {
120  SplitMix64Engine stateGenerator{value};
121  std::generate(state.begin(), state.end(), stateGenerator);
122  }
123 
124  constexpr result_type operator()() noexcept {
125  const std::uint64_t s0 = state[0];
126  std::uint64_t s1 = state[1];
127  const std::uint64_t result = std::rotl(s0 + s1, 17) + s0;
128  s1 ^= s0;
129  state[0] = std::rotl(s0, 49) ^ s1 ^ (s1 << 21);
130  state[1] = std::rotl(s1, 28);
131  return result;
132  }
133 
134  constexpr void discard(unsigned long long z) noexcept {
135  while (z-- > 0) {
136  (*this)();
137  }
138  }
139 
143  constexpr void jump() noexcept {
144  std::uint64_t s0 = 0;
145  std::uint64_t s1 = 0;
146  for (const std::uint64_t c : {0x2BD7A6A6E99C2DDCull, 0x0992CCAF6A6FCA05ull}) {
147  for (int b = 0; b < 64; ++b) {
148  if ((c & (std::uint64_t{1} << b)) != 0) {
149  s0 ^= state[0];
150  s1 ^= state[1];
151  }
152  (*this)();
153  }
154  }
155  state[0] = s0;
156  state[1] = s1;
157  }
158 
162  constexpr void longJump() noexcept {
163  std::uint64_t s0 = 0;
164  std::uint64_t s1 = 0;
165  for (const std::uint64_t c : {0x360FD5F2CF8D5D99ull, 0x9C6E6877736C46E3ull}) {
166  for (int b = 0; b < 64; ++b) {
167  if ((c & (std::uint64_t{1} << b)) != 0) {
168  s0 ^= state[0];
169  s1 ^= state[1];
170  }
171  (*this)();
172  }
173  }
174  state[0] = s0;
175  state[1] = s1;
176  }
177 
178  [[nodiscard]] constexpr bool operator==(const Xoroshiro128PlusPlusEngine& other) const noexcept {
179  return state == other.state;
180  }
181 
182  template <typename CharT, typename Traits>
183  friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& stream, const Xoroshiro128PlusPlusEngine& engine) {
184  return stream << engine.state[0] << ' ' << engine.state[1];
185  }
186 
187  template <typename CharT, typename Traits>
188  friend std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& stream, Xoroshiro128PlusPlusEngine& engine) {
189  return stream >> engine.state[0] >> engine.state[1];
190  }
191 
192 private:
193  std::array<std::uint64_t, 2> state{};
194 };
195 
196 } // namespace donut::random
197 
198 #endif
Implementation of the SplitMix64 pseudorandom number generator that provides the API required for a s...
Definition: random.hpp:28
static constexpr result_type min()
Definition: random.hpp:34
constexpr void discard(unsigned long long z) noexcept
Definition: random.hpp:60
static constexpr result_type max()
Definition: random.hpp:38
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &stream, SplitMix64Engine &engine)
Definition: random.hpp:76
constexpr result_type operator()() noexcept
Definition: random.hpp:52
constexpr void seed(result_type value=default_seed) noexcept
Definition: random.hpp:48
constexpr bool operator==(const SplitMix64Engine &other) const noexcept
Definition: random.hpp:66
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &stream, const SplitMix64Engine &engine)
Definition: random.hpp:71
constexpr SplitMix64Engine(result_type value) noexcept
Definition: random.hpp:45
constexpr SplitMix64Engine() noexcept
Definition: random.hpp:42
static constexpr result_type default_seed
Definition: random.hpp:32
std::uint64_t result_type
Definition: random.hpp:30
Implementation of the xoroshiro128++ pseudorandom number generator that provides the API required for...
Definition: random.hpp:98
static constexpr result_type min()
Definition: random.hpp:104
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &stream, const Xoroshiro128PlusPlusEngine &engine)
Definition: random.hpp:183
static constexpr result_type max()
Definition: random.hpp:108
std::uint64_t result_type
Definition: random.hpp:100
constexpr Xoroshiro128PlusPlusEngine() noexcept
Definition: random.hpp:112
static constexpr result_type default_seed
Definition: random.hpp:102
constexpr void longJump() noexcept
Advance the internal state 2^96 times.
Definition: random.hpp:162
constexpr void seed(result_type value=default_seed) noexcept
Definition: random.hpp:119
constexpr void discard(unsigned long long z) noexcept
Definition: random.hpp:134
constexpr void jump() noexcept
Advance the internal state 2^64 times.
Definition: random.hpp:143
constexpr bool operator==(const Xoroshiro128PlusPlusEngine &other) const noexcept
Definition: random.hpp:178
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &stream, Xoroshiro128PlusPlusEngine &engine)
Definition: random.hpp:188
constexpr result_type operator()() noexcept
Definition: random.hpp:124
constexpr Xoroshiro128PlusPlusEngine(result_type value) noexcept
Definition: random.hpp:115
Definition: utilities.hpp:135