13#ifndef WPIUTIL_WPI_MATHEXTRAS_H
14#define WPIUTIL_WPI_MATHEXTRAS_H
31 static_assert(std::is_unsigned_v<T>,
"Invalid type!");
32 const unsigned Bits = CHAR_BIT *
sizeof(T);
33 assert(N <= Bits &&
"Invalid bit index");
34 return N == 0 ? 0 : (T(-1) >> (Bits - N));
40 return ~maskTrailingOnes<T>(CHAR_BIT *
sizeof(T) - N);
46 return maskLeadingOnes<T>(CHAR_BIT *
sizeof(T) - N);
52 return maskTrailingOnes<T>(CHAR_BIT *
sizeof(T) - N);
59#define R2(n) n, n + 2 * 64, n + 1 * 64, n + 3 * 64
60#define R4(n) R2(n), R2(n + 2 * 16), R2(n + 1 * 16), R2(n + 3 * 16)
61#define R6(n) R4(n), R4(n + 2 * 4), R4(n + 1 * 4), R4(n + 3 * 4)
70#if __has_builtin(__builtin_bitreverse8)
71 if constexpr (std::is_same_v<T, uint8_t>)
72 return __builtin_bitreverse8(Val);
74#if __has_builtin(__builtin_bitreverse16)
75 if constexpr (std::is_same_v<T, uint16_t>)
76 return __builtin_bitreverse16(Val);
78#if __has_builtin(__builtin_bitreverse32)
79 if constexpr (std::is_same_v<T, uint32_t>)
80 return __builtin_bitreverse32(Val);
82#if __has_builtin(__builtin_bitreverse64)
83 if constexpr (std::is_same_v<T, uint64_t>)
84 return __builtin_bitreverse64(Val);
87 unsigned char in[
sizeof(Val)];
88 unsigned char out[
sizeof(Val)];
89 std::memcpy(
in, &Val,
sizeof(Val));
90 for (
unsigned i = 0; i <
sizeof(Val); ++i)
92 std::memcpy(&Val, out,
sizeof(Val));
101constexpr inline uint32_t
Hi_32(uint64_t Value) {
102 return static_cast<uint32_t
>(Value >> 32);
106constexpr inline uint32_t
Lo_32(uint64_t Value) {
107 return static_cast<uint32_t
>(Value);
111constexpr inline uint64_t
Make_64(uint32_t High, uint32_t Low) {
112 return ((uint64_t)High << 32) | (uint64_t)Low;
116template <
unsigned N>
constexpr inline bool isInt(int64_t x) {
117 if constexpr (N == 8)
118 return static_cast<int8_t
>(x) == x;
119 if constexpr (N == 16)
120 return static_cast<int16_t
>(x) == x;
121 if constexpr (N == 32)
122 return static_cast<int32_t
>(x) == x;
123 if constexpr (N < 64)
124 return -(INT64_C(1) << (N - 1)) <= x && x < (INT64_C(1) << (N - 1));
130template <
unsigned N,
unsigned S>
133 N > 0,
"isShiftedInt<0> doesn't make sense (refers to a 0-bit number.");
134 static_assert(N +
S <= 64,
"isShiftedInt<N, S> with N + S > 64 is too wide.");
135 return isInt<N + S>(x) && (x % (UINT64_C(1) <<
S) == 0);
139template <
unsigned N>
constexpr inline bool isUInt(uint64_t x) {
140 static_assert(N > 0,
"isUInt<0> doesn't make sense");
141 if constexpr (N == 8)
142 return static_cast<uint8_t
>(x) == x;
143 if constexpr (N == 16)
144 return static_cast<uint16_t
>(x) == x;
145 if constexpr (N == 32)
146 return static_cast<uint32_t
>(x) == x;
147 if constexpr (N < 64)
148 return x < (UINT64_C(1) << (N));
154template <
unsigned N,
unsigned S>
157 N > 0,
"isShiftedUInt<0> doesn't make sense (refers to a 0-bit number)");
158 static_assert(N +
S <= 64,
159 "isShiftedUInt<N, S> with N + S > 64 is too wide.");
162 return isUInt<N + S>(x) && (x % (UINT64_C(1) <<
S) == 0);
167 assert(N > 0 && N <= 64 &&
"integer width out of range");
173 return UINT64_MAX >> (64 - N);
178#pragma warning(disable : 4146)
183 assert(N > 0 && N <= 64 &&
"integer width out of range");
185 return UINT64_C(1) + ~(UINT64_C(1) << (N - 1));
194 assert(N > 0 && N <= 64 &&
"integer width out of range");
198 return (UINT64_C(1) << (N - 1)) - 1;
207inline bool isIntN(
unsigned N, int64_t x) {
215 return Value && ((Value + 1) & Value) == 0;
221 return Value && ((Value + 1) & Value) == 0;
227 return Value &&
isMask_32((Value - 1) | Value);
233 return Value &&
isMask_64((Value - 1) | Value);
239 return std::has_single_bit(Value);
244 return std::has_single_bit(Value);
256 MaskIdx = std::countr_zero(Value);
257 MaskLen = std::popcount(Value);
269 MaskIdx = std::countr_zero(Value);
270 MaskLen = std::popcount(Value);
276template <
size_t kValue>
constexpr inline size_t CTLog2() {
278 "Value is not a valid power of 2");
279 return 1 +
CTLog2<kValue / 2>();
282template <>
constexpr inline size_t CTLog2<1>() {
return 0; }
312constexpr inline uint64_t
MinAlign(uint64_t A, uint64_t B) {
318 return (A | B) & (1 + ~(A | B));
351inline uint64_t
alignTo(uint64_t Value, uint64_t Align) {
352 assert(Align != 0u &&
"Align can't be 0.");
353 return (Value + Align - 1) / Align * Align;
357 assert(Align != 0 && (Align & (Align - 1)) == 0 &&
358 "Align must be a power of 2");
361 uint64_t negAlign = (~Align) + 1;
362 return (Value + Align - 1) & negAlign;
377inline uint64_t
alignTo(uint64_t Value, uint64_t Align, uint64_t Skew) {
378 assert(Align != 0u &&
"Align can't be 0.");
380 return alignTo(Value - Skew, Align) + Skew;
385template <u
int64_t Align>
constexpr inline uint64_t
alignTo(uint64_t Value) {
386 static_assert(Align != 0u,
"Align must be non-zero");
387 return (Value + Align - 1) / Align * Align;
391inline uint64_t
divideCeil(uint64_t Numerator, uint64_t Denominator) {
392 return alignTo(Numerator, Denominator) / Denominator;
397 return (Numerator + (Denominator / 2)) / Denominator;
402inline uint64_t
alignDown(uint64_t Value, uint64_t Align, uint64_t Skew = 0) {
403 assert(Align != 0u &&
"Align can't be 0.");
405 return (Value - Skew) / Align * Align + Skew;
410template <
unsigned B>
constexpr inline int32_t
SignExtend32(uint32_t X) {
411 static_assert(B > 0,
"Bit width can't be 0.");
412 static_assert(B <= 32,
"Bit width out of range.");
413 return int32_t(X << (32 - B)) >> (32 - B);
419 assert(B > 0 &&
"Bit width can't be 0.");
420 assert(B <= 32 &&
"Bit width out of range.");
421 return int32_t(X << (32 - B)) >> (32 - B);
426template <
unsigned B>
constexpr inline int64_t
SignExtend64(uint64_t x) {
427 static_assert(B > 0,
"Bit width can't be 0.");
428 static_assert(B <= 64,
"Bit width out of range.");
429 return int64_t(x << (64 - B)) >> (64 - B);
435 assert(B > 0 &&
"Bit width can't be 0.");
436 assert(B <= 64 &&
"Bit width out of range.");
437 return int64_t(X << (64 - B)) >> (64 - B);
444 return X > Y ? (X - Y) : (Y - X);
451std::enable_if_t<std::is_unsigned_v<T>, T>
454 bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
457 Overflowed = (Z < X || Z < Y);
466template <
class T,
class... Ts>
469 bool Overflowed =
false;
480std::enable_if_t<std::is_unsigned_v<T>, T>
483 bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
498 if (Log2Z < Log2Max) {
501 if (Log2Z > Log2Max) {
510 if (Z & ~(Max >> 1)) {
526std::enable_if_t<std::is_unsigned_v<T>, T>
529 bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
545std::enable_if_t<std::is_signed_v<T>, T>
AddOverflow(T X, T Y, T &Result) {
546#if __has_builtin(__builtin_add_overflow)
547 return __builtin_add_overflow(X, Y, &Result);
550 using U = std::make_unsigned_t<T>;
551 const U UX =
static_cast<U
>(X);
552 const U UY =
static_cast<U
>(Y);
553 const U UResult = UX + UY;
556 Result =
static_cast<T
>(UResult);
571std::enable_if_t<std::is_signed_v<T>, T>
SubOverflow(T X, T Y, T &Result) {
572#if __has_builtin(__builtin_sub_overflow)
573 return __builtin_sub_overflow(X, Y, &Result);
576 using U = std::make_unsigned_t<T>;
577 const U UX =
static_cast<U
>(X);
578 const U UY =
static_cast<U
>(Y);
579 const U UResult = UX - UY;
582 Result =
static_cast<T
>(UResult);
597std::enable_if_t<std::is_signed_v<T>, T>
MulOverflow(T X, T Y, T &Result) {
599 using U = std::make_unsigned_t<T>;
600 const U UX = X < 0 ? (0 -
static_cast<U
>(X)) :
static_cast<U
>(X);
601 const U UY = Y < 0 ? (0 -
static_cast<U
>(Y)) :
static_cast<U
>(Y);
602 const U UResult = UX * UY;
605 const bool IsNegative = (X < 0) ^ (Y < 0);
606 Result = IsNegative ? (0 - UResult) : UResult;
609 if (UX == 0 || UY == 0)
625 return (T(0) < val) - (val < T(0));
638constexpr T
Lerp(
const T& startValue,
const T& endValue,
double t) {
639 return startValue + (endValue - startValue) * t;
This file implements the C++20 <bit> header.
constexpr auto in(type t, int set) -> bool
Definition: core.h:611
FMT_CONSTEXPR20 auto countl_zero(uint32_t n) -> int
Definition: format.h:526
UnitTypeLhs() max(const UnitTypeLhs &lhs, const UnitTypeRhs &rhs)
Definition: base.h:3417
Definition: ntcore_cpp.h:26
int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
Definition: MathExtras.h:193
std::enable_if_t< std::is_signed_v< T >, T > SubOverflow(T X, T Y, T &Result)
Subtract two signed integers, computing the two's complement truncated result, returning true if an o...
Definition: MathExtras.h:571
T maskLeadingOnes(unsigned N)
Create a bitmask with the N left-most bits set to 1, and all other bits set to 0.
Definition: MathExtras.h:39
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition: MathExtras.h:139
constexpr int sgn(T val)
Definition: MathExtras.h:624
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition: MathExtras.h:287
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
Definition: MathExtras.h:300
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
Definition: MathExtras.h:335
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition: MathExtras.h:106
T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition: MathExtras.h:30
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
Definition: MathExtras.h:131
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
Definition: MathExtras.h:226
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition: MathExtras.h:426
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition: MathExtras.h:238
T reverseBits(T Val)
Reverse the bits in Val.
Definition: MathExtras.h:69
std::enable_if_t< std::is_signed_v< T >, T > MulOverflow(T X, T Y, T &Result)
Multiply two signed integers, computing the two's complement truncated result, returning true if an o...
Definition: MathExtras.h:597
constexpr size_t CTLog2()
Compile time Log2.
Definition: MathExtras.h:276
std::enable_if_t< std::is_unsigned_v< T >, T > SaturatingMultiply(T X, T Y, bool *ResultOverflowed=nullptr)
Multiply two unsigned integers, X and Y, of type T.
Definition: MathExtras.h:481
std::enable_if_t< std::is_unsigned_v< T >, T > SaturatingAdd(T X, T Y, bool *ResultOverflowed=nullptr)
Add two unsigned integers, X and Y, of type T.
Definition: MathExtras.h:452
constexpr size_t CTLog2< 1 >()
Definition: MathExtras.h:282
uint64_t divideNearest(uint64_t Numerator, uint64_t Denominator)
Returns the integer nearest(Numerator / Denominator).
Definition: MathExtras.h:396
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition: MathExtras.h:116
uint64_t alignTo(uint64_t Value, uint64_t Align)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
Definition: MathExtras.h:351
uint64_t divideCeil(uint64_t Numerator, uint64_t Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition: MathExtras.h:391
std::enable_if_t< std::is_unsigned_v< T >, T > SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed=nullptr)
Multiply two unsigned integers, X and Y, and add the unsigned integer, A to the product.
Definition: MathExtras.h:527
constexpr T Lerp(const T &startValue, const T &endValue, double t)
Linearly interpolates between two values.
Definition: MathExtras.h:638
constexpr uint64_t MinAlign(uint64_t A, uint64_t B)
A and B are either alignments or offsets.
Definition: MathExtras.h:312
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition: MathExtras.h:293
uint64_t alignToPowerOf2(uint64_t Value, uint64_t Align)
Definition: MathExtras.h:356
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition: MathExtras.h:243
std::enable_if_t< std::is_signed_v< T >, T > AddOverflow(T X, T Y, T &Result)
Add two signed integers, computing the two's complement truncated result, returning true if overflow ...
Definition: MathExtras.h:545
std::enable_if_t< std::is_unsigned_v< T >, T > AbsoluteDifference(T X, T Y)
Subtract two unsigned integers, X and Y, of type T and return the absolute value of the result.
Definition: MathExtras.h:443
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
Definition: MathExtras.h:220
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
Definition: MathExtras.h:323
int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
Definition: MathExtras.h:182
constexpr uint64_t Make_64(uint32_t High, uint32_t Low)
Make a 64-bit integer from a high / low pair of 32-bit integers.
Definition: MathExtras.h:111
T maskTrailingZeros(unsigned N)
Create a bitmask with the N right-most bits set to 0, and all other bits set to 1.
Definition: MathExtras.h:45
uint64_t maxUIntN(uint64_t N)
Gets the maximum value for a N-bit unsigned integer.
Definition: MathExtras.h:166
bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:202
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
Definition: MathExtras.h:155
bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:207
unsigned Log2_64_Ceil(uint64_t Value)
Return the ceil log base 2 of the specified value, 64 if the value is zero.
Definition: MathExtras.h:306
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
Definition: MathExtras.h:232
constexpr int32_t SignExtend32(uint32_t X)
Sign-extend the number in the bottom B bits of X to a 32-bit integer.
Definition: MathExtras.h:410
T maskLeadingZeros(unsigned N)
Create a bitmask with the N left-most bits set to 0, and all other bits set to 1.
Definition: MathExtras.h:51
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition: MathExtras.h:101
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
Definition: MathExtras.h:214
uint64_t alignDown(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the largest uint64_t less than or equal to Value and is Skew mod Align.
Definition: MathExtras.h:402
static const unsigned char BitReverseTable256[256]
Macro compressed bit reversal table for 256 bits.
Definition: MathExtras.h:58
const float huge_valf
Use this rather than HUGE_VALF; the latter causes warnings on MSVC.
Definition: MathExtras.h:539
#define S(label, offset, message)
Definition: Errors.h:119