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