Advertisement
ulfben

RNG

Jan 13th, 2023 (edited)
1,001
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 1.71 KB | None | 0 0
  1. #pragma once
  2. #include <type_traits>
  3. #include <cassert>
  4. // The "xoshiro256** 1.0" generator.
  5. // C++ port by Arthur O'Dwyer (2021).
  6. // https://quuxplusone.github.io/blog/2021/11/23/xoshiro/
  7. // Based on the C version by David Blackman and Sebastiano Vigna (2018),
  8. // https://prng.di.unimi.it/xoshiro256starstar.c
  9. static_assert(sizeof(long long) == 8, "64-bit machines only");
  10.  
  11. class RNG {
  12.  public:
  13.   using u64 = unsigned long long;
  14.   using result_type = u64;
  15.   static constexpr u64 min() noexcept { return 0; }
  16.   static constexpr u64 max() noexcept { return static_cast<u64>(-1); }
  17.  
  18.   constexpr explicit RNG(u64 seed = 0) noexcept {
  19.     s[0] = splitmix64(seed);
  20.     s[1] = splitmix64(seed);
  21.     s[2] = splitmix64(seed);
  22.     s[3] = splitmix64(seed);
  23.   }
  24.  
  25.   constexpr explicit RNG(float seed) noexcept
  26.       : RNG(static_cast<u64>(seed)) {}
  27.  
  28.   constexpr result_type operator()() noexcept {
  29.     const result_type result = rotl(s[1] * 5, 7) * 9;
  30.     const u64 t = s[1] << 17;
  31.     s[2] ^= s[0];
  32.     s[3] ^= s[1];
  33.     s[1] ^= s[2];
  34.     s[0] ^= s[3];
  35.     s[2] ^= t;
  36.     s[3] = rotl(s[3], 45);
  37.     return result;
  38.   }
  39.    
  40.   constexpr result_type operator()(u64 from, u64 to) noexcept {    
  41.     assert(from < to && "RNG: inverted range.");
  42.     const auto range = to-from;
  43.     const auto result = this->operator()();
  44.     return from + (result % range);
  45.   }
  46.  
  47.  private:
  48.   u64 s[4]{};
  49.  
  50.   static constexpr u64 rotl(u64 x, int k) noexcept {
  51.     return (x << k) | (x >> (64 - k));
  52.   }
  53.  
  54.   static constexpr u64 splitmix64(u64& x) noexcept {
  55.     u64 z = (x += 0x9e3779b97f4a7c15uLL);
  56.     z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9uLL;
  57.     z = (z ^ (z >> 27)) * 0x94d049bb133111ebuLL;
  58.     return z ^ (z >> 31);
  59.   }
  60. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement