Fortune for cpprng's current commit: Future small blessing − 末小吉lib
parent
7eaba3c1b3
commit
5d69550fff
@ -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 }; }
|
||||
}
|
Loading…
Reference in new issue