/root/bitcoin/src/util/overflow.h
Line | Count | Source |
1 | | // Copyright (c) 2021-present 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 <cassert> |
9 | | #include <climits> |
10 | | #include <concepts> |
11 | | #include <limits> |
12 | | #include <optional> |
13 | | #include <type_traits> |
14 | | |
15 | | template <class T> |
16 | | [[nodiscard]] bool AdditionOverflow(const T i, const T j) noexcept |
17 | 0 | { |
18 | 0 | static_assert(std::is_integral_v<T>, "Integral required."); |
19 | 0 | if constexpr (std::numeric_limits<T>::is_signed) { |
20 | 0 | return (i > 0 && j > std::numeric_limits<T>::max() - i) || |
21 | 0 | (i < 0 && j < std::numeric_limits<T>::min() - i); |
22 | 0 | } |
23 | 0 | return std::numeric_limits<T>::max() - i < j; |
24 | 0 | } Unexecuted instantiation: bool AdditionOverflow<long>(long, long) Unexecuted instantiation: bool AdditionOverflow<unsigned long>(unsigned long, unsigned long) Unexecuted instantiation: bool AdditionOverflow<int>(int, int) Unexecuted instantiation: bool AdditionOverflow<unsigned int>(unsigned int, unsigned int) Unexecuted instantiation: bool AdditionOverflow<short>(short, short) Unexecuted instantiation: bool AdditionOverflow<unsigned short>(unsigned short, unsigned short) Unexecuted instantiation: bool AdditionOverflow<char>(char, char) Unexecuted instantiation: bool AdditionOverflow<unsigned char>(unsigned char, unsigned char) Unexecuted instantiation: bool AdditionOverflow<signed char>(signed char, signed char) |
25 | | |
26 | | template <class T> |
27 | | [[nodiscard]] std::optional<T> CheckedAdd(const T i, const T j) noexcept |
28 | 0 | { |
29 | 0 | if (AdditionOverflow(i, j)) { |
30 | 0 | return std::nullopt; |
31 | 0 | } |
32 | 0 | return i + j; |
33 | 0 | } Unexecuted instantiation: std::optional<long> CheckedAdd<long>(long, long) Unexecuted instantiation: std::optional<unsigned long> CheckedAdd<unsigned long>(unsigned long, unsigned long) Unexecuted instantiation: std::optional<int> CheckedAdd<int>(int, int) Unexecuted instantiation: std::optional<unsigned int> CheckedAdd<unsigned int>(unsigned int, unsigned int) Unexecuted instantiation: std::optional<short> CheckedAdd<short>(short, short) Unexecuted instantiation: std::optional<unsigned short> CheckedAdd<unsigned short>(unsigned short, unsigned short) Unexecuted instantiation: std::optional<char> CheckedAdd<char>(char, char) Unexecuted instantiation: std::optional<unsigned char> CheckedAdd<unsigned char>(unsigned char, unsigned char) Unexecuted instantiation: std::optional<signed char> CheckedAdd<signed char>(signed char, signed char) |
34 | | |
35 | | template <std::unsigned_integral T, std::unsigned_integral U> |
36 | | [[nodiscard]] constexpr bool TrySub(T& i, const U j) noexcept |
37 | 0 | { |
38 | 0 | if (i < T{j}) return false; |
39 | 0 | i -= T{j}; |
40 | 0 | return true; |
41 | 0 | } Unexecuted instantiation: _Z6TrySubITkSt17unsigned_integralmTkSt17unsigned_integralbEbRT_T0_ Unexecuted instantiation: _Z6TrySubITkSt17unsigned_integralmTkSt17unsigned_integralmEbRT_T0_ |
42 | | |
43 | | template <class T> |
44 | | [[nodiscard]] T SaturatingAdd(const T i, const T j) noexcept |
45 | 0 | { |
46 | 0 | if constexpr (std::numeric_limits<T>::is_signed) { |
47 | 0 | if (i > 0 && j > std::numeric_limits<T>::max() - i) { |
48 | 0 | return std::numeric_limits<T>::max(); |
49 | 0 | } |
50 | 0 | if (i < 0 && j < std::numeric_limits<T>::min() - i) { |
51 | 0 | return std::numeric_limits<T>::min(); |
52 | 0 | } |
53 | 0 | } else { |
54 | 0 | if (std::numeric_limits<T>::max() - i < j) { |
55 | 0 | return std::numeric_limits<T>::max(); |
56 | 0 | } |
57 | 0 | } |
58 | 0 | return i + j; |
59 | 0 | } Unexecuted instantiation: long SaturatingAdd<long>(long, long) Unexecuted instantiation: unsigned long SaturatingAdd<unsigned long>(unsigned long, unsigned long) Unexecuted instantiation: int SaturatingAdd<int>(int, int) Unexecuted instantiation: unsigned int SaturatingAdd<unsigned int>(unsigned int, unsigned int) Unexecuted instantiation: short SaturatingAdd<short>(short, short) Unexecuted instantiation: unsigned short SaturatingAdd<unsigned short>(unsigned short, unsigned short) Unexecuted instantiation: char SaturatingAdd<char>(char, char) Unexecuted instantiation: unsigned char SaturatingAdd<unsigned char>(unsigned char, unsigned char) Unexecuted instantiation: signed char SaturatingAdd<signed char>(signed char, signed char) |
60 | | |
61 | | /** |
62 | | * @brief Integer ceiling division (for unsigned values). |
63 | | * |
64 | | * Computes the smallest integer q such that q * divisor >= dividend. |
65 | | * Both dividend and divisor must be unsigned, and divisor must be non-zero. |
66 | | * |
67 | | * The implementation avoids overflow that can occur with `(dividend + divisor - 1) / divisor`. |
68 | | */ |
69 | | template <std::unsigned_integral Dividend, std::unsigned_integral Divisor> |
70 | | [[nodiscard]] constexpr auto CeilDiv(const Dividend dividend, const Divisor divisor) |
71 | 0 | { |
72 | 0 | assert(divisor > 0); |
73 | 0 | return dividend / divisor + (dividend % divisor != 0); |
74 | 0 | } Unexecuted instantiation: _Z7CeilDivITkSt17unsigned_integralmTkSt17unsigned_integraljEDaT_T0_ Unexecuted instantiation: _Z7CeilDivITkSt17unsigned_integralmTkSt17unsigned_integralmEDaT_T0_ Unexecuted instantiation: _Z7CeilDivITkSt17unsigned_integraljTkSt17unsigned_integralmEDaT_T0_ Unexecuted instantiation: _Z7CeilDivITkSt17unsigned_integraljTkSt17unsigned_integraljEDaT_T0_ |
75 | | |
76 | | /** |
77 | | * @brief Left bit shift with overflow checking. |
78 | | * @param input The input value to be left shifted. |
79 | | * @param shift The number of bits to left shift. |
80 | | * @return (input * 2^shift) or nullopt if it would not fit in the return type. |
81 | | */ |
82 | | template <std::integral T> |
83 | | constexpr std::optional<T> CheckedLeftShift(T input, unsigned shift) noexcept |
84 | 0 | { |
85 | 0 | if (shift == 0 || input == 0) return input; |
86 | | // Avoid undefined c++ behaviour if shift is >= number of bits in T. |
87 | 0 | if (shift >= sizeof(T) * CHAR_BIT) return std::nullopt; |
88 | | // If input << shift is too big to fit in T, return nullopt. |
89 | 0 | if (input > (std::numeric_limits<T>::max() >> shift)) return std::nullopt; |
90 | 0 | if (input < (std::numeric_limits<T>::min() >> shift)) return std::nullopt; |
91 | 0 | return input << shift; |
92 | 0 | } Unexecuted instantiation: _Z16CheckedLeftShiftITkSt8integralyESt8optionalIT_ES1_j Unexecuted instantiation: _Z16CheckedLeftShiftITkSt8integralaESt8optionalIT_ES1_j Unexecuted instantiation: _Z16CheckedLeftShiftITkSt8integralsESt8optionalIT_ES1_j Unexecuted instantiation: _Z16CheckedLeftShiftITkSt8integraliESt8optionalIT_ES1_j Unexecuted instantiation: _Z16CheckedLeftShiftITkSt8integralhESt8optionalIT_ES1_j Unexecuted instantiation: _Z16CheckedLeftShiftITkSt8integraltESt8optionalIT_ES1_j Unexecuted instantiation: _Z16CheckedLeftShiftITkSt8integraljESt8optionalIT_ES1_j Unexecuted instantiation: _Z16CheckedLeftShiftITkSt8integralmESt8optionalIT_ES1_j |
93 | | |
94 | | /** |
95 | | * @brief Left bit shift with safe minimum and maximum values. |
96 | | * @param input The input value to be left shifted. |
97 | | * @param shift The number of bits to left shift. |
98 | | * @return (input * 2^shift) clamped to fit between the lowest and highest |
99 | | * representable values of the type T. |
100 | | */ |
101 | | template <std::integral T> |
102 | | constexpr T SaturatingLeftShift(T input, unsigned shift) noexcept |
103 | 0 | { |
104 | 0 | if (auto result{CheckedLeftShift(input, shift)}) return *result; |
105 | | // If input << shift is too big to fit in T, return biggest positive or negative |
106 | | // number that fits. |
107 | 0 | return input < 0 ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max(); |
108 | 0 | } Unexecuted instantiation: _Z19SaturatingLeftShiftITkSt8integralaET_S0_j Unexecuted instantiation: _Z19SaturatingLeftShiftITkSt8integralsET_S0_j Unexecuted instantiation: _Z19SaturatingLeftShiftITkSt8integraliET_S0_j Unexecuted instantiation: _Z19SaturatingLeftShiftITkSt8integralhET_S0_j Unexecuted instantiation: _Z19SaturatingLeftShiftITkSt8integraltET_S0_j Unexecuted instantiation: _Z19SaturatingLeftShiftITkSt8integraljET_S0_j Unexecuted instantiation: _Z19SaturatingLeftShiftITkSt8integralmET_S0_j |
109 | | |
110 | | #endif // BITCOIN_UTIL_OVERFLOW_H |