Fucking hell... First "attempt" at range API... it doesn"t look good :/

Fortune for cpprng's current commit: Future small blessing − 末小吉
lib
Avril 3 years ago
parent 7eaba3c1b3
commit 5d69550fff
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -0,0 +1,91 @@
#pragma once
#include <utility>
#include <tuple>
#include <common.h>
namespace util{
enum class bound
{
Inclusive,
Exclusive,
};
template<typename T> struct range;
using bounds = range<bound>;
constexpr static inline const bounds default_bounds();
template<typename T>
struct range final
{
using type = T;
//constexpr inline range(T start, T end) : start(start), end(end){}
constexpr inline range(T&& start, T&& end) : start(std::move(start)), end(std::move(end)){}
constexpr inline range(const T& start, const T& end) : start(start), end(end){}
constexpr inline range(range<T>&& move) : start(std::move(move.start)), end(std::move(move.end)) {}
constexpr inline range(const range<T>& copy) : start(copy.start), end(copy.end){}
constexpr inline ~range() {}
constexpr inline auto length() const { return end-start; }
constexpr inline auto length(const T& from) const { return from - start; }
constexpr inline bool negative() const { return length() < 0; }
constexpr inline range<T>& normalise() {
if(negative()) std::swap(start, end);
return *this;
}
template<usize I>
requires (I < 2)
constexpr inline T& get() { return I ? end : start; }
template<usize I>
requires (I < 2)
constexpr inline const T& get() const { return I ? end : start; }
template<bounds Bounds = default_bounds()>
constexpr inline bool contains(const T& value) const
{
return (Bounds.get<0>() == bound::Exclusive
? value > start
: value >= start) &&
(Bounds.get<1>() == bound::Exclusive
? value < end
: value <= end);
}
template<bounds Bounds = default_bounds()>
constexpr inline void clamp(T& value) const
{
if constexpr(Bounds.get<0>() == bound::Exclusive) {
if (value <= start) value = start + 1;
} else if (value < start) value = start;
if constexpr(Bounds.get<1>() == bound::Exclusive) {
if (value >= end) value = end - 1;
} else if (value > end) value = end;
}
// Scale the `value` from this range to another one (of a compatable type).
template<bounds Bounds = default_bounds()>
constexpr inline auto scale(const range<auto>& to, T value)
{
clamp<Bounds>(value);
const auto diff = length(value);
const f64 fract = f64(diff) / f64(length());
const auto diff2 = decltype(to)::type(fract * f64(to.length()));
return to.start + diff2;
}
template<bounds Bounds>
constexpr inline auto scale(const range<T>& to, T value);
T start, end;
};
constexpr static inline const bounds default_bounds() { return { bound::Inclusive, bound::Exclusive }; }
}

@ -20,6 +20,9 @@ namespace rng
inline i64 next_i64() override { return _sample_int(); } inline i64 next_i64() override { return _sample_int(); }
u64 next_u64() override; u64 next_u64() override;
i32 next_i32() override;
u32 next_u32() override;
protected: protected:
inline constexpr i64 _max_i64() const override { return RANGE_MAX; } inline constexpr i64 _max_i64() const override { return RANGE_MAX; }
inline constexpr u64 _max_u64() const override { return (u64)RANGE_MAX; } inline constexpr u64 _max_u64() const override { return (u64)RANGE_MAX; }

@ -1,5 +1,6 @@
#include <rng.h> #include <rng.h>
#include <range.h>
template<typename T> template<typename T>
static inline constexpr T _scale(f64 sample, T max) static inline constexpr T _scale(f64 sample, T max)
@ -48,3 +49,9 @@ N_INTS
#undef NEXT #undef NEXT
//TODO: next_*(min, max) //TODO: next_*(min, max)
void __()
{
util::range<int> test(-10, 20);
test.scale({ 100, 200 }, 5);
}

@ -32,12 +32,20 @@ namespace rng
// Overrides // // Overrides //
u64 crand::next_u64() { return std::bit_cast<u64>(std::abs(_sample_int()) & INT32_MAX); } 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 // 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*() //TODO: next_bytes(), next_v*()
} }
void rng_test() void rng_test()
{ {
rng::crand r(123); rng::crand _r(123);
Random& r = _r;
printf("%lu %lu %lu\n", r.next_u64(), r.next_u64(), r.next_u64()); 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));
} }

Loading…
Cancel
Save