/* * Created by Martin on 30/08/2017. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #include "catch_random_number_generator.h" #include "catch_context.h" #include "catch_run_context.h" #include "catch_interfaces_config.h" namespace Catch { namespace { #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable:4146) // we negate uint32 during the rotate #endif // Safe rotr implementation thanks to John Regehr uint32_t rotate_right(uint32_t val, uint32_t count) { const uint32_t mask = 31; count &= mask; return (val >> count) | (val << (-count & mask)); } #if defined(_MSC_VER) #pragma warning(pop) #endif } SimplePcg32::SimplePcg32(result_type seed_) { seed(seed_); } void SimplePcg32::seed(result_type seed_) { m_state = 0; (*this)(); m_state += seed_; (*this)(); } void SimplePcg32::discard(uint64_t skip) { // We could implement this to run in O(log n) steps, but this // should suffice for our use case. for (uint64_t s = 0; s < skip; ++s) { static_cast((*this)()); } } SimplePcg32::result_type SimplePcg32::operator()() { // prepare the output value const uint32_t xorshifted = static_cast(((m_state >> 18u) ^ m_state) >> 27u); const auto output = rotate_right(xorshifted, m_state >> 59u); // advance state m_state = m_state * 6364136223846793005ULL + s_inc; return output; } bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs) { return lhs.m_state == rhs.m_state; } bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs) { return lhs.m_state != rhs.m_state; } }