FastLED 3.9.15
Loading...
Searching...
No Matches
bitset_dynamic.h
Go to the documentation of this file.
1#pragma once
2
3#include <stdint.h>
4#include <string.h> // for memcpy
5
6#include "fl/math_macros.h"
7
8namespace fl {
9
12 private:
13 static constexpr uint32_t bits_per_block = 8 * sizeof(uint64_t);
14 using block_type = uint64_t;
15
16 block_type *_blocks = nullptr;
17 uint32_t _block_count = 0;
18 uint32_t _size = 0;
19
20 // Helper to calculate block count from bit count
21 static uint32_t calc_block_count(uint32_t bit_count) {
22 return (bit_count + bits_per_block - 1) / bits_per_block;
23 }
24
25 public:
26 // Default constructor
27 bitset_dynamic() = default;
28
29 // Constructor with initial size
30 explicit bitset_dynamic(uint32_t size) { resize(size); }
31
32 // Copy constructor
34 if (other._size > 0) {
35 resize(other._size);
36 memcpy(_blocks, other._blocks, _block_count * sizeof(block_type));
37 }
38 }
39
40 // Move constructor
42 : _blocks(other._blocks), _block_count(other._block_count),
43 _size(other._size) {
44 other._blocks = nullptr;
45 other._block_count = 0;
46 other._size = 0;
47 }
48
49 // Copy assignment
51 if (this != &other) {
52 if (other._size > 0) {
53 resize(other._size);
54 memcpy(_blocks, other._blocks,
55 _block_count * sizeof(block_type));
56 } else {
57 clear();
58 }
59 }
60 return *this;
61 }
62
63 // Move assignment
65 if (this != &other) {
66 delete[] _blocks;
67 _blocks = other._blocks;
68 _block_count = other._block_count;
69 _size = other._size;
70 other._blocks = nullptr;
71 other._block_count = 0;
72 other._size = 0;
73 }
74 return *this;
75 }
76
77 // Destructor
78 ~bitset_dynamic() { delete[] _blocks; }
79
80 void assign(size_t n, bool val) {
81 if (n > _size) {
82 resize(n);
83 }
84 if (val) {
85 for (uint32_t i = 0; i < _block_count; ++i) {
86 _blocks[i] = ~0;
87 }
88 } else {
89 reset();
90 }
91 }
92
93 // Resize the bitset
94 void resize(uint32_t new_size) {
95 if (new_size == _size)
96 return;
97
98 uint32_t new_block_count = calc_block_count(new_size);
99
100 if (new_block_count != _block_count) {
101 block_type *new_blocks = nullptr;
102
103 if (new_block_count > 0) {
104 new_blocks = new block_type[new_block_count]();
105
106 // Copy existing data if any
107 if (_blocks && _block_count > 0) {
108 memcpy(new_blocks, _blocks,
109 MIN(_block_count, new_block_count) *
110 sizeof(block_type));
111 }
112 }
113
114 delete[] _blocks;
115 _blocks = new_blocks;
116 _block_count = new_block_count;
117 }
118
119 _size = new_size;
120
121 // Clear any bits beyond the new size
122 if (_block_count > 0) {
123 uint32_t last_block_idx = (_size - 1) / bits_per_block;
124 uint32_t last_bit_pos = (_size - 1) % bits_per_block;
125
126 // Create a mask for valid bits in the last block
127 block_type mask =
128 (static_cast<block_type>(1) << (last_bit_pos + 1)) - 1;
129
130 if (last_block_idx < _block_count) {
131 _blocks[last_block_idx] &= mask;
132
133 // Clear any remaining blocks
134 for (uint32_t i = last_block_idx + 1; i < _block_count; ++i) {
135 _blocks[i] = 0;
136 }
137 }
138 }
139 }
140
141 // Clear the bitset (reset to empty)
142 void clear() {
143 delete[] _blocks;
144 _blocks = nullptr;
145 _block_count = 0;
146 _size = 0;
147 }
148
149 // Reset all bits to 0 without changing size
150 void reset() noexcept {
151 if (_blocks && _block_count > 0) {
152 memset(_blocks, 0, _block_count * sizeof(block_type));
153 }
154 }
155
156 // Reset a specific bit to 0
157 void reset(uint32_t pos) noexcept {
158 if (pos < _size) {
159 const uint32_t idx = pos / bits_per_block;
160 const uint32_t off = pos % bits_per_block;
161 _blocks[idx] &= ~(static_cast<block_type>(1) << off);
162 }
163 }
164
165 // Set a specific bit to 1
166 void set(uint32_t pos) noexcept {
167 if (pos < _size) {
168 const uint32_t idx = pos / bits_per_block;
169 const uint32_t off = pos % bits_per_block;
170 _blocks[idx] |= (static_cast<block_type>(1) << off);
171 }
172 }
173
174 // Set a specific bit to a given value
175 void set(uint32_t pos, bool value) noexcept {
176 if (value) {
177 set(pos);
178 } else {
179 reset(pos);
180 }
181 }
182
183 // Flip a specific bit
184 void flip(uint32_t pos) noexcept {
185 if (pos < _size) {
186 const uint32_t idx = pos / bits_per_block;
187 const uint32_t off = pos % bits_per_block;
188 _blocks[idx] ^= (static_cast<block_type>(1) << off);
189 }
190 }
191
192 // Flip all bits
193 void flip() noexcept {
194 for (uint32_t i = 0; i < _block_count; ++i) {
195 _blocks[i] = ~_blocks[i];
196 }
197
198 // Clear any bits beyond size
199 if (_block_count > 0 && _size % bits_per_block != 0) {
200 uint32_t last_block_idx = (_size - 1) / bits_per_block;
201 uint32_t last_bit_pos = (_size - 1) % bits_per_block;
202 block_type mask =
203 (static_cast<block_type>(1) << (last_bit_pos + 1)) - 1;
204 _blocks[last_block_idx] &= mask;
205 }
206 }
207
208 // Test if a bit is set
209 bool test(uint32_t pos) const noexcept {
210 if (pos < _size) {
211 const uint32_t idx = pos / bits_per_block;
212 const uint32_t off = pos % bits_per_block;
213 return (_blocks[idx] >> off) & 1;
214 }
215 return false;
216 }
217
218 // Count the number of set bits
219 uint32_t count() const noexcept {
220 uint32_t result = 0;
221 for (uint32_t i = 0; i < _block_count; ++i) {
222 block_type v = _blocks[i];
223 // Brian Kernighan's algorithm for counting bits
224 while (v) {
225 v &= (v - 1);
226 ++result;
227 }
228 }
229 return result;
230 }
231
232 // Check if any bit is set
233 bool any() const noexcept {
234 for (uint32_t i = 0; i < _block_count; ++i) {
235 if (_blocks[i] != 0)
236 return true;
237 }
238 return false;
239 }
240
241 // Check if no bit is set
242 bool none() const noexcept { return !any(); }
243
244 // Check if all bits are set
245 bool all() const noexcept {
246 if (_size == 0)
247 return true;
248
249 for (uint32_t i = 0; i < _block_count - 1; ++i) {
250 if (_blocks[i] != ~static_cast<block_type>(0))
251 return false;
252 }
253
254 // Check last block with mask for valid bits
255 if (_block_count > 0) {
256 uint32_t last_bit_pos = (_size - 1) % bits_per_block;
257 block_type mask =
258 (static_cast<block_type>(1) << (last_bit_pos + 1)) - 1;
259 return (_blocks[_block_count - 1] & mask) == mask;
260 }
261
262 return true;
263 }
264
265 // Get the size of the bitset
266 uint32_t size() const noexcept { return _size; }
267
268 // Access operator
269 bool operator[](uint32_t pos) const noexcept { return test(pos); }
270
271 // Bitwise AND operator
273 bitset_dynamic result(_size);
274 uint32_t min_blocks = MIN(_block_count, other._block_count);
275
276 for (uint32_t i = 0; i < min_blocks; ++i) {
277 result._blocks[i] = _blocks[i] & other._blocks[i];
278 }
279
280 return result;
281 }
282
283 // Bitwise OR operator
285 bitset_dynamic result(_size);
286 uint32_t min_blocks = MIN(_block_count, other._block_count);
287
288 for (uint32_t i = 0; i < min_blocks; ++i) {
289 result._blocks[i] = _blocks[i] | other._blocks[i];
290 }
291
292 // Copy remaining blocks from the larger bitset
293 if (_block_count > min_blocks) {
294 memcpy(result._blocks + min_blocks, _blocks + min_blocks,
295 (_block_count - min_blocks) * sizeof(block_type));
296 }
297
298 return result;
299 }
300
301 // Bitwise XOR operator
303 bitset_dynamic result(_size);
304 uint32_t min_blocks = MIN(_block_count, other._block_count);
305
306 for (uint32_t i = 0; i < min_blocks; ++i) {
307 result._blocks[i] = _blocks[i] ^ other._blocks[i];
308 }
309
310 // Copy remaining blocks from the larger bitset
311 if (_block_count > min_blocks) {
312 memcpy(result._blocks + min_blocks, _blocks + min_blocks,
313 (_block_count - min_blocks) * sizeof(block_type));
314 }
315
316 return result;
317 }
318
319 // Bitwise NOT operator
321 bitset_dynamic result(_size);
322
323 for (uint32_t i = 0; i < _block_count; ++i) {
324 result._blocks[i] = ~_blocks[i];
325 }
326
327 // Clear any bits beyond size
328 if (_block_count > 0 && _size % bits_per_block != 0) {
329 uint32_t last_block_idx = (_size - 1) / bits_per_block;
330 uint32_t last_bit_pos = (_size - 1) % bits_per_block;
331 block_type mask =
332 (static_cast<block_type>(1) << (last_bit_pos + 1)) - 1;
333 result._blocks[last_block_idx] &= mask;
334 }
335
336 return result;
337 }
338};
339
340} // namespace fl
uint8_t pos
Definition Blur.ino:11
bool all() const noexcept
bitset_dynamic & operator=(const bitset_dynamic &other)
uint32_t size() const noexcept
void set(uint32_t pos, bool value) noexcept
bool none() const noexcept
bool test(uint32_t pos) const noexcept
bitset_dynamic operator&(const bitset_dynamic &other) const
bool operator[](uint32_t pos) const noexcept
static uint32_t calc_block_count(uint32_t bit_count)
bitset_dynamic operator|(const bitset_dynamic &other) const
void resize(uint32_t new_size)
void reset(uint32_t pos) noexcept
bitset_dynamic(const bitset_dynamic &other)
void flip(uint32_t pos) noexcept
void assign(size_t n, bool val)
void set(uint32_t pos) noexcept
void reset() noexcept
bitset_dynamic operator~() const
static constexpr uint32_t bits_per_block
void flip() noexcept
block_type * _blocks
bitset_dynamic()=default
bool any() const noexcept
bitset_dynamic(uint32_t size)
bitset_dynamic operator^(const bitset_dynamic &other) const
bitset_dynamic(bitset_dynamic &&other) noexcept
uint32_t count() const noexcept
bitset_dynamic & operator=(bitset_dynamic &&other) noexcept
#define MIN(a, b)
Definition math_macros.h:15
Implements a simple red square effect for 2D LED grids.
Definition crgb.h:16