66 lines
1.2 KiB
C++
66 lines
1.2 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <limits>
|
|
|
|
#include <psemek/random/device.hpp>
|
|
|
|
namespace psemek::random
|
|
{
|
|
|
|
// based on www.pcg-random.org
|
|
struct generator
|
|
{
|
|
generator() = default;
|
|
generator(generator const &) = default;
|
|
|
|
generator(std::uint64_t state, std::uint64_t inc)
|
|
: state_{state}
|
|
, inc_{inc}
|
|
{}
|
|
|
|
generator(device & rd)
|
|
: state_{gen64(rd)}
|
|
, inc_{gen64(rd)}
|
|
{}
|
|
|
|
generator(device && rd)
|
|
: state_{gen64(rd)}
|
|
, inc_{gen64(rd)}
|
|
{}
|
|
|
|
generator & operator = (generator const &) = default;
|
|
|
|
using result_type = std::uint32_t;
|
|
|
|
result_type operator()()
|
|
{
|
|
std::uint64_t oldstate = state_;
|
|
state_ = oldstate * 6364136223846793005ULL + (inc_ | 1);
|
|
std::uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
|
|
std::uint32_t rot = oldstate >> 59u;
|
|
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
|
|
}
|
|
|
|
static result_type min()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static result_type max()
|
|
{
|
|
return std::numeric_limits<result_type>::max();
|
|
}
|
|
|
|
private:
|
|
std::uint64_t state_ = 0;
|
|
std::uint64_t inc_ = 0;
|
|
|
|
template <typename RD>
|
|
static std::uint64_t gen64(RD & rd)
|
|
{
|
|
return (static_cast<std::uint64_t>(rd()) << 32) | rd();
|
|
}
|
|
};
|
|
|
|
}
|