Bitcoin Core 31.99.0
P2P Digital Currency
overflow.h
Go to the documentation of this file.
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 <util/check.h>
9
10#include <climits>
11#include <concepts>
12#include <limits>
13#include <optional>
14#include <type_traits>
15
16template <class T>
17[[nodiscard]] bool AdditionOverflow(const T i, const T j) noexcept
18{
19 static_assert(std::is_integral_v<T>, "Integral required.");
20 if constexpr (std::numeric_limits<T>::is_signed) {
21 return (i > 0 && j > std::numeric_limits<T>::max() - i) ||
22 (i < 0 && j < std::numeric_limits<T>::min() - i);
23 }
24 return std::numeric_limits<T>::max() - i < j;
25}
26
27template <class T>
28[[nodiscard]] std::optional<T> CheckedAdd(const T i, const T j) noexcept
29{
30 if (AdditionOverflow(i, j)) {
31 return std::nullopt;
32 }
33 return i + j;
34}
35
36template <std::unsigned_integral T, std::unsigned_integral U>
37[[nodiscard]] constexpr bool TrySub(T& i, const U j) noexcept
38{
39 if (i < T{j}) return false;
40 i -= T{j};
41 return true;
42}
43
44template <class T>
45[[nodiscard]] T SaturatingAdd(const T i, const T j) noexcept
46{
47 if constexpr (std::numeric_limits<T>::is_signed) {
48 if (i > 0 && j > std::numeric_limits<T>::max() - i) {
49 return std::numeric_limits<T>::max();
50 }
51 if (i < 0 && j < std::numeric_limits<T>::min() - i) {
52 return std::numeric_limits<T>::min();
53 }
54 } else {
55 if (std::numeric_limits<T>::max() - i < j) {
56 return std::numeric_limits<T>::max();
57 }
58 }
59 return i + j;
60}
61
70template <std::unsigned_integral Dividend, std::unsigned_integral Divisor>
71[[nodiscard]] constexpr auto CeilDiv(const Dividend dividend, const Divisor divisor)
72{
73 assert(divisor > 0);
74 return dividend / divisor + (dividend % divisor != 0);
75}
76
83template <std::integral T>
84constexpr std::optional<T> CheckedLeftShift(T input, unsigned shift) noexcept
85{
86 if (shift == 0 || input == 0) return input;
87 // Avoid undefined c++ behaviour if shift is >= number of bits in T.
88 if (shift >= sizeof(T) * CHAR_BIT) return std::nullopt;
89 // If input << shift is too big to fit in T, return nullopt.
90 if (input > (std::numeric_limits<T>::max() >> shift)) return std::nullopt;
91 if (input < (std::numeric_limits<T>::min() >> shift)) return std::nullopt;
92 return input << shift;
93}
94
102template <std::integral T>
103constexpr T SaturatingLeftShift(T input, unsigned shift) noexcept
104{
105 if (auto result{CheckedLeftShift(input, shift)}) return *result;
106 // If input << shift is too big to fit in T, return biggest positive or negative
107 // number that fits.
108 return input < 0 ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
109}
110
111#endif // BITCOIN_UTIL_OVERFLOW_H
#define T(expected, seed, data)
constexpr bool TrySub(T &i, const U j) noexcept
Definition: overflow.h:37
std::optional< T > CheckedAdd(const T i, const T j) noexcept
Definition: overflow.h:28
constexpr T SaturatingLeftShift(T input, unsigned shift) noexcept
Left bit shift with safe minimum and maximum values.
Definition: overflow.h:103
bool AdditionOverflow(const T i, const T j) noexcept
Definition: overflow.h:17
constexpr auto CeilDiv(const Dividend dividend, const Divisor divisor)
Integer ceiling division (for unsigned values).
Definition: overflow.h:71
T SaturatingAdd(const T i, const T j) noexcept
Definition: overflow.h:45
constexpr std::optional< T > CheckedLeftShift(T input, unsigned shift) noexcept
Left bit shift with overflow checking.
Definition: overflow.h:84
assert(!tx.IsCoinBase())