BAN: Implement will_{addition,multiplication}_overflow
This commit is contained in:
parent
ea7fc7f6c4
commit
05e9d76c77
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/Limits.h>
|
||||||
#include <BAN/Traits.h>
|
#include <BAN/Traits.h>
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
@ -65,6 +66,27 @@ namespace BAN::Math
|
||||||
return (value & (value - 1)) == 0;
|
return (value & (value - 1)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<BAN::integral T>
|
||||||
|
static constexpr bool will_multiplication_overflow(T a, T b)
|
||||||
|
{
|
||||||
|
if (a == 0 || b == 0)
|
||||||
|
return false;
|
||||||
|
if ((a > 0) == (b > 0))
|
||||||
|
return a > BAN::numeric_limits<T>::max() / b;
|
||||||
|
else
|
||||||
|
return a < BAN::numeric_limits<T>::min() / b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<BAN::integral T>
|
||||||
|
static constexpr bool will_addition_overflow(T a, T b)
|
||||||
|
{
|
||||||
|
if (a > 0 && b > 0)
|
||||||
|
return a > BAN::numeric_limits<T>::max() - b;
|
||||||
|
if (a < 0 && b < 0)
|
||||||
|
return a < BAN::numeric_limits<T>::min() - b;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
requires is_same_v<T, unsigned int> || is_same_v<T, unsigned long> || is_same_v<T, unsigned long long>
|
requires is_same_v<T, unsigned int> || is_same_v<T, unsigned long> || is_same_v<T, unsigned long long>
|
||||||
inline constexpr T ilog2(T value)
|
inline constexpr T ilog2(T value)
|
||||||
|
|
|
@ -64,35 +64,14 @@ static constexpr int get_base_digit(char c, int base)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<BAN::integral T>
|
|
||||||
static constexpr bool will_multiplication_overflow(T a, T b)
|
|
||||||
{
|
|
||||||
if (a == 0 || b == 0)
|
|
||||||
return false;
|
|
||||||
if ((a > 0) == (b > 0))
|
|
||||||
return a > BAN::numeric_limits<T>::max() / b;
|
|
||||||
else
|
|
||||||
return a < BAN::numeric_limits<T>::min() / b;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<BAN::integral T>
|
|
||||||
static constexpr bool will_addition_overflow(T a, T b)
|
|
||||||
{
|
|
||||||
if (a > 0 && b > 0)
|
|
||||||
return a > BAN::numeric_limits<T>::max() - b;
|
|
||||||
if (a < 0 && b < 0)
|
|
||||||
return a < BAN::numeric_limits<T>::min() - b;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<BAN::integral T>
|
template<BAN::integral T>
|
||||||
static constexpr bool will_digit_append_overflow(bool negative, T current, int digit, int base)
|
static constexpr bool will_digit_append_overflow(bool negative, T current, int digit, int base)
|
||||||
{
|
{
|
||||||
if (BAN::is_unsigned_v<T> && negative && digit)
|
if (BAN::is_unsigned_v<T> && negative && digit)
|
||||||
return true;
|
return true;
|
||||||
if (will_multiplication_overflow<T>(current, base))
|
if (BAN::Math::will_multiplication_overflow<T>(current, base))
|
||||||
return true;
|
return true;
|
||||||
if (will_addition_overflow<T>(current * base, current < 0 ? -digit : digit))
|
if (BAN::Math::will_addition_overflow<T>(current * base, current < 0 ? -digit : digit))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -286,7 +265,7 @@ static T strtoT(const char* str, char** endp, int& error)
|
||||||
int extra_exponent = strtoT<int>(str + 1, &maybe_end, 10, exp_error);
|
int extra_exponent = strtoT<int>(str + 1, &maybe_end, 10, exp_error);
|
||||||
if (exp_error != EINVAL)
|
if (exp_error != EINVAL)
|
||||||
{
|
{
|
||||||
if (exp_error == ERANGE || will_addition_overflow(exponent, extra_exponent))
|
if (exp_error == ERANGE || BAN::Math::will_addition_overflow(exponent, extra_exponent))
|
||||||
exponent = negative ? BAN::numeric_limits<int>::min() : BAN::numeric_limits<int>::max();
|
exponent = negative ? BAN::numeric_limits<int>::min() : BAN::numeric_limits<int>::max();
|
||||||
else
|
else
|
||||||
exponent += extra_exponent;
|
exponent += extra_exponent;
|
||||||
|
|
Loading…
Reference in New Issue