From 8e20b8636523b488e1cdaae500dceefb44fa7012 Mon Sep 17 00:00:00 2001 From: Avril Date: Fri, 1 Oct 2021 16:06:13 +0100 Subject: [PATCH] crand::_sample() uniformly distributes between 0..1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fortune for cpprng's current commit: Blessing − 吉 --- include/rng/crand.h | 4 ++-- src/rng/crand.c | 13 ++++++++++++- src/rng/crand.cpp | 11 +++++------ src/rng/crand.h | 1 + 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/include/rng/crand.h b/include/rng/crand.h index 21034ef..0466dea 100644 --- a/include/rng/crand.h +++ b/include/rng/crand.h @@ -18,7 +18,7 @@ namespace rng inline ~crand(){} - inline i64 next_i64() override { return _sample_raw(); } + inline i64 next_i64() override { return _sample_int(); } u64 next_u64() override; protected: inline constexpr i64 _max_i64() const override { return RANGE_MAX; } @@ -31,6 +31,6 @@ namespace rng mem::aligned_ptr<_opaque, _deleter> _state; explicit crand(_opaque* raw); - i64 _sample_raw(); + i64 _sample_int(); }; } diff --git a/src/rng/crand.c b/src/rng/crand.c index 4540a54..d4501ae 100644 --- a/src/rng/crand.c +++ b/src/rng/crand.c @@ -11,7 +11,10 @@ typedef unsigned short uint48_t[3]; struct jr_state { - long result; + union { + long result; + double fresult; + }; struct drand48_data data; union { unsigned short xsubi[3]; @@ -59,6 +62,14 @@ long _jr_proc(struct jr_state* restrict state) return state->result; } +//TODO: a version of _jr_proc that uses use `erand48_r()` to return between 0..1.0 for _sample() + +double _jr_procf(struct jr_state* restrict state) +{ + erand48_r(_jr_st_resolv(state), &state->data, &state->fresult); + return state->fresult; +} + struct jr_state* _jr_alloc() { struct jr_state* bx = aligned_alloc(_Alignof(struct jr_state), sizeof(struct jr_state)); diff --git a/src/rng/crand.cpp b/src/rng/crand.cpp index 50314ce..c75b1bf 100644 --- a/src/rng/crand.cpp +++ b/src/rng/crand.cpp @@ -26,15 +26,14 @@ namespace rng crand::crand(u64 seed) : crand(reinterpret_cast<_opaque*>(_jr_new(seed))){} crand::crand() : crand(0xabad1dea){} - i64 crand::_sample_raw() { return _jr_proc(reinterpret_cast(_state.get_ptr())); } - - //TODO: properly implemet this f64 crand::_sample() { return (f64)std::bit_cast(_sample_raw()) / (f64)UINT64_MAX; } + i64 crand::_sample_int() { return _jr_proc(reinterpret_cast(_state.get_ptr())); } //RANGE_MIN..=RANGE_MAX + f64 crand::_sample() { return _jr_procf(reinterpret_cast(_state.get_ptr())); } //0..1 // Overrides // - u64 crand::next_u64() { return std::bit_cast(std::abs(_sample_raw()) & INT32_MAX); } // remove sign bit because it messes with the range. + u64 crand::next_u64() { return std::bit_cast(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 - //TODO: Implementing next_i64(i64 max) should be trivial. the man page for drand48 shows its output range, just map that range to `0..=max` - //TODO: make the default range for all non-bounded `next_i/u*` the same range as drand48's. If that's too big for the integer type, scale it down. + //TODO: next_bytes(), next_v*() } void rng_test() diff --git a/src/rng/crand.h b/src/rng/crand.h index af70e67..2da1611 100644 --- a/src/rng/crand.h +++ b/src/rng/crand.h @@ -15,6 +15,7 @@ struct jr_state; void _jr_seed(struct jr_state* restrict state, unsigned long with); long _jr_proc(struct jr_state* restrict state); +double _jr_procf(struct jr_state* restrict state); struct jr_state* _jr_alloc(); void _jr_free(struct jr_state* restrict state);