6 #ifndef METALL_UTILITY_RANDOM_HPP
7 #define METALL_UTILITY_RANDOM_HPP
15 #if !defined(DOXYGEN_SKIP)
32 explicit SplitMix64(
const uint64_t seed) : m_x(seed) {}
41 uint64_t z = (m_x += 0x9e3779b97f4a7c15);
42 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
43 z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
76 using result_type = uint64_t;
78 explicit xoshiro512pp(
const uint64_t seed) {
79 SplitMix64 seed_gen(seed);
80 for (
int i = 0; i < 8; ++i) {
81 m_s[i] = seed_gen.next();
85 bool equal(
const xoshiro512pp &other)
const {
86 for (
int i = 0; i < 8; ++i) {
87 if (m_s[i] != other.m_s[i])
return false;
93 const uint64_t result = rotl(m_s[0] + m_s[2], 17) + m_s[2];
95 const uint64_t t = m_s[1] << 11;
108 m_s[7] = rotl(m_s[7], 21);
117 static const uint64_t JUMP[] = {0x33ed89b6e7a353f9, 0x760083d7955323be,
118 0x2837f2fbb5f22fae, 0x4b8c5674d309511c,
119 0xb11ac47a7ba28c25, 0xf1be7667092bcc1c,
120 0x53851efdb6df0aaf, 0x1ebbc8b23eaf25db};
122 uint64_t t[
sizeof m_s /
sizeof *m_s];
123 memset(t, 0,
sizeof t);
124 for (
int i = 0; i < (int)(
sizeof JUMP /
sizeof *JUMP); i++)
125 for (
int b = 0; b < 64; b++) {
126 if (JUMP[i] & UINT64_C(1) << b)
127 for (
int w = 0; w < (int)(
sizeof m_s /
sizeof *m_s); w++)
132 memcpy(m_s, t,
sizeof m_s);
140 static const uint64_t LONG_JUMP[] = {
141 0x11467fef8f921d28, 0xa2a819f2e79c8ea8, 0xa8299fc284b3959a,
142 0xb4d347340ca63ee1, 0x1cb0940bedbff6ce, 0xd956c5c4fa1f8e17,
143 0x915e38fd4eda93bc, 0x5b3ccdfa5d7daca5};
145 uint64_t t[
sizeof m_s /
sizeof *m_s];
146 memset(t, 0,
sizeof t);
147 for (
int i = 0; i < (int)(
sizeof LONG_JUMP /
sizeof *LONG_JUMP); i++)
148 for (
int b = 0; b < 64; b++) {
149 if (LONG_JUMP[i] & UINT64_C(1) << b)
150 for (
int w = 0; w < (int)(
sizeof m_s /
sizeof *m_s); w++)
155 memcpy(m_s, t,
sizeof m_s);
159 static constexpr uint64_t rotl(
const uint64_t x,
int k) {
160 return (x << k) | (x >> (64 - k));
190 class xoshiro1024pp {
192 using result_type = uint64_t;
194 explicit xoshiro1024pp(
const uint64_t seed) {
195 SplitMix64 seed_gen(seed);
196 for (
int i = 0; i < 16; ++i) {
197 m_s[i] = seed_gen.next();
201 bool equal(
const xoshiro1024pp &other)
const {
202 for (
int i = 0; i < 16; ++i) {
203 if (m_s[i] != other.m_s[i])
return false;
210 const uint64_t s0 = m_s[m_p = (m_p + 1) & 15];
211 uint64_t s15 = m_s[q];
212 const uint64_t result = rotl(s0 + s15, 23) + s15;
215 m_s[q] = rotl(s0, 25) ^ s15 ^ (s15 << 27);
216 m_s[m_p] = rotl(s15, 36);
225 static const uint64_t JUMP[] = {
226 0x931197d8e3177f17, 0xb59422e0b9138c5f, 0xf06a6afb49d668bb,
227 0xacb8a6412c8a1401, 0x12304ec85f0b3468, 0xb7dfe7079209891e,
228 0x405b7eec77d9eb14, 0x34ead68280c44e4a, 0xe0e4ba3e0ac9e366,
229 0x8f46eda8348905b7, 0x328bf4dbad90d6ff, 0xc8fd6fb31c9effc3,
230 0xe899d452d4b67652, 0x45f387286ade3205, 0x03864f454a8920bd,
233 uint64_t t[
sizeof m_s /
sizeof *m_s];
234 memset(t, 0,
sizeof t);
235 for (
int i = 0; i < (int)(
sizeof JUMP /
sizeof *JUMP); i++)
236 for (
int b = 0; b < 64; b++) {
237 if (JUMP[i] & UINT64_C(1) << b)
238 for (
int j = 0; j < int(
sizeof m_s /
sizeof *m_s); j++)
239 t[j] ^= m_s[(j + m_p) & (
sizeof m_s /
sizeof *m_s - 1)];
243 for (
int i = 0; i < (int)(
sizeof m_s /
sizeof *m_s); i++) {
244 m_s[(i + m_p) & (
sizeof m_s /
sizeof *m_s - 1)] = t[i];
253 static const uint64_t LONG_JUMP[] = {
254 0x7374156360bbf00f, 0x4630c2efa3b3c1f6, 0x6654183a892786b1,
255 0x94f7bfcbfb0f1661, 0x27d8243d3d13eb2d, 0x9701730f3dfb300f,
256 0x2f293baae6f604ad, 0xa661831cb60cd8b6, 0x68280c77d9fe008c,
257 0x50554160f5ba9459, 0x2fc20b17ec7b2a9a, 0x49189bbdc8ec9f8f,
258 0x92a65bca41852cc1, 0xf46820dd0509c12a, 0x52b00c35fbf92185,
261 uint64_t t[
sizeof m_s /
sizeof *m_s];
262 memset(t, 0,
sizeof t);
263 for (
int i = 0; i < (int)(
sizeof LONG_JUMP /
sizeof *LONG_JUMP); i++)
264 for (
int b = 0; b < 64; b++) {
265 if (LONG_JUMP[i] & UINT64_C(1) << b)
266 for (
int j = 0; j < (int)(
sizeof m_s /
sizeof *m_s); j++)
267 t[j] ^= m_s[(j + m_p) & (
sizeof m_s /
sizeof *m_s - 1)];
271 for (
int i = 0; i < (int)(
sizeof m_s /
sizeof *m_s); i++) {
272 m_s[(i + m_p) & (
sizeof m_s /
sizeof *m_s - 1)] = t[i];
277 static constexpr uint64_t rotl(
const uint64_t x,
const int k) {
278 return (x << k) | (x >> (64 - k));
285 template <
typename xoshiro_type>
286 class base_rand_xoshiro {
288 using result_type =
typename xoshiro_type::result_type;
290 explicit base_rand_xoshiro(
const uint64_t seed = 123)
291 : m_rand_generator(seed) {}
296 const auto n = m_rand_generator.next();
297 assert(min() <= n && n <= max());
304 bool equal(
const base_rand_xoshiro &other) {
305 return m_rand_generator.equal(other.m_rand_generator);
310 static constexpr result_type min() {
311 return std::numeric_limits<result_type>::min();
316 static constexpr result_type max() {
317 return std::numeric_limits<result_type>::max();
325 xoshiro_type m_rand_generator;
328 template <
typename xoshiro_type>
329 inline bool operator==(
const base_rand_xoshiro<xoshiro_type> &lhs,
330 const base_rand_xoshiro<xoshiro_type> &rhs) {
331 return lhs.equal(rhs);
334 template <
typename xoshiro_type>
335 inline bool operator!=(
const base_rand_xoshiro<xoshiro_type> &lhs,
336 const base_rand_xoshiro<xoshiro_type> &rhs) {
337 return !(lhs == rhs);
346 using rand_512 = detail::base_rand_xoshiro<detail::xoshiro512pp>;
351 using rand_1024 = detail::base_rand_xoshiro<detail::xoshiro1024pp>;