25#ifndef JAU_INT_MATH_HPP_
26#define JAU_INT_MATH_HPP_
37 #define JAU_USE_BUILDIN_OVERFLOW 1
57 typename std::enable_if<std::is_integral_v<T>,
bool>::type
70 typename std::enable_if<std::is_integral_v<T>,
bool>::type
71 constexpr equals(
const T& a,
const T& b)
noexcept {
84 typename std::enable_if<std::is_integral_v<T>,
bool>::type
85 constexpr equals(
const T& a,
const T& b,
const T& allowed_deviation)
noexcept {
86 return std::abs(a - b) <= allowed_deviation;
98 template <
typename T,
typename U,
99 std::enable_if_t< std::is_integral_v<T> && std::is_unsigned_v<T> &&
100 std::is_integral_v<U> && std::is_unsigned_v<U>,
bool> =
true>
101 constexpr T
round_up(
const T n,
const U align_to) {
102 assert(align_to != 0);
105 return n + ( align_to - ( n % align_to ) );
120 template <
typename T,
typename U,
121 std::enable_if_t< std::is_integral_v<T> && std::is_unsigned_v<T> &&
122 std::is_integral_v<U> && std::is_unsigned_v<U>,
bool> =
true>
124 return align_to == 0 ? n : ( n - ( n % align_to ) );
138 template <
typename T,
139 std::enable_if_t< std::is_integral_v<T> && std::is_unsigned_v<T>,
bool> =
true>
142 return 0<x && 0 == ( x &
static_cast<T
>( x - 1 ) );
162 template <
typename T,
163 std::enable_if_t< std::is_integral_v<T> && std::is_unsigned_v<T>,
bool> =
true>
167 for(
nsize_t s = ( CHAR_BIT *
sizeof(T) ) >> 1; s > 0; s >>= 1) {
189 template <
typename T,
190 std::enable_if_t< std::is_integral_v<T>,
bool> =
true>
193#if JAU_USE_BUILDIN_OVERFLOW && ( defined(__GNUC__) || defined(__clang__) )
194 return __builtin_add_overflow(a, b, &res);
223 template <
typename T,
224 std::enable_if_t< std::is_integral_v<T>,
bool> =
true>
227#if JAU_USE_BUILDIN_OVERFLOW && ( defined(__GNUC__) || defined(__clang__) )
228 return __builtin_sub_overflow(a, b, &res);
257 template <
typename T,
258 std::enable_if_t< std::is_integral_v<T>,
bool> =
true>
261#if JAU_USE_BUILDIN_OVERFLOW && ( defined(__GNUC__) || defined(__clang__) )
262 return __builtin_mul_overflow(a, b, &res);
295 template <
typename T,
296 std::enable_if_t< std::is_integral_v<T> &&
297 !std::is_unsigned_v<T>,
bool> =
true>
298 constexpr T
gcd(T a, T b)
noexcept
310 template <
typename T,
311 std::enable_if_t< std::is_integral_v<T> &&
312 std::is_unsigned_v<T>,
bool> =
true>
313 constexpr T
gcd(T a, T b)
noexcept
332 template <
typename T,
333 std::enable_if_t< std::is_integral_v<T>,
bool> =
true>
336 const T _gcd = gcd<T>( a, b );
369 template <
typename T,
370 std::enable_if_t< std::is_integral_v<T>,
bool> =
true>
377 return 1 +
static_cast<nsize_t>( std::log10<T>( invert_sign<T>( x ) ) ) + ( sign_is_digit ? 1 : 0 );
379 return 1 +
static_cast<nsize_t>( std::log10<T>( x ) );
397 template <
typename T,
398 std::enable_if_t< std::is_integral_v<T>,
bool> =
true>
401 return digits10<T>(x, jau::sign<T>(x), sign_is_digit);
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).
std::enable_if< std::is_floating_point_v< T >, bool >::type 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.
std::enable_if< std::is_floating_point_v< T >, bool >::type 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.
constexpr T round_up(const T n, const U align_to)
Round up w/ branching in O(1)
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).
constexpr T min(const T x, const T y) noexcept
Returns the minimum of two integrals (w/ branching) in O(1)
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 T max(const T x, const T y) noexcept
Returns the maximum of two integrals (w/ branching) in O(1)
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...
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.