2017-08-30 15:32:44 +02:00
|
|
|
/*
|
|
|
|
* 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"
|
2019-10-06 21:47:54 +02:00
|
|
|
#include "catch_run_context.h"
|
2017-08-30 15:32:44 +02:00
|
|
|
#include "catch_interfaces_config.h"
|
|
|
|
|
|
|
|
namespace Catch {
|
|
|
|
|
2019-10-06 21:47:54 +02:00
|
|
|
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)();
|
2018-06-15 15:35:47 +02:00
|
|
|
}
|
|
|
|
|
2019-10-06 21:47:54 +02:00
|
|
|
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<void>((*this)());
|
2018-06-15 15:35:47 +02:00
|
|
|
}
|
2017-08-30 15:32:44 +02:00
|
|
|
}
|
2018-06-15 15:35:47 +02:00
|
|
|
|
2019-10-06 21:47:54 +02:00
|
|
|
SimplePcg32::result_type SimplePcg32::operator()() {
|
|
|
|
// prepare the output value
|
|
|
|
const uint32_t xorshifted = static_cast<uint32_t>(((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;
|
2017-08-30 15:32:44 +02:00
|
|
|
}
|
|
|
|
}
|