diff options
Diffstat (limited to 'src/common/overflow.h')
| -rw-r--r-- | src/common/overflow.h | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/src/common/overflow.h b/src/common/overflow.h index 44d8e7e73..e184ead95 100644 --- a/src/common/overflow.h +++ b/src/common/overflow.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <algorithm> | ||
| 6 | #include <type_traits> | 7 | #include <type_traits> |
| 7 | #include "bit_cast.h" | 8 | #include "bit_cast.h" |
| 8 | 9 | ||
| @@ -19,4 +20,21 @@ inline T WrappingAdd(T lhs, T rhs) { | |||
| 19 | return BitCast<T>(lhs_u + rhs_u); | 20 | return BitCast<T>(lhs_u + rhs_u); |
| 20 | } | 21 | } |
| 21 | 22 | ||
| 23 | template <typename T> | ||
| 24 | requires(std::is_integral_v<T> && std::is_signed_v<T>) | ||
| 25 | inline bool CanAddWithoutOverflow(T lhs, T rhs) { | ||
| 26 | #ifdef _MSC_VER | ||
| 27 | if (lhs >= 0 && rhs >= 0) { | ||
| 28 | return WrappingAdd(lhs, rhs) >= std::max(lhs, rhs); | ||
| 29 | } else if (lhs < 0 && rhs < 0) { | ||
| 30 | return WrappingAdd(lhs, rhs) <= std::min(lhs, rhs); | ||
| 31 | } else { | ||
| 32 | return true; | ||
| 33 | } | ||
| 34 | #else | ||
| 35 | T res; | ||
| 36 | return !__builtin_add_overflow(lhs, rhs, &res); | ||
| 37 | #endif | ||
| 38 | } | ||
| 39 | |||
| 22 | } // namespace Common | 40 | } // namespace Common |