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.
rngxx/src/rng/crand.cpp

52 lines
1.9 KiB

#include <bit>
#include <climits>
#include <cmath>
#include <rng.h>
#include <mem.h>
#include <rng/crand.h>
#include "crand.h"
// Note: the output of drand48 is uniform between INT32_MIN..=INT32_MAX (inclusive)
constexpr const i64 _J_RANGE_MIN = (i64)INT32_MIN;
constexpr const i64 _J_RANGE_MAX = (i64)INT32_MAX;
static_assert(_J_RANGE_MIN == rng::crand::RANGE_MIN);
static_assert(_J_RANGE_MAX == rng::crand::RANGE_MAX);
namespace rng
{
void crand::_deleter::delete_object(_opaque** state) { _jr_free(reinterpret_cast<jr_state*>(*state)); *state = nullptr; }
crand::crand(_opaque* raw) :_state(mem::aligned_ptr<_opaque, _deleter>(raw)){}
crand::crand(u64 seed) : crand(reinterpret_cast<_opaque*>(_jr_new(seed))){}
crand::crand() : crand(0xabad1dea){}
i64 crand::_sample_int() { return _jr_proc(reinterpret_cast<jr_state*>(&_state)); } //RANGE_MIN..=RANGE_MAX
f64 crand::_sample() { return _jr_procf(reinterpret_cast<jr_state*>(&_state)); } //0..1
// Overrides //
u64 crand::next_u64() { return std::bit_cast<u64>(std::abs(_sample_int()) & INT32_MAX); }
// next_i/u64(max) overrides not nessicary, the impl would be same as base. same with array next_*(p, n) overrides
i32 crand::next_i32() { return (i32)next_i64(); }
u32 crand::next_u32() { return std::bit_cast<u32>((i32)_sample_int()); } // I think keeping the sign bit in the transmute here doesn't violate the distribution, since it's between int32's min and max value...
//TODO: next_bytes(), next_v*()
}
void rng_test()
{
rng::crand _r(123);
Random& r = _r;
printf("%lu %lu %lu\n", r.next_u64(), r.next_u64(), r.next_u64());
printf("%d %d %d\n", r.next_i32(), r.next_i32(), r.next_i32());
printf("%u %u %u\n", r.next_u32(), r.next_u32(), r.next_u32());
// TODO: these aren't implemented yet in the base Random huh...
printf("---\n%u %d %d %u\n", r.next_u32(10, 20), r.next_i32(10, 20), r.next_i32(10), r.next_u32(10));
}