Bitcoin Core 31.99.0
P2P Digital Currency
bitset.h
Go to the documentation of this file.
1// Copyright (c) The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#ifndef BITCOIN_UTIL_BITSET_H
6#define BITCOIN_UTIL_BITSET_H
7
8#include <util/check.h>
9#include <util/overflow.h>
10
11#include <array>
12#include <bit>
13#include <cstdint>
14#include <limits>
15#include <type_traits>
16
17/* This file provides data types similar to std::bitset, but adds the following functionality:
18 *
19 * - Efficient iteration over all set bits (compatible with range-based for loops).
20 * - Efficient search for the first and last set bit (First() and Last()).
21 * - Efficient set subtraction: (a - b) implements "a and not b".
22 * - Efficient non-strict subset/superset testing: IsSubsetOf() and IsSupersetOf().
23 * - Efficient set overlap testing: a.Overlaps(b)
24 * - Efficient construction of set containing 0..N-1 (S::Fill).
25 * - Efficient construction of a single set (S::Singleton).
26 * - Construction from initializer lists.
27 *
28 * Other differences:
29 * - BitSet<N> is a bitset that supports at least N elements, but may support more (Size() reports
30 * the actual number). Because the actual number is unpredictable, there are no operations that
31 * affect all positions (like std::bitset's operator~, flip(), or all()).
32 * - Various other unimplemented features.
33 */
34
35namespace bitset_detail {
36
38template<typename I>
39unsigned inline constexpr PopCount(I v)
40{
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;
43 // Algorithms from https://en.wikipedia.org/wiki/Hamming_weight#Efficient_implementation.
44 // These seem to be faster than std::popcount when compiling for non-SSE4 on x86_64.
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;
51 return v & 0x3f;
52 } else {
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;
58 }
59}
60
62template<typename I>
64{
65 // Only binary, unsigned, integer, types allowed.
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;
72 IntBitSet(I val) noexcept : m_val{val} {}
75 {
76 friend class IntBitSet;
77 constexpr IteratorEnd() = default;
78 public:
79 constexpr IteratorEnd(const IteratorEnd&) = default;
80 };
83 {
84 friend class IntBitSet;
86 unsigned m_pos;
87 constexpr Iterator(I val) noexcept : m_val(val), m_pos(0)
88 {
89 if (m_val != 0) m_pos = std::countr_zero(m_val);
90 }
91 public:
93 Iterator() = delete;
94 // Copying is allowed.
95 constexpr Iterator(const Iterator&) noexcept = default;
96 constexpr Iterator& operator=(const Iterator&) noexcept = default;
98 constexpr friend bool operator==(const Iterator& a, const IteratorEnd&) noexcept
99 {
100 return a.m_val == 0;
101 }
103 constexpr Iterator& operator++() noexcept
104 {
105 Assume(m_val != 0);
106 m_val &= m_val - I{1U};
107 if (m_val != 0) m_pos = std::countr_zero(m_val);
108 return *this;
109 }
111 constexpr unsigned operator*() const noexcept
112 {
113 Assume(m_val != 0);
114 return m_pos;
115 }
116 };
117
118public:
120 constexpr IntBitSet() noexcept : m_val{0} {}
122 constexpr IntBitSet(const IntBitSet&) noexcept = default;
124 constexpr IntBitSet(std::initializer_list<unsigned> ilist) noexcept : m_val(0)
125 {
126 for (auto pos : ilist) Set(pos);
127 }
129 constexpr IntBitSet& operator=(const IntBitSet&) noexcept = default;
131 constexpr IntBitSet& operator=(std::initializer_list<unsigned> ilist) noexcept
132 {
133 m_val = 0;
134 for (auto pos : ilist) Set(pos);
135 return *this;
136 }
138 static constexpr IntBitSet Singleton(unsigned i) noexcept
139 {
140 Assume(i < MAX_SIZE);
141 return IntBitSet(I(1U) << i);
142 }
144 static constexpr IntBitSet Fill(unsigned count) noexcept
145 {
148 if (count) ret.m_val = I(~I{0}) >> (MAX_SIZE - count);
149 return ret;
150 }
152 constexpr void Set(unsigned pos) noexcept
153 {
154 Assume(pos < MAX_SIZE);
155 m_val |= I{1U} << pos;
156 }
158 constexpr void Set(unsigned pos, bool val) noexcept
159 {
160 Assume(pos < MAX_SIZE);
161 m_val = (m_val & ~I(I{1U} << pos)) | (I(val) << pos);
162 }
164 constexpr void Reset(unsigned pos) noexcept
165 {
166 Assume(pos < MAX_SIZE);
167 m_val &= ~I(I{1U} << pos);
168 }
170 constexpr bool operator[](unsigned pos) const noexcept
171 {
172 Assume(pos < MAX_SIZE);
173 return (m_val >> pos) & 1U;
174 }
176 constexpr unsigned Count() const noexcept { return PopCount(m_val); }
178 static constexpr unsigned Size() noexcept { return MAX_SIZE; }
180 constexpr bool None() const noexcept { return m_val == 0; }
182 constexpr bool Any() const noexcept { return !None(); }
184 constexpr Iterator begin() const noexcept { return Iterator(m_val); }
186 constexpr IteratorEnd end() const noexcept { return IteratorEnd(); }
188 constexpr unsigned First() const noexcept
189 {
190 Assume(m_val != 0);
191 return std::countr_zero(m_val);
192 }
194 constexpr unsigned Last() const noexcept
195 {
196 Assume(m_val != 0);
197 return std::bit_width(m_val) - 1;
198 }
200 constexpr IntBitSet& operator|=(const IntBitSet& a) noexcept { m_val |= a.m_val; return *this; }
202 constexpr IntBitSet& operator&=(const IntBitSet& a) noexcept { m_val &= a.m_val; return *this; }
204 constexpr IntBitSet& operator-=(const IntBitSet& a) noexcept { m_val &= ~a.m_val; return *this; }
206 constexpr IntBitSet& operator^=(const IntBitSet& a) noexcept { m_val ^= a.m_val; return *this; }
208 constexpr bool Overlaps(const IntBitSet& a) const noexcept { return m_val & a.m_val; }
210 friend constexpr IntBitSet operator&(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val & b.m_val); }
212 friend constexpr IntBitSet operator|(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val | b.m_val); }
214 friend constexpr IntBitSet operator-(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val & ~b.m_val); }
216 friend constexpr IntBitSet operator^(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val ^ b.m_val); }
218 friend constexpr bool operator==(const IntBitSet& a, const IntBitSet& b) noexcept = default;
220 constexpr bool IsSupersetOf(const IntBitSet& a) const noexcept { return (a.m_val & ~m_val) == 0; }
222 constexpr bool IsSubsetOf(const IntBitSet& a) const noexcept { return (m_val & ~a.m_val) == 0; }
224 friend constexpr void swap(IntBitSet& a, IntBitSet& b) noexcept { std::swap(a.m_val, b.m_val); }
225};
226
228template<typename I, unsigned N>
230{
231 // Only binary, unsigned, integer, types allowed.
232 static_assert(std::is_integral_v<I> && std::is_unsigned_v<I> && std::numeric_limits<I>::radix == 2);
233 // Cannot be empty.
234 static_assert(N > 0);
236 static constexpr unsigned LIMB_BITS = std::numeric_limits<I>::digits;
238 static constexpr unsigned MAX_SIZE = LIMB_BITS * N;
239 // No overflow allowed here.
240 static_assert(MAX_SIZE / LIMB_BITS == N);
242 std::array<I, N> m_val;
245 {
246 friend class MultiIntBitSet;
247 constexpr IteratorEnd() = default;
248 public:
249 constexpr IteratorEnd(const IteratorEnd&) = default;
250 };
253 {
254 friend class MultiIntBitSet;
255 const std::array<I, N>* m_ptr;
257 unsigned m_pos;
258 unsigned m_idx;
259 constexpr Iterator(const std::array<I, N>& ref) noexcept : m_ptr(&ref), m_idx(0)
260 {
261 do {
262 m_val = (*m_ptr)[m_idx];
263 if (m_val) {
264 m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS;
265 break;
266 }
267 ++m_idx;
268 } while(m_idx < N);
269 }
270
271 public:
273 Iterator() = delete;
274 // Copying is allowed.
275 constexpr Iterator(const Iterator&) noexcept = default;
276 constexpr Iterator& operator=(const Iterator&) noexcept = default;
278 friend constexpr bool operator==(const Iterator& a, const IteratorEnd&) noexcept
279 {
280 return a.m_idx == N;
281 }
283 constexpr Iterator& operator++() noexcept
284 {
285 Assume(m_idx < N);
286 m_val &= m_val - I{1U};
287 if (m_val == 0) {
288 while (true) {
289 ++m_idx;
290 if (m_idx == N) break;
291 m_val = (*m_ptr)[m_idx];
292 if (m_val) {
293 m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS;
294 break;
295 }
296 }
297 } else {
298 m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS;
299 }
300 return *this;
301 }
303 constexpr unsigned operator*() const noexcept
304 {
305 Assume(m_idx < N);
306 return m_pos;
307 }
308 };
309
310public:
312 constexpr MultiIntBitSet() noexcept : m_val{} {}
314 constexpr MultiIntBitSet(const MultiIntBitSet&) noexcept = default;
316 constexpr MultiIntBitSet& operator=(const MultiIntBitSet&) noexcept = default;
318 void constexpr Set(unsigned pos) noexcept
319 {
320 Assume(pos < MAX_SIZE);
321 m_val[pos / LIMB_BITS] |= I{1U} << (pos % LIMB_BITS);
322 }
324 void constexpr Set(unsigned pos, bool val) noexcept
325 {
326 Assume(pos < MAX_SIZE);
327 m_val[pos / LIMB_BITS] = (m_val[pos / LIMB_BITS] & ~I(I{1U} << (pos % LIMB_BITS))) |
328 (I{val} << (pos % LIMB_BITS));
329 }
331 constexpr MultiIntBitSet(std::initializer_list<unsigned> ilist) noexcept : m_val{}
332 {
333 for (auto pos : ilist) Set(pos);
334 }
336 constexpr MultiIntBitSet& operator=(std::initializer_list<unsigned> ilist) noexcept
337 {
338 m_val.fill(0);
339 for (auto pos : ilist) Set(pos);
340 return *this;
341 }
343 void constexpr Reset(unsigned pos) noexcept
344 {
345 Assume(pos < MAX_SIZE);
346 m_val[pos / LIMB_BITS] &= ~I(I{1U} << (pos % LIMB_BITS));
347 }
349 bool constexpr operator[](unsigned pos) const noexcept
350 {
351 Assume(pos < MAX_SIZE);
352 return (m_val[pos / LIMB_BITS] >> (pos % LIMB_BITS)) & 1U;
353 }
355 static constexpr MultiIntBitSet Singleton(unsigned pos) noexcept
356 {
357 Assume(pos < MAX_SIZE);
359 ret.m_val[pos / LIMB_BITS] = I{1U} << (pos % LIMB_BITS);
360 return ret;
361 }
363 static constexpr MultiIntBitSet Fill(unsigned count) noexcept
364 {
367 if (count) {
368 unsigned i = 0;
369 while (count > LIMB_BITS) {
370 ret.m_val[i++] = I(~I{0});
371 count -= LIMB_BITS;
372 }
373 ret.m_val[i] = I(~I{0}) >> (LIMB_BITS - count);
374 }
375 return ret;
376 }
378 static constexpr unsigned Size() noexcept { return MAX_SIZE; }
380 unsigned constexpr Count() const noexcept
381 {
382 unsigned ret{0};
383 for (I v : m_val) ret += PopCount(v);
384 return ret;
385 }
387 bool constexpr None() const noexcept
388 {
389 for (auto v : m_val) {
390 if (v != 0) return false;
391 }
392 return true;
393 }
395 bool constexpr Any() const noexcept { return !None(); }
397 Iterator constexpr begin() const noexcept { return Iterator(m_val); }
399 IteratorEnd constexpr end() const noexcept { return IteratorEnd(); }
401 unsigned constexpr First() const noexcept
402 {
403 unsigned p = 0;
404 while (m_val[p] == 0) {
405 ++p;
406 Assume(p < N);
407 }
408 return std::countr_zero(m_val[p]) + p * LIMB_BITS;
409 }
411 unsigned constexpr Last() const noexcept
412 {
413 unsigned p = N - 1;
414 while (m_val[p] == 0) {
415 Assume(p > 0);
416 --p;
417 }
418 return std::bit_width(m_val[p]) - 1 + p * LIMB_BITS;
419 }
421 constexpr MultiIntBitSet& operator|=(const MultiIntBitSet& a) noexcept
422 {
423 for (unsigned i = 0; i < N; ++i) {
424 m_val[i] |= a.m_val[i];
425 }
426 return *this;
427 }
429 constexpr MultiIntBitSet& operator&=(const MultiIntBitSet& a) noexcept
430 {
431 for (unsigned i = 0; i < N; ++i) {
432 m_val[i] &= a.m_val[i];
433 }
434 return *this;
435 }
437 constexpr MultiIntBitSet& operator-=(const MultiIntBitSet& a) noexcept
438 {
439 for (unsigned i = 0; i < N; ++i) {
440 m_val[i] &= ~a.m_val[i];
441 }
442 return *this;
443 }
445 constexpr MultiIntBitSet& operator^=(const MultiIntBitSet& a) noexcept
446 {
447 for (unsigned i = 0; i < N; ++i) {
448 m_val[i] ^= a.m_val[i];
449 }
450 return *this;
451 }
453 constexpr bool Overlaps(const MultiIntBitSet& a) const noexcept
454 {
455 for (unsigned i = 0; i < N; ++i) {
456 if (m_val[i] & a.m_val[i]) return true;
457 }
458 return false;
459 }
461 friend constexpr MultiIntBitSet operator&(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept
462 {
464 for (unsigned i = 0; i < N; ++i) {
465 r.m_val[i] = a.m_val[i] & b.m_val[i];
466 }
467 return r;
468 }
470 friend constexpr MultiIntBitSet operator|(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept
471 {
473 for (unsigned i = 0; i < N; ++i) {
474 r.m_val[i] = a.m_val[i] | b.m_val[i];
475 }
476 return r;
477 }
479 friend constexpr MultiIntBitSet operator-(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept
480 {
482 for (unsigned i = 0; i < N; ++i) {
483 r.m_val[i] = a.m_val[i] & ~b.m_val[i];
484 }
485 return r;
486 }
488 friend constexpr MultiIntBitSet operator^(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept
489 {
491 for (unsigned i = 0; i < N; ++i) {
492 r.m_val[i] = a.m_val[i] ^ b.m_val[i];
493 }
494 return r;
495 }
497 constexpr bool IsSupersetOf(const MultiIntBitSet& a) const noexcept
498 {
499 for (unsigned i = 0; i < N; ++i) {
500 if (a.m_val[i] & ~m_val[i]) return false;
501 }
502 return true;
503 }
505 constexpr bool IsSubsetOf(const MultiIntBitSet& a) const noexcept
506 {
507 for (unsigned i = 0; i < N; ++i) {
508 if (m_val[i] & ~a.m_val[i]) return false;
509 }
510 return true;
511 }
513 friend constexpr bool operator==(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept = default;
515 friend constexpr void swap(MultiIntBitSet& a, MultiIntBitSet& b) noexcept { std::swap(a.m_val, b.m_val); }
516};
517
518} // namespace bitset_detail
519
520// BitSet dispatches to IntBitSet or MultiIntBitSet as appropriate for the requested minimum number
521// of bits. Use IntBitSet up to 32-bit, or up to 64-bit on 64-bit platforms; above that, use a
522// MultiIntBitSet of size_t.
523template<unsigned BITS>
524using BitSet = std::conditional_t<(BITS <= 32), bitset_detail::IntBitSet<uint32_t>,
525 std::conditional_t<(BITS <= std::numeric_limits<size_t>::digits), bitset_detail::IntBitSet<size_t>,
526 bitset_detail::MultiIntBitSet<size_t, CeilDiv(BITS, size_t{std::numeric_limits<size_t>::digits})>>>;
527
528#endif // BITCOIN_UTIL_BITSET_H
int ret
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
Definition: bitset.h:526
#define Assume(val)
Assume is the identity function.
Definition: check.h:125
Dummy type to return using end().
Definition: bitset.h:75
constexpr IteratorEnd(const IteratorEnd &)=default
Iterator type returned by begin(), which efficiently iterates all 1 positions.
Definition: bitset.h:83
Iterator()=delete
Do not allow external code to construct an Iterator.
I m_val
The original integer's remaining bits.
Definition: bitset.h:85
constexpr friend bool operator==(const Iterator &a, const IteratorEnd &) noexcept
Test whether we are done (can only compare with IteratorEnd).
Definition: bitset.h:98
constexpr unsigned operator*() const noexcept
Get the current bit position (only if != IteratorEnd).
Definition: bitset.h:111
constexpr Iterator(const Iterator &) noexcept=default
constexpr Iterator & operator++() noexcept
Progress to the next 1 bit (only if != IteratorEnd).
Definition: bitset.h:103
constexpr Iterator(I val) noexcept
Last reported 1 position (if m_pos != 0).
Definition: bitset.h:87
constexpr Iterator & operator=(const Iterator &) noexcept=default
A bitset implementation backed by a single integer of type I.
Definition: bitset.h:64
constexpr void Reset(unsigned pos) noexcept
Set a bit to 0.
Definition: bitset.h:164
IntBitSet(I val) noexcept
Internal constructor with a given integer as contents.
Definition: bitset.h:72
constexpr IteratorEnd end() const noexcept
Return a dummy object to compare Iterators with.
Definition: bitset.h:186
constexpr IntBitSet & operator=(std::initializer_list< unsigned > ilist) noexcept
Assign from a list of positions (which will be made true, all others false).
Definition: bitset.h:131
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.
Definition: bitset.h:214
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.
Definition: bitset.h:210
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).
Definition: bitset.h:222
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.
Definition: bitset.h:212
static constexpr IntBitSet Fill(unsigned count) noexcept
Construct a bitset with bits 0..count-1 (inclusive) set to 1.
Definition: bitset.h:144
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.
Definition: bitset.h:204
constexpr unsigned First() const noexcept
Find the first element (requires Any()).
Definition: bitset.h:188
constexpr bool Any() const noexcept
Check if any bits are 1.
Definition: bitset.h:182
constexpr IntBitSet(const IntBitSet &) noexcept=default
Copy construct a bitset.
friend constexpr void swap(IntBitSet &a, IntBitSet &b) noexcept
Swap two bitsets.
Definition: bitset.h:224
constexpr IntBitSet & operator|=(const IntBitSet &a) noexcept
Set this object's bits to be the binary AND between respective bits from this and a.
Definition: bitset.h:200
constexpr bool None() const noexcept
Check if all bits are 0.
Definition: bitset.h:180
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).
Definition: bitset.h:220
constexpr IntBitSet & operator^=(const IntBitSet &a) noexcept
Set this object's bits to be the binary XOR between respective bits from this as a.
Definition: bitset.h:206
static constexpr unsigned MAX_SIZE
The maximum number of bits this bitset supports.
Definition: bitset.h:68
constexpr unsigned Last() const noexcept
Find the last element (requires Any()).
Definition: bitset.h:194
static constexpr unsigned Size() noexcept
Return the number of bits that this object holds.
Definition: bitset.h:178
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.
Definition: bitset.h:216
constexpr void Set(unsigned pos) noexcept
Set a bit to 1.
Definition: bitset.h:152
constexpr IntBitSet() noexcept
Construct an all-zero bitset.
Definition: bitset.h:120
constexpr bool Overlaps(const IntBitSet &a) const noexcept
Check if the intersection between two sets is non-empty.
Definition: bitset.h:208
constexpr unsigned Count() const noexcept
Compute the number of 1 bits in the bitset.
Definition: bitset.h:176
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()).
Definition: bitset.h:184
static constexpr IntBitSet Singleton(unsigned i) noexcept
Construct a bitset with the singleton i.
Definition: bitset.h:138
constexpr bool operator[](unsigned pos) const noexcept
Retrieve a bit at the given position.
Definition: bitset.h:170
I m_val
Integer whose bits represent this bitset.
Definition: bitset.h:70
constexpr IntBitSet & operator&=(const IntBitSet &a) noexcept
Set this object's bits to be the binary OR between respective bits from this and a.
Definition: bitset.h:202
constexpr void Set(unsigned pos, bool val) noexcept
Set a bit to the specified value.
Definition: bitset.h:158
constexpr IntBitSet(std::initializer_list< unsigned > ilist) noexcept
Construct from a list of values.
Definition: bitset.h:124
Dummy type to return using end().
Definition: bitset.h:245
constexpr IteratorEnd(const IteratorEnd &)=default
Iterator type returned by begin(), which efficiently iterates all 1 positions.
Definition: bitset.h:253
constexpr Iterator(const std::array< I, N > &ref) noexcept
Definition: bitset.h:259
I m_val
The remaining bits of (*m_ptr)[m_idx].
Definition: bitset.h:256
constexpr Iterator(const Iterator &) noexcept=default
constexpr unsigned operator*() const noexcept
Get the current bit position (only if != IteratorEnd).
Definition: bitset.h:303
constexpr Iterator & operator=(const Iterator &) noexcept=default
const std::array< I, N > * m_ptr
Pointer to array to fetch bits from.
Definition: bitset.h:255
unsigned m_pos
The last reported position.
Definition: bitset.h:257
Iterator()=delete
Do not allow external code to construct an Iterator.
unsigned m_idx
The index in *m_ptr currently being iterated over.
Definition: bitset.h:258
friend constexpr bool operator==(const Iterator &a, const IteratorEnd &) noexcept
Test whether we are done (can only compare with IteratorEnd).
Definition: bitset.h:278
constexpr Iterator & operator++() noexcept
Progress to the next 1 bit (only if != IteratorEnd).
Definition: bitset.h:283
A bitset implementation backed by N integers of type I.
Definition: bitset.h:230
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).
Definition: bitset.h:505
bool constexpr None() const noexcept
Check if all bits are 0.
Definition: bitset.h:387
Iterator constexpr begin() const noexcept
Return an object that iterates over all 1 bits (++ and * only allowed when != end()).
Definition: bitset.h:397
std::array< I, N > m_val
Array whose member integers store the bits of the set.
Definition: bitset.h:242
IteratorEnd constexpr end() const noexcept
Return a dummy object to compare Iterators with.
Definition: bitset.h:399
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).
Definition: bitset.h:497
static constexpr MultiIntBitSet Fill(unsigned count) noexcept
Construct a bitset with bits 0..count-1 (inclusive) set to 1.
Definition: bitset.h:363
void constexpr Set(unsigned pos) noexcept
Set a bit to 1.
Definition: bitset.h:318
unsigned constexpr First() const noexcept
Find the first element (requires Any()).
Definition: bitset.h:401
unsigned constexpr Count() const noexcept
Compute the number of 1 bits in the bitset.
Definition: bitset.h:380
void constexpr Set(unsigned pos, bool val) noexcept
Set a bit to the specified value.
Definition: bitset.h:324
static constexpr unsigned Size() noexcept
Return the number of bits that this object holds.
Definition: bitset.h:378
unsigned constexpr Last() const noexcept
Find the last element (requires Any()).
Definition: bitset.h:411
constexpr MultiIntBitSet(const MultiIntBitSet &) noexcept=default
Copy construct a bitset.
constexpr MultiIntBitSet() noexcept
Construct an all-zero bitset.
Definition: bitset.h:312
constexpr MultiIntBitSet & operator|=(const MultiIntBitSet &a) noexcept
Set this object's bits to be the binary OR between respective bits from this and a.
Definition: bitset.h:421
bool constexpr operator[](unsigned pos) const noexcept
Retrieve a bit at the given position.
Definition: bitset.h:349
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.
Definition: bitset.h:488
static constexpr unsigned MAX_SIZE
Number of elements this set type supports.
Definition: bitset.h:238
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.
Definition: bitset.h:461
friend constexpr void swap(MultiIntBitSet &a, MultiIntBitSet &b) noexcept
Swap two bitsets.
Definition: bitset.h:515
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.
Definition: bitset.h:470
constexpr bool Overlaps(const MultiIntBitSet &a) const noexcept
Check whether the intersection between two sets is non-empty.
Definition: bitset.h:453
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.
Definition: bitset.h:437
constexpr MultiIntBitSet & operator^=(const MultiIntBitSet &a) noexcept
Set this object's bits to be the binary XOR between respective bits from this and a.
Definition: bitset.h:445
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.
Definition: bitset.h:429
constexpr MultiIntBitSet & operator=(std::initializer_list< unsigned > ilist) noexcept
Set a bitset to a list of values.
Definition: bitset.h:336
constexpr MultiIntBitSet(std::initializer_list< unsigned > ilist) noexcept
Construct a bitset from a list of values.
Definition: bitset.h:331
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.
Definition: bitset.h:479
static constexpr MultiIntBitSet Singleton(unsigned pos) noexcept
Construct a bitset with the singleton pos.
Definition: bitset.h:355
void constexpr Reset(unsigned pos) noexcept
Set a bit to 0.
Definition: bitset.h:343
static constexpr unsigned LIMB_BITS
The number of bits per integer.
Definition: bitset.h:236
bool constexpr Any() const noexcept
Check if any bits are 1.
Definition: bitset.h:395
unsigned constexpr PopCount(I v)
Count the number of bits set in an unsigned integer type.
Definition: bitset.h:39
constexpr auto CeilDiv(const Dividend dividend, const Divisor divisor)
Integer ceiling division (for unsigned values).
Definition: overflow.h:70
static int count