ZeroErr
rng.h
Go to the documentation of this file.
1 #pragma once
2 
4 
5 #include <cstdint>
6 #include <cstring>
7 #include <vector>
8 
10 
11 namespace zeroerr {
12 
30 class Rng final {
31 public:
35  using result_type = uint64_t;
36 
37  static uint64_t min();
38  static uint64_t max();
39 
46  Rng(Rng const&) = delete;
47 
52  Rng& operator=(Rng const&) = delete;
53 
54  // moving is ok
55  Rng(Rng&&) noexcept = default;
56  Rng& operator=(Rng&&) noexcept = default;
57  ~Rng() noexcept = default;
58 
67  Rng();
68 
81  explicit Rng(uint64_t seed) noexcept;
82  Rng(uint64_t x, uint64_t y) noexcept;
83  Rng(std::vector<uint64_t> const& data);
84 
89  Rng copy() const noexcept;
90 
99  inline uint64_t operator()() noexcept {
100  auto x = mX;
101 
102  mX = UINT64_C(15241094284759029579) * mY;
103  mY = rotl(mY - x, 27);
104 
105  return x;
106  }
107 
108  // This is slightly biased. See
109 
126  inline uint32_t bounded(uint32_t range) noexcept {
127  uint64_t r32 = static_cast<uint32_t>(operator()());
128  auto multiresult = r32 * range;
129  return static_cast<uint32_t>(multiresult >> 32U);
130  }
131 
132  // random double in range [0, 1]
133  // see http://prng.di.unimi.it/
134 
142  inline double uniform01() noexcept {
143  auto i = (UINT64_C(0x3ff) << 52U) | (operator()() >> 12U);
144  // can't use union in c++ here for type puning, it's undefined behavior.
145  // std::memcpy is optimized anyways.
146  double d;
147  std::memcpy(&d, &i, sizeof(double));
148  return d - 1.0;
149  }
150 
159  template <typename Container>
160  void shuffle(Container& container) noexcept {
161  auto size = static_cast<uint32_t>(container.size());
162  for (auto i = size; i > 1U; --i) {
163  using std::swap;
164  auto p = bounded(i); // number in [0, i)
165  swap(container[i - 1], container[p]);
166  }
167  }
168 
176  std::vector<uint64_t> state() const;
177 
178 private:
179  static uint64_t rotl(uint64_t x, unsigned k) noexcept;
180 
181  uint64_t mX;
182  uint64_t mY;
183 };
184 
185 } // namespace zeroerr
186 
Definition: rng.h:30
Rng(Rng const &)=delete
Rng(Rng &&) noexcept=default
Rng & operator=(Rng const &)=delete
static uint64_t min()
Definition: rng.cpp:54
uint32_t bounded(uint32_t range) noexcept
Definition: rng.h:126
std::vector< uint64_t > state() const
Definition: rng.cpp:46
uint64_t result_type
This RNG provides 64bit randomness.
Definition: rng.h:35
double uniform01() noexcept
Definition: rng.h:142
void shuffle(Container &container) noexcept
Definition: rng.h:160
Rng copy() const noexcept
Definition: rng.cpp:35
static uint64_t max()
Definition: rng.cpp:56
uint64_t operator()() noexcept
Produces a 64bit random value. This should be very fast, thus it is marked as inline....
Definition: rng.h:99
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
Definition: config.h:265
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH
Definition: config.h:218
Definition: benchmark.cpp:17