/ externals / catch / src / catch2 / internal / catch_random_number_generator.cpp
catch_random_number_generator.cpp
 1  
 2  //              Copyright Catch2 Authors
 3  // Distributed under the Boost Software License, Version 1.0.
 4  //   (See accompanying file LICENSE.txt or copy at
 5  //        https://www.boost.org/LICENSE_1_0.txt)
 6  
 7  // SPDX-License-Identifier: BSL-1.0
 8  #include <catch2/internal/catch_random_number_generator.hpp>
 9  
10  namespace Catch {
11  
12  namespace {
13  
14  #if defined(_MSC_VER)
15  #pragma warning(push)
16  #pragma warning(disable:4146) // we negate uint32 during the rotate
17  #endif
18          // Safe rotr implementation thanks to John Regehr
19          uint32_t rotate_right(uint32_t val, uint32_t count) {
20              const uint32_t mask = 31;
21              count &= mask;
22              return (val >> count) | (val << (-count & mask));
23          }
24  
25  #if defined(_MSC_VER)
26  #pragma warning(pop)
27  #endif
28  
29  }
30  
31  
32      SimplePcg32::SimplePcg32(result_type seed_) {
33          seed(seed_);
34      }
35  
36  
37      void SimplePcg32::seed(result_type seed_) {
38          m_state = 0;
39          (*this)();
40          m_state += seed_;
41          (*this)();
42      }
43  
44      void SimplePcg32::discard(uint64_t skip) {
45          // We could implement this to run in O(log n) steps, but this
46          // should suffice for our use case.
47          for (uint64_t s = 0; s < skip; ++s) {
48              static_cast<void>((*this)());
49          }
50      }
51  
52      SimplePcg32::result_type SimplePcg32::operator()() {
53          // prepare the output value
54          const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u);
55          const auto output = rotate_right(xorshifted, m_state >> 59u);
56  
57          // advance state
58          m_state = m_state * 6364136223846793005ULL + s_inc;
59  
60          return output;
61      }
62  
63      bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {
64          return lhs.m_state == rhs.m_state;
65      }
66  
67      bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {
68          return lhs.m_state != rhs.m_state;
69      }
70  }