Line data Source code
1 : // Copyright (c) 2021 The Bitcoin Core developers 2 : // Distributed under the MIT software license, see the accompanying 3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : 5 : #ifndef BITCOIN_UTIL_OVERFLOW_H 6 : #define BITCOIN_UTIL_OVERFLOW_H 7 : 8 : #include <limits> 9 : #include <optional> 10 : #include <type_traits> 11 : 12 : template <class T> 13 4311371 : [[nodiscard]] bool AdditionOverflow(const T i, const T j) noexcept 14 : { 15 : static_assert(std::is_integral<T>::value, "Integral required."); 16 : if constexpr (std::numeric_limits<T>::is_signed) { 17 2862 : return (i > 0 && j > std::numeric_limits<T>::max() - i) || 18 1429 : (i < 0 && j < std::numeric_limits<T>::min() - i); 19 : } 20 4309938 : return std::numeric_limits<T>::max() - i < j; 21 : } 22 : 23 : template <class T> 24 4311371 : [[nodiscard]] std::optional<T> CheckedAdd(const T i, const T j) noexcept 25 : { 26 4311371 : if (AdditionOverflow(i, j)) { 27 12 : return std::nullopt; 28 : } 29 4311359 : return i + j; 30 4311371 : } 31 : 32 : template <class T> 33 1036214 : [[nodiscard]] T SaturatingAdd(const T i, const T j) noexcept 34 : { 35 : if constexpr (std::numeric_limits<T>::is_signed) { 36 1036202 : if (i > 0 && j > std::numeric_limits<T>::max() - i) { 37 4 : return std::numeric_limits<T>::max(); 38 : } 39 1036198 : if (i < 0 && j < std::numeric_limits<T>::min() - i) { 40 4 : return std::numeric_limits<T>::min(); 41 : } 42 : } else { 43 12 : if (std::numeric_limits<T>::max() - i < j) { 44 4 : return std::numeric_limits<T>::max(); 45 : } 46 : } 47 1036202 : return i + j; 48 1036214 : } 49 : 50 : #endif // BITCOIN_UTIL_OVERFLOW_H