Skip to content

Commit fa79f7c

Browse files
committed
Add math left_zeros, right_zeros, left_ones, right_ones.
1 parent d0b6b2c commit fa79f7c

3 files changed

Lines changed: 60 additions & 0 deletions

File tree

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,30 @@ constexpr size_t bit_width(Value value) NOEXCEPT
4949
return is_negative(value) ? bits<Value> : bit_width(to_unsigned(value));
5050
}
5151

52+
template <typename Value, if_unsigned_integer<Value>>
53+
constexpr size_t left_zeros(Value value) NOEXCEPT
54+
{
55+
return to_unsigned(std::countl_zero<Value>(value));
56+
}
57+
58+
template <typename Value, if_unsigned_integer<Value>>
59+
constexpr size_t right_zeros(Value value) NOEXCEPT
60+
{
61+
return to_unsigned(std::countr_zero<Value>(value));
62+
}
63+
64+
template <typename Value, if_unsigned_integer<Value>>
65+
constexpr size_t left_ones(Value value) NOEXCEPT
66+
{
67+
return to_unsigned(std::countl_one<Value>(value));
68+
}
69+
70+
template <typename Value, if_unsigned_integer<Value>>
71+
constexpr size_t right_ones(Value value) NOEXCEPT
72+
{
73+
return to_unsigned(std::countr_one<Value>(value));
74+
}
75+
5276
// Bitwise logical operations.
5377
// ----------------------------------------------------------------------------
5478

include/bitcoin/system/math/bits.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ constexpr size_t bit_width(Value value) NOEXCEPT;
3939
template <typename Value, if_signed_integer<Value> = true>
4040
constexpr size_t bit_width(Value value) NOEXCEPT;
4141

42+
// Because std::countl_* (C++20) functions return int.
43+
template <typename Value, if_unsigned_integer<Value> = true>
44+
constexpr size_t left_zeros(Value value) NOEXCEPT;
45+
template <typename Value, if_unsigned_integer<Value> = true>
46+
constexpr size_t right_zeros(Value value) NOEXCEPT;
47+
48+
// Because std::countr_* (C++20) functions return int.
49+
template <typename Value, if_unsigned_integer<Value> = true>
50+
constexpr size_t left_ones(Value value) NOEXCEPT;
51+
template <typename Value, if_unsigned_integer<Value> = true>
52+
constexpr size_t right_ones(Value value) NOEXCEPT;
53+
4254
/// Bitwise logical operations.
4355
/// ---------------------------------------------------------------------------
4456

test/math/bits.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,30 @@ static_assert(bit_width<int64_t>(0x800000000000_ni64) == 64u);
111111
static_assert(bit_width<int64_t>(0x80010000000000_ni64) == 64u);
112112
static_assert(bit_width<int64_t>(0x8000000000000000_ni64) == 64u);
113113

114+
// zeroes
115+
116+
static_assert(left_zeros(uint8_t{ 0b00000000 }) == 8);
117+
static_assert(left_zeros(uint8_t{ 0b11111111 }) == 0);
118+
static_assert(left_zeros(uint8_t{ 0b11110000 }) == 0);
119+
static_assert(left_zeros(uint8_t{ 0b00011110 }) == 3);
120+
121+
static_assert(right_zeros(uint8_t{ 0b00000000 }) == 8);
122+
static_assert(right_zeros(uint8_t{ 0b11111111 }) == 0);
123+
static_assert(right_zeros(uint8_t{ 0b00011100 }) == 2);
124+
static_assert(right_zeros(uint8_t{ 0b00011101 }) == 0);
125+
126+
// ones
127+
128+
static_assert(left_ones(uint8_t{ 0b00000000 }) == 0);
129+
static_assert(left_ones(uint8_t{ 0b11111111 }) == 8);
130+
static_assert(left_ones(uint8_t{ 0b01111111 }) == 0);
131+
static_assert(left_ones(uint8_t{ 0b11100011 }) == 3);
132+
133+
static_assert(right_ones(uint8_t{ 0b00000000 }) == 0);
134+
static_assert(right_ones(uint8_t{ 0b11111111 }) == 8);
135+
static_assert(right_ones(uint8_t{ 0b11111110 }) == 0);
136+
static_assert(right_ones(uint8_t{ 0b11100011 }) == 2);
137+
114138
// ones_complement (NOT)
115139
// inverts all bits (~n, !bool)
116140
static_assert(bit_not(-4) == 3);

0 commit comments

Comments
 (0)