Skip to content

Commit 85a6aca

Browse files
authored
Merge pull request #1571 from evoskuil/master
Add math left_zeros, right_zeros, left_ones, right_ones.
2 parents d0b6b2c + c30e0d9 commit 85a6aca

7 files changed

Lines changed: 732 additions & 3 deletions

File tree

include/bitcoin/system/chain/block.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ class BC_API block
137137
code confirm(const context& ctx) const NOEXCEPT;
138138

139139
/// Populate previous outputs (only, no metadata) internal to the block.
140-
void populate() const NOEXCEPT;
140+
size_t populate() const NOEXCEPT;
141141

142142
protected:
143143
block(const chain::header::cptr& header,

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

src/chain/block.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ bool block::is_unspent_coinbase_collision() const NOEXCEPT
688688
}
689689

690690
// Search is not ordered, forward references are caught by block.check.
691-
void block::populate() const NOEXCEPT
691+
size_t block::populate() const NOEXCEPT
692692
{
693693
std::unordered_map<point, output::cptr> points{};
694694
uint32_t index{};
@@ -699,16 +699,22 @@ void block::populate() const NOEXCEPT
699699
points.emplace(std::pair{ point{ (*tx)->hash(false), index++ },
700700
out });
701701

702-
// Populate input prevouts from hash table.
702+
// Populate input prevouts from hash table and obtain count.
703+
size_t count{};
703704
for (auto tx = txs_->begin(); tx != txs_->end(); ++tx)
704705
{
705706
for (const auto& in: *(*tx)->inputs_ptr())
706707
{
707708
const auto point = points.find(in->point());
708709
if (point != points.end())
710+
{
711+
++count;
709712
in->prevout = point->second;
713+
}
710714
}
711715
}
716+
717+
return count;
712718
}
713719

714720
// Delegated.

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)