Lamp-Da 0.1
A compact lantern project
Loading...
Searching...
No Matches
bitset.h
Go to the documentation of this file.
1
5#pragma once
6
7#include <array>
8#include <cstdint>
9#include <cstddef>
10
11namespace lampda {
12namespace common {
13
22template<uint16_t N> class BitSet
23{
24public:
25 using storage_t = uint32_t;
27 static constexpr uint16_t storageSize = (N + sizeof(storage_t) * 8 - 1) / (sizeof(storage_t) * 8);
28 static constexpr uint16_t bitsPerStorage = sizeof(storage_t) * 8;
29
30private:
31 std::array<storage_t, storageSize> _data;
32
34 static constexpr uint16_t word_index(uint16_t i) noexcept { return i / bitsPerStorage; }
35
37 static constexpr storage_t bit_mask(uint16_t i) noexcept { return static_cast<storage_t>(1) << (i % bitsPerStorage); }
38
40 static constexpr storage_t last_word_mask() noexcept
41 {
42 const uint16_t lastWordBits = N % bitsPerStorage;
43 if (lastWordBits == 0)
44 return static_cast<storage_t>(~storage_t {0});
45 storage_t mask = static_cast<storage_t>(1) << lastWordBits;
46 return mask - 1;
47 }
48
49public:
51 constexpr BitSet() : _data {} { reset(); }
52
57 explicit constexpr BitSet(storage_t value) : _data {}
58 {
59 for (uint16_t i = 0; i < storageSize - 1; ++i)
60 _data[i] = value;
61 _data[storageSize - 1] = value & last_word_mask();
62 }
63
65 void set() noexcept
66 {
67 storage_t fullMask = static_cast<storage_t>(~storage_t {0});
68 for (uint16_t i = 0; i < storageSize - 1; ++i)
69 _data[i] = fullMask;
70 _data[storageSize - 1] = last_word_mask();
71 }
72
74 void reset() noexcept
75 {
76 for (auto& word: _data)
77 word = 0;
78 }
79
84 void set(uint16_t pos) noexcept
85 {
86 if (pos >= N)
87 return;
88 _data[word_index(pos)] |= bit_mask(pos);
89 }
90
96 void set(uint16_t pos, bool value) noexcept
97 {
98 if (pos >= N)
99 return;
100 if (value)
101 _data[word_index(pos)] |= bit_mask(pos);
102 else
103 _data[word_index(pos)] &= ~bit_mask(pos);
104 }
105
110 void reset(uint16_t pos) noexcept
111 {
112 if (pos >= N)
113 return;
114 _data[word_index(pos)] &= ~bit_mask(pos);
115 }
116
121 void flip(uint16_t pos) noexcept
122 {
123 if (pos >= N)
124 return;
125 _data[word_index(pos)] ^= bit_mask(pos);
126 }
127
133 constexpr bool test(uint16_t pos) const noexcept
134 {
135 if (pos >= N)
136 return false;
137 return (_data[word_index(pos)] & bit_mask(pos)) != 0;
138 }
139
141 constexpr bool operator[](uint16_t pos) const noexcept { return test(pos); }
142
145 {
146 BitSet* parent;
147 uint16_t pos;
148
149 reference& operator=(bool v) noexcept
150 {
151 if (pos >= parent->size())
152 return *this;
153 if (v)
154 parent->_data[parent->word_index(pos)] |= parent->bit_mask(pos);
155 else
156 parent->_data[parent->word_index(pos)] &= ~parent->bit_mask(pos);
157 return *this;
158 }
159
160 reference& operator=(const reference& other) noexcept
161 {
162 if (pos >= parent->size())
163 return *this;
164 bool val = other;
165 if (val)
166 parent->_data[parent->word_index(pos)] |= parent->bit_mask(pos);
167 else
168 parent->_data[parent->word_index(pos)] &= ~parent->bit_mask(pos);
169 return *this;
170 }
171
172 constexpr operator bool() const noexcept
173 {
174 if (pos >= parent->size())
175 return false;
176 return (parent->_data[parent->word_index(pos)] & parent->bit_mask(pos)) != 0;
177 }
178
179 reference& flip() noexcept
180 {
181 if (pos >= parent->size())
182 return *this;
183 parent->_data[parent->word_index(pos)] ^= parent->bit_mask(pos);
184 return *this;
185 }
186 };
187
189 reference operator[](uint16_t pos) noexcept { return reference {this, pos}; }
190
195 constexpr uint16_t count() const noexcept
196 {
197 uint16_t total = 0;
198 for (const auto& word: _data)
199 {
200 storage_t w = word;
201 while (w)
202 {
203 total += static_cast<uint16_t>(w & 1);
204 w >>= 1;
205 }
206 }
207 return total;
208 }
209
211 constexpr bool any() const noexcept
212 {
213 for (const auto& word: _data)
214 if (word != 0)
215 return true;
216 return false;
217 }
218
220 constexpr bool all() const noexcept
221 {
222 storage_t fullMask = static_cast<storage_t>(~storage_t {0});
223 for (uint16_t i = 0; i < storageSize - 1; ++i)
224 if (_data[i] != fullMask)
225 return false;
226 return (_data[storageSize - 1] & last_word_mask()) == last_word_mask();
227 }
228
230 constexpr bool none() const noexcept
231 {
232 for (const auto& word: _data)
233 if (word != 0)
234 return false;
235 return true;
236 }
237
239 void flip() noexcept
240 {
241 storage_t fullMask = static_cast<storage_t>(~storage_t {0});
242 for (uint16_t i = 0; i < storageSize - 1; ++i)
243 _data[i] ^= fullMask;
244 _data[storageSize - 1] ^= last_word_mask();
245 }
246
252 constexpr BitSet<N> operator&(const BitSet<N>& other) const noexcept
253 {
254 BitSet<N> result;
255 for (uint16_t i = 0; i < storageSize; ++i)
256 result._data[i] = _data[i] & other._data[i];
257 return result;
258 }
259
265 constexpr BitSet<N> operator|(const BitSet<N>& other) const noexcept
266 {
267 BitSet<N> result;
268 for (uint16_t i = 0; i < storageSize; ++i)
269 result._data[i] = _data[i] | other._data[i];
270 return result;
271 }
272
278 constexpr BitSet<N> operator-(const BitSet<N>& other) const noexcept
279 {
280 BitSet<N> result;
281 for (uint16_t i = 0; i < storageSize; ++i)
282 result._data[i] = _data[i] & ~other._data[i];
283 return result;
284 }
285
290 BitSet<N> operator~() const noexcept
291 {
292 BitSet<N> result;
293 storage_t fullMask = static_cast<storage_t>(~storage_t {0});
294 for (uint16_t i = 0; i < storageSize - 1; ++i)
295 result._data[i] = ~_data[i];
296 result._data[storageSize - 1] = ~_data[storageSize - 1] & last_word_mask(); // <-- use helper
297 return result;
298 }
299
301 BitSet<N>& operator&=(const BitSet<N>& other) noexcept
302 {
303 for (uint16_t i = 0; i < storageSize; ++i)
304 _data[i] &= other._data[i];
305 return *this;
306 }
307
309 BitSet<N>& operator|=(const BitSet<N>& other) noexcept
310 {
311 for (uint16_t i = 0; i < storageSize; ++i)
312 _data[i] |= other._data[i];
313 return *this;
314 }
315
317 BitSet<N>& operator^=(const BitSet<N>& other) noexcept
318 {
319 for (uint16_t i = 0; i < storageSize; ++i)
320 _data[i] ^= other._data[i];
321 return *this;
322 }
323
325 constexpr bool operator==(const BitSet<N>& other) const noexcept
326 {
327 for (uint16_t i = 0; i < storageSize; ++i)
328 if (_data[i] != other._data[i])
329 return false;
330 return true;
331 }
332
334 constexpr bool operator!=(const BitSet<N>& other) const noexcept { return not operator==(other); }
335
337 static constexpr uint16_t size() noexcept { return N; }
338
340 static constexpr uint16_t size_words() noexcept { return storageSize; }
341};
342
343} // namespace common
344} // namespace lampda
A compact, zero-allocation bitset for compile-time sized bit arrays.
Definition: bitset.h:23
void set(uint16_t pos, bool value) noexcept
Set the bit at position pos to the given value.
Definition: bitset.h:96
void flip() noexcept
Flip all bits.
Definition: bitset.h:239
constexpr bool operator==(const BitSet< N > &other) const noexcept
Check equality with another bitset.
Definition: bitset.h:325
constexpr bool all() const noexcept
Return true if all bits are set.
Definition: bitset.h:220
constexpr bool operator[](uint16_t pos) const noexcept
Alias for test(pos)
Definition: bitset.h:141
void set() noexcept
Set all bits to 1.
Definition: bitset.h:65
constexpr BitSet(storage_t value)
Construct with a single storage value repeated for all words.
Definition: bitset.h:57
BitSet< N > & operator|=(const BitSet< N > &other) noexcept
In-place bitwise OR.
Definition: bitset.h:309
void flip(uint16_t pos) noexcept
Flip (invert) the bit at position pos.
Definition: bitset.h:121
BitSet< N > & operator&=(const BitSet< N > &other) noexcept
In-place bitwise AND.
Definition: bitset.h:301
BitSet< N > operator~() const noexcept
Compute the bitwise NOT of this bitset.
Definition: bitset.h:290
constexpr bool test(uint16_t pos) const noexcept
Get the value of the bit at position pos.
Definition: bitset.h:133
constexpr BitSet< N > operator|(const BitSet< N > &other) const noexcept
Compute the union of this bitset with another.
Definition: bitset.h:265
void set(uint16_t pos) noexcept
Set the bit at position pos to 1.
Definition: bitset.h:84
BitSet< N > & operator^=(const BitSet< N > &other) noexcept
In-place bitwise XOR.
Definition: bitset.h:317
constexpr BitSet< N > operator-(const BitSet< N > &other) const noexcept
Compute the difference of this bitset with another.
Definition: bitset.h:278
constexpr BitSet< N > operator&(const BitSet< N > &other) const noexcept
Compute the intersection of this bitset with another.
Definition: bitset.h:252
constexpr bool none() const noexcept
Return true if no bits are set.
Definition: bitset.h:230
constexpr uint16_t count() const noexcept
Count the number of bits set to 1.
Definition: bitset.h:195
void reset(uint16_t pos) noexcept
Clear the bit at position pos.
Definition: bitset.h:110
constexpr BitSet()
Default constructor: all bits set to zero.
Definition: bitset.h:51
static constexpr uint16_t size() noexcept
Return the number of bits this bitset can hold.
Definition: bitset.h:337
void reset() noexcept
Set all bits to 0.
Definition: bitset.h:74
constexpr bool any() const noexcept
Return true if any bit is set.
Definition: bitset.h:211
static constexpr uint16_t storageSize
The underlying storage type, sized to hold at least N bits.
Definition: bitset.h:27
static constexpr uint16_t size_words() noexcept
Return the number of storage words used.
Definition: bitset.h:340
reference operator[](uint16_t pos) noexcept
Non-const operator[] returning a proxy for bit manipulation.
Definition: bitset.h:189
constexpr bool operator!=(const BitSet< N > &other) const noexcept
Check inequality with another bitset.
Definition: bitset.h:334
Program scope.
Definition: control_fixed_modes.hpp:12
Non-const operator[]: returns a reference-like proxy that allows set/reset.
Definition: bitset.h:145