psemek/libs/random/include/psemek/random/generator.hpp

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();
}
};
}