22#ifndef Rcpp__sugar__tools_safe_math_h
23#define Rcpp__sugar__tools_safe_math_h
25#ifndef safe_math__has_builtin
27# define safe_math__has_builtin(x) __has_builtin(x)
29# define safe_math__has_builtin(x) 0
33#define RCPP_SAFE_ADD(a, b) Rcpp::sugar::detail::safe_add(a, b, __func__)
34#define RCPP_SAFE_SUB(a, b) Rcpp::sugar::detail::safe_sub(a, b, __func__)
35#define RCPP_SAFE_MUL(a, b) Rcpp::sugar::detail::safe_mul(a, b, __func__)
49 inline typename std::enable_if<std::is_integral<T>::value, T>
::type
50 safe_add(T a, T b,
const char* caller =
nullptr) {
51 #if safe_math__has_builtin(__builtin_add_overflow)
53 if (__builtin_add_overflow(a, b, &
result))
57 if (std::is_signed<T>::value) {
58 if ((b > 0 && a > std::numeric_limits<T>::max() - b) ||
59 (b < 0 && a < std::numeric_limits<T>::min() - b))
62 if (a > std::numeric_limits<T>::max() - b)
70 inline typename std::enable_if<!std::is_integral<T>::value, T>
::type
71 safe_add(T a, T b,
const char* caller =
nullptr) {
return a + b; }
75 inline typename std::enable_if<std::is_integral<T>::value, T>
::type
76 safe_sub(T a, T b,
const char* caller =
nullptr) {
77 #if safe_math__has_builtin(__builtin_sub_overflow)
79 if (__builtin_sub_overflow(a, b, &
result))
83 if (std::is_signed<T>::value) {
84 if ((b < 0 && a > std::numeric_limits<T>::max() + b) ||
85 (b > 0 && a < std::numeric_limits<T>::min() + b))
96 inline typename std::enable_if<!std::is_integral<T>::value, T>
::type
97 safe_sub(T a, T b,
const char* caller =
nullptr) {
return a - b; }
100 template <
typename T>
101 inline typename std::enable_if<std::is_integral<T>::value, T>
::type
103 #if safe_math__has_builtin(__builtin_mul_overflow)
105 if (__builtin_mul_overflow(a, b, &
result))
109 if (a == 0 || b == 0)
return 0;
110 if (std::is_signed<T>::value) {
111 if ((a > 0 && b > 0 && a > std::numeric_limits<T>::max() / b) ||
112 (a > 0 && b < 0 && b < std::numeric_limits<T>::min() / a) ||
113 (a < 0 && b > 0 && a < std::numeric_limits<T>::min() / b) ||
114 (a < 0 && b < 0 && a < std::numeric_limits<T>::max() / b))
117 if (b > 0 && a > std::numeric_limits<T>::max() / b)
124 template <
typename T>
125 inline typename std::enable_if<!std::is_integral<T>::value, T>
::type
126 safe_mul(T a, T b,
const char* caller =
nullptr) {
return a * b; }
132#undef safe_math__has_builtin
std::enable_if< std::is_integral< T >::value, T >::type safe_mul(T a, T b, const char *caller=nullptr)
std::enable_if< std::is_integral< T >::value, T >::type safe_sub(T a, T b, const char *caller=nullptr)
std::enable_if< std::is_integral< T >::value, T >::type safe_add(T a, T b, const char *caller=nullptr)
void stop_overflow(const char *caller)
void NORET stop(const std::string &message)