/tmp/bitcoin/src/util/bitset.h
Line | Count | Source |
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 | | |
35 | | namespace bitset_detail { |
36 | | |
37 | | /** Count the number of bits set in an unsigned integer type. */ |
38 | | template<typename I> |
39 | | unsigned inline constexpr PopCount(I v) |
40 | 345M | { |
41 | 345M | static_assert(std::is_integral_v<I> && std::is_unsigned_v<I> && std::numeric_limits<I>::radix == 2); |
42 | 345M | 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 | 345M | if constexpr (BITS <= 32) { |
46 | 314M | v -= (v >> 1) & 0x55555555; |
47 | 314M | v = (v & 0x33333333) + ((v >> 2) & 0x33333333); |
48 | 314M | v = (v + (v >> 4)) & 0x0f0f0f0f; |
49 | 314M | if constexpr (BITS > 8) v += v >> 8; |
50 | 314M | if constexpr (BITS > 16) v += v >> 16; |
51 | 314M | return v & 0x3f; |
52 | 314M | } else { |
53 | 30.6M | static_assert(BITS <= 64); |
54 | 30.6M | v -= (v >> 1) & 0x5555555555555555; |
55 | 30.6M | v = (v & 0x3333333333333333) + ((v >> 2) & 0x3333333333333333); |
56 | 30.6M | v = (v + (v >> 4)) & 0x0f0f0f0f0f0f0f0f; |
57 | 30.6M | return (v * uint64_t{0x0101010101010101}) >> 56; |
58 | 30.6M | } |
59 | 345M | } unsigned int bitset_detail::PopCount<unsigned long>(unsigned long) Line | Count | Source | 40 | 30.6M | { | 41 | 30.6M | static_assert(std::is_integral_v<I> && std::is_unsigned_v<I> && std::numeric_limits<I>::radix == 2); | 42 | 30.6M | 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 | 30.6M | } else { | 53 | 30.6M | static_assert(BITS <= 64); | 54 | 30.6M | v -= (v >> 1) & 0x5555555555555555; | 55 | 30.6M | v = (v & 0x3333333333333333) + ((v >> 2) & 0x3333333333333333); | 56 | 30.6M | v = (v + (v >> 4)) & 0x0f0f0f0f0f0f0f0f; | 57 | 30.6M | return (v * uint64_t{0x0101010101010101}) >> 56; | 58 | 30.6M | } | 59 | 30.6M | } |
unsigned int bitset_detail::PopCount<unsigned int>(unsigned int) Line | Count | Source | 40 | 62.8M | { | 41 | 62.8M | static_assert(std::is_integral_v<I> && std::is_unsigned_v<I> && std::numeric_limits<I>::radix == 2); | 42 | 62.8M | 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 | 62.8M | if constexpr (BITS <= 32) { | 46 | 62.8M | v -= (v >> 1) & 0x55555555; | 47 | 62.8M | v = (v & 0x33333333) + ((v >> 2) & 0x33333333); | 48 | 62.8M | v = (v + (v >> 4)) & 0x0f0f0f0f; | 49 | 62.8M | if constexpr (BITS > 8) v += v >> 8; | 50 | 62.8M | if constexpr (BITS > 16) v += v >> 16; | 51 | 62.8M | 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 | 62.8M | } |
unsigned int bitset_detail::PopCount<unsigned char>(unsigned char) Line | Count | Source | 40 | 251M | { | 41 | 251M | static_assert(std::is_integral_v<I> && std::is_unsigned_v<I> && std::numeric_limits<I>::radix == 2); | 42 | 251M | 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 | 251M | if constexpr (BITS <= 32) { | 46 | 251M | v -= (v >> 1) & 0x55555555; | 47 | 251M | v = (v & 0x33333333) + ((v >> 2) & 0x33333333); | 48 | 251M | v = (v + (v >> 4)) & 0x0f0f0f0f; | 49 | | if constexpr (BITS > 8) v += v >> 8; | 50 | | if constexpr (BITS > 16) v += v >> 16; | 51 | 251M | 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 | 251M | } |
|
60 | | |
61 | | /** A bitset implementation backed by a single integer of type I. */ |
62 | | template<typename I> |
63 | | class IntBitSet |
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); |
67 | | /** The maximum number of bits this bitset supports. */ |
68 | | static constexpr unsigned MAX_SIZE = std::numeric_limits<I>::digits; |
69 | | /** Integer whose bits represent this bitset. */ |
70 | | I m_val; |
71 | | /** Internal constructor with a given integer as contents. */ |
72 | 32.0M | IntBitSet(I val) noexcept : m_val{val} {}bitset_detail::IntBitSet<unsigned long>::IntBitSet(unsigned long) Line | Count | Source | 72 | 26.6M | IntBitSet(I val) noexcept : m_val{val} {} |
bitset_detail::IntBitSet<unsigned int>::IntBitSet(unsigned int) Line | Count | Source | 72 | 5.38M | IntBitSet(I val) noexcept : m_val{val} {} |
|
73 | | /** Dummy type to return using end(). Only used for comparing with Iterator. */ |
74 | | class IteratorEnd |
75 | | { |
76 | | friend class IntBitSet; |
77 | | constexpr IteratorEnd() = default; |
78 | | public: |
79 | | constexpr IteratorEnd(const IteratorEnd&) = default; |
80 | | }; |
81 | | /** Iterator type returned by begin(), which efficiently iterates all 1 positions. */ |
82 | | class Iterator |
83 | | { |
84 | | friend class IntBitSet; |
85 | | I m_val; /**< The original integer's remaining bits. */ |
86 | | unsigned m_pos; /** Last reported 1 position (if m_pos != 0). */ |
87 | 65.6M | constexpr Iterator(I val) noexcept : m_val(val), m_pos(0) |
88 | 65.6M | { |
89 | 65.6M | if (m_val != 0) m_pos = std::countr_zero(m_val); |
90 | 65.6M | } bitset_detail::IntBitSet<unsigned long>::Iterator::Iterator(unsigned long) Line | Count | Source | 87 | 54.7M | constexpr Iterator(I val) noexcept : m_val(val), m_pos(0) | 88 | 54.7M | { | 89 | 54.7M | if (m_val != 0) m_pos = std::countr_zero(m_val); | 90 | 54.7M | } |
bitset_detail::IntBitSet<unsigned int>::Iterator::Iterator(unsigned int) Line | Count | Source | 87 | 10.9M | constexpr Iterator(I val) noexcept : m_val(val), m_pos(0) | 88 | 10.9M | { | 89 | 10.9M | if (m_val != 0) m_pos = std::countr_zero(m_val); | 90 | 10.9M | } |
|
91 | | public: |
92 | | /** Do not allow external code to construct an Iterator. */ |
93 | | Iterator() = delete; |
94 | | // Copying is allowed. |
95 | | constexpr Iterator(const Iterator&) noexcept = default; |
96 | | constexpr Iterator& operator=(const Iterator&) noexcept = default; |
97 | | /** Test whether we are done (can only compare with IteratorEnd). */ |
98 | | constexpr friend bool operator==(const Iterator& a, const IteratorEnd&) noexcept |
99 | 204M | { |
100 | 204M | return a.m_val == 0; |
101 | 204M | } bitset_detail::operator==(bitset_detail::IntBitSet<unsigned long>::Iterator const&, bitset_detail::IntBitSet<unsigned long>::IteratorEnd const&) Line | Count | Source | 99 | 172M | { | 100 | 172M | return a.m_val == 0; | 101 | 172M | } |
bitset_detail::operator==(bitset_detail::IntBitSet<unsigned int>::Iterator const&, bitset_detail::IntBitSet<unsigned int>::IteratorEnd const&) Line | Count | Source | 99 | 31.5M | { | 100 | 31.5M | return a.m_val == 0; | 101 | 31.5M | } |
|
102 | | /** Progress to the next 1 bit (only if != IteratorEnd). */ |
103 | | constexpr Iterator& operator++() noexcept |
104 | 139M | { |
105 | 139M | Assume(m_val != 0); |
106 | 139M | m_val &= m_val - I{1U}; |
107 | 139M | if (m_val != 0) m_pos = std::countr_zero(m_val); |
108 | 139M | return *this; |
109 | 139M | } bitset_detail::IntBitSet<unsigned long>::Iterator::operator++() Line | Count | Source | 104 | 118M | { | 105 | 118M | Assume(m_val != 0); | 106 | 118M | m_val &= m_val - I{1U}; | 107 | 118M | if (m_val != 0) m_pos = std::countr_zero(m_val); | 108 | 118M | return *this; | 109 | 118M | } |
bitset_detail::IntBitSet<unsigned int>::Iterator::operator++() Line | Count | Source | 104 | 20.7M | { | 105 | 20.7M | Assume(m_val != 0); | 106 | 20.7M | m_val &= m_val - I{1U}; | 107 | 20.7M | if (m_val != 0) m_pos = std::countr_zero(m_val); | 108 | 20.7M | return *this; | 109 | 20.7M | } |
|
110 | | /** Get the current bit position (only if != IteratorEnd). */ |
111 | | constexpr unsigned operator*() const noexcept |
112 | 144M | { |
113 | 144M | Assume(m_val != 0); |
114 | 144M | return m_pos; |
115 | 144M | } bitset_detail::IntBitSet<unsigned long>::Iterator::operator*() const Line | Count | Source | 112 | 122M | { | 113 | 122M | Assume(m_val != 0); | 114 | 122M | return m_pos; | 115 | 122M | } |
bitset_detail::IntBitSet<unsigned int>::Iterator::operator*() const Line | Count | Source | 112 | 21.9M | { | 113 | 21.9M | Assume(m_val != 0); | 114 | 21.9M | return m_pos; | 115 | 21.9M | } |
|
116 | | }; |
117 | | |
118 | | public: |
119 | | /** Construct an all-zero bitset. */ |
120 | 14.5M | constexpr IntBitSet() noexcept : m_val{0} {}bitset_detail::IntBitSet<unsigned int>::IntBitSet() Line | Count | Source | 120 | 3.11M | constexpr IntBitSet() noexcept : m_val{0} {} |
bitset_detail::IntBitSet<unsigned long>::IntBitSet() Line | Count | Source | 120 | 11.4M | constexpr IntBitSet() noexcept : m_val{0} {} |
|
121 | | /** Copy construct a bitset. */ |
122 | | constexpr IntBitSet(const IntBitSet&) noexcept = default; |
123 | | /** Construct from a list of values. */ |
124 | 11 | constexpr IntBitSet(std::initializer_list<unsigned> ilist) noexcept : m_val(0) |
125 | 11 | { |
126 | 14 | for (auto pos : ilist) Set(pos); |
127 | 11 | } |
128 | | /** Copy assign a bitset. */ |
129 | | constexpr IntBitSet& operator=(const IntBitSet&) noexcept = default; |
130 | | /** Assign from a list of positions (which will be made true, all others false). */ |
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 | | } |
137 | | /** Construct a bitset with the singleton i. */ |
138 | | static constexpr IntBitSet Singleton(unsigned i) noexcept |
139 | 4.79M | { |
140 | 4.79M | Assume(i < MAX_SIZE); |
141 | 4.79M | return IntBitSet(I(1U) << i); |
142 | 4.79M | } bitset_detail::IntBitSet<unsigned long>::Singleton(unsigned int) Line | Count | Source | 139 | 3.90M | { | 140 | 3.90M | Assume(i < MAX_SIZE); | 141 | 3.90M | return IntBitSet(I(1U) << i); | 142 | 3.90M | } |
bitset_detail::IntBitSet<unsigned int>::Singleton(unsigned int) Line | Count | Source | 139 | 882k | { | 140 | 882k | Assume(i < MAX_SIZE); | 141 | 882k | return IntBitSet(I(1U) << i); | 142 | 882k | } |
|
143 | | /** Construct a bitset with bits 0..count-1 (inclusive) set to 1. */ |
144 | | static constexpr IntBitSet Fill(unsigned count) noexcept |
145 | 148k | { |
146 | 148k | IntBitSet ret; |
147 | 148k | Assume(count <= MAX_SIZE); |
148 | 148k | if (count) ret.m_val = I(~I{0}) >> (MAX_SIZE - count); |
149 | 148k | return ret; |
150 | 148k | } bitset_detail::IntBitSet<unsigned long>::Fill(unsigned int) Line | Count | Source | 145 | 119k | { | 146 | 119k | IntBitSet ret; | 147 | 119k | Assume(count <= MAX_SIZE); | 148 | 119k | if (count) ret.m_val = I(~I{0}) >> (MAX_SIZE - count); | 149 | 119k | return ret; | 150 | 119k | } |
bitset_detail::IntBitSet<unsigned int>::Fill(unsigned int) Line | Count | Source | 145 | 29.2k | { | 146 | 29.2k | IntBitSet ret; | 147 | 29.2k | Assume(count <= MAX_SIZE); | 148 | 29.2k | if (count) ret.m_val = I(~I{0}) >> (MAX_SIZE - count); | 149 | 29.2k | return ret; | 150 | 29.2k | } |
|
151 | | /** Set a bit to 1. */ |
152 | | constexpr void Set(unsigned pos) noexcept |
153 | 19.2M | { |
154 | 19.2M | Assume(pos < MAX_SIZE); |
155 | 19.2M | m_val |= I{1U} << pos; |
156 | 19.2M | } bitset_detail::IntBitSet<unsigned int>::Set(unsigned int) Line | Count | Source | 153 | 3.33M | { | 154 | 3.33M | Assume(pos < MAX_SIZE); | 155 | 3.33M | m_val |= I{1U} << pos; | 156 | 3.33M | } |
bitset_detail::IntBitSet<unsigned long>::Set(unsigned int) Line | Count | Source | 153 | 15.8M | { | 154 | 15.8M | Assume(pos < MAX_SIZE); | 155 | 15.8M | m_val |= I{1U} << pos; | 156 | 15.8M | } |
|
157 | | /** Set a bit to the specified value. */ |
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 | | } |
163 | | /** Set a bit to 0. */ |
164 | | constexpr void Reset(unsigned pos) noexcept |
165 | 5.97M | { |
166 | 5.97M | Assume(pos < MAX_SIZE); |
167 | 5.97M | m_val &= ~I(I{1U} << pos); |
168 | 5.97M | } bitset_detail::IntBitSet<unsigned long>::Reset(unsigned int) Line | Count | Source | 165 | 4.70M | { | 166 | 4.70M | Assume(pos < MAX_SIZE); | 167 | 4.70M | m_val &= ~I(I{1U} << pos); | 168 | 4.70M | } |
bitset_detail::IntBitSet<unsigned int>::Reset(unsigned int) Line | Count | Source | 165 | 1.27M | { | 166 | 1.27M | Assume(pos < MAX_SIZE); | 167 | 1.27M | m_val &= ~I(I{1U} << pos); | 168 | 1.27M | } |
|
169 | | /** Retrieve a bit at the given position. */ |
170 | | constexpr bool operator[](unsigned pos) const noexcept |
171 | 65.9M | { |
172 | 65.9M | Assume(pos < MAX_SIZE); |
173 | 65.9M | return (m_val >> pos) & 1U; |
174 | 65.9M | } bitset_detail::IntBitSet<unsigned long>::operator[](unsigned int) const Line | Count | Source | 171 | 54.8M | { | 172 | 54.8M | Assume(pos < MAX_SIZE); | 173 | 54.8M | return (m_val >> pos) & 1U; | 174 | 54.8M | } |
bitset_detail::IntBitSet<unsigned int>::operator[](unsigned int) const Line | Count | Source | 171 | 11.0M | { | 172 | 11.0M | Assume(pos < MAX_SIZE); | 173 | 11.0M | return (m_val >> pos) & 1U; | 174 | 11.0M | } |
|
175 | | /** Compute the number of 1 bits in the bitset. */ |
176 | 37.4M | constexpr unsigned Count() const noexcept { return PopCount(m_val); }bitset_detail::IntBitSet<unsigned long>::Count() const Line | Count | Source | 176 | 30.6M | constexpr unsigned Count() const noexcept { return PopCount(m_val); } |
bitset_detail::IntBitSet<unsigned int>::Count() const Line | Count | Source | 176 | 6.79M | constexpr unsigned Count() const noexcept { return PopCount(m_val); } |
|
177 | | /** Return the number of bits that this object holds. */ |
178 | 109k | static constexpr unsigned Size() noexcept { return MAX_SIZE; }bitset_detail::IntBitSet<unsigned long>::Size() Line | Count | Source | 178 | 83.4k | static constexpr unsigned Size() noexcept { return MAX_SIZE; } |
bitset_detail::IntBitSet<unsigned int>::Size() Line | Count | Source | 178 | 25.6k | static constexpr unsigned Size() noexcept { return MAX_SIZE; } |
|
179 | | /** Check if all bits are 0. */ |
180 | 14.2M | constexpr bool None() const noexcept { return m_val == 0; }bitset_detail::IntBitSet<unsigned long>::None() const Line | Count | Source | 180 | 12.0M | constexpr bool None() const noexcept { return m_val == 0; } |
bitset_detail::IntBitSet<unsigned int>::None() const Line | Count | Source | 180 | 2.21M | constexpr bool None() const noexcept { return m_val == 0; } |
|
181 | | /** Check if any bits are 1. */ |
182 | 13.8M | constexpr bool Any() const noexcept { return !None(); }bitset_detail::IntBitSet<unsigned long>::Any() const Line | Count | Source | 182 | 11.6M | constexpr bool Any() const noexcept { return !None(); } |
bitset_detail::IntBitSet<unsigned int>::Any() const Line | Count | Source | 182 | 2.19M | constexpr bool Any() const noexcept { return !None(); } |
|
183 | | /** Return an object that iterates over all 1 bits (++ and * only allowed when != end()). */ |
184 | 65.6M | constexpr Iterator begin() const noexcept { return Iterator(m_val); }bitset_detail::IntBitSet<unsigned long>::begin() const Line | Count | Source | 184 | 54.7M | constexpr Iterator begin() const noexcept { return Iterator(m_val); } |
bitset_detail::IntBitSet<unsigned int>::begin() const Line | Count | Source | 184 | 10.9M | constexpr Iterator begin() const noexcept { return Iterator(m_val); } |
|
185 | | /** Return a dummy object to compare Iterators with. */ |
186 | 66.8M | constexpr IteratorEnd end() const noexcept { return IteratorEnd(); }bitset_detail::IntBitSet<unsigned long>::end() const Line | Count | Source | 186 | 55.6M | constexpr IteratorEnd end() const noexcept { return IteratorEnd(); } |
bitset_detail::IntBitSet<unsigned int>::end() const Line | Count | Source | 186 | 11.2M | constexpr IteratorEnd end() const noexcept { return IteratorEnd(); } |
|
187 | | /** Find the first element (requires Any()). */ |
188 | | constexpr unsigned First() const noexcept |
189 | 11.3M | { |
190 | 11.3M | Assume(m_val != 0); |
191 | 11.3M | return std::countr_zero(m_val); |
192 | 11.3M | } bitset_detail::IntBitSet<unsigned long>::First() const Line | Count | Source | 189 | 9.59M | { | 190 | 9.59M | Assume(m_val != 0); | 191 | 9.59M | return std::countr_zero(m_val); | 192 | 9.59M | } |
bitset_detail::IntBitSet<unsigned int>::First() const Line | Count | Source | 189 | 1.72M | { | 190 | 1.72M | Assume(m_val != 0); | 191 | 1.72M | return std::countr_zero(m_val); | 192 | 1.72M | } |
|
193 | | /** Find the last element (requires Any()). */ |
194 | | constexpr unsigned Last() const noexcept |
195 | 1.07k | { |
196 | 1.07k | Assume(m_val != 0); |
197 | 1.07k | return std::bit_width(m_val) - 1; |
198 | 1.07k | } bitset_detail::IntBitSet<unsigned long>::Last() const Line | Count | Source | 195 | 681 | { | 196 | 681 | Assume(m_val != 0); | 197 | 681 | return std::bit_width(m_val) - 1; | 198 | 681 | } |
bitset_detail::IntBitSet<unsigned int>::Last() const Line | Count | Source | 195 | 393 | { | 196 | 393 | Assume(m_val != 0); | 197 | 393 | return std::bit_width(m_val) - 1; | 198 | 393 | } |
|
199 | | /** Set this object's bits to be the binary AND between respective bits from this and a. */ |
200 | 38.6M | constexpr IntBitSet& operator|=(const IntBitSet& a) noexcept { m_val |= a.m_val; return *this; }bitset_detail::IntBitSet<unsigned long>::operator|=(bitset_detail::IntBitSet<unsigned long> const&) Line | Count | Source | 200 | 33.3M | constexpr IntBitSet& operator|=(const IntBitSet& a) noexcept { m_val |= a.m_val; return *this; } |
bitset_detail::IntBitSet<unsigned int>::operator|=(bitset_detail::IntBitSet<unsigned int> const&) Line | Count | Source | 200 | 5.29M | constexpr IntBitSet& operator|=(const IntBitSet& a) noexcept { m_val |= a.m_val; return *this; } |
|
201 | | /** Set this object's bits to be the binary OR between respective bits from this and a. */ |
202 | 467k | constexpr IntBitSet& operator&=(const IntBitSet& a) noexcept { m_val &= a.m_val; return *this; }bitset_detail::IntBitSet<unsigned int>::operator&=(bitset_detail::IntBitSet<unsigned int> const&) Line | Count | Source | 202 | 58 | constexpr IntBitSet& operator&=(const IntBitSet& a) noexcept { m_val &= a.m_val; return *this; } |
bitset_detail::IntBitSet<unsigned long>::operator&=(bitset_detail::IntBitSet<unsigned long> const&) Line | Count | Source | 202 | 467k | constexpr IntBitSet& operator&=(const IntBitSet& a) noexcept { m_val &= a.m_val; return *this; } |
|
203 | | /** Set this object's bits to be the binary AND NOT between respective bits from this and a. */ |
204 | 26.6M | constexpr IntBitSet& operator-=(const IntBitSet& a) noexcept { m_val &= ~a.m_val; return *this; }bitset_detail::IntBitSet<unsigned long>::operator-=(bitset_detail::IntBitSet<unsigned long> const&) Line | Count | Source | 204 | 22.5M | constexpr IntBitSet& operator-=(const IntBitSet& a) noexcept { m_val &= ~a.m_val; return *this; } |
bitset_detail::IntBitSet<unsigned int>::operator-=(bitset_detail::IntBitSet<unsigned int> const&) Line | Count | Source | 204 | 4.12M | constexpr IntBitSet& operator-=(const IntBitSet& a) noexcept { m_val &= ~a.m_val; return *this; } |
|
205 | | /** Set this object's bits to be the binary XOR between respective bits from this as a. */ |
206 | | constexpr IntBitSet& operator^=(const IntBitSet& a) noexcept { m_val ^= a.m_val; return *this; } |
207 | | /** Check if the intersection between two sets is non-empty. */ |
208 | 13.2M | constexpr bool Overlaps(const IntBitSet& a) const noexcept { return m_val & a.m_val; }bitset_detail::IntBitSet<unsigned long>::Overlaps(bitset_detail::IntBitSet<unsigned long> const&) const Line | Count | Source | 208 | 11.1M | constexpr bool Overlaps(const IntBitSet& a) const noexcept { return m_val & a.m_val; } |
bitset_detail::IntBitSet<unsigned int>::Overlaps(bitset_detail::IntBitSet<unsigned int> const&) const Line | Count | Source | 208 | 2.12M | constexpr bool Overlaps(const IntBitSet& a) const noexcept { return m_val & a.m_val; } |
|
209 | | /** Return an object with the binary AND between respective bits from a and b. */ |
210 | 20.9M | friend constexpr IntBitSet operator&(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val & b.m_val); }bitset_detail::operator&(bitset_detail::IntBitSet<unsigned long> const&, bitset_detail::IntBitSet<unsigned long> const&) Line | Count | Source | 210 | 17.7M | friend constexpr IntBitSet operator&(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val & b.m_val); } |
bitset_detail::operator&(bitset_detail::IntBitSet<unsigned int> const&, bitset_detail::IntBitSet<unsigned int> const&) Line | Count | Source | 210 | 3.25M | friend constexpr IntBitSet operator&(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val & b.m_val); } |
|
211 | | /** Return an object with the binary OR between respective bits from a and b. */ |
212 | | friend constexpr IntBitSet operator|(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val | b.m_val); } |
213 | | /** Return an object with the binary AND NOT between respective bits from a and b. */ |
214 | 6.28M | friend constexpr IntBitSet operator-(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val & ~b.m_val); }bitset_detail::operator-(bitset_detail::IntBitSet<unsigned long> const&, bitset_detail::IntBitSet<unsigned long> const&) Line | Count | Source | 214 | 5.03M | friend constexpr IntBitSet operator-(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val & ~b.m_val); } |
bitset_detail::operator-(bitset_detail::IntBitSet<unsigned int> const&, bitset_detail::IntBitSet<unsigned int> const&) Line | Count | Source | 214 | 1.24M | friend constexpr IntBitSet operator-(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val & ~b.m_val); } |
|
215 | | /** Return an object with the binary XOR between respective bits from a and b. */ |
216 | | friend constexpr IntBitSet operator^(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val ^ b.m_val); } |
217 | | /** Check if bitset a and bitset b are identical. */ |
218 | 2.70M | friend constexpr bool operator==(const IntBitSet& a, const IntBitSet& b) noexcept = default; bitset_detail::operator==(bitset_detail::IntBitSet<unsigned long> const&, bitset_detail::IntBitSet<unsigned long> const&) Line | Count | Source | 218 | 2.25M | friend constexpr bool operator==(const IntBitSet& a, const IntBitSet& b) noexcept = default; |
bitset_detail::operator==(bitset_detail::IntBitSet<unsigned int> const&, bitset_detail::IntBitSet<unsigned int> const&) Line | Count | Source | 218 | 447k | friend constexpr bool operator==(const IntBitSet& a, const IntBitSet& b) noexcept = default; |
|
219 | | /** Check if bitset a is a superset of bitset b (= every 1 bit in b is also in a). */ |
220 | 288k | constexpr bool IsSupersetOf(const IntBitSet& a) const noexcept { return (a.m_val & ~m_val) == 0; }bitset_detail::IntBitSet<unsigned long>::IsSupersetOf(bitset_detail::IntBitSet<unsigned long> const&) const Line | Count | Source | 220 | 277k | constexpr bool IsSupersetOf(const IntBitSet& a) const noexcept { return (a.m_val & ~m_val) == 0; } |
bitset_detail::IntBitSet<unsigned int>::IsSupersetOf(bitset_detail::IntBitSet<unsigned int> const&) const Line | Count | Source | 220 | 10.2k | constexpr bool IsSupersetOf(const IntBitSet& a) const noexcept { return (a.m_val & ~m_val) == 0; } |
|
221 | | /** Check if bitset a is a subset of bitset b (= every 1 bit in a is also in b). */ |
222 | 6.00M | constexpr bool IsSubsetOf(const IntBitSet& a) const noexcept { return (m_val & ~a.m_val) == 0; }bitset_detail::IntBitSet<unsigned long>::IsSubsetOf(bitset_detail::IntBitSet<unsigned long> const&) const Line | Count | Source | 222 | 5.27M | constexpr bool IsSubsetOf(const IntBitSet& a) const noexcept { return (m_val & ~a.m_val) == 0; } |
bitset_detail::IntBitSet<unsigned int>::IsSubsetOf(bitset_detail::IntBitSet<unsigned int> const&) const Line | Count | Source | 222 | 723k | constexpr bool IsSubsetOf(const IntBitSet& a) const noexcept { return (m_val & ~a.m_val) == 0; } |
|
223 | | /** Swap two bitsets. */ |
224 | | friend constexpr void swap(IntBitSet& a, IntBitSet& b) noexcept { std::swap(a.m_val, b.m_val); } |
225 | | }; |
226 | | |
227 | | /** A bitset implementation backed by N integers of type I. */ |
228 | | template<typename I, unsigned N> |
229 | | class MultiIntBitSet |
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); |
235 | | /** The number of bits per integer. */ |
236 | | static constexpr unsigned LIMB_BITS = std::numeric_limits<I>::digits; |
237 | | /** Number of elements this set type supports. */ |
238 | | static constexpr unsigned MAX_SIZE = LIMB_BITS * N; |
239 | | // No overflow allowed here. |
240 | | static_assert(MAX_SIZE / LIMB_BITS == N); |
241 | | /** Array whose member integers store the bits of the set. */ |
242 | | std::array<I, N> m_val; |
243 | | /** Dummy type to return using end(). Only used for comparing with Iterator. */ |
244 | | class IteratorEnd |
245 | | { |
246 | | friend class MultiIntBitSet; |
247 | | constexpr IteratorEnd() = default; |
248 | | public: |
249 | | constexpr IteratorEnd(const IteratorEnd&) = default; |
250 | | }; |
251 | | /** Iterator type returned by begin(), which efficiently iterates all 1 positions. */ |
252 | | class Iterator |
253 | | { |
254 | | friend class MultiIntBitSet; |
255 | | const std::array<I, N>* m_ptr; /**< Pointer to array to fetch bits from. */ |
256 | | I m_val; /**< The remaining bits of (*m_ptr)[m_idx]. */ |
257 | | unsigned m_pos; /**< The last reported position. */ |
258 | | unsigned m_idx; /**< The index in *m_ptr currently being iterated over. */ |
259 | 113M | constexpr Iterator(const std::array<I, N>& ref) noexcept : m_ptr(&ref), m_idx(0) |
260 | 113M | { |
261 | 352M | do { |
262 | 352M | m_val = (*m_ptr)[m_idx]; |
263 | 352M | if (m_val) { |
264 | 67.1M | m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS; |
265 | 67.1M | break; |
266 | 67.1M | } |
267 | 285M | ++m_idx; |
268 | 285M | } while(m_idx < N); |
269 | 113M | } bitset_detail::MultiIntBitSet<unsigned int, 2u>::Iterator::Iterator(std::array<unsigned int, 2ul> const&) Line | Count | Source | 259 | 51.2M | constexpr Iterator(const std::array<I, N>& ref) noexcept : m_ptr(&ref), m_idx(0) | 260 | 51.2M | { | 261 | 77.6M | do { | 262 | 77.6M | m_val = (*m_ptr)[m_idx]; | 263 | 77.6M | if (m_val) { | 264 | 30.1M | m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS; | 265 | 30.1M | break; | 266 | 30.1M | } | 267 | 47.4M | ++m_idx; | 268 | 47.4M | } while(m_idx < N); | 269 | 51.2M | } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Iterator::Iterator(std::array<unsigned char, 8ul> const&) Line | Count | Source | 259 | 51.2M | constexpr Iterator(const std::array<I, N>& ref) noexcept : m_ptr(&ref), m_idx(0) | 260 | 51.2M | { | 261 | 247M | do { | 262 | 247M | m_val = (*m_ptr)[m_idx]; | 263 | 247M | if (m_val) { | 264 | 30.1M | m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS; | 265 | 30.1M | break; | 266 | 30.1M | } | 267 | 217M | ++m_idx; | 268 | 217M | } while(m_idx < N); | 269 | 51.2M | } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Iterator::Iterator(std::array<unsigned char, 4ul> const&) Line | Count | Source | 259 | 10.9M | constexpr Iterator(const std::array<I, N>& ref) noexcept : m_ptr(&ref), m_idx(0) | 260 | 10.9M | { | 261 | 26.8M | do { | 262 | 26.8M | m_val = (*m_ptr)[m_idx]; | 263 | 26.8M | if (m_val) { | 264 | 6.84M | m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS; | 265 | 6.84M | break; | 266 | 6.84M | } | 267 | 20.0M | ++m_idx; | 268 | 20.0M | } while(m_idx < N); | 269 | 10.9M | } |
|
270 | | |
271 | | public: |
272 | | /** Do not allow external code to construct an Iterator. */ |
273 | | Iterator() = delete; |
274 | | // Copying is allowed. |
275 | | constexpr Iterator(const Iterator&) noexcept = default; |
276 | | constexpr Iterator& operator=(const Iterator&) noexcept = default; |
277 | | /** Test whether we are done (can only compare with IteratorEnd). */ |
278 | | friend constexpr bool operator==(const Iterator& a, const IteratorEnd&) noexcept |
279 | 351M | { |
280 | 351M | return a.m_idx == N; |
281 | 351M | } bitset_detail::operator==(bitset_detail::MultiIntBitSet<unsigned int, 2u>::Iterator const&, bitset_detail::MultiIntBitSet<unsigned int, 2u>::IteratorEnd const&) Line | Count | Source | 279 | 160M | { | 280 | 160M | return a.m_idx == N; | 281 | 160M | } |
bitset_detail::operator==(bitset_detail::MultiIntBitSet<unsigned char, 8u>::Iterator const&, bitset_detail::MultiIntBitSet<unsigned char, 8u>::IteratorEnd const&) Line | Count | Source | 279 | 159M | { | 280 | 159M | return a.m_idx == N; | 281 | 159M | } |
bitset_detail::operator==(bitset_detail::MultiIntBitSet<unsigned char, 4u>::Iterator const&, bitset_detail::MultiIntBitSet<unsigned char, 4u>::IteratorEnd const&) Line | Count | Source | 279 | 31.5M | { | 280 | 31.5M | return a.m_idx == N; | 281 | 31.5M | } |
|
282 | | /** Progress to the next 1 bit (only if != IteratorEnd). */ |
283 | | constexpr Iterator& operator++() noexcept |
284 | 238M | { |
285 | 238M | Assume(m_idx < N); |
286 | 238M | m_val &= m_val - I{1U}; |
287 | 238M | if (m_val == 0) { |
288 | 244M | while (true) { |
289 | 244M | ++m_idx; |
290 | 244M | if (m_idx == N) break; |
291 | 184M | m_val = (*m_ptr)[m_idx]; |
292 | 184M | if (m_val) { |
293 | 33.2M | m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS; |
294 | 33.2M | break; |
295 | 33.2M | } |
296 | 184M | } |
297 | 145M | } else { |
298 | 145M | m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS; |
299 | 145M | } |
300 | 238M | return *this; |
301 | 238M | } bitset_detail::MultiIntBitSet<unsigned int, 2u>::Iterator::operator++() Line | Count | Source | 284 | 109M | { | 285 | 109M | Assume(m_idx < N); | 286 | 109M | m_val &= m_val - I{1U}; | 287 | 109M | if (m_val == 0) { | 288 | 49.6M | while (true) { | 289 | 49.6M | ++m_idx; | 290 | 49.6M | if (m_idx == N) break; | 291 | 22.4M | m_val = (*m_ptr)[m_idx]; | 292 | 22.4M | if (m_val) { | 293 | 6.13M | m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS; | 294 | 6.13M | break; | 295 | 6.13M | } | 296 | 22.4M | } | 297 | 76.3M | } else { | 298 | 76.3M | m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS; | 299 | 76.3M | } | 300 | 109M | return *this; | 301 | 109M | } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Iterator::operator++() Line | Count | Source | 284 | 108M | { | 285 | 108M | Assume(m_idx < N); | 286 | 108M | m_val &= m_val - I{1U}; | 287 | 108M | if (m_val == 0) { | 288 | 174M | while (true) { | 289 | 174M | ++m_idx; | 290 | 174M | if (m_idx == N) break; | 291 | 147M | m_val = (*m_ptr)[m_idx]; | 292 | 147M | if (m_val) { | 293 | 24.2M | m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS; | 294 | 24.2M | break; | 295 | 24.2M | } | 296 | 147M | } | 297 | 57.1M | } else { | 298 | 57.1M | m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS; | 299 | 57.1M | } | 300 | 108M | return *this; | 301 | 108M | } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Iterator::operator++() Line | Count | Source | 284 | 20.7M | { | 285 | 20.7M | Assume(m_idx < N); | 286 | 20.7M | m_val &= m_val - I{1U}; | 287 | 20.7M | if (m_val == 0) { | 288 | 20.9M | while (true) { | 289 | 20.9M | ++m_idx; | 290 | 20.9M | if (m_idx == N) break; | 291 | 15.0M | m_val = (*m_ptr)[m_idx]; | 292 | 15.0M | if (m_val) { | 293 | 2.82M | m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS; | 294 | 2.82M | break; | 295 | 2.82M | } | 296 | 15.0M | } | 297 | 11.9M | } else { | 298 | 11.9M | m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS; | 299 | 11.9M | } | 300 | 20.7M | return *this; | 301 | 20.7M | } |
|
302 | | /** Get the current bit position (only if != IteratorEnd). */ |
303 | | constexpr unsigned operator*() const noexcept |
304 | 247M | { |
305 | 247M | Assume(m_idx < N); |
306 | 247M | return m_pos; |
307 | 247M | } bitset_detail::MultiIntBitSet<unsigned int, 2u>::Iterator::operator*() const Line | Count | Source | 304 | 113M | { | 305 | 113M | Assume(m_idx < N); | 306 | 113M | return m_pos; | 307 | 113M | } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Iterator::operator*() const Line | Count | Source | 304 | 112M | { | 305 | 112M | Assume(m_idx < N); | 306 | 112M | return m_pos; | 307 | 112M | } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Iterator::operator*() const Line | Count | Source | 304 | 21.8M | { | 305 | 21.8M | Assume(m_idx < N); | 306 | 21.8M | return m_pos; | 307 | 21.8M | } |
|
308 | | }; |
309 | | |
310 | | public: |
311 | | /** Construct an all-zero bitset. */ |
312 | 74.8M | constexpr MultiIntBitSet() noexcept : m_val{} {}bitset_detail::MultiIntBitSet<unsigned int, 2u>::MultiIntBitSet() Line | Count | Source | 312 | 33.1M | constexpr MultiIntBitSet() noexcept : m_val{} {} |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::MultiIntBitSet() Line | Count | Source | 312 | 33.1M | constexpr MultiIntBitSet() noexcept : m_val{} {} |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::MultiIntBitSet() Line | Count | Source | 312 | 8.53M | constexpr MultiIntBitSet() noexcept : m_val{} {} |
|
313 | | /** Copy construct a bitset. */ |
314 | | constexpr MultiIntBitSet(const MultiIntBitSet&) noexcept = default; |
315 | | /** Copy assign a bitset. */ |
316 | | constexpr MultiIntBitSet& operator=(const MultiIntBitSet&) noexcept = default; |
317 | | /** Set a bit to 1. */ |
318 | | void constexpr Set(unsigned pos) noexcept |
319 | 32.6M | { |
320 | 32.6M | Assume(pos < MAX_SIZE); |
321 | 32.6M | m_val[pos / LIMB_BITS] |= I{1U} << (pos % LIMB_BITS); |
322 | 32.6M | } bitset_detail::MultiIntBitSet<unsigned int, 2u>::Set(unsigned int) Line | Count | Source | 319 | 14.6M | { | 320 | 14.6M | Assume(pos < MAX_SIZE); | 321 | 14.6M | m_val[pos / LIMB_BITS] |= I{1U} << (pos % LIMB_BITS); | 322 | 14.6M | } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Set(unsigned int) Line | Count | Source | 319 | 14.6M | { | 320 | 14.6M | Assume(pos < MAX_SIZE); | 321 | 14.6M | m_val[pos / LIMB_BITS] |= I{1U} << (pos % LIMB_BITS); | 322 | 14.6M | } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Set(unsigned int) Line | Count | Source | 319 | 3.33M | { | 320 | 3.33M | Assume(pos < MAX_SIZE); | 321 | 3.33M | m_val[pos / LIMB_BITS] |= I{1U} << (pos % LIMB_BITS); | 322 | 3.33M | } |
|
323 | | /** Set a bit to the specified value. */ |
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 | | } |
330 | | /** Construct a bitset from a list of values. */ |
331 | | constexpr MultiIntBitSet(std::initializer_list<unsigned> ilist) noexcept : m_val{} |
332 | | { |
333 | | for (auto pos : ilist) Set(pos); |
334 | | } |
335 | | /** Set a bitset to a list of values. */ |
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 | | } |
342 | | /** Set a bit to 0. */ |
343 | | void constexpr Reset(unsigned pos) noexcept |
344 | 10.1M | { |
345 | 10.1M | Assume(pos < MAX_SIZE); |
346 | 10.1M | m_val[pos / LIMB_BITS] &= ~I(I{1U} << (pos % LIMB_BITS)); |
347 | 10.1M | } bitset_detail::MultiIntBitSet<unsigned int, 2u>::Reset(unsigned int) Line | Count | Source | 344 | 4.43M | { | 345 | 4.43M | Assume(pos < MAX_SIZE); | 346 | 4.43M | m_val[pos / LIMB_BITS] &= ~I(I{1U} << (pos % LIMB_BITS)); | 347 | 4.43M | } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Reset(unsigned int) Line | Count | Source | 344 | 4.43M | { | 345 | 4.43M | Assume(pos < MAX_SIZE); | 346 | 4.43M | m_val[pos / LIMB_BITS] &= ~I(I{1U} << (pos % LIMB_BITS)); | 347 | 4.43M | } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Reset(unsigned int) Line | Count | Source | 344 | 1.27M | { | 345 | 1.27M | Assume(pos < MAX_SIZE); | 346 | 1.27M | m_val[pos / LIMB_BITS] &= ~I(I{1U} << (pos % LIMB_BITS)); | 347 | 1.27M | } |
|
348 | | /** Retrieve a bit at the given position. */ |
349 | | bool constexpr operator[](unsigned pos) const noexcept |
350 | 111M | { |
351 | 111M | Assume(pos < MAX_SIZE); |
352 | 111M | return (m_val[pos / LIMB_BITS] >> (pos % LIMB_BITS)) & 1U; |
353 | 111M | } bitset_detail::MultiIntBitSet<unsigned int, 2u>::operator[](unsigned int) const Line | Count | Source | 350 | 50.6M | { | 351 | 50.6M | Assume(pos < MAX_SIZE); | 352 | 50.6M | return (m_val[pos / LIMB_BITS] >> (pos % LIMB_BITS)) & 1U; | 353 | 50.6M | } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::operator[](unsigned int) const Line | Count | Source | 350 | 49.5M | { | 351 | 49.5M | Assume(pos < MAX_SIZE); | 352 | 49.5M | return (m_val[pos / LIMB_BITS] >> (pos % LIMB_BITS)) & 1U; | 353 | 49.5M | } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::operator[](unsigned int) const Line | Count | Source | 350 | 10.9M | { | 351 | 10.9M | Assume(pos < MAX_SIZE); | 352 | 10.9M | return (m_val[pos / LIMB_BITS] >> (pos % LIMB_BITS)) & 1U; | 353 | 10.9M | } |
|
354 | | /** Construct a bitset with the singleton pos. */ |
355 | | static constexpr MultiIntBitSet Singleton(unsigned pos) noexcept |
356 | 6.72M | { |
357 | 6.72M | Assume(pos < MAX_SIZE); |
358 | 6.72M | MultiIntBitSet ret; |
359 | 6.72M | ret.m_val[pos / LIMB_BITS] = I{1U} << (pos % LIMB_BITS); |
360 | 6.72M | return ret; |
361 | 6.72M | } bitset_detail::MultiIntBitSet<unsigned int, 2u>::Singleton(unsigned int) Line | Count | Source | 356 | 2.92M | { | 357 | 2.92M | Assume(pos < MAX_SIZE); | 358 | 2.92M | MultiIntBitSet ret; | 359 | 2.92M | ret.m_val[pos / LIMB_BITS] = I{1U} << (pos % LIMB_BITS); | 360 | 2.92M | return ret; | 361 | 2.92M | } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Singleton(unsigned int) Line | Count | Source | 356 | 2.92M | { | 357 | 2.92M | Assume(pos < MAX_SIZE); | 358 | 2.92M | MultiIntBitSet ret; | 359 | 2.92M | ret.m_val[pos / LIMB_BITS] = I{1U} << (pos % LIMB_BITS); | 360 | 2.92M | return ret; | 361 | 2.92M | } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Singleton(unsigned int) Line | Count | Source | 356 | 882k | { | 357 | 882k | Assume(pos < MAX_SIZE); | 358 | 882k | MultiIntBitSet ret; | 359 | 882k | ret.m_val[pos / LIMB_BITS] = I{1U} << (pos % LIMB_BITS); | 360 | 882k | return ret; | 361 | 882k | } |
|
362 | | /** Construct a bitset with bits 0..count-1 (inclusive) set to 1. */ |
363 | | static constexpr MultiIntBitSet Fill(unsigned count) noexcept |
364 | 147k | { |
365 | 147k | Assume(count <= MAX_SIZE); |
366 | 147k | MultiIntBitSet ret; |
367 | 147k | if (count) { |
368 | 146k | unsigned i = 0; |
369 | 379k | while (count > LIMB_BITS) { |
370 | 233k | ret.m_val[i++] = I(~I{0}); |
371 | 233k | count -= LIMB_BITS; |
372 | 233k | } |
373 | 146k | ret.m_val[i] = I(~I{0}) >> (LIMB_BITS - count); |
374 | 146k | } |
375 | 147k | return ret; |
376 | 147k | } bitset_detail::MultiIntBitSet<unsigned int, 2u>::Fill(unsigned int) Line | Count | Source | 364 | 59.2k | { | 365 | 59.2k | Assume(count <= MAX_SIZE); | 366 | 59.2k | MultiIntBitSet ret; | 367 | 59.2k | if (count) { | 368 | 58.8k | unsigned i = 0; | 369 | 82.1k | while (count > LIMB_BITS) { | 370 | 23.3k | ret.m_val[i++] = I(~I{0}); | 371 | 23.3k | count -= LIMB_BITS; | 372 | 23.3k | } | 373 | 58.8k | ret.m_val[i] = I(~I{0}) >> (LIMB_BITS - count); | 374 | 58.8k | } | 375 | 59.2k | return ret; | 376 | 59.2k | } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Fill(unsigned int) Line | Count | Source | 364 | 59.2k | { | 365 | 59.2k | Assume(count <= MAX_SIZE); | 366 | 59.2k | MultiIntBitSet ret; | 367 | 59.2k | if (count) { | 368 | 58.8k | unsigned i = 0; | 369 | 230k | while (count > LIMB_BITS) { | 370 | 171k | ret.m_val[i++] = I(~I{0}); | 371 | 171k | count -= LIMB_BITS; | 372 | 171k | } | 373 | 58.8k | ret.m_val[i] = I(~I{0}) >> (LIMB_BITS - count); | 374 | 58.8k | } | 375 | 59.2k | return ret; | 376 | 59.2k | } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Fill(unsigned int) Line | Count | Source | 364 | 29.2k | { | 365 | 29.2k | Assume(count <= MAX_SIZE); | 366 | 29.2k | MultiIntBitSet ret; | 367 | 29.2k | if (count) { | 368 | 28.9k | unsigned i = 0; | 369 | 67.2k | while (count > LIMB_BITS) { | 370 | 38.2k | ret.m_val[i++] = I(~I{0}); | 371 | 38.2k | count -= LIMB_BITS; | 372 | 38.2k | } | 373 | 28.9k | ret.m_val[i] = I(~I{0}) >> (LIMB_BITS - count); | 374 | 28.9k | } | 375 | 29.2k | return ret; | 376 | 29.2k | } |
|
377 | | /** Return the number of bits that this object holds. */ |
378 | 192k | static constexpr unsigned Size() noexcept { return MAX_SIZE; }bitset_detail::MultiIntBitSet<unsigned int, 2u>::Size() Line | Count | Source | 378 | 83.4k | static constexpr unsigned Size() noexcept { return MAX_SIZE; } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Size() Line | Count | Source | 378 | 83.4k | static constexpr unsigned Size() noexcept { return MAX_SIZE; } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Size() Line | Count | Source | 378 | 25.3k | static constexpr unsigned Size() noexcept { return MAX_SIZE; } |
|
379 | | /** Compute the number of 1 bits in the bitset. */ |
380 | | unsigned constexpr Count() const noexcept |
381 | 62.8M | { |
382 | 62.8M | unsigned ret{0}; |
383 | 307M | for (I v : m_val) ret += PopCount(v); |
384 | 62.8M | return ret; |
385 | 62.8M | } bitset_detail::MultiIntBitSet<unsigned int, 2u>::Count() const Line | Count | Source | 381 | 28.0M | { | 382 | 28.0M | unsigned ret{0}; | 383 | 56.0M | for (I v : m_val) ret += PopCount(v); | 384 | 28.0M | return ret; | 385 | 28.0M | } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Count() const Line | Count | Source | 381 | 28.0M | { | 382 | 28.0M | unsigned ret{0}; | 383 | 224M | for (I v : m_val) ret += PopCount(v); | 384 | 28.0M | return ret; | 385 | 28.0M | } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Count() const Line | Count | Source | 381 | 6.82M | { | 382 | 6.82M | unsigned ret{0}; | 383 | 27.3M | for (I v : m_val) ret += PopCount(v); | 384 | 6.82M | return ret; | 385 | 6.82M | } |
|
386 | | /** Check if all bits are 0. */ |
387 | | bool constexpr None() const noexcept |
388 | 23.9M | { |
389 | 67.5M | for (auto v : m_val) { |
390 | 67.5M | if (v != 0) return false; |
391 | 67.5M | } |
392 | 5.83M | return true; |
393 | 23.9M | } bitset_detail::MultiIntBitSet<unsigned int, 2u>::None() const Line | Count | Source | 388 | 10.8M | { | 389 | 15.5M | for (auto v : m_val) { | 390 | 15.5M | if (v != 0) return false; | 391 | 15.5M | } | 392 | 2.54M | return true; | 393 | 10.8M | } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::None() const Line | Count | Source | 388 | 10.8M | { | 389 | 46.4M | for (auto v : m_val) { | 390 | 46.4M | if (v != 0) return false; | 391 | 46.4M | } | 392 | 2.54M | return true; | 393 | 10.8M | } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::None() const Line | Count | Source | 388 | 2.21M | { | 389 | 5.54M | for (auto v : m_val) { | 390 | 5.54M | if (v != 0) return false; | 391 | 5.54M | } | 392 | 753k | return true; | 393 | 2.21M | } |
|
394 | | /** Check if any bits are 1. */ |
395 | 23.8M | bool constexpr Any() const noexcept { return !None(); }bitset_detail::MultiIntBitSet<unsigned int, 2u>::Any() const Line | Count | Source | 395 | 10.8M | bool constexpr Any() const noexcept { return !None(); } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Any() const Line | Count | Source | 395 | 10.8M | bool constexpr Any() const noexcept { return !None(); } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Any() const Line | Count | Source | 395 | 2.20M | bool constexpr Any() const noexcept { return !None(); } |
|
396 | | /** Return an object that iterates over all 1 bits (++ and * only allowed when != end()). */ |
397 | 113M | Iterator constexpr begin() const noexcept { return Iterator(m_val); }bitset_detail::MultiIntBitSet<unsigned int, 2u>::begin() const Line | Count | Source | 397 | 51.2M | Iterator constexpr begin() const noexcept { return Iterator(m_val); } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::begin() const Line | Count | Source | 397 | 51.2M | Iterator constexpr begin() const noexcept { return Iterator(m_val); } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::begin() const Line | Count | Source | 397 | 10.9M | Iterator constexpr begin() const noexcept { return Iterator(m_val); } |
|
398 | | /** Return a dummy object to compare Iterators with. */ |
399 | 115M | IteratorEnd constexpr end() const noexcept { return IteratorEnd(); }bitset_detail::MultiIntBitSet<unsigned int, 2u>::end() const Line | Count | Source | 399 | 52.1M | IteratorEnd constexpr end() const noexcept { return IteratorEnd(); } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::end() const Line | Count | Source | 399 | 52.1M | IteratorEnd constexpr end() const noexcept { return IteratorEnd(); } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::end() const Line | Count | Source | 399 | 11.2M | IteratorEnd constexpr end() const noexcept { return IteratorEnd(); } |
|
400 | | /** Find the first element (requires Any()). */ |
401 | | unsigned constexpr First() const noexcept |
402 | 20.1M | { |
403 | 20.1M | unsigned p = 0; |
404 | 43.4M | while (m_val[p] == 0) { |
405 | 23.3M | ++p; |
406 | 23.3M | Assume(p < N); |
407 | 23.3M | } |
408 | 20.1M | return std::countr_zero(m_val[p]) + p * LIMB_BITS; |
409 | 20.1M | } bitset_detail::MultiIntBitSet<unsigned int, 2u>::First() const Line | Count | Source | 402 | 9.20M | { | 403 | 9.20M | unsigned p = 0; | 404 | 11.5M | while (m_val[p] == 0) { | 405 | 2.32M | ++p; | 406 | 2.32M | Assume(p < N); | 407 | 2.32M | } | 408 | 9.20M | return std::countr_zero(m_val[p]) + p * LIMB_BITS; | 409 | 9.20M | } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::First() const Line | Count | Source | 402 | 9.19M | { | 403 | 9.19M | unsigned p = 0; | 404 | 28.9M | while (m_val[p] == 0) { | 405 | 19.7M | ++p; | 406 | 19.7M | Assume(p < N); | 407 | 19.7M | } | 408 | 9.19M | return std::countr_zero(m_val[p]) + p * LIMB_BITS; | 409 | 9.19M | } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::First() const Line | Count | Source | 402 | 1.73M | { | 403 | 1.73M | unsigned p = 0; | 404 | 3.03M | while (m_val[p] == 0) { | 405 | 1.29M | ++p; | 406 | 1.29M | Assume(p < N); | 407 | 1.29M | } | 408 | 1.73M | return std::countr_zero(m_val[p]) + p * LIMB_BITS; | 409 | 1.73M | } |
|
410 | | /** Find the last element (requires Any()). */ |
411 | | unsigned constexpr Last() const noexcept |
412 | 1.73k | { |
413 | 1.73k | unsigned p = N - 1; |
414 | 5.28k | while (m_val[p] == 0) { |
415 | 3.54k | Assume(p > 0); |
416 | 3.54k | --p; |
417 | 3.54k | } |
418 | 1.73k | return std::bit_width(m_val[p]) - 1 + p * LIMB_BITS; |
419 | 1.73k | } bitset_detail::MultiIntBitSet<unsigned int, 2u>::Last() const Line | Count | Source | 412 | 681 | { | 413 | 681 | unsigned p = N - 1; | 414 | 1.05k | while (m_val[p] == 0) { | 415 | 375 | Assume(p > 0); | 416 | 375 | --p; | 417 | 375 | } | 418 | 681 | return std::bit_width(m_val[p]) - 1 + p * LIMB_BITS; | 419 | 681 | } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Last() const Line | Count | Source | 412 | 681 | { | 413 | 681 | unsigned p = N - 1; | 414 | 3.26k | while (m_val[p] == 0) { | 415 | 2.58k | Assume(p > 0); | 416 | 2.58k | --p; | 417 | 2.58k | } | 418 | 681 | return std::bit_width(m_val[p]) - 1 + p * LIMB_BITS; | 419 | 681 | } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Last() const Line | Count | Source | 412 | 375 | { | 413 | 375 | unsigned p = N - 1; | 414 | 960 | while (m_val[p] == 0) { | 415 | 585 | Assume(p > 0); | 416 | 585 | --p; | 417 | 585 | } | 418 | 375 | return std::bit_width(m_val[p]) - 1 + p * LIMB_BITS; | 419 | 375 | } |
|
420 | | /** Set this object's bits to be the binary OR between respective bits from this and a. */ |
421 | | constexpr MultiIntBitSet& operator|=(const MultiIntBitSet& a) noexcept |
422 | 66.4M | { |
423 | 393M | for (unsigned i = 0; i < N; ++i) { |
424 | 326M | m_val[i] |= a.m_val[i]; |
425 | 326M | } |
426 | 66.4M | return *this; |
427 | 66.4M | } bitset_detail::MultiIntBitSet<unsigned int, 2u>::operator|=(bitset_detail::MultiIntBitSet<unsigned int, 2u> const&) Line | Count | Source | 422 | 30.5M | { | 423 | 91.6M | for (unsigned i = 0; i < N; ++i) { | 424 | 61.1M | m_val[i] |= a.m_val[i]; | 425 | 61.1M | } | 426 | 30.5M | return *this; | 427 | 30.5M | } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::operator|=(bitset_detail::MultiIntBitSet<unsigned char, 8u> const&) Line | Count | Source | 422 | 30.5M | { | 423 | 275M | for (unsigned i = 0; i < N; ++i) { | 424 | 244M | m_val[i] |= a.m_val[i]; | 425 | 244M | } | 426 | 30.5M | return *this; | 427 | 30.5M | } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::operator|=(bitset_detail::MultiIntBitSet<unsigned char, 4u> const&) Line | Count | Source | 422 | 5.33M | { | 423 | 26.6M | for (unsigned i = 0; i < N; ++i) { | 424 | 21.3M | m_val[i] |= a.m_val[i]; | 425 | 21.3M | } | 426 | 5.33M | return *this; | 427 | 5.33M | } |
|
428 | | /** Set this object's bits to be the binary AND between respective bits from this and a. */ |
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 | | } |
436 | | /** Set this object's bits to be the binary AND NOT between respective bits from this and a. */ |
437 | | constexpr MultiIntBitSet& operator-=(const MultiIntBitSet& a) noexcept |
438 | 46.8M | { |
439 | 276M | for (unsigned i = 0; i < N; ++i) { |
440 | 230M | m_val[i] &= ~a.m_val[i]; |
441 | 230M | } |
442 | 46.8M | return *this; |
443 | 46.8M | } bitset_detail::MultiIntBitSet<unsigned int, 2u>::operator-=(bitset_detail::MultiIntBitSet<unsigned int, 2u> const&) Line | Count | Source | 438 | 21.3M | { | 439 | 64.0M | for (unsigned i = 0; i < N; ++i) { | 440 | 42.7M | m_val[i] &= ~a.m_val[i]; | 441 | 42.7M | } | 442 | 21.3M | return *this; | 443 | 21.3M | } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::operator-=(bitset_detail::MultiIntBitSet<unsigned char, 8u> const&) Line | Count | Source | 438 | 21.3M | { | 439 | 192M | for (unsigned i = 0; i < N; ++i) { | 440 | 170M | m_val[i] &= ~a.m_val[i]; | 441 | 170M | } | 442 | 21.3M | return *this; | 443 | 21.3M | } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::operator-=(bitset_detail::MultiIntBitSet<unsigned char, 4u> const&) Line | Count | Source | 438 | 4.14M | { | 439 | 20.7M | for (unsigned i = 0; i < N; ++i) { | 440 | 16.5M | m_val[i] &= ~a.m_val[i]; | 441 | 16.5M | } | 442 | 4.14M | return *this; | 443 | 4.14M | } |
|
444 | | /** Set this object's bits to be the binary XOR between respective bits from this and a. */ |
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 | | } |
452 | | /** Check whether the intersection between two sets is non-empty. */ |
453 | | constexpr bool Overlaps(const MultiIntBitSet& a) const noexcept |
454 | 23.8M | { |
455 | 138M | for (unsigned i = 0; i < N; ++i) { |
456 | 115M | if (m_val[i] & a.m_val[i]) return true; |
457 | 115M | } |
458 | 23.2M | return false; |
459 | 23.8M | } bitset_detail::MultiIntBitSet<unsigned int, 2u>::Overlaps(bitset_detail::MultiIntBitSet<unsigned int, 2u> const&) const Line | Count | Source | 454 | 10.8M | { | 455 | 32.0M | for (unsigned i = 0; i < N; ++i) { | 456 | 21.4M | if (m_val[i] & a.m_val[i]) return true; | 457 | 21.4M | } | 458 | 10.6M | return false; | 459 | 10.8M | } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Overlaps(bitset_detail::MultiIntBitSet<unsigned char, 8u> const&) const Line | Count | Source | 454 | 10.8M | { | 455 | 95.8M | for (unsigned i = 0; i < N; ++i) { | 456 | 85.2M | if (m_val[i] & a.m_val[i]) return true; | 457 | 85.2M | } | 458 | 10.6M | return false; | 459 | 10.8M | } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Overlaps(bitset_detail::MultiIntBitSet<unsigned char, 4u> const&) const Line | Count | Source | 454 | 2.13M | { | 455 | 10.4M | for (unsigned i = 0; i < N; ++i) { | 456 | 8.37M | if (m_val[i] & a.m_val[i]) return true; | 457 | 8.37M | } | 458 | 2.07M | return false; | 459 | 2.13M | } |
|
460 | | /** Return an object with the binary AND between respective bits from a and b. */ |
461 | | friend constexpr MultiIntBitSet operator&(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept |
462 | 34.8M | { |
463 | 34.8M | MultiIntBitSet r; |
464 | 205M | for (unsigned i = 0; i < N; ++i) { |
465 | 171M | r.m_val[i] = a.m_val[i] & b.m_val[i]; |
466 | 171M | } |
467 | 34.8M | return r; |
468 | 34.8M | } bitset_detail::operator&(bitset_detail::MultiIntBitSet<unsigned int, 2u> const&, bitset_detail::MultiIntBitSet<unsigned int, 2u> const&) Line | Count | Source | 462 | 15.8M | { | 463 | 15.8M | MultiIntBitSet r; | 464 | 47.4M | for (unsigned i = 0; i < N; ++i) { | 465 | 31.6M | r.m_val[i] = a.m_val[i] & b.m_val[i]; | 466 | 31.6M | } | 467 | 15.8M | return r; | 468 | 15.8M | } |
bitset_detail::operator&(bitset_detail::MultiIntBitSet<unsigned char, 8u> const&, bitset_detail::MultiIntBitSet<unsigned char, 8u> const&) Line | Count | Source | 462 | 15.7M | { | 463 | 15.7M | MultiIntBitSet r; | 464 | 142M | for (unsigned i = 0; i < N; ++i) { | 465 | 126M | r.m_val[i] = a.m_val[i] & b.m_val[i]; | 466 | 126M | } | 467 | 15.7M | return r; | 468 | 15.7M | } |
bitset_detail::operator&(bitset_detail::MultiIntBitSet<unsigned char, 4u> const&, bitset_detail::MultiIntBitSet<unsigned char, 4u> const&) Line | Count | Source | 462 | 3.28M | { | 463 | 3.28M | MultiIntBitSet r; | 464 | 16.4M | for (unsigned i = 0; i < N; ++i) { | 465 | 13.1M | r.m_val[i] = a.m_val[i] & b.m_val[i]; | 466 | 13.1M | } | 467 | 3.28M | return r; | 468 | 3.28M | } |
|
469 | | /** Return an object with the binary OR between respective bits from a and b. */ |
470 | | friend constexpr MultiIntBitSet operator|(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept |
471 | | { |
472 | | MultiIntBitSet r; |
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 | | } |
478 | | /** Return an object with the binary AND NOT between respective bits from a and b. */ |
479 | | friend constexpr MultiIntBitSet operator-(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept |
480 | 9.81M | { |
481 | 9.81M | MultiIntBitSet r; |
482 | 57.6M | for (unsigned i = 0; i < N; ++i) { |
483 | 47.8M | r.m_val[i] = a.m_val[i] & ~b.m_val[i]; |
484 | 47.8M | } |
485 | 9.81M | return r; |
486 | 9.81M | } bitset_detail::operator-(bitset_detail::MultiIntBitSet<unsigned int, 2u> const&, bitset_detail::MultiIntBitSet<unsigned int, 2u> const&) Line | Count | Source | 480 | 4.27M | { | 481 | 4.27M | MultiIntBitSet r; | 482 | 12.8M | for (unsigned i = 0; i < N; ++i) { | 483 | 8.55M | r.m_val[i] = a.m_val[i] & ~b.m_val[i]; | 484 | 8.55M | } | 485 | 4.27M | return r; | 486 | 4.27M | } |
bitset_detail::operator-(bitset_detail::MultiIntBitSet<unsigned char, 8u> const&, bitset_detail::MultiIntBitSet<unsigned char, 8u> const&) Line | Count | Source | 480 | 4.28M | { | 481 | 4.28M | MultiIntBitSet r; | 482 | 38.5M | for (unsigned i = 0; i < N; ++i) { | 483 | 34.2M | r.m_val[i] = a.m_val[i] & ~b.m_val[i]; | 484 | 34.2M | } | 485 | 4.28M | return r; | 486 | 4.28M | } |
bitset_detail::operator-(bitset_detail::MultiIntBitSet<unsigned char, 4u> const&, bitset_detail::MultiIntBitSet<unsigned char, 4u> const&) Line | Count | Source | 480 | 1.25M | { | 481 | 1.25M | MultiIntBitSet r; | 482 | 6.27M | for (unsigned i = 0; i < N; ++i) { | 483 | 5.01M | r.m_val[i] = a.m_val[i] & ~b.m_val[i]; | 484 | 5.01M | } | 485 | 1.25M | return r; | 486 | 1.25M | } |
|
487 | | /** Return an object with the binary XOR between respective bits from a and b. */ |
488 | | friend constexpr MultiIntBitSet operator^(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept |
489 | | { |
490 | | MultiIntBitSet r; |
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 | | } |
496 | | /** Check if bitset a is a superset of bitset b (= every 1 bit in b is also in a). */ |
497 | | constexpr bool IsSupersetOf(const MultiIntBitSet& a) const noexcept |
498 | 104k | { |
499 | 614k | for (unsigned i = 0; i < N; ++i) { |
500 | 510k | if (a.m_val[i] & ~m_val[i]) return false; |
501 | 510k | } |
502 | 104k | return true; |
503 | 104k | } bitset_detail::MultiIntBitSet<unsigned int, 2u>::IsSupersetOf(bitset_detail::MultiIntBitSet<unsigned int, 2u> const&) const Line | Count | Source | 498 | 47.0k | { | 499 | 141k | for (unsigned i = 0; i < N; ++i) { | 500 | 94.0k | if (a.m_val[i] & ~m_val[i]) return false; | 501 | 94.0k | } | 502 | 47.0k | return true; | 503 | 47.0k | } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::IsSupersetOf(bitset_detail::MultiIntBitSet<unsigned char, 8u> const&) const Line | Count | Source | 498 | 47.0k | { | 499 | 423k | for (unsigned i = 0; i < N; ++i) { | 500 | 376k | if (a.m_val[i] & ~m_val[i]) return false; | 501 | 376k | } | 502 | 47.0k | return true; | 503 | 47.0k | } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::IsSupersetOf(bitset_detail::MultiIntBitSet<unsigned char, 4u> const&) const Line | Count | Source | 498 | 10.1k | { | 499 | 50.8k | for (unsigned i = 0; i < N; ++i) { | 500 | 40.6k | if (a.m_val[i] & ~m_val[i]) return false; | 501 | 40.6k | } | 502 | 10.1k | return true; | 503 | 10.1k | } |
|
504 | | /** Check if bitset a is a subset of bitset b (= every 1 bit in a is also in b). */ |
505 | | constexpr bool IsSubsetOf(const MultiIntBitSet& a) const noexcept |
506 | 10.3M | { |
507 | 61.4M | for (unsigned i = 0; i < N; ++i) { |
508 | 51.1M | if (m_val[i] & ~a.m_val[i]) return false; |
509 | 51.1M | } |
510 | 10.3M | return true; |
511 | 10.3M | } bitset_detail::MultiIntBitSet<unsigned int, 2u>::IsSubsetOf(bitset_detail::MultiIntBitSet<unsigned int, 2u> const&) const Line | Count | Source | 506 | 4.82M | { | 507 | 14.4M | for (unsigned i = 0; i < N; ++i) { | 508 | 9.64M | if (m_val[i] & ~a.m_val[i]) return false; | 509 | 9.64M | } | 510 | 4.82M | return true; | 511 | 4.82M | } |
bitset_detail::MultiIntBitSet<unsigned char, 8u>::IsSubsetOf(bitset_detail::MultiIntBitSet<unsigned char, 8u> const&) const Line | Count | Source | 506 | 4.81M | { | 507 | 43.3M | for (unsigned i = 0; i < N; ++i) { | 508 | 38.5M | if (m_val[i] & ~a.m_val[i]) return false; | 509 | 38.5M | } | 510 | 4.81M | return true; | 511 | 4.81M | } |
bitset_detail::MultiIntBitSet<unsigned char, 4u>::IsSubsetOf(bitset_detail::MultiIntBitSet<unsigned char, 4u> const&) const Line | Count | Source | 506 | 732k | { | 507 | 3.66M | for (unsigned i = 0; i < N; ++i) { | 508 | 2.92M | if (m_val[i] & ~a.m_val[i]) return false; | 509 | 2.92M | } | 510 | 732k | return true; | 511 | 732k | } |
|
512 | | /** Check if bitset a and bitset b are identical. */ |
513 | 3.38M | friend constexpr bool operator==(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept = default; bitset_detail::operator==(bitset_detail::MultiIntBitSet<unsigned int, 2u> const&, bitset_detail::MultiIntBitSet<unsigned int, 2u> const&) Line | Count | Source | 513 | 1.47M | friend constexpr bool operator==(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept = default; |
bitset_detail::operator==(bitset_detail::MultiIntBitSet<unsigned char, 8u> const&, bitset_detail::MultiIntBitSet<unsigned char, 8u> const&) Line | Count | Source | 513 | 1.46M | friend constexpr bool operator==(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept = default; |
bitset_detail::operator==(bitset_detail::MultiIntBitSet<unsigned char, 4u> const&, bitset_detail::MultiIntBitSet<unsigned char, 4u> const&) Line | Count | Source | 513 | 446k | friend constexpr bool operator==(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept = default; |
|
514 | | /** Swap two bitsets. */ |
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. |
523 | | template<unsigned BITS> |
524 | | using 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 |