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.
104 lines
1.9 KiB
104 lines
1.9 KiB
#include <rng_impl.h>
|
|
#include <stdint.h>
|
|
|
|
/* Written in 2016-2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
|
|
|
|
To the extent possible under law, the author has dedicated all copyright
|
|
and related and neighboring rights to this software to the public domain
|
|
worldwide. This software is distributed without any warranty.
|
|
|
|
See <http://creativecommons.org/publicdomain/zero/1.0/>. */
|
|
|
|
static inline uint64_t rotl(const uint64_t x, int k) {
|
|
return (x << k) | (x >> (64 - k));
|
|
}
|
|
|
|
_Atomic static uint64_t s[2];
|
|
|
|
static uint64_t next(void) {
|
|
const uint64_t s0 = s[0];
|
|
uint64_t s1 = s[1];
|
|
const uint64_t result = s0 + s1;
|
|
|
|
s1 ^= s0;
|
|
s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b
|
|
s[1] = rotl(s1, 37); // c
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
static void jump(void) {
|
|
static const uint64_t JUMP[] = { 0xdf900294d8f554a5, 0x170865df4b3201fc };
|
|
|
|
uint64_t s0 = 0;
|
|
uint64_t s1 = 0;
|
|
for(int 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[0] = s0;
|
|
s[1] = s1;
|
|
}
|
|
|
|
static void long_jump(void) {
|
|
static const uint64_t LONG_JUMP[] = { 0xd2a98b26625eee7b, 0xdddf9b1090aa7ac1 };
|
|
|
|
uint64_t s0 = 0;
|
|
uint64_t s1 = 0;
|
|
for(int 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[0] = s0;
|
|
s[1] = s1;
|
|
}
|
|
|
|
static void seed(uint64_t s0, uint64_t s1) {
|
|
s[0] = s0;
|
|
s[1] = s1;
|
|
}
|
|
|
|
void _seed(const void* from)
|
|
{
|
|
const uint64_t *ptr = from;
|
|
seed(ptr[0], ptr[1]);
|
|
}
|
|
|
|
double _sample()
|
|
{
|
|
return (next() & ((INT64_C(1) << 53) - 1)) * (1.00 / (INT64_C(1) << 53));
|
|
}
|
|
|
|
RNG_IMPL_DEFINITION(xoroshiro128plus)
|
|
{
|
|
struct rng_algo algo;
|
|
algo.sample = &_sample;
|
|
algo.seed = &_seed;
|
|
|
|
algo.construct=NULL;
|
|
algo.destruct=NULL;
|
|
|
|
return rng_new_impl(&algo);
|
|
}
|
|
|
|
void xoro_jump()
|
|
{
|
|
jump();
|
|
}
|
|
|
|
void xoro_long_jump()
|
|
{
|
|
long_jump();
|
|
}
|