Bitcoin Core  29.1.0
P2P Digital Currency
overflow.h
Go to the documentation of this file.
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 <climits>
9 #include <concepts>
10 #include <limits>
11 #include <optional>
12 #include <type_traits>
13 
14 template <class T>
15 [[nodiscard]] bool AdditionOverflow(const T i, const T j) noexcept
16 {
17  static_assert(std::is_integral<T>::value, "Integral required.");
18  if constexpr (std::numeric_limits<T>::is_signed) {
19  return (i > 0 && j > std::numeric_limits<T>::max() - i) ||
20  (i < 0 && j < std::numeric_limits<T>::min() - i);
21  }
22  return std::numeric_limits<T>::max() - i < j;
23 }
24 
25 template <class T>
26 [[nodiscard]] std::optional<T> CheckedAdd(const T i, const T j) noexcept
27 {
28  if (AdditionOverflow(i, j)) {
29  return std::nullopt;
30  }
31  return i + j;
32 }
33 
34 template <class T>
35 [[nodiscard]] T SaturatingAdd(const T i, const T j) noexcept
36 {
37  if constexpr (std::numeric_limits<T>::is_signed) {
38  if (i > 0 && j > std::numeric_limits<T>::max() - i) {
39  return std::numeric_limits<T>::max();
40  }
41  if (i < 0 && j < std::numeric_limits<T>::min() - i) {
42  return std::numeric_limits<T>::min();
43  }
44  } else {
45  if (std::numeric_limits<T>::max() - i < j) {
46  return std::numeric_limits<T>::max();
47  }
48  }
49  return i + j;
50 }
51 
58 template <std::integral T>
59 constexpr std::optional<T> CheckedLeftShift(T input, unsigned shift) noexcept
60 {
61  if (shift == 0 || input == 0) return input;
62  // Avoid undefined c++ behaviour if shift is >= number of bits in T.
63  if (shift >= sizeof(T) * CHAR_BIT) return std::nullopt;
64  // If input << shift is too big to fit in T, return nullopt.
65  if (input > (std::numeric_limits<T>::max() >> shift)) return std::nullopt;
66  if (input < (std::numeric_limits<T>::min() >> shift)) return std::nullopt;
67  return input << shift;
68 }
69 
77 template <std::integral T>
78 constexpr T SaturatingLeftShift(T input, unsigned shift) noexcept
79 {
80  if (auto result{CheckedLeftShift(input, shift)}) return *result;
81  // If input << shift is too big to fit in T, return biggest positive or negative
82  // number that fits.
83  return input < 0 ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
84 }
85 
86 #endif // BITCOIN_UTIL_OVERFLOW_H
bool AdditionOverflow(const T i, const T j) noexcept
Definition: overflow.h:15
constexpr std::optional< T > CheckedLeftShift(T input, unsigned shift) noexcept
Left bit shift with overflow checking.
Definition: overflow.h:59
std::optional< T > CheckedAdd(const T i, const T j) noexcept
Definition: overflow.h:26
T SaturatingAdd(const T i, const T j) noexcept
Definition: overflow.h:35
constexpr T SaturatingLeftShift(T input, unsigned shift) noexcept
Left bit shift with safe minimum and maximum values.
Definition: overflow.h:78
auto result
Definition: common-types.h:74
#define T(expected, seed, data)