Line data Source code
1 : // Copyright (c) 2021-2022 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 160402 : [[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 0 : return (i > 0 && j > std::numeric_limits<T>::max() - i) || 18 0 : (i < 0 && j < std::numeric_limits<T>::min() - i); 19 : } 20 160402 : return std::numeric_limits<T>::max() - i < j; 21 : } 22 : 23 : template <class T> 24 160402 : [[nodiscard]] std::optional<T> CheckedAdd(const T i, const T j) noexcept 25 : { 26 160402 : if (AdditionOverflow(i, j)) { 27 0 : return std::nullopt; 28 : } 29 160402 : return i + j; 30 160402 : } 31 : 32 : template <class T> 33 6790 : [[nodiscard]] T SaturatingAdd(const T i, const T j) noexcept 34 : { 35 : if constexpr (std::numeric_limits<T>::is_signed) { 36 6790 : if (i > 0 && j > std::numeric_limits<T>::max() - i) { 37 0 : return std::numeric_limits<T>::max(); 38 : } 39 6790 : if (i < 0 && j < std::numeric_limits<T>::min() - i) { 40 0 : return std::numeric_limits<T>::min(); 41 : } 42 : } else { 43 0 : if (std::numeric_limits<T>::max() - i < j) { 44 0 : return std::numeric_limits<T>::max(); 45 : } 46 : } 47 6790 : return i + j; 48 6790 : } 49 : 50 : #endif // BITCOIN_UTIL_OVERFLOW_H