Skip to content

Commit ae6441d

Browse files
committed
Add is_left|right_shift_overflow math functions/tests.
1 parent c045763 commit ae6441d

3 files changed

Lines changed: 89 additions & 2 deletions

File tree

include/bitcoin/system/impl/math/overflow.ipp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,21 @@ constexpr Integral minimum_ = std::numeric_limits<Integral>::min();
3333
template <typename Integral, if_integer<Integral> = true>
3434
constexpr Integral maximum_ = std::numeric_limits<Integral>::max();
3535

36+
// shift
37+
// ----------------------------------------------------------------------------
38+
39+
template <typename Value, if_unsigned_integral_integer<Value>>
40+
constexpr bool is_left_shift_overflow(Value value, size_t shift) NOEXCEPT
41+
{
42+
return to_bool(bit_and(value, unmask_left<Value>(shift)));
43+
}
44+
45+
template <typename Value, if_unsigned_integral_integer<Value>>
46+
constexpr bool is_right_shift_overflow(Value value, size_t shift) NOEXCEPT
47+
{
48+
return to_bool(bit_and(value, unmask_right<Value>(shift)));
49+
}
50+
3651
// add/subtract
3752
// ----------------------------------------------------------------------------
3853

include/bitcoin/system/math/overflow.hpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,19 @@
2323

2424
namespace libbitcoin {
2525
namespace system {
26+
27+
/// shift
28+
/// ---------------------------------------------------------------------------
29+
30+
/// Shift would cause 1-valued bit(s) to be left-shifted out.
31+
template <typename Value, if_unsigned_integral_integer<Value> = true>
32+
constexpr bool is_left_shift_overflow(Value value, size_t shift) NOEXCEPT;
33+
34+
/// Shift would cause 1-valued bit(s) to be right-shifted out.
35+
template <typename Value, if_unsigned_integral_integer<Value> = true>
36+
constexpr bool is_right_shift_overflow(Value value, size_t shift) NOEXCEPT;
2637

27-
/// add/subtract.
38+
/// shift/add/subtract.
2839
/// ---------------------------------------------------------------------------
2940
// TODO: generalize is_add_overflow() and is_subtract_overflow() argument types.
3041

test/math/overflow.cpp

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,67 @@ constexpr auto signed_zero = 0_i16;
3030
constexpr auto signed_max = max_int16;
3131
constexpr auto signed_half = to_half(signed_max);
3232

33+
// is_left_shift_overflow
34+
// ----------------------------------------------------------------------------
35+
36+
// unsigned only
37+
static_assert(!is_left_shift_overflow<uint8_t>(0b00000000, 0));
38+
static_assert(!is_left_shift_overflow<uint8_t>(0b00000000, 1));
39+
static_assert(!is_left_shift_overflow<uint8_t>(0b00000000, 2));
40+
static_assert(!is_left_shift_overflow<uint8_t>(0b00000000, 4));
41+
static_assert(!is_left_shift_overflow<uint8_t>(0b00000000, 8));
42+
43+
static_assert(!is_left_shift_overflow<uint8_t>(0b00000001, 0));
44+
static_assert(!is_left_shift_overflow<uint8_t>(0b00000001, 1));
45+
static_assert(!is_left_shift_overflow<uint8_t>(0b00000001, 2));
46+
static_assert(!is_left_shift_overflow<uint8_t>(0b00000001, 4));
47+
static_assert( is_left_shift_overflow<uint8_t>(0b00000001, 8));
48+
49+
static_assert(!is_left_shift_overflow<uint8_t>(0b10000000, 0));
50+
static_assert( is_left_shift_overflow<uint8_t>(0b10000000, 1));
51+
static_assert( is_left_shift_overflow<uint8_t>(0b10000000, 2));
52+
static_assert( is_left_shift_overflow<uint8_t>(0b10000000, 4));
53+
static_assert( is_left_shift_overflow<uint8_t>(0b10000000, 8));
54+
55+
static_assert(!is_left_shift_overflow<uint8_t>(0b00101010, 0));
56+
static_assert(!is_left_shift_overflow<uint8_t>(0b00101010, 1));
57+
static_assert(!is_left_shift_overflow<uint8_t>(0b00101010, 2));
58+
static_assert( is_left_shift_overflow<uint8_t>(0b00101010, 4));
59+
static_assert( is_left_shift_overflow<uint8_t>(0b00101010, 8));
60+
61+
static_assert(!is_left_shift_overflow<uint8_t>(0b11111111, 0));
62+
static_assert( is_left_shift_overflow<uint8_t>(0b11111111, 1));
63+
static_assert( is_left_shift_overflow<uint8_t>(0b11111111, 2));
64+
static_assert( is_left_shift_overflow<uint8_t>(0b11111111, 4));
65+
static_assert( is_left_shift_overflow<uint8_t>(0b11111111, 8));
66+
67+
static_assert(!is_left_shift_overflow<uint16_t>(0b00010000'00000000, 0));
68+
static_assert(!is_left_shift_overflow<uint16_t>(0b00010000'00000000, 1));
69+
static_assert(!is_left_shift_overflow<uint16_t>(0b00010000'00000000, 2));
70+
static_assert( is_left_shift_overflow<uint16_t>(0b00010000'00000000, 4));
71+
static_assert( is_left_shift_overflow<uint16_t>(0b00010000'00000000, 8));
72+
static_assert( is_left_shift_overflow<uint16_t>(0b00000000'00000001, bits<uint16_t>));
73+
static_assert(!is_left_shift_overflow<uint16_t>(0b00000000'00000001, sub1(bits<uint16_t>)));
74+
75+
static_assert(!is_left_shift_overflow<uint32_t>(0b00010000'00000000'00000000'00000000, 0));
76+
static_assert(!is_left_shift_overflow<uint32_t>(0b00010000'00000000'00000000'00000000, 1));
77+
static_assert(!is_left_shift_overflow<uint32_t>(0b00010000'00000000'00000000'00000000, 2));
78+
static_assert( is_left_shift_overflow<uint32_t>(0b00010000'00000000'00000000'00000000, 4));
79+
static_assert( is_left_shift_overflow<uint32_t>(0b00010000'00000000'00000000'00000000, 8));
80+
static_assert( is_left_shift_overflow<uint32_t>(0b00000000'00000000'00000000'00000001, bits<uint32_t>));
81+
static_assert(!is_left_shift_overflow<uint32_t>(0b00000000'00000000'00000000'00000001, sub1(bits<uint32_t>)));
82+
83+
static_assert(!is_left_shift_overflow<uint64_t>(0b00010000'00000000'00000000'00000000'00010000'00000000'00000000'00000000, 0));
84+
static_assert(!is_left_shift_overflow<uint64_t>(0b00010000'00000000'00000000'00000000'00010000'00000000'00000000'00000000, 1));
85+
static_assert(!is_left_shift_overflow<uint64_t>(0b00010000'00000000'00000000'00000000'00010000'00000000'00000000'00000000, 2));
86+
static_assert( is_left_shift_overflow<uint64_t>(0b00010000'00000000'00000000'00000000'00010000'00000000'00000000'00000000, 4));
87+
static_assert( is_left_shift_overflow<uint64_t>(0b00010000'00000000'00000000'00000000'00010000'00000000'00000000'00000000, 8));
88+
static_assert( is_left_shift_overflow<uint64_t>(0b00000000'00000000'00000000'00000000'00000000'00000000'00000000'00000001, bits<uint64_t>));
89+
static_assert(!is_left_shift_overflow<uint64_t>(0b00000000'00000000'00000000'00000000'00000000'00000000'00000000'00000001, sub1(bits<uint64_t>)));
90+
91+
// is_right_shift_overflow
92+
// ----------------------------------------------------------------------------
93+
3394
// is_negate_overflow
3495
// ----------------------------------------------------------------------------
3596

@@ -68,7 +129,7 @@ static_assert(is_add_overflow(unsigned_max, unsigned_half));
68129
static_assert(is_add_overflow(unsigned_half, unsigned_max));
69130
static_assert(!is_add_overflow(unsigned_half, unsigned_half));
70131

71-
// is_underflow
132+
// is_subtract_overflow
72133
// ----------------------------------------------------------------------------
73134

74135
// signed

0 commit comments

Comments
 (0)