23 constexpr T
abs(
const T a)
25 return (a <
static_cast<T
>(0)) ? -a : a;
37 constexpr T
Align(
const T x, uint n)
39 assert((n & (n - 1)) == 0 && n != 0);
41 return static_cast<T
>((x + n) & ~
static_cast<T
>(n));
57 static_assert(
sizeof(uintptr_t) ==
sizeof(
void *));
58 return reinterpret_cast<T *
>(
Align(
reinterpret_cast<uintptr_t
>(x), n));
79 constexpr T
Clamp(
const T a,
const T min,
const T max)
82 if (a <= min)
return min;
83 if (a >= max)
return max;
101 template <
typename T>
102 constexpr T
SoftClamp(
const T a,
const T min,
const T max)
105 using U = std::make_unsigned_t<T>;
106 return min - (U(min) - max) / 2;
108 if (a <= min)
return min;
109 if (a >= max)
return max;
129 constexpr
int Clamp(
const int a,
const int min,
const int max)
131 return Clamp<int>(a, min, max);
150 constexpr uint
ClampU(
const uint a,
const uint min,
const uint max)
152 return Clamp<uint>(a, min, max);
166 template <typename To, typename From, std::enable_if_t<std::is_integral<From>::value,
int> = 0>
169 static_assert(std::numeric_limits<To>::is_integer,
"Do not clamp from non-integer values");
170 static_assert(std::numeric_limits<From>::is_integer,
"Do not clamp to non-integer values");
172 if constexpr (
sizeof(To) >=
sizeof(From) && std::numeric_limits<To>::is_signed == std::numeric_limits<From>::is_signed) {
174 return static_cast<To
>(value);
177 if constexpr (
sizeof(To) >
sizeof(From) && std::numeric_limits<To>::is_signed) {
179 return static_cast<To
>(value);
183 using BiggerType =
typename std::conditional<
sizeof(From) >=
sizeof(To), From, To>::type;
185 if constexpr (std::numeric_limits<To>::is_signed) {
187 if constexpr (std::numeric_limits<From>::is_signed) {
189 return static_cast<To
>(std::clamp<BiggerType>(value,
190 std::numeric_limits<To>::lowest(), std::numeric_limits<To>::max()));
194 using BiggerUnsignedType =
typename std::make_unsigned<BiggerType>::type;
195 return static_cast<To
>(std::min<BiggerUnsignedType>(std::numeric_limits<To>::max(), value));
200 if constexpr (std::numeric_limits<From>::is_signed) {
202 if constexpr (
sizeof(To) >=
sizeof(From)) {
204 return static_cast<To
>(std::max<From>(value, 0));
208 using BiggerSignedType =
typename std::make_signed<BiggerType>::type;
209 return static_cast<To
>(std::clamp<BiggerSignedType>(value,
210 std::numeric_limits<To>::lowest(), std::numeric_limits<To>::max()));
214 return static_cast<To
>(std::min<BiggerType>(value, std::numeric_limits<To>::max()));
220 template <typename To, typename From, std::enable_if_t<std::is_base_of<StrongTypedefBase, From>::value,
int> = 0>
221 constexpr To
ClampTo(From value)
223 return ClampTo<To>(value.base());
233 template <
typename T>
234 constexpr T
Delta(
const T a,
const T b)
236 return (a < b) ? b - a : a - b;
251 template <
typename T>
252 constexpr
bool IsInsideBS(
const T x,
const size_t base,
const size_t size)
254 return static_cast<size_t>(x - base) < size;
267 template <
typename T, std::enable_if_t<std::disjunction_v<std::is_convertible<T,
size_t>, std::is_base_of<StrongTypedefBase, T>>,
int> = 0>
268 constexpr
bool IsInsideMM(
const T x,
const size_t min,
const size_t max) noexcept
270 if constexpr (std::is_base_of_v<StrongTypedefBase, T>) {
271 return static_cast<size_t>(x.base() - min) < (max - min);
273 return static_cast<size_t>(x - min) < (max - min);
282 template <
typename T>
283 constexpr
void Swap(T &a, T &b)
309 return i * 101 >> 16;
322 return (a + b - 1) / b;
331 constexpr uint
Ceil(uint a, uint b)
346 return (a +
static_cast<int>(b) / 2) /
static_cast<int>(b);
349 return (a - (
static_cast<int>(b) - 1) / 2) /
static_cast<int>(b);
360 assert(power >= 0 && power <= 20 );
362 for (
int i = 0; i < power; i++) result *= 10;
366 uint32_t
IntSqrt(uint32_t num);
constexpr bool IsInsideBS(const T x, const size_t base, const size_t size)
Checks if a value is between a window started at some base point.
int DivideApprox(int a, int b)
Deterministic approximate division.
constexpr uint ToPercent16(uint i)
Converts a "fract" value 0..65535 to "percent" value 0..100.
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
constexpr uint64_t PowerOfTen(int power)
Computes ten to the given power.
constexpr T Align(const T x, uint n)
Return the smallest multiple of n equal or greater than x.
uint32_t IntSqrt(uint32_t num)
Compute the integer square root.
constexpr int RoundDivSU(int a, uint b)
Computes round(a / b) for signed a and unsigned b.
constexpr T SoftClamp(const T a, const T min, const T max)
Clamp a value between an interval.
constexpr uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
constexpr T Delta(const T a, const T b)
Returns the (absolute) difference between two (scalar) variables.
constexpr uint ToPercent8(uint i)
Converts a "fract" value 0..255 to "percent" value 0..100.
constexpr uint Ceil(uint a, uint b)
Computes ceil(a / b) * b for non-negative a and b.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
constexpr uint ClampU(const uint a, const uint min, const uint max)
Clamp an unsigned integer between an interval.
constexpr T * AlignPtr(T *x, uint n)
Return the smallest multiple of n equal or greater than x Applies to pointers only.
constexpr To ClampTo(From value)
Clamp the given value down to lie within the requested type.
constexpr bool IsInsideMM(const T x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
constexpr void Swap(T &a, T &b)
Type safe swap operation.
Type (helpers) for making a strong typedef that is a distinct type.