Skip to content

Add math left_zeros, right_zeros, left_ones, right_ones. #1571

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading