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 }