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