You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
1.6 KiB
87 lines
1.6 KiB
#include <rng/xoroshiro128plus.hpp>
|
|
#include <iostream>
|
|
|
|
using u64 = std::uint64_t;
|
|
|
|
#define XO xoroshiro128plus
|
|
|
|
static inline constexpr u64 rotl(u64 x, int k)
|
|
{
|
|
return (x << k) | (x >> (64 - k));
|
|
}
|
|
|
|
namespace rng
|
|
{
|
|
inline constexpr u64 next(XO::State& s)
|
|
{
|
|
u64 s0 = s[0];
|
|
u64 s1 = s[1];
|
|
u64 result = s0 + s1;
|
|
|
|
s1 ^= s0;
|
|
s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16);
|
|
s[1] = rotl(s1, 37);
|
|
|
|
return result;
|
|
}
|
|
inline constexpr void xo_jump(XO::State& s)
|
|
{
|
|
constexpr const std::uint64_t JUMP[] = { 0xdf900294d8f554a5, 0x170865df4b3201fc };
|
|
|
|
std::uint64_t s0 = 0;
|
|
std::uint64_t s1 = 0;
|
|
for(u64 i = 0; i < sizeof JUMP / sizeof *JUMP; i++)
|
|
for(int b = 0; b < 64; b++) {
|
|
if (JUMP[i] & UINT64_C(1) << b) {
|
|
s0 ^= s[0];
|
|
s1 ^= s[1];
|
|
}
|
|
next(s);
|
|
}
|
|
|
|
s[0] = s0;
|
|
s[1] = s1;
|
|
}
|
|
|
|
inline constexpr void xo_long_jump(XO::State& s)
|
|
{
|
|
constexpr const uint64_t LONG_JUMP[] = { 0xd2a98b26625eee7b, 0xdddf9b1090aa7ac1 };
|
|
|
|
std::uint64_t s0 = 0;
|
|
std::uint64_t s1 = 0;
|
|
for(u64 i = 0; i < sizeof LONG_JUMP / sizeof *LONG_JUMP; i++)
|
|
for(int b = 0; b < 64; b++) {
|
|
if (LONG_JUMP[i] & UINT64_C(1) << b) {
|
|
s0 ^= s[0];
|
|
s1 ^= s[1];
|
|
}
|
|
next(s);
|
|
}
|
|
|
|
s[0] = s0;
|
|
s[1] = s1;
|
|
}
|
|
|
|
|
|
void XO::jump() { xo_jump(state); }
|
|
void XO::long_jump() { xo_long_jump(state); }
|
|
|
|
std::uint64_t XO::next_ulong()
|
|
{
|
|
return next(state);
|
|
}
|
|
std:: int64_t XO::next_long()
|
|
{
|
|
const u64 v = next_ulong();
|
|
static_assert(sizeof(v) == sizeof(decltype(next_long())));
|
|
|
|
return *(const std::int64_t*)&v;
|
|
}
|
|
|
|
|
|
double XO::sample()
|
|
{
|
|
return (next(state) & ((INT64_C(1) << 53) - 1)) * (1.00 / (INT64_C(1) << 53));
|
|
}
|
|
}
|