3 impls test okay

lean
Avril 4 years ago
parent 48301abe6b
commit eec7fa4167
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -7,10 +7,13 @@ extern "C" {
// Tests // Tests
void frng_test(); void frng_test();
void xorng_test();
void drng_test();
#ifdef __cplusplus #ifdef __cplusplus
} }
// RNG interfaces // RNG interfaces
#include <rng/frng.hpp> #include <rng/frng.hpp>
#include <rng/xoroshiro128plus.hpp>
#endif #endif

@ -0,0 +1,19 @@
#include "impl.hpp"
namespace rng
{
struct drng : public RNG
{
inline drng(std::uint32_t seed) : state(seed){sample();}
inline drng() : drng(1){}
static drng from_time();
int rand();
protected:
double sample() override;
private:
std::uint32_t state;
};
}

@ -23,7 +23,6 @@ struct RNG {
std::int32_t next_int(std::int32_t min, std::int32_t max); std::int32_t next_int(std::int32_t min, std::int32_t max);
virtual std::int64_t next_long(); virtual std::int64_t next_long();
inline std::int64_t next_long(std::int64_t max) { return next_long(0, max); } inline std::int64_t next_long(std::int64_t max) { return next_long(0, max); }
std::int64_t next_long(std::int64_t min, std::int64_t max); std::int64_t next_long(std::int64_t min, std::int64_t max);

@ -0,0 +1,26 @@
#pragma once
#include "impl.hpp"
namespace rng
{
struct xoroshiro128plus : public RNG
{
using State = std::array<std::uint64_t, 2>;
inline constexpr xoroshiro128plus(std::uint64_t s0, std::uint64_t s1) : state({s0, s1}){}
inline constexpr xoroshiro128plus(std::array<std::uint64_t, 2>&& ar) : state(ar){}
inline constexpr xoroshiro128plus(const std::array<std::uint64_t, 2>& ar) : state(ar){}
inline constexpr xoroshiro128plus(const std::uint64_t (&ar)[2]) : state({ar[0], ar[1]}){}
std::uint64_t next_ulong();
using RNG::next_long;
std::int64_t next_long() override;
void jump();
void long_jump();
protected:
double sample() override;
private:
State state;
};
}

@ -44,6 +44,8 @@ int main(int argc, char** argv)
struct prog_args args = {.argc = argc, .argv = argv}; struct prog_args args = {.argc = argc, .argv = argv};
frng_test(); frng_test();
xorng_test();
drng_test();
if( argv[1] ) { if( argv[1] ) {
map_and_then(argv[1], &map_callback, &args); map_and_then(argv[1], &map_callback, &args);

@ -0,0 +1,46 @@
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <rng/drng.h>
namespace rng
{
static inline void d_test()
{
using namespace std;
drng rng(100);
for(int i=0;i<10;i++) {
double d = rng.next_double();
long l = rng.next_long(-10, 10);
std::array<bool, 10> ar;
for(auto& i : ar) i = rng.chance();
cout << "D Sampled: " << d << endl;
cout << "D Long: " << l << endl;
cout << "D Bools: [ ";
for(const auto& i : ar) cout << i << " ";
cout << "]" << endl;
}
}
drng drng::from_time() { return drng(time(NULL)); }
int drng::rand()
{
return rand_r(&state);
}
double drng::sample()
{
int val = rand_r(&state);
return (double)val / (double)RAND_MAX;
}
}
extern "C" void drng_test()
{
return rng::d_test();
}

@ -4,7 +4,7 @@
namespace rng { namespace rng {
using namespace std; using namespace std;
inline void test() static inline void f_test()
{ {
frng rng(1.0, 2.0); frng rng(1.0, 2.0);
@ -22,11 +22,10 @@ namespace rng {
cout << "]" << endl; cout << "]" << endl;
} }
} }
} }
extern "C" void frng_test() extern "C" void frng_test()
{ {
rng::test(); rng::f_test();
} }

@ -0,0 +1,111 @@
#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
{
static inline void xo_test()
{
using namespace std;
XO rng(100ul, 123123123ul);
for(int i=0;i<10;i++) {
double d = rng.next_double();
long l = rng.next_long(-10, 10);
std::array<bool, 10> ar;
for(auto& i : ar) i = rng.chance();
cout << "XO Sampled: " << d << endl;
cout << "XO Long: " << l << endl;
cout << "XO Bools: [ ";
for(const auto& i : ar) cout << i << " ";
cout << "]" << endl;
}
}
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));
}
}
extern "C" void xorng_test()
{
return rng::xo_test();
}
Loading…
Cancel
Save