Bitcoin Core
31.1.0
P2P Digital Currency
Toggle main menu visibility
Loading...
Searching...
No Matches
src
util
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 <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_v<T>,
"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
<std::
unsigned
_
int
egral T, std::
unsigned
_
int
egral U>
35
[[nodiscard]]
constexpr
bool
TrySub
(
T
& i,
const
U j)
noexcept
36
{
37
if
(i <
T
{j})
return
false
;
38
i -=
T
{j};
39
return
true
;
40
}
41
42
template
<
class
T>
43
[[nodiscard]]
T
SaturatingAdd
(
const
T
i,
const
T
j)
noexcept
44
{
45
if
constexpr
(std::numeric_limits<T>::is_signed) {
46
if
(i > 0 && j > std::numeric_limits<T>::max() - i) {
47
return
std::numeric_limits<T>::max();
48
}
49
if
(i < 0 && j < std::numeric_limits<T>::min() - i) {
50
return
std::numeric_limits<T>::min();
51
}
52
}
else
{
53
if
(std::numeric_limits<T>::max() - i < j) {
54
return
std::numeric_limits<T>::max();
55
}
56
}
57
return
i + j;
58
}
59
66
template
<std::
int
egral T>
67
constexpr
std::optional<T>
CheckedLeftShift
(
T
input,
unsigned
shift)
noexcept
68
{
69
if
(shift == 0 || input == 0)
return
input;
70
// Avoid undefined c++ behaviour if shift is >= number of bits in T.
71
if
(shift >=
sizeof
(
T
) * CHAR_BIT)
return
std::nullopt;
72
// If input << shift is too big to fit in T, return nullopt.
73
if
(input > (std::numeric_limits<T>::max() >> shift))
return
std::nullopt;
74
if
(input < (std::numeric_limits<T>::min() >> shift))
return
std::nullopt;
75
return
input << shift;
76
}
77
85
template
<std::
int
egral T>
86
constexpr
T
SaturatingLeftShift
(
T
input,
unsigned
shift)
noexcept
87
{
88
if
(
auto
result{
CheckedLeftShift
(input, shift)})
return
*result;
89
// If input << shift is too big to fit in T, return biggest positive or negative
90
// number that fits.
91
return
input < 0 ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
92
}
93
94
#endif
// BITCOIN_UTIL_OVERFLOW_H
T
#define T(expected, seed, data)
TrySub
constexpr bool TrySub(T &i, const U j) noexcept
Definition
overflow.h:35
CheckedAdd
std::optional< T > CheckedAdd(const T i, const T j) noexcept
Definition
overflow.h:26
SaturatingLeftShift
constexpr T SaturatingLeftShift(T input, unsigned shift) noexcept
Left bit shift with safe minimum and maximum values.
Definition
overflow.h:86
AdditionOverflow
bool AdditionOverflow(const T i, const T j) noexcept
Definition
overflow.h:15
SaturatingAdd
T SaturatingAdd(const T i, const T j) noexcept
Definition
overflow.h:43
CheckedLeftShift
constexpr std::optional< T > CheckedLeftShift(T input, unsigned shift) noexcept
Left bit shift with overflow checking.
Definition
overflow.h:67
Generated on
for Bitcoin Core by
1.17.0