//constexpr variant of the PCG (Permuted Congruential Generator) algorithm
//See: https://www.pcg-random.org/download.html#minimal-c-implementation
constexpr auto seed() noexcept{
std::uint64_t shifted = 0;
const char* datetime = __DATE__ " " __TIME__;
for (const auto c : datetime) {
shifted <<= 8;
shifted |= c;
}
#ifdef __COUNTER__
shifted ^= __COUNTER__;
#endif
return shifted;
}
//ldexp(pcg32_random_r(&myrng), -32);
struct PCG{
struct pcg32_random_t {
std::uint64_t state = 0;
std::uint64_t inc=seed();
};
pcg32_random_t rng;
using result_type = double;
constexpr result_type operator()() noexcept{
return std::ldexp(pcg32_random_r(), -32); //https://mumble.net/~campbell/tmp/random_real.c
//return pcg32_random_r() * (1.0 / std::numeric_limits<std::uint32_t>::max());
}
constexpr std::uint32_t operator()(std::uint32_t bound) noexcept{
return pcg32_boundedrand_r(bound);
}
static result_type constexpr min() noexcept {
return std::numeric_limits<result_type>::min();
}
static result_type constexpr max() noexcept {
return std::numeric_limits<result_type>::max();
}
private:
constexpr std::uint32_t pcg32_random_r() noexcept {
const std::uint64_t oldstate = rng.state;
rng.state = oldstate * 6364136223846793005ULL + (rng.inc|1);
const auto xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
const auto rot = oldstate >> 59u;
return static_cast<std::uint32_t>((xorshifted >> rot) | (xorshifted << ((-rot) & 31)));
}
constexper std::uint32_t pcg32_boundedrand_r(std::uint32_t bound) noexcept{
if (bound == 1) return 0;
std::uint32_t threshold = -bound % bound;
for (;;) {
std::uint32_t r = pcg32_random_r();
if (r >= threshold){
return r % bound;
}
}
}
};
Comments
0 B
|👍
/👎
0 B
|👍
/👎