25#ifndef JAU_INT_MATH_HPP_
26#define JAU_INT_MATH_HPP_
55 typename std::enable_if_t<std::is_integral_v<T>,
bool>
68 typename std::enable_if_t<std::is_integral_v<T>,
bool>
69 constexpr equals(
const T& a,
const T& b)
noexcept {
82 typename std::enable_if_t<std::is_integral_v<T>,
bool>
83 constexpr equals(
const T& a,
const T& b,
const T& allowed_deviation)
noexcept {
84 return std::abs(a - b) <= allowed_deviation;
96 template <
typename T,
typename U,
97 std::enable_if_t< std::is_integral_v<T> && std::is_unsigned_v<T> &&
98 std::is_integral_v<U> && std::is_unsigned_v<U>,
bool> =
true>
99 constexpr T
round_up(
const T n,
const U align_to) {
100 assert(align_to != 0);
103 return n + ( align_to - ( n % align_to ) );
118 template <
typename T,
typename U,
119 std::enable_if_t< std::is_integral_v<T> && std::is_unsigned_v<T> &&
120 std::is_integral_v<U> && std::is_unsigned_v<U>,
bool> =
true>
122 return align_to == 0 ? n : ( n - ( n % align_to ) );
136 template <
typename T,
137 std::enable_if_t< std::is_integral_v<T> && std::is_unsigned_v<T>,
bool> =
true>
140 return 0<x && 0 == ( x &
static_cast<T
>( x - 1 ) );
160 template <
typename T,
161 std::enable_if_t< std::is_integral_v<T> && std::is_unsigned_v<T>,
bool> =
true>
165 for(
nsize_t s = ( CHAR_BIT *
sizeof(T) ) >> 1; s > 0; s >>= 1) {
178 #if defined __has_builtin && __has_builtin(__builtin_add_overflow)
189 #if defined __has_builtin && __has_builtin(__builtin_sub_overflow)
200 #if defined __has_builtin && __has_builtin(__builtin_mul_overflow)
221 template <
typename T,
222 std::enable_if_t< std::is_integral_v<T>,
bool> =
true>
226 return __builtin_add_overflow(a, b, &res);
230 if ( ( b >= 0 && a > std::numeric_limits<T>::max() - b ) ||
231 ( b < 0 && a < std::numeric_limits<T>::min() - b ) )
255 template <
typename T,
256 std::enable_if_t< std::is_integral_v<T>,
bool> =
true>
260 return __builtin_sub_overflow(a, b, &res);
264 if ( ( b < 0 && a > std::numeric_limits<T>::max() + b ) ||
265 ( b >= 0 && a < std::numeric_limits<T>::min() + b ) )
289 template <
typename T,
290 std::enable_if_t< std::is_integral_v<T>,
bool> =
true>
294 return __builtin_mul_overflow(a, b, &res);
297 if ( ( b > 0 &&
abs(a) > std::numeric_limits<T>::max() / b ) ||
298 ( b < 0 &&
abs(a) > std::numeric_limits<T>::min() / b ) )
327 template <
typename T,
328 std::enable_if_t< std::is_integral_v<T> &&
329 !std::is_unsigned_v<T>,
bool> =
true>
330 constexpr T
gcd(T a, T b)
noexcept
342 template <
typename T,
343 std::enable_if_t< std::is_integral_v<T> &&
344 std::is_unsigned_v<T>,
bool> =
true>
345 constexpr T
gcd(T a, T b)
noexcept
364 template <
typename T,
365 std::enable_if_t< std::is_integral_v<T>,
bool> =
true>
368 const T _gcd =
gcd<T>( a, b );
401 template <
typename T,
402 std::enable_if_t< std::is_integral_v<T>,
bool> =
true>
411 return 1 +
static_cast<nsize_t>( std::log10<T>( x ) );
429 template <
typename T,
430 std::enable_if_t< std::is_integral_v<T>,
bool> =
true>
constexpr uint32_t ct_next_power_of_2(uint32_t n)
Returns the next higher power of 2 of given unsigned 32-bit n (w/o branching) in O(1) and constant ti...
constexpr T ct_is_zero(T x)
Returns ~0 (2-complement) if arg is zero, otherwise 0 (w/o branching) in O(1) and constant time (CT).
#define consteval_cxx20
consteval qualifier replacement for C++20 consteval.
std::enable_if_t< std::is_floating_point_v< T >, bool > constexpr equals(const T &a, const T &b, const T &epsilon=std::numeric_limits< T >::epsilon()) noexcept
Returns true if both values are equal, i.e.
std::enable_if_t< std::is_floating_point_v< T >, bool > constexpr is_zero(const T &a, const T &epsilon=std::numeric_limits< T >::epsilon()) noexcept
Returns true if the given value is less than epsilon, w/ epsilon > 0.
constexpr T invert_sign(const T x) noexcept
Safely inverts the sign of an arithmetic number w/ branching in O(1)
constexpr T round_up(const T n, const U align_to)
Round up w/ branching in O(1)
consteval_cxx20 bool has_builtin_mul_overflow() noexcept
Query whether __builtin_mul_overflow is available via __has_builtin(__builtin_mul_overflow).
constexpr nsize_t digits10(const T x, const snsize_t x_sign, const bool sign_is_digit=true) noexcept
Returns the number of decimal digits of the given integral value number using std::log10<T>().
constexpr nsize_t high_bit(T x)
Return the index of the highest set bit w/ branching (loop) in O(n), actually O(n/2).
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
constexpr bool mul_overflow(const T a, const T b, T &res) noexcept
Integer overflow aware multiplication returning true if overflow occurred, otherwise false having the...
constexpr bool sub_overflow(const T a, const T b, T &res) noexcept
Integer overflow aware subtraction returning true if overflow occurred, otherwise false having the re...
int_fast32_t snsize_t
Natural 'ssize_t' alternative using int_fast32_t as its natural sized type.
constexpr uint32_t round_to_power_of_2(const uint32_t n)
If the given n is not is_power_of_2() return next_power_of_2(), otherwise return n unchanged.
constexpr T gcd(T a, T b) noexcept
Returns the greatest common divisor (GCD) of the two given integer values following Euclid's algorith...
constexpr int sign(const T x) noexcept
Returns the value of the sign function (w/o branching ?) in O(1).
consteval_cxx20 bool has_builtin_add_overflow() noexcept
Query whether __builtin_add_overflow is available via __has_builtin(__builtin_add_overflow).
constexpr T round_down(T n, U align_to)
Round down w/ branching in O(1)
constexpr bool add_overflow(const T a, const T b, T &res) noexcept
Integer overflow aware addition returning true if overflow occurred, otherwise false having the resul...
consteval_cxx20 bool has_builtin_sub_overflow() noexcept
Query whether __builtin_sub_overflow is available via __has_builtin(__builtin_sub_overflow).
constexpr bool lcm_overflow(const T a, const T b, T &result) noexcept
Integer overflow aware calculation of least common multiple (LCM) following Euclid's algorithm from E...
constexpr T abs(const T x) noexcept
Returns the absolute value of an arithmetic number (w/ branching) in O(1)
constexpr bool is_power_of_2(const T x) noexcept
Power of 2 test (w/o branching ?) in O(1)
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.