23# define __has_builtin(x) 0
33 if (
a <= std::numeric_limits<T>::max() - b) {
36 return std::numeric_limits<T>::max();
39 if (
a >= std::numeric_limits<T>::min() - b) {
42 return std::numeric_limits<T>::min();
50 if (
a >= std::numeric_limits<T>::min() + b) {
53 return std::numeric_limits<T>::min();
56 if (
a <= std::numeric_limits<T>::max() + b) {
59 return std::numeric_limits<T>::max();
64template<
typename T>
inline
68 if (
a == std::numeric_limits<T>::min())
69 return std::numeric_limits<T>::max();
77 return !msl::utilities::SafeMultiply(a, b, result);
80template<
typename T>
inline bool checked_add(T a, T b, T& result)
82 return !msl::utilities::SafeAdd(a, b, result);
85template<
typename T>
inline bool checked_sub(T a, T b, T& result)
87 return !msl::utilities::SafeSubtract(a, b, result);
90#elif (defined __GNUC__ && !defined __clang__) || (__has_builtin(__builtin_mul_overflow) && !(defined ANDROID && defined __clang__) && !(defined(__clang__) && (defined(__arm__) || defined(__i386__))))
95 return __builtin_mul_overflow(a, b, &result);
98template<
typename T>
inline bool checked_add(T a, T b, T& result)
100 return __builtin_add_overflow(a, b, &result);
103template<
typename T>
inline bool checked_sub(T a, T b, T& result)
105 return __builtin_sub_overflow(a, b, &result);
111template<
typename T>
inline typename std::enable_if<std::is_signed<T>::value,
bool>::type
checked_multiply(T a, T b, T& result)
115 if (
a > (std::numeric_limits<T>::max() / b)) {
119 if (b < (std::numeric_limits<T>::min() /
a)) {
125 if (
a < (std::numeric_limits<T>::min() / b)) {
129 if ( (
a != 0) && (b < (std::numeric_limits<T>::max() /
a))) {
141template<
typename T>
inline typename std::enable_if<std::is_unsigned<T>::value,
bool>::type
checked_multiply(T a, T b, T& result)
143 if (b &&
a > std::numeric_limits<T>::max() / b) {
153template<
typename T>
inline typename std::enable_if<std::is_signed<T>::value,
bool>::type
checked_add(T a, T b, T& result)
155 if (((b > 0) && (
a > (std::numeric_limits<T>::max() - b))) ||
156 ((b < 0) && (
a < (std::numeric_limits<T>::min() - b)))) {
166template<
typename T>
inline typename std::enable_if<std::is_unsigned<T>::value,
bool>::type
checked_add(T a, T b, T& result)
168 if (std::numeric_limits<T>::max() -
a < b) {
178template<
typename T>
inline typename std::enable_if<std::is_signed<T>::value,
bool>::type
checked_sub(T a, T b, T& result)
180 if ((b > 0 &&
a < std::numeric_limits<T>::min() + b) ||
181 (b < 0 && a > std::numeric_limits<T>::max() + b)) {
191template<
typename T>
inline typename std::enable_if<std::is_unsigned<T>::value,
bool>::type
checked_sub(T a, T b, T& result)
204template<
typename T>
constexpr std::enable_if_t<std::is_signed_v<T>, std::make_unsigned_t<T>>
211template<
typename T1,
typename T2>
constexpr std::enable_if_t<std::is_unsigned_v<T1>, T1>
213 if constexpr (std::is_unsigned_v<T2>) {
215 return value <= std::numeric_limits<T1>::max() ?
value : std::numeric_limits<T1>::max();
217 static_assert(std::is_signed_v<T2>);
225template<
typename T1,
typename T2>
constexpr T1
narrowing(T2 value) {
return value; }
231 return std::min(
a, b);
std::enable_if< std::is_signed< T >::value, bool >::type checked_add(T a, T b, T &result)
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
constexpr T1 narrowing(T2 value)
std::enable_if< std::is_signed< T >::value, T >::type saturating_toggle_sign(T a)
T sanitizing_min(T a, T b)
std::enable_if< std::is_signed< T >::value, bool >::type checked_multiply(T a, T b, T &result)
constexpr T saturating_add(T a, T b)
constexpr std::enable_if_t< std::is_unsigned_v< T1 >, T1 > clamp_to_unsigned(T2 value)
constexpr T saturating_sub(T a, T b)
std::enable_if< std::is_signed< T >::value, bool >::type checked_sub(T a, T b, T &result)