Skip to content

Commit

Permalink
Merge pull request #1571 from evoskuil/master
Browse files Browse the repository at this point in the history
Add math left_zeros, right_zeros, left_ones, right_ones.
  • Loading branch information
evoskuil authored Dec 20, 2024
2 parents d0b6b2c + c30e0d9 commit 85a6aca
Show file tree
Hide file tree
Showing 7 changed files with 732 additions and 3 deletions.
2 changes: 1 addition & 1 deletion include/bitcoin/system/chain/block.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ class BC_API block
code confirm(const context& ctx) const NOEXCEPT;

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

protected:
block(const chain::header::cptr& header,
Expand Down
24 changes: 24 additions & 0 deletions include/bitcoin/system/impl/math/bits.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,30 @@ constexpr size_t bit_width(Value value) NOEXCEPT
return is_negative(value) ? bits<Value> : bit_width(to_unsigned(value));
}

template <typename Value, if_unsigned_integer<Value>>
constexpr size_t left_zeros(Value value) NOEXCEPT
{
return to_unsigned(std::countl_zero<Value>(value));
}

template <typename Value, if_unsigned_integer<Value>>
constexpr size_t right_zeros(Value value) NOEXCEPT
{
return to_unsigned(std::countr_zero<Value>(value));
}

template <typename Value, if_unsigned_integer<Value>>
constexpr size_t left_ones(Value value) NOEXCEPT
{
return to_unsigned(std::countl_one<Value>(value));
}

template <typename Value, if_unsigned_integer<Value>>
constexpr size_t right_ones(Value value) NOEXCEPT
{
return to_unsigned(std::countr_one<Value>(value));
}

// Bitwise logical operations.
// ----------------------------------------------------------------------------

Expand Down
12 changes: 12 additions & 0 deletions include/bitcoin/system/math/bits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,18 @@ constexpr size_t bit_width(Value value) NOEXCEPT;
template <typename Value, if_signed_integer<Value> = true>
constexpr size_t bit_width(Value value) NOEXCEPT;

// Because std::countl_* (C++20) functions return int.
template <typename Value, if_unsigned_integer<Value> = true>
constexpr size_t left_zeros(Value value) NOEXCEPT;
template <typename Value, if_unsigned_integer<Value> = true>
constexpr size_t right_zeros(Value value) NOEXCEPT;

// Because std::countr_* (C++20) functions return int.
template <typename Value, if_unsigned_integer<Value> = true>
constexpr size_t left_ones(Value value) NOEXCEPT;
template <typename Value, if_unsigned_integer<Value> = true>
constexpr size_t right_ones(Value value) NOEXCEPT;

/// Bitwise logical operations.
/// ---------------------------------------------------------------------------

Expand Down
10 changes: 8 additions & 2 deletions src/chain/block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ bool block::is_unspent_coinbase_collision() const NOEXCEPT
}

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

// Populate input prevouts from hash table.
// Populate input prevouts from hash table and obtain count.
size_t count{};
for (auto tx = txs_->begin(); tx != txs_->end(); ++tx)
{
for (const auto& in: *(*tx)->inputs_ptr())
{
const auto point = points.find(in->point());
if (point != points.end())
{
++count;
in->prevout = point->second;
}
}
}

return count;
}

// Delegated.
Expand Down
24 changes: 24 additions & 0 deletions test/math/bits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,30 @@ static_assert(bit_width<int64_t>(0x800000000000_ni64) == 64u);
static_assert(bit_width<int64_t>(0x80010000000000_ni64) == 64u);
static_assert(bit_width<int64_t>(0x8000000000000000_ni64) == 64u);

// zeroes

static_assert(left_zeros(uint8_t{ 0b00000000 }) == 8);
static_assert(left_zeros(uint8_t{ 0b11111111 }) == 0);
static_assert(left_zeros(uint8_t{ 0b11110000 }) == 0);
static_assert(left_zeros(uint8_t{ 0b00011110 }) == 3);

static_assert(right_zeros(uint8_t{ 0b00000000 }) == 8);
static_assert(right_zeros(uint8_t{ 0b11111111 }) == 0);
static_assert(right_zeros(uint8_t{ 0b00011100 }) == 2);
static_assert(right_zeros(uint8_t{ 0b00011101 }) == 0);

// ones

static_assert(left_ones(uint8_t{ 0b00000000 }) == 0);
static_assert(left_ones(uint8_t{ 0b11111111 }) == 8);
static_assert(left_ones(uint8_t{ 0b01111111 }) == 0);
static_assert(left_ones(uint8_t{ 0b11100011 }) == 3);

static_assert(right_ones(uint8_t{ 0b00000000 }) == 0);
static_assert(right_ones(uint8_t{ 0b11111111 }) == 8);
static_assert(right_ones(uint8_t{ 0b11111110 }) == 0);
static_assert(right_ones(uint8_t{ 0b11100011 }) == 2);

// ones_complement (NOT)
// inverts all bits (~n, !bool)
static_assert(bit_not(-4) == 3);
Expand Down
Loading

0 comments on commit 85a6aca

Please sign in to comment.