#include #include constexpr const static util::range SAMPLE_RANGE { 0.0, 1.0 }; template static inline constexpr T _scale(f64 sample, T max) { return (T)(sample * (f64)max); } template static inline constexpr T _scale(f64 sample, T min, T max) { return SAMPLE_RANGE.scale({ min, max }, sample); } bool Random::next_bool() { return sample() < 0.5; } #define NEXT(T) T Random::next_ ## T(T max) { return _scale(sample(), max); } #define NEXTT(n) NEXT(i ## n) NEXT(u ## n) #define N_INTS \ NEXTT(8) \ NEXTT(16) \ NEXTT(32) \ NEXTT(64) N_INTS #undef NEXTT #undef NEXT f64 Random::sample() { auto s = _sample(); if (UNLIKELY(s < 0 || s > 1)) throw InvalidRandomSample{ s }; return s; } // Inefficient sample() based impl of `bytes()` void Random::next_bytes(u8* ptr, usize n) { while( n --> 0 ) *ptr++ = next_u8(); } // Non-vertorised impl of _v methods for base void Random::next_v64(u64* p, usize n) { return next_bytes(reinterpret_cast(p), n * sizeof(u64)); } void Random::next_v32(u32* p, usize n) { return next_bytes(reinterpret_cast(p), n * sizeof(u32)); } // Array getters #define NEXT(T) void Random::next_ ## T(T* a, usize n) { while( n --> 0 ) *a++ = next_ ## T(); } #define NEXTT(n) NEXT(i ## n) NEXT(u ## n) N_INTS #undef NEXTT #undef NEXT // --- //next_*(min, max) #define NEXT(T) T Random::next_ ## T(T min, T max) { return _scale(sample(), min, max); } #define NEXTT(n) NEXT(i ## n) NEXT(u ## n) N_INTS #undef NEXTT #undef NEXT // ---