Added ranges to Random base.

Added crand::RANGE_MIN/MAX, overriden required base ranges to point to them.

crand::next_u64() returns within this range but discards the negative result

Fortune for cpprng's current commit: Small blessing − 小吉
lib
Avril 3 years ago
parent 977e32c711
commit b59c0671d2
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -78,8 +78,8 @@ struct Random
virtual bool next_bool();
#define NDEF(t, M) inline virtual t next_ ## t() { return next_ ## t(M); }
#define NDEFF(n) NDEF(i ## n, INT ## n ## _MAX) NDEF(u ## n, UINT ## n ## _MAX)
#define NDEF(t) inline virtual t next_ ## t() { return next_ ## t(_max_ ## t()); }
#define NDEFF(n) NDEF(i ## n) NDEF(u ## n)
NDEFF(8)
NDEFF(16)
NDEFF(32)
@ -151,6 +151,15 @@ struct Random
template<typename T>
inline iterator<T> iter() { return iterator(*this); } //TODO: An iterator that yields `next<T>()` forever.
protected:
//TODO: Should we have _min_* functions too? or just continue to use 0 as the lower bound for next_*(..max)? I think use 0...
#define MAX(T, M) constexpr inline virtual T _max_ ## T() const { return M; }
#define MAXX(n) MAX(u ## n, UINT ## n ## _MAX) MAX(i ## n, INT ## n ## _MAX)
MAXX(8)
MAXX(16)
MAXX(32)
MAXX(64)
#undef MAXX
#undef MAX
//constexpr inline virtual i8 _max() const { return 100; } // use limits.h stuff instead.
// Vectorised versions of `next_bytes()`. These will fall back to that if they are not overriden, but if the implementation has a more efficient way of generating 4/8 bytes of random data it should override these.

@ -9,6 +9,10 @@ namespace rng
{
struct crand final : public Random
{
// This range is inclusive
constexpr static inline i64 RANGE_MIN = - (1L << 31);
constexpr static inline i64 RANGE_MAX = (1L << 31) - 1;
crand();
crand(u64 seed);
@ -17,6 +21,9 @@ namespace rng
inline i64 next_i64() override { return _sample_raw(); }
u64 next_u64() override;
protected:
inline constexpr i64 _max_i64() const override { return RANGE_MAX; }
inline constexpr u64 _max_u64() const override { return (u64)RANGE_MAX; }
// the rest of the base `_max_*` functions are valid, as they will always be equal to or less than INT32_MAX (the upper bound of dr48.)
f64 _sample() override;
private:
struct _opaque;

@ -46,3 +46,5 @@ N_INTS
#undef NEXTT
#undef NEXT
//TODO: next_*(min, max)

@ -8,6 +8,14 @@
#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; }
@ -22,7 +30,8 @@ namespace rng
//TODO: properly implemet this f64 crand::_sample() { return (f64)std::bit_cast<u64>(_sample_raw()) / (f64)UINT64_MAX; }
// Overrides //
u64 crand::next_u64() { return std::bit_cast<u64>(_sample_raw()); }
u64 crand::next_u64() { return std::bit_cast<u64>(_sample_raw() & INT32_MAX); } // remove sign bit because it messes with the range.
//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.
}

Loading…
Cancel
Save