5#ifndef BITCOIN_UTIL_BITSET_H
6#define BITCOIN_UTIL_BITSET_H
41 static_assert(std::is_integral_v<I> && std::is_unsigned_v<I> && std::numeric_limits<I>::radix == 2);
42 constexpr auto BITS = std::numeric_limits<I>::digits;
45 if constexpr (BITS <= 32) {
46 v -= (v >> 1) & 0x55555555;
47 v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
48 v = (v + (v >> 4)) & 0x0f0f0f0f;
49 if constexpr (BITS > 8) v += v >> 8;
50 if constexpr (BITS > 16) v += v >> 16;
53 static_assert(BITS <= 64);
54 v -= (v >> 1) & 0x5555555555555555;
55 v = (v & 0x3333333333333333) + ((v >> 2) & 0x3333333333333333);
56 v = (v + (v >> 4)) & 0x0f0f0f0f0f0f0f0f;
57 return (v * uint64_t{0x0101010101010101}) >> 56;
66 static_assert(std::is_integral_v<I> && std::is_unsigned_v<I> && std::numeric_limits<I>::radix == 2);
68 static constexpr unsigned MAX_SIZE = std::numeric_limits<I>::digits;
126 for (
auto pos : ilist)
Set(pos);
134 for (
auto pos : ilist)
Set(pos);
152 constexpr void Set(
unsigned pos)
noexcept
155 m_val |= I{1U} << pos;
158 constexpr void Set(
unsigned pos,
bool val)
noexcept
161 m_val = (
m_val & ~I(I{1U} << pos)) | (I(val) << pos);
164 constexpr void Reset(
unsigned pos)
noexcept
167 m_val &= ~I(I{1U} << pos);
173 return (
m_val >> pos) & 1U;
180 constexpr bool None() const noexcept {
return m_val == 0; }
182 constexpr bool Any() const noexcept {
return !
None(); }
188 constexpr unsigned First() const noexcept
191 return std::countr_zero(
m_val);
194 constexpr unsigned Last() const noexcept
197 return std::bit_width(
m_val) - 1;
228template<
typename I,
unsigned N>
232 static_assert(std::is_integral_v<I> && std::is_unsigned_v<I> && std::numeric_limits<I>::radix == 2);
234 static_assert(N > 0);
236 static constexpr unsigned LIMB_BITS = std::numeric_limits<I>::digits;
290 if (
m_idx == N)
break;
318 void constexpr Set(
unsigned pos)
noexcept
324 void constexpr Set(
unsigned pos,
bool val)
noexcept
333 for (
auto pos : ilist)
Set(pos);
339 for (
auto pos : ilist)
Set(pos);
343 void constexpr Reset(
unsigned pos)
noexcept
370 ret.m_val[i++] = I(~I{0});
380 unsigned constexpr Count() const noexcept
387 bool constexpr None() const noexcept
389 for (
auto v :
m_val) {
390 if (v != 0)
return false;
395 bool constexpr Any() const noexcept {
return !
None(); }
401 unsigned constexpr First() const noexcept
404 while (
m_val[p] == 0) {
411 unsigned constexpr Last() const noexcept
414 while (
m_val[p] == 0) {
423 for (
unsigned i = 0; i < N; ++i) {
424 m_val[i] |= a.m_val[i];
431 for (
unsigned i = 0; i < N; ++i) {
432 m_val[i] &= a.m_val[i];
439 for (
unsigned i = 0; i < N; ++i) {
440 m_val[i] &= ~a.m_val[i];
447 for (
unsigned i = 0; i < N; ++i) {
448 m_val[i] ^= a.m_val[i];
455 for (
unsigned i = 0; i < N; ++i) {
456 if (
m_val[i] & a.m_val[i])
return true;
464 for (
unsigned i = 0; i < N; ++i) {
465 r.
m_val[i] = a.m_val[i] & b.m_val[i];
473 for (
unsigned i = 0; i < N; ++i) {
474 r.
m_val[i] = a.m_val[i] | b.m_val[i];
482 for (
unsigned i = 0; i < N; ++i) {
483 r.
m_val[i] = a.m_val[i] & ~b.m_val[i];
491 for (
unsigned i = 0; i < N; ++i) {
492 r.
m_val[i] = a.m_val[i] ^ b.m_val[i];
499 for (
unsigned i = 0; i < N; ++i) {
500 if (a.m_val[i] & ~
m_val[i])
return false;
507 for (
unsigned i = 0; i < N; ++i) {
508 if (
m_val[i] & ~a.m_val[i])
return false;
523template<
unsigned BITS>
524using 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, CeilDiv(BITS, size_t{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.
constexpr auto CeilDiv(const Dividend dividend, const Divisor divisor)
Integer ceiling division (for unsigned values).