5#ifndef BITCOIN_UTIL_BITSET_H
6#define BITCOIN_UTIL_BITSET_H
40 static_assert(std::is_integral_v<I> && std::is_unsigned_v<I> && std::numeric_limits<I>::radix == 2);
41 constexpr auto BITS = std::numeric_limits<I>::digits;
44 if constexpr (BITS <= 32) {
45 v -= (v >> 1) & 0x55555555;
46 v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
47 v = (v + (v >> 4)) & 0x0f0f0f0f;
48 if constexpr (BITS > 8) v += v >> 8;
49 if constexpr (BITS > 16) v += v >> 16;
52 static_assert(BITS <= 64);
53 v -= (v >> 1) & 0x5555555555555555;
54 v = (v & 0x3333333333333333) + ((v >> 2) & 0x3333333333333333);
55 v = (v + (v >> 4)) & 0x0f0f0f0f0f0f0f0f;
56 return (v * uint64_t{0x0101010101010101}) >> 56;
65 static_assert(std::is_integral_v<I> && std::is_unsigned_v<I> && std::numeric_limits<I>::radix == 2);
67 static constexpr unsigned MAX_SIZE = std::numeric_limits<I>::digits;
125 for (
auto pos : ilist)
Set(pos);
133 for (
auto pos : ilist)
Set(pos);
151 constexpr void Set(
unsigned pos)
noexcept
154 m_val |= I{1U} << pos;
157 constexpr void Set(
unsigned pos,
bool val)
noexcept
160 m_val = (
m_val & ~I(I{1U} << pos)) | (I(val) << pos);
163 constexpr void Reset(
unsigned pos)
noexcept
166 m_val &= ~I(I{1U} << pos);
172 return (
m_val >> pos) & 1U;
179 constexpr bool None() const noexcept {
return m_val == 0; }
181 constexpr bool Any() const noexcept {
return !
None(); }
187 constexpr unsigned First() const noexcept
190 return std::countr_zero(
m_val);
193 constexpr unsigned Last() const noexcept
196 return std::bit_width(
m_val) - 1;
227template<
typename I,
unsigned N>
231 static_assert(std::is_integral_v<I> && std::is_unsigned_v<I> && std::numeric_limits<I>::radix == 2);
233 static_assert(N > 0);
235 static constexpr unsigned LIMB_BITS = std::numeric_limits<I>::digits;
289 if (
m_idx == N)
break;
317 void constexpr Set(
unsigned pos)
noexcept
323 void constexpr Set(
unsigned pos,
bool val)
noexcept
332 for (
auto pos : ilist)
Set(pos);
338 for (
auto pos : ilist)
Set(pos);
342 void constexpr Reset(
unsigned pos)
noexcept
369 ret.m_val[i++] = I(~I{0});
379 unsigned constexpr Count() const noexcept
386 bool constexpr None() const noexcept
388 for (
auto v :
m_val) {
389 if (v != 0)
return false;
394 bool constexpr Any() const noexcept {
return !
None(); }
400 unsigned constexpr First() const noexcept
403 while (
m_val[p] == 0) {
410 unsigned constexpr Last() const noexcept
413 while (
m_val[p] == 0) {
422 for (
unsigned i = 0; i < N; ++i) {
423 m_val[i] |= a.m_val[i];
430 for (
unsigned i = 0; i < N; ++i) {
431 m_val[i] &= a.m_val[i];
438 for (
unsigned i = 0; i < N; ++i) {
439 m_val[i] &= ~a.m_val[i];
446 for (
unsigned i = 0; i < N; ++i) {
447 m_val[i] ^= a.m_val[i];
454 for (
unsigned i = 0; i < N; ++i) {
455 if (
m_val[i] & a.m_val[i])
return true;
463 for (
unsigned i = 0; i < N; ++i) {
464 r.
m_val[i] = a.m_val[i] & b.m_val[i];
472 for (
unsigned i = 0; i < N; ++i) {
473 r.
m_val[i] = a.m_val[i] | b.m_val[i];
481 for (
unsigned i = 0; i < N; ++i) {
482 r.
m_val[i] = a.m_val[i] & ~b.m_val[i];
490 for (
unsigned i = 0; i < N; ++i) {
491 r.
m_val[i] = a.m_val[i] ^ b.m_val[i];
498 for (
unsigned i = 0; i < N; ++i) {
499 if (a.m_val[i] & ~
m_val[i])
return false;
506 for (
unsigned i = 0; i < N; ++i) {
507 if (
m_val[i] & ~a.m_val[i])
return false;
522template<
unsigned BITS>
523using BitSet = std::conditional_t<(BITS <= 32), bitset_detail::IntBitSet<uint32_t>,
std::conditional_t<(BITS<=32), bitset_detail::IntBitSet< uint32_t >, std::conditional_t<(BITS<=std::numeric_limits< size_t >::digits), bitset_detail::IntBitSet< size_t >, bitset_detail::MultiIntBitSet< size_t,(BITS+std::numeric_limits< size_t >::digits - 1)/std::numeric_limits< size_t >::digits > > > BitSet
#define Assume(val)
Assume is the identity function.
Dummy type to return using end().
constexpr IteratorEnd(const IteratorEnd &)=default
constexpr IteratorEnd()=default
Iterator type returned by begin(), which efficiently iterates all 1 positions.
Iterator()=delete
Do not allow external code to construct an Iterator.
I m_val
The original integer's remaining bits.
constexpr friend bool operator==(const Iterator &a, const IteratorEnd &) noexcept
Test whether we are done (can only compare with IteratorEnd).
constexpr unsigned operator*() const noexcept
Get the current bit position (only if != IteratorEnd).
constexpr Iterator(const Iterator &) noexcept=default
constexpr Iterator & operator++() noexcept
Progress to the next 1 bit (only if != IteratorEnd).
constexpr Iterator(I val) noexcept
Last reported 1 position (if m_pos != 0).
constexpr Iterator & operator=(const Iterator &) noexcept=default
A bitset implementation backed by a single integer of type I.
constexpr void Reset(unsigned pos) noexcept
Set a bit to 0.
IntBitSet(I val) noexcept
Internal constructor with a given integer as contents.
constexpr IteratorEnd end() const noexcept
Return a dummy object to compare Iterators with.
constexpr IntBitSet & operator=(std::initializer_list< unsigned > ilist) noexcept
Assign from a list of positions (which will be made true, all others false).
friend constexpr IntBitSet operator-(const IntBitSet &a, const IntBitSet &b) noexcept
Return an object with the binary AND NOT between respective bits from a and b.
friend constexpr IntBitSet operator&(const IntBitSet &a, const IntBitSet &b) noexcept
Return an object with the binary AND between respective bits from a and b.
constexpr bool IsSubsetOf(const IntBitSet &a) const noexcept
Check if bitset a is a subset of bitset b (= every 1 bit in a is also in b).
friend constexpr IntBitSet operator|(const IntBitSet &a, const IntBitSet &b) noexcept
Return an object with the binary OR between respective bits from a and b.
static constexpr IntBitSet Fill(unsigned count) noexcept
Construct a bitset with bits 0..count-1 (inclusive) set to 1.
constexpr IntBitSet & operator-=(const IntBitSet &a) noexcept
Set this object's bits to be the binary AND NOT between respective bits from this and a.
constexpr unsigned First() const noexcept
Find the first element (requires Any()).
constexpr bool Any() const noexcept
Check if any bits are 1.
constexpr IntBitSet(const IntBitSet &) noexcept=default
Copy construct a bitset.
friend constexpr void swap(IntBitSet &a, IntBitSet &b) noexcept
Swap two bitsets.
constexpr IntBitSet & operator|=(const IntBitSet &a) noexcept
Set this object's bits to be the binary AND between respective bits from this and a.
constexpr bool None() const noexcept
Check if all bits are 0.
constexpr bool IsSupersetOf(const IntBitSet &a) const noexcept
Check if bitset a is a superset of bitset b (= every 1 bit in b is also in a).
constexpr IntBitSet & operator^=(const IntBitSet &a) noexcept
Set this object's bits to be the binary XOR between respective bits from this as a.
static constexpr unsigned MAX_SIZE
The maximum number of bits this bitset supports.
constexpr unsigned Last() const noexcept
Find the last element (requires Any()).
static constexpr unsigned Size() noexcept
Return the number of bits that this object holds.
friend constexpr IntBitSet operator^(const IntBitSet &a, const IntBitSet &b) noexcept
Return an object with the binary XOR between respective bits from a and b.
constexpr void Set(unsigned pos) noexcept
Set a bit to 1.
constexpr IntBitSet() noexcept
Construct an all-zero bitset.
constexpr bool Overlaps(const IntBitSet &a) const noexcept
Check if the intersection between two sets is non-empty.
constexpr unsigned Count() const noexcept
Compute the number of 1 bits in the bitset.
friend constexpr bool operator==(const IntBitSet &a, const IntBitSet &b) noexcept=default
Check if bitset a and bitset b are identical.
constexpr IntBitSet & operator=(const IntBitSet &) noexcept=default
Copy assign a bitset.
constexpr Iterator begin() const noexcept
Return an object that iterates over all 1 bits (++ and * only allowed when != end()).
static constexpr IntBitSet Singleton(unsigned i) noexcept
Construct a bitset with the singleton i.
constexpr bool operator[](unsigned pos) const noexcept
Retrieve a bit at the given position.
I m_val
Integer whose bits represent this bitset.
constexpr IntBitSet & operator&=(const IntBitSet &a) noexcept
Set this object's bits to be the binary OR between respective bits from this and a.
constexpr void Set(unsigned pos, bool val) noexcept
Set a bit to the specified value.
constexpr IntBitSet(std::initializer_list< unsigned > ilist) noexcept
Construct from a list of values.
Dummy type to return using end().
constexpr IteratorEnd(const IteratorEnd &)=default
constexpr IteratorEnd()=default
Iterator type returned by begin(), which efficiently iterates all 1 positions.
constexpr Iterator(const std::array< I, N > &ref) noexcept
I m_val
The remaining bits of (*m_ptr)[m_idx].
constexpr Iterator(const Iterator &) noexcept=default
constexpr unsigned operator*() const noexcept
Get the current bit position (only if != IteratorEnd).
constexpr Iterator & operator=(const Iterator &) noexcept=default
const std::array< I, N > * m_ptr
Pointer to array to fetch bits from.
unsigned m_pos
The last reported position.
Iterator()=delete
Do not allow external code to construct an Iterator.
unsigned m_idx
The index in *m_ptr currently being iterated over.
friend constexpr bool operator==(const Iterator &a, const IteratorEnd &) noexcept
Test whether we are done (can only compare with IteratorEnd).
constexpr Iterator & operator++() noexcept
Progress to the next 1 bit (only if != IteratorEnd).
A bitset implementation backed by N integers of type I.
constexpr bool IsSubsetOf(const MultiIntBitSet &a) const noexcept
Check if bitset a is a subset of bitset b (= every 1 bit in a is also in b).
bool constexpr None() const noexcept
Check if all bits are 0.
Iterator constexpr begin() const noexcept
Return an object that iterates over all 1 bits (++ and * only allowed when != end()).
std::array< I, N > m_val
Array whose member integers store the bits of the set.
IteratorEnd constexpr end() const noexcept
Return a dummy object to compare Iterators with.
constexpr bool IsSupersetOf(const MultiIntBitSet &a) const noexcept
Check if bitset a is a superset of bitset b (= every 1 bit in b is also in a).
static constexpr MultiIntBitSet Fill(unsigned count) noexcept
Construct a bitset with bits 0..count-1 (inclusive) set to 1.
void constexpr Set(unsigned pos) noexcept
Set a bit to 1.
unsigned constexpr First() const noexcept
Find the first element (requires Any()).
unsigned constexpr Count() const noexcept
Compute the number of 1 bits in the bitset.
void constexpr Set(unsigned pos, bool val) noexcept
Set a bit to the specified value.
static constexpr unsigned Size() noexcept
Return the number of bits that this object holds.
unsigned constexpr Last() const noexcept
Find the last element (requires Any()).
constexpr MultiIntBitSet(const MultiIntBitSet &) noexcept=default
Copy construct a bitset.
constexpr MultiIntBitSet() noexcept
Construct an all-zero bitset.
constexpr MultiIntBitSet & operator|=(const MultiIntBitSet &a) noexcept
Set this object's bits to be the binary OR between respective bits from this and a.
bool constexpr operator[](unsigned pos) const noexcept
Retrieve a bit at the given position.
friend constexpr MultiIntBitSet operator^(const MultiIntBitSet &a, const MultiIntBitSet &b) noexcept
Return an object with the binary XOR between respective bits from a and b.
static constexpr unsigned MAX_SIZE
Number of elements this set type supports.
friend constexpr MultiIntBitSet operator&(const MultiIntBitSet &a, const MultiIntBitSet &b) noexcept
Return an object with the binary AND between respective bits from a and b.
friend constexpr void swap(MultiIntBitSet &a, MultiIntBitSet &b) noexcept
Swap two bitsets.
friend constexpr MultiIntBitSet operator|(const MultiIntBitSet &a, const MultiIntBitSet &b) noexcept
Return an object with the binary OR between respective bits from a and b.
constexpr bool Overlaps(const MultiIntBitSet &a) const noexcept
Check whether the intersection between two sets is non-empty.
constexpr MultiIntBitSet & operator=(const MultiIntBitSet &) noexcept=default
Copy assign a bitset.
constexpr MultiIntBitSet & operator-=(const MultiIntBitSet &a) noexcept
Set this object's bits to be the binary AND NOT between respective bits from this and a.
constexpr MultiIntBitSet & operator^=(const MultiIntBitSet &a) noexcept
Set this object's bits to be the binary XOR between respective bits from this and a.
friend constexpr bool operator==(const MultiIntBitSet &a, const MultiIntBitSet &b) noexcept=default
Check if bitset a and bitset b are identical.
constexpr MultiIntBitSet & operator&=(const MultiIntBitSet &a) noexcept
Set this object's bits to be the binary AND between respective bits from this and a.
constexpr MultiIntBitSet & operator=(std::initializer_list< unsigned > ilist) noexcept
Set a bitset to a list of values.
constexpr MultiIntBitSet(std::initializer_list< unsigned > ilist) noexcept
Construct a bitset from a list of values.
friend constexpr MultiIntBitSet operator-(const MultiIntBitSet &a, const MultiIntBitSet &b) noexcept
Return an object with the binary AND NOT between respective bits from a and b.
static constexpr MultiIntBitSet Singleton(unsigned pos) noexcept
Construct a bitset with the singleton pos.
void constexpr Reset(unsigned pos) noexcept
Set a bit to 0.
static constexpr unsigned LIMB_BITS
The number of bits per integer.
bool constexpr Any() const noexcept
Check if any bits are 1.
unsigned constexpr PopCount(I v)
Count the number of bits set in an unsigned integer type.