FastLED 3.9.15
Loading...
Searching...
No Matches

◆ FL_DISABLE_WARNING()

FL_DISABLE_WARNING_PUSH FL_DISABLE_WARNING ( double- promotion)

A simple fixed-size Bitset implementation similar to std::Bitset.

Constructs a bitset_fixed with all bits reset.

Resets all bits to zero.

Sets or clears the bit at position pos.

Clears the bit at position pos.

Flips (toggles) the bit at position pos.

Flips all bits.

Tests whether the bit at position pos is set.

Returns the value of the bit at position pos.

Returns the number of set bits.

Queries.

Bitwise AND

Bitwise OR

Bitwise XOR

Size of the bitset_fixed (number of bits).

Finds the first bit that matches the test value. Returns the index of the first matching bit, or -1 if none found.

Parameters
test_valueThe value to search for (true or false)
offsetStarting position to search from (default: 0)

Finds the first run of consecutive bits that match the test value. Returns the index of the first bit in the run, or -1 if no run found.

Parameters
test_valueThe value to search for (true or false)
min_lengthMinimum length of the run (default: 1)
offsetStarting position to search from (default: 0)

Equality comparison

Lexicographic comparison

Friend operators for convenience.

A Bitset implementation with inline storage that can grow if needed. T is the storage type (u8, u16, u32, u64) N is the initial number of bits to store inline

Constructs a Bitset with all bits reset.

Resets all bits to zero.

Resizes the Bitset if needed

Sets or clears the bit at position pos.

Clears the bit at position pos.

Flips (toggles) the bit at position pos.

Flips all bits.

Add a bit to the end (initialized to 0)

Emplace back - for consistency with other containers

Remove the last bit

Tests whether the bit at position pos is set.

Returns the value of the bit at position pos.

Returns the number of set bits.

Queries.

Size of the Bitset (number of bits).

Convert bitset to string representation

Finds the first bit that matches the test value. Returns the index of the first matching bit, or -1 if none found.

Parameters
test_valueThe value to search for (true or false)
offsetStarting position to search from (default: 0)

Bitwise operators

Equality comparison

Lexicographic comparison

Definition at line 13 of file bitset.h.

20 {
21
22template <fl::u32 N> class bitset_inlined;
23
24template <fl::u32 N> class bitset_fixed;
25
26class string;
27template <fl::u32 N = 16>
28using bitset = bitset_inlined<N>; // inlined but can go bigger.
29
30
31// TODO: move this to fl/math.h
32template<typename IntType>
33inline fl::u8 popcount(IntType value) FL_NOEXCEPT {
34 return static_cast<fl::u8>(__builtin_popcount(value));
35}
36
37template<typename IntType>
38inline fl::u8 countr_zero(IntType value) FL_NOEXCEPT {
39 return static_cast<fl::u8>(__builtin_ctz(value));
40}
41
43template <fl::u32 N> class bitset_fixed {
44 private:
45 FL_STATIC_ASSERT(sizeof(fl::u16) == 2, "u16 should be 2 bytes");
46 static constexpr fl::u32 bits_per_block = 8 * sizeof(fl::u16);
47 static constexpr fl::u32 block_count =
48 (N + bits_per_block - 1) / bits_per_block;
49 using block_type = fl::u16;
50
51 // Underlying blocks storing bits
52 block_type _blocks[block_count];
53
54 public:
55 struct Proxy {
56 bitset_fixed &_bitset;
57 fl::u32 _pos;
58
59 Proxy(bitset_fixed &bitset, fl::u32 pos) FL_NOEXCEPT : _bitset(bitset), _pos(pos) {}
60
61 Proxy &operator=(bool value) FL_NOEXCEPT {
62 _bitset.set(_pos, value);
63 return *this;
64 }
65
66 operator bool() const FL_NOEXCEPT { return _bitset.test(_pos); }
67 };
68
69 Proxy operator[](fl::u32 pos) FL_NOEXCEPT { return Proxy(*this, pos); }
70
72 constexpr bitset_fixed() FL_NOEXCEPT : _blocks{} {}
73
74 void to_string(string* dst) const FL_NOEXCEPT {
75 detail::to_string(_blocks, N, dst);
76 }
77
79 void reset() FL_NOEXCEPT {
80 for (fl::u32 i = 0; i < block_count; ++i) {
81 _blocks[i] = 0;
82 }
83 }
84
86 bitset_fixed &set(fl::u32 pos, bool value = true) FL_NOEXCEPT {
87 if (pos < N) {
88 const fl::u32 idx = pos / bits_per_block;
89 const fl::u32 off = pos % bits_per_block;
90 if (value) {
91 _blocks[idx] |= (block_type(1) << off);
92 } else {
93 _blocks[idx] &= ~(block_type(1) << off);
94 }
95 }
96 return *this;
97 }
98
99 void assign(fl::size n, bool value) FL_NOEXCEPT {
100 if (n > N) {
101 n = N;
102 }
103 for (fl::size i = 0; i < n; ++i) {
104 set(i, value);
105 }
106 }
107
109 bitset_fixed &reset(fl::u32 pos) FL_NOEXCEPT { return set(pos, false); }
110
112 bitset_fixed &flip(fl::u32 pos) FL_NOEXCEPT {
113 if (pos < N) {
114 const fl::u32 idx = pos / bits_per_block;
115 const fl::u32 off = pos % bits_per_block;
116 _blocks[idx] ^= (block_type(1) << off);
117 }
118 return *this;
119 }
120
122 bitset_fixed &flip() FL_NOEXCEPT {
123 for (fl::u32 i = 0; i < block_count; ++i) {
124 _blocks[i] = ~_blocks[i];
125 }
126 // Mask out unused high bits in the last block
127 if (N % bits_per_block != 0) {
128 const fl::u32 extra = bits_per_block - (N % bits_per_block);
129 _blocks[block_count - 1] &= (~block_type(0) >> extra);
130 }
131 return *this;
132 }
133
135 bool test(fl::u32 pos) const FL_NOEXCEPT {
136 if (pos < N) {
137 const fl::u32 idx = pos / bits_per_block;
138 const fl::u32 off = pos % bits_per_block;
139 return (_blocks[idx] >> off) & 1;
140 }
141 return false;
142 }
143
145 bool operator[](fl::u32 pos) const FL_NOEXCEPT { return test(pos); }
146
148 fl::u32 count() const FL_NOEXCEPT {
149 fl::u32 cnt = 0;
150 // Count bits in all complete blocks
151 for (fl::u32 i = 0; i < block_count - 1; ++i) {
152 cnt += fl::popcount(_blocks[i]);
153 }
154
155 // For the last block, we need to be careful about counting only valid
156 // bits
157 if (block_count > 0) {
158 block_type last_block = _blocks[block_count - 1];
159 // If N is not a multiple of bits_per_block, mask out the unused
160 // bits
161 if (N % bits_per_block != 0) {
162 const fl::u32 valid_bits = N % bits_per_block;
163 // Create a mask with only the valid bits set to 1
164 block_type mask = (valid_bits == bits_per_block)
165 ? static_cast<block_type>(~block_type(0))
166 : ((block_type(1) << valid_bits) - 1);
167 last_block &= mask;
168 }
169 cnt += fl::popcount(last_block);
170 }
171
172 return cnt;
173 }
174
176 bool any() const FL_NOEXCEPT { return count() > 0; }
177 bool none() const FL_NOEXCEPT { return count() == 0; }
178 bool all() const FL_NOEXCEPT {
179 if (N == 0)
180 return true;
181
182 // Check all complete blocks
183 for (fl::u32 i = 0; i < block_count - 1; ++i) {
184 if (_blocks[i] != ~block_type(0)) {
185 return false;
186 }
187 }
188
189 // Check the last block
190 if (block_count > 0) {
191 block_type mask;
192 if (N % bits_per_block != 0) {
193 // Create a mask for the valid bits in the last block
194 mask = (block_type(1) << (N % bits_per_block)) - 1;
195 } else {
196 mask = static_cast<block_type>(~block_type(0));
197 }
198
199 if ((_blocks[block_count - 1] & mask) != mask) {
200 return false;
201 }
202 }
203
204 return true;
205 }
206
208 bitset_fixed &operator&=(const bitset_fixed &other) FL_NOEXCEPT {
209 for (fl::u32 i = 0; i < block_count; ++i) {
210 _blocks[i] &= other._blocks[i];
211 }
212 return *this;
213 }
215 bitset_fixed &operator|=(const bitset_fixed &other) FL_NOEXCEPT {
216 for (fl::u32 i = 0; i < block_count; ++i) {
217 _blocks[i] |= other._blocks[i];
218 }
219 return *this;
220 }
222 bitset_fixed &operator^=(const bitset_fixed &other) FL_NOEXCEPT {
223 for (fl::u32 i = 0; i < block_count; ++i) {
224 _blocks[i] ^= other._blocks[i];
225 }
226 return *this;
227 }
228
230 constexpr fl::u32 size() const FL_NOEXCEPT { return N; }
231
236 fl::i32 find_first(bool test_value, fl::u32 offset = 0) const FL_NOEXCEPT {
237 // If offset is beyond our size, no match possible
238 if (offset >= N) {
239 return -1;
240 }
241
242 // Calculate which block to start from
243 fl::u32 start_block = offset / bits_per_block;
244 fl::u32 start_bit = offset % bits_per_block;
245
246 for (fl::u32 block_idx = start_block; block_idx < block_count; ++block_idx) {
247 block_type current_block = _blocks[block_idx];
248
249 // For the last block, we need to mask out unused bits
250 if (block_idx == block_count - 1 && N % bits_per_block != 0) {
251 const fl::u32 valid_bits = N % bits_per_block;
252 block_type mask = (valid_bits == bits_per_block)
253 ? static_cast<block_type>(~block_type(0))
254 : ((block_type(1) << valid_bits) - 1);
255 current_block &= mask;
256 }
257
258 // If looking for false bits, invert the block
259 if (!test_value) {
260 current_block = ~current_block;
261 }
262
263 // For the first block, mask out bits before the offset
264 if (block_idx == start_block && start_bit > 0) {
265 current_block &= ~((block_type(1) << start_bit) - 1);
266 }
267
268 // If there are any matching bits in this block
269 if (current_block != 0) {
270 // Find the first set bit
271 fl::u32 bit_pos = fl::countr_zero(current_block);
272 fl::u32 absolute_pos = block_idx * bits_per_block + bit_pos;
273
274 // Make sure we haven't gone past the end of the bitset
275 if (absolute_pos < N) {
276 return static_cast<fl::i32>(absolute_pos);
277 }
278 }
279 }
280
281 return -1; // No matching bit found
282 }
283
289 fl::i32 find_run(bool test_value, fl::u32 min_length, fl::u32 offset = 0) const FL_NOEXCEPT {
290 fl::u32 run_start = offset;
291 fl::u32 run_length = 0;
292
293 for (fl::u32 i = offset; i < N && run_length < min_length; ++i) {
294 bool current_bit = test(i);
295 if (current_bit != test_value) {
296 run_length = 0;
297 if (i + 1 < N) {
298 run_start = i + 1;
299 }
300 } else {
301 ++run_length;
302 }
303 }
304
305 if (run_length >= min_length) {
306 return static_cast<fl::i32>(run_start);
307 }
308
309 return -1; // No run found
310 }
311
313 bool operator==(const bitset_fixed &other) const FL_NOEXCEPT {
314 for (fl::u32 i = 0; i < block_count; ++i) {
315 if (_blocks[i] != other._blocks[i]) {
316 return false;
317 }
318 }
319 return true;
320 }
321
322 bool operator!=(const bitset_fixed &other) const FL_NOEXCEPT {
323 return !(*this == other);
324 }
325
327 bool operator<(const bitset_fixed &other) const FL_NOEXCEPT {
328 for (fl::i32 i = static_cast<fl::i32>(block_count) - 1; i >= 0; --i) {
329 if (_blocks[i] < other._blocks[i]) {
330 return true;
331 }
332 if (_blocks[i] > other._blocks[i]) {
333 return false;
334 }
335 }
336 return false;
337 }
338
339 bool operator<=(const bitset_fixed &other) const FL_NOEXCEPT {
340 return *this < other || *this == other;
341 }
342
343 bool operator>(const bitset_fixed &other) const FL_NOEXCEPT {
344 return other < *this;
345 }
346
347 bool operator>=(const bitset_fixed &other) const FL_NOEXCEPT {
348 return other <= *this;
349 }
350
352 friend bitset_fixed operator&(bitset_fixed lhs,
353 const bitset_fixed &rhs) FL_NOEXCEPT {
354 return lhs &= rhs;
355 }
356 friend bitset_fixed operator|(bitset_fixed lhs,
357 const bitset_fixed &rhs) FL_NOEXCEPT {
358 return lhs |= rhs;
359 }
360 friend bitset_fixed operator^(bitset_fixed lhs,
361 const bitset_fixed &rhs) FL_NOEXCEPT {
362 return lhs ^= rhs;
363 }
364 friend bitset_fixed operator~(bitset_fixed bs) FL_NOEXCEPT { return bs.flip(); }
365};
366
370template <fl::u32 N = 16> // Default size is 16 bits, or 2 bytes
371class bitset_inlined {
372 private:
373 // Either store a fixed Bitset<N> or a dynamic Bitset
374 using fixed_bitset = bitset_fixed<N>;
375 variant<fixed_bitset, bitset_dynamic> _storage;
376
377 public:
378 struct Proxy {
379 bitset_inlined &_bitset;
380 fl::u32 _pos;
381
382 Proxy(bitset_inlined &bitset, fl::u32 pos) FL_NOEXCEPT
383 : _bitset(bitset), _pos(pos) {}
384
385 Proxy &operator=(bool value) FL_NOEXCEPT {
386 _bitset.set(_pos, value);
387 return *this;
388 }
389
390 operator bool() const FL_NOEXCEPT { return _bitset.test(_pos); }
391 };
392
393 Proxy operator[](fl::u32 pos) FL_NOEXCEPT { return Proxy(*this, pos); }
394
396 bitset_inlined() FL_NOEXCEPT : _storage(fixed_bitset()) {}
397 bitset_inlined(fl::size size) FL_NOEXCEPT : _storage(fixed_bitset()) {
398 if (size > N) {
399 _storage = bitset_dynamic(size);
400 }
401 }
402 bitset_inlined(const bitset_inlined &other) FL_NOEXCEPT : _storage(other._storage) {}
403 bitset_inlined(bitset_inlined &&other) FL_NOEXCEPT
404 : _storage(fl::move(other._storage)) {}
405 bitset_inlined &operator=(const bitset_inlined &other) FL_NOEXCEPT {
406 if (this != &other) {
407 _storage = other._storage;
408 }
409 return *this;
410 }
411 bitset_inlined &operator=(bitset_inlined &&other) FL_NOEXCEPT {
412 if (this != &other) {
413 _storage = fl::move(other._storage);
414 }
415 return *this;
416 }
417
419 void reset() FL_NOEXCEPT {
420 if (_storage.template is<fixed_bitset>()) {
421 _storage.template ptr<fixed_bitset>()->reset();
422 } else {
423 _storage.template ptr<bitset_dynamic>()->reset();
424 }
425 }
426
427 void assign(fl::size n, bool value) FL_NOEXCEPT {
428 resize(n);
429 if (_storage.template is<fixed_bitset>()) {
430 _storage.template ptr<fixed_bitset>()->assign(n, value);
431 } else {
432 _storage.template ptr<bitset_dynamic>()->assign(n, value);
433 }
434 }
435
436
437
439 void resize(fl::u32 new_size) FL_NOEXCEPT {
440 if (new_size <= N) {
441 // If we're already using the fixed Bitset, nothing to do
442 if (_storage.template is<bitset_dynamic>()) {
443 // Convert back to fixed Bitset
444 fixed_bitset fixed;
445 bitset_dynamic *dynamic =
446 _storage.template ptr<bitset_dynamic>();
447
448 // Copy bits from dynamic to fixed
449 for (fl::u32 i = 0; i < N && i < dynamic->size(); ++i) {
450 if (dynamic->test(i)) {
451 fixed.set(i);
452 }
453 }
454
455 _storage = fixed;
456 }
457 } else {
458 // Need to use dynamic Bitset
459 if (_storage.template is<fixed_bitset>()) {
460 // Convert from fixed to dynamic
461 bitset_dynamic dynamic(new_size);
462 fixed_bitset *fixed = _storage.template ptr<fixed_bitset>();
463
464 // Copy bits from fixed to dynamic
465 for (fl::u32 i = 0; i < N; ++i) {
466 if (fixed->test(i)) {
467 dynamic.set(i);
468 }
469 }
470
471 _storage = dynamic;
472 } else {
473 // Already using dynamic, just resize
474 _storage.template ptr<bitset_dynamic>()->resize(new_size);
475 }
476 }
477 }
478
480 bitset_inlined &set(fl::u32 pos, bool value = true) FL_NOEXCEPT {
481 if (pos >= N && _storage.template is<fixed_bitset>()) {
482 resize(pos + 1);
483 }
484
485 if (_storage.template is<fixed_bitset>()) {
486 if (pos < N) {
487 _storage.template ptr<fixed_bitset>()->set(pos, value);
488 }
489 } else {
490 if (pos >= _storage.template ptr<bitset_dynamic>()->size()) {
491 _storage.template ptr<bitset_dynamic>()->resize(pos + 1);
492 }
493 _storage.template ptr<bitset_dynamic>()->set(pos, value);
494 }
495 return *this;
496 }
497
499 bitset_inlined &reset(fl::u32 pos) FL_NOEXCEPT { return set(pos, false); }
500
502 bitset_inlined &flip(fl::u32 pos) FL_NOEXCEPT {
503 if (pos >= N && _storage.template is<fixed_bitset>()) {
504 resize(pos + 1);
505 }
506
507 if (_storage.template is<fixed_bitset>()) {
508 if (pos < N) {
509 _storage.template ptr<fixed_bitset>()->flip(pos);
510 }
511 } else {
512 if (pos >= _storage.template ptr<bitset_dynamic>()->size()) {
513 _storage.template ptr<bitset_dynamic>()->resize(pos + 1);
514 }
515 _storage.template ptr<bitset_dynamic>()->flip(pos);
516 }
517 return *this;
518 }
519
521 bitset_inlined &flip() FL_NOEXCEPT {
522 if (_storage.template is<fixed_bitset>()) {
523 _storage.template ptr<fixed_bitset>()->flip();
524 } else {
525 _storage.template ptr<bitset_dynamic>()->flip();
526 }
527 return *this;
528 }
529
531 void push_back() FL_NOEXCEPT {
532 fl::u32 new_size = size() + 1;
533 resize(new_size);
534 }
535
537 template<typename... Args>
538 void emplace_back(Args&&...) FL_NOEXCEPT {
539 push_back(); // bitset bits are bool, just expand
540 }
541
543 void pop_back() FL_NOEXCEPT {
544 if (size() > 0) {
545 resize(size() - 1);
546 }
547 }
548
550 bool test(fl::u32 pos) const FL_NOEXCEPT {
551 if (_storage.template is<fixed_bitset>()) {
552 return pos < N ? _storage.template ptr<fixed_bitset>()->test(pos)
553 : false;
554 } else {
555 return _storage.template ptr<bitset_dynamic>()->test(pos);
556 }
557 }
558
560 bool operator[](fl::u32 pos) const FL_NOEXCEPT { return test(pos); }
561
563 fl::u32 count() const FL_NOEXCEPT {
564 if (_storage.template is<fixed_bitset>()) {
565 return _storage.template ptr<fixed_bitset>()->count();
566 } else {
567 return _storage.template ptr<bitset_dynamic>()->count();
568 }
569 }
570
572 bool any() const FL_NOEXCEPT {
573 if (_storage.template is<fixed_bitset>()) {
574 return _storage.template ptr<fixed_bitset>()->any();
575 } else {
576 return _storage.template ptr<bitset_dynamic>()->any();
577 }
578 }
579
580 bool none() const FL_NOEXCEPT {
581 if (_storage.template is<fixed_bitset>()) {
582 return _storage.template ptr<fixed_bitset>()->none();
583 } else {
584 return _storage.template ptr<bitset_dynamic>()->none();
585 }
586 }
587
588 bool all() const FL_NOEXCEPT {
589 if (_storage.template is<fixed_bitset>()) {
590 return _storage.template ptr<fixed_bitset>()->all();
591 } else {
592 return _storage.template ptr<bitset_dynamic>()->all();
593 }
594 }
595
597 fl::u32 size() const FL_NOEXCEPT {
598 if (_storage.template is<fixed_bitset>()) {
599 return N;
600 } else {
601 return _storage.template ptr<bitset_dynamic>()->size();
602 }
603 }
604
606 void to_string(string* dst) const FL_NOEXCEPT {
607 if (_storage.template is<fixed_bitset>()) {
608 _storage.template ptr<fixed_bitset>()->to_string(dst);
609 } else {
610 _storage.template ptr<bitset_dynamic>()->to_string(dst);
611 }
612 }
613
618 fl::i32 find_first(bool test_value, fl::u32 offset = 0) const FL_NOEXCEPT {
619 if (_storage.template is<fixed_bitset>()) {
620 return _storage.template ptr<fixed_bitset>()->find_first(test_value, offset);
621 } else {
622 return _storage.template ptr<bitset_dynamic>()->find_first(test_value, offset);
623 }
624 }
625
627 friend bitset_inlined operator~(const bitset_inlined &bs) FL_NOEXCEPT {
628 bitset_inlined result = bs;
629 result.flip();
630 return result;
631 }
632
633 friend bitset_inlined operator&(const bitset_inlined &lhs,
634 const bitset_inlined &rhs) FL_NOEXCEPT {
635 bitset_inlined result = lhs;
636
637 if (result._storage.template is<fixed_bitset>() &&
638 rhs._storage.template is<fixed_bitset>()) {
639 // Both are fixed, use the fixed implementation
640 *result._storage.template ptr<fixed_bitset>() &=
641 *rhs._storage.template ptr<fixed_bitset>();
642 } else {
643 // At least one is dynamic, handle bit by bit
644 fl::u32 min_size =
645 result.size() < rhs.size() ? result.size() : rhs.size();
646 for (fl::u32 i = 0; i < min_size; ++i) {
647 result.set(i, result.test(i) && rhs.test(i));
648 }
649 // Clear any bits beyond the size of rhs
650 for (fl::u32 i = min_size; i < result.size(); ++i) {
651 result.reset(i);
652 }
653 }
654
655 return result;
656 }
657
658 friend bitset_inlined operator|(const bitset_inlined &lhs,
659 const bitset_inlined &rhs) FL_NOEXCEPT {
660 bitset_inlined result = lhs;
661
662 if (result._storage.template is<fixed_bitset>() &&
663 rhs._storage.template is<fixed_bitset>()) {
664 // Both are fixed, use the fixed implementation
665 *result._storage.template ptr<fixed_bitset>() |=
666 *rhs._storage.template ptr<fixed_bitset>();
667 } else {
668 // At least one is dynamic, handle bit by bit
669 fl::u32 max_size =
670 result.size() > rhs.size() ? result.size() : rhs.size();
671
672 // Resize if needed
673 if (result.size() < max_size) {
674 result.resize(max_size);
675 }
676
677 // Set bits from rhs
678 for (fl::u32 i = 0; i < rhs.size(); ++i) {
679 if (rhs.test(i)) {
680 result.set(i);
681 }
682 }
683 }
684
685 return result;
686 }
687
688 friend bitset_inlined operator^(const bitset_inlined &lhs,
689 const bitset_inlined &rhs) FL_NOEXCEPT {
690 bitset_inlined result = lhs;
691
692 if (result._storage.template is<fixed_bitset>() &&
693 rhs._storage.template is<fixed_bitset>()) {
694 // Both are fixed, use the fixed implementation
695 *result._storage.template ptr<fixed_bitset>() ^=
696 *rhs._storage.template ptr<fixed_bitset>();
697 } else {
698 // At least one is dynamic, handle bit by bit
699 fl::u32 max_size =
700 result.size() > rhs.size() ? result.size() : rhs.size();
701
702 // Resize if needed
703 if (result.size() < max_size) {
704 result.resize(max_size);
705 }
706
707 // XOR bits from rhs
708 for (fl::u32 i = 0; i < rhs.size(); ++i) {
709 result.set(i, result.test(i) != rhs.test(i));
710 }
711 }
712
713 return result;
714 }
715
717 bool operator==(const bitset_inlined &other) const FL_NOEXCEPT {
718 if (size() != other.size()) {
719 return false;
720 }
721 for (fl::u32 i = 0; i < size(); ++i) {
722 if (test(i) != other.test(i)) {
723 return false;
724 }
725 }
726 return true;
727 }
728
729 bool operator!=(const bitset_inlined &other) const FL_NOEXCEPT {
730 return !(*this == other);
731 }
732
734 bool operator<(const bitset_inlined &other) const FL_NOEXCEPT {
735 fl::u32 min_size = size() < other.size() ? size() : other.size();
736 for (fl::u32 i = min_size; i > 0; --i) {
737 bool this_bit = test(i - 1);
738 bool other_bit = other.test(i - 1);
739 if (this_bit != other_bit) {
740 return !this_bit; // false < true
741 }
742 }
743 // All common bits are equal, shorter is less
744 return size() < other.size();
745 }
746
747 bool operator<=(const bitset_inlined &other) const FL_NOEXCEPT {
748 return *this < other || *this == other;
749 }
750
751 bool operator>(const bitset_inlined &other) const FL_NOEXCEPT {
752 return other < *this;
753 }
754
755 bool operator>=(const bitset_inlined &other) const FL_NOEXCEPT {
756 return other <= *this;
757 }
758};
759
760} // namespace fl
uint8_t pos
Definition Blur.ino:11
ClearFlags & operator|=(ClearFlags &a, ClearFlags b)
Enable bitwise OR assignment for ClearFlags.
Definition FastLED.h:599
ClearFlags operator|(ClearFlags a, ClearFlags b)
Enable bitwise OR for ClearFlags.
Definition FastLED.h:589
ClearFlags operator&(ClearFlags a, ClearFlags b)
Enable bitwise AND for ClearFlags.
Definition FastLED.h:594
fl::UISlider offset("Offset", 0.0f, 0.0f, 1.0f, 0.01f)
void to_string(const fl::u16 *bit_data, fl::u32 bit_count, string *dst)
Definition bitset.cpp.hpp:9
constexpr remove_reference< T >::type && move(T &&t) FL_NOEXCEPT
Definition move.h:28
unsigned char u8
Definition stdint.h:131
FASTLED_FORCE_INLINE bool operator!=(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if two CRGB objects do not have the same color data.
Definition crgb.h:739
FASTLED_FORCE_INLINE bool operator<(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if the sum of the color channels in one CRGB object is less than another.
Definition crgb.h:745
FASTLED_FORCE_INLINE bool operator==(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if two CRGB objects have the same color data.
Definition crgb.h:733
FASTLED_FORCE_INLINE bool operator>(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if the sum of the color channels in one CRGB object is greater than another.
Definition crgb.h:754
expected< T, E > result
Alias for expected (Rust-style naming)
Definition result.h:31
FASTLED_FORCE_INLINE bool operator<=(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if the sum of the color channels in one CRGB object is less than or equal to another.
Definition crgb.h:772
FASTLED_FORCE_INLINE bool operator>=(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if the sum of the color channels in one CRGB object is greater than or equal to another.
Definition crgb.h:763
#define FL_STATIC_ASSERT(...)
#define FL_NOEXCEPT

References FL_DISABLE_WARNING_FLOAT_CONVERSION, FL_DISABLE_WARNING_IMPLICIT_INT_CONVERSION, FL_NOEXCEPT, FL_STATIC_ASSERT, fl::fl::move(), fl::move(), offset(), fl::operator!=(), fl::operator&(), fl::operator<(), fl::operator<=(), fl::operator==(), fl::operator>(), fl::operator>=(), fl::operator|(), operator|=(), pos, fl::detail::to_string(), fl::to_string(), and fl::type_rank< T >::value.

+ Here is the call graph for this function: