10 #ifndef INCLUDED_O3TL_SAFEINT_HXX
11 #define INCLUDED_O3TL_SAFEINT_HXX
17 #include <type_traits>
23 # define __has_builtin(x) 0
30 template<
typename T>
inline
35 if (a <= std::numeric_limits<T>::max() - b) {
38 return std::numeric_limits<T>::max();
41 if (a >= std::numeric_limits<T>::min() - b) {
44 return std::numeric_limits<T>::min();
49 template<
typename T>
inline
53 if (a <= std::numeric_limits<T>::max() - b) {
56 return std::numeric_limits<T>::max();
60 template<
typename T>
inline
65 if (a >= std::numeric_limits<T>::min() + b) {
68 return std::numeric_limits<T>::min();
71 if (a <= std::numeric_limits<T>::max() + b) {
74 return std::numeric_limits<T>::max();
79 template<
typename T>
inline
83 if (a >= std::numeric_limits<T>::min() + b) {
86 return std::numeric_limits<T>::min();
90 template<
typename T>
inline
94 if (a == std::numeric_limits<T>::min())
95 return std::numeric_limits<T>::max();
103 return !msl::utilities::SafeMultiply(a, b, result);
106 template<
typename T>
inline bool checked_add(T a, T b, T& result)
108 return !msl::utilities::SafeAdd(a, b, result);
111 template<
typename T>
inline bool checked_sub(T a, T b, T& result)
113 return !msl::utilities::SafeSubtract(a, b, result);
116 #elif (defined __GNUC__ && !defined __clang__) || (__has_builtin(__builtin_mul_overflow) && !(defined ANDROID && defined __clang__) && !(defined(__clang__) && (defined(__arm__) || defined(__i386__))))
121 return __builtin_mul_overflow(a, b, &result);
124 template<
typename T>
inline bool checked_add(T a, T b, T& result)
126 return __builtin_add_overflow(a, b, &result);
129 template<
typename T>
inline bool checked_sub(T a, T b, T& result)
131 return __builtin_sub_overflow(a, b, &result);
137 template<
typename T>
inline typename std::enable_if<std::is_signed<T>::value,
bool>::type
checked_multiply(T a, T b, T& result)
141 if (a > (std::numeric_limits<T>::max() / b)) {
145 if (b < (std::numeric_limits<T>::min() / a)) {
151 if (a < (std::numeric_limits<T>::min() / b)) {
155 if ( (a != 0) && (b < (std::numeric_limits<T>::max() / a))) {
167 template<
typename T>
inline typename std::enable_if<std::is_unsigned<T>::value,
bool>::type
checked_multiply(T a, T b, T& result)
169 if (b && a > std::numeric_limits<T>::max() / b) {
179 template<
typename T>
inline typename std::enable_if<std::is_signed<T>::value,
bool>::type
checked_add(T a, T b, T& result)
181 if (((b > 0) && (a > (std::numeric_limits<T>::max() - b))) ||
182 ((b < 0) && (a < (std::numeric_limits<T>::min() - b)))) {
192 template<
typename T>
inline typename std::enable_if<std::is_unsigned<T>::value,
bool>::type
checked_add(T a, T b, T& result)
194 if (std::numeric_limits<T>::max() - a < b) {
204 template<
typename T>
inline typename std::enable_if<std::is_signed<T>::value,
bool>::type
checked_sub(T a, T b, T& result)
206 if ((b > 0 && a < std::numeric_limits<T>::min() + b) ||
207 (b < 0 && a > std::numeric_limits<T>::max() + b)) {
217 template<
typename T>
inline typename std::enable_if<std::is_unsigned<T>::value,
bool>::type
checked_sub(T a, T b, T& result)
230 template<
typename T> constexpr std::enable_if_t<std::is_signed_v<T>, std::make_unsigned_t<T>>
240 template<
typename T1,
typename T2> constexpr T1
narrowing(T2 value) {
return value; }
std::enable_if< std::is_signed< T >::value, bool >::type checked_sub(T a, T b, T &result)
std::enable_if< std::is_signed< T >::value, T >::type saturating_sub(T a, T b)
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
std::enable_if< std::is_signed< T >::value, T >::type saturating_toggle_sign(T a)
constexpr T1 narrowing(T2 value)
std::enable_if< std::is_signed< T >::value, T >::type saturating_add(T a, T 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)
std::enable_if< std::is_signed< T >::value, bool >::type checked_multiply(T a, T b, T &result)