1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // bitset_utils:
7 // Bitset-related helper classes, such as a fast iterator to scan for set bits.
8 //
9
10 #ifndef COMMON_BITSETITERATOR_H_
11 #define COMMON_BITSETITERATOR_H_
12
13 #include <stdint.h>
14
15 #include <array>
16
17 #include "common/angleutils.h"
18 #include "common/debug.h"
19 #include "common/mathutil.h"
20 #include "common/platform.h"
21
22 namespace angle
23 {
24 // Given x, create 1 << x.
25 template <typename BitsT, typename ParamT>
Bit(ParamT x)26 constexpr BitsT Bit(ParamT x)
27 {
28 // It's undefined behavior if the shift size is equal to or larger than the width of the type.
29 ASSERT(static_cast<size_t>(x) < sizeof(BitsT) * 8);
30
31 return (static_cast<BitsT>(1) << static_cast<size_t>(x));
32 }
33
34 // Given x, create (1 << x) - 1, i.e. a mask with x bits set.
35 template <typename BitsT, typename ParamT>
BitMask(ParamT x)36 constexpr BitsT BitMask(ParamT x)
37 {
38 if (static_cast<size_t>(x) == 0)
39 {
40 return 0;
41 }
42 return ((Bit<BitsT>(static_cast<ParamT>(static_cast<size_t>(x) - 1)) - 1) << 1) | 1;
43 }
44
45 template <size_t N, typename BitsT, typename ParamT = std::size_t>
46 class BitSetT final
47 {
48 public:
49 class Reference final
50 {
51 public:
~Reference()52 ~Reference() {}
53 Reference &operator=(bool x)
54 {
55 mParent->set(mBit, x);
56 return *this;
57 }
58 explicit operator bool() const { return mParent->test(mBit); }
59
60 private:
61 friend class BitSetT;
62
Reference(BitSetT * parent,ParamT bit)63 Reference(BitSetT *parent, ParamT bit) : mParent(parent), mBit(bit) {}
64
65 BitSetT *mParent;
66 ParamT mBit;
67 };
68
69 class Iterator final
70 {
71 public:
72 Iterator(const BitSetT &bits);
73 Iterator &operator++();
74
75 bool operator==(const Iterator &other) const;
76 bool operator!=(const Iterator &other) const;
77 ParamT operator*() const;
78
79 // These helper functions allow mutating an iterator in-flight.
80 // They only operate on later bits to ensure we don't iterate the same bit twice.
resetLaterBit(std::size_t index)81 void resetLaterBit(std::size_t index)
82 {
83 ASSERT(index > mCurrentBit);
84 mBitsCopy.reset(index);
85 }
86
setLaterBit(std::size_t index)87 void setLaterBit(std::size_t index)
88 {
89 ASSERT(index > mCurrentBit);
90 mBitsCopy.set(index);
91 }
92
setLaterBits(const BitSetT & bits)93 void setLaterBits(const BitSetT &bits)
94 {
95 ASSERT((BitSetT(bits) &= Mask(mCurrentBit + 1)).none());
96 mBitsCopy |= bits;
97 }
98
99 private:
100 std::size_t getNextBit();
101
102 BitSetT mBitsCopy;
103 std::size_t mCurrentBit;
104 };
105
106 using value_type = BitsT;
107 using param_type = ParamT;
108
109 constexpr BitSetT();
110 constexpr explicit BitSetT(BitsT value);
111 constexpr explicit BitSetT(std::initializer_list<ParamT> init);
112
113 constexpr BitSetT(const BitSetT &other);
114 constexpr BitSetT &operator=(const BitSetT &other);
115
116 constexpr bool operator==(const BitSetT &other) const;
117 constexpr bool operator!=(const BitSetT &other) const;
118
119 constexpr bool operator[](ParamT pos) const;
120 Reference operator[](ParamT pos) { return Reference(this, pos); }
121
122 constexpr bool test(ParamT pos) const;
123
124 constexpr bool all() const;
125 constexpr bool any() const;
126 constexpr bool none() const;
127 constexpr std::size_t count() const;
128
size()129 constexpr std::size_t size() const { return N; }
130
131 constexpr BitSetT &operator&=(const BitSetT &other);
132 constexpr BitSetT &operator|=(const BitSetT &other);
133 constexpr BitSetT &operator^=(const BitSetT &other);
134 constexpr BitSetT operator~() const;
135
136 constexpr BitSetT &operator&=(BitsT value);
137 constexpr BitSetT &operator|=(BitsT value);
138 constexpr BitSetT &operator^=(BitsT value);
139
140 constexpr BitSetT operator<<(std::size_t pos) const;
141 constexpr BitSetT &operator<<=(std::size_t pos);
142 constexpr BitSetT operator>>(std::size_t pos) const;
143 constexpr BitSetT &operator>>=(std::size_t pos);
144
145 constexpr BitSetT &set();
146 constexpr BitSetT &set(ParamT pos, bool value = true);
147
148 constexpr BitSetT &reset();
149 constexpr BitSetT &reset(ParamT pos);
150
151 constexpr BitSetT &flip();
152 constexpr BitSetT &flip(ParamT pos);
153
to_ulong()154 constexpr unsigned long to_ulong() const { return static_cast<unsigned long>(mBits); }
bits()155 constexpr BitsT bits() const { return mBits; }
156
begin()157 Iterator begin() const { return Iterator(*this); }
end()158 Iterator end() const { return Iterator(BitSetT()); }
159
Zero()160 constexpr static BitSetT Zero() { return BitSetT(); }
161
162 constexpr ParamT first() const;
163 constexpr ParamT last() const;
164
165 // Produces a mask of ones up to the "x"th bit.
Mask(std::size_t x)166 constexpr static BitsT Mask(std::size_t x) { return BitMask<BitsT>(static_cast<ParamT>(x)); }
167
168 private:
169 BitsT mBits;
170 };
171
172 template <size_t N, typename BitsT, typename ParamT>
BitSetT()173 constexpr BitSetT<N, BitsT, ParamT>::BitSetT() : mBits(0)
174 {
175 static_assert(N > 0, "Bitset type cannot support zero bits.");
176 static_assert(N <= sizeof(BitsT) * 8, "Bitset type cannot support a size this large.");
177 }
178
179 template <size_t N, typename BitsT, typename ParamT>
BitSetT(BitsT value)180 constexpr BitSetT<N, BitsT, ParamT>::BitSetT(BitsT value) : mBits(value & Mask(N))
181 {}
182
183 template <size_t N, typename BitsT, typename ParamT>
BitSetT(std::initializer_list<ParamT> init)184 constexpr BitSetT<N, BitsT, ParamT>::BitSetT(std::initializer_list<ParamT> init) : mBits(0)
185 {
186 for (ParamT element : init)
187 {
188 mBits |= Bit<BitsT>(element);
189 }
190 ASSERT(mBits == (mBits & Mask(N)));
191 }
192
193 template <size_t N, typename BitsT, typename ParamT>
BitSetT(const BitSetT & other)194 constexpr BitSetT<N, BitsT, ParamT>::BitSetT(const BitSetT &other) : mBits(other.mBits)
195 {}
196
197 template <size_t N, typename BitsT, typename ParamT>
198 constexpr BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator=(const BitSetT &other)
199 {
200 mBits = other.mBits;
201 return *this;
202 }
203
204 template <size_t N, typename BitsT, typename ParamT>
205 constexpr bool BitSetT<N, BitsT, ParamT>::operator==(const BitSetT &other) const
206 {
207 return mBits == other.mBits;
208 }
209
210 template <size_t N, typename BitsT, typename ParamT>
211 constexpr bool BitSetT<N, BitsT, ParamT>::operator!=(const BitSetT &other) const
212 {
213 return mBits != other.mBits;
214 }
215
216 template <size_t N, typename BitsT, typename ParamT>
217 constexpr bool BitSetT<N, BitsT, ParamT>::operator[](ParamT pos) const
218 {
219 return test(pos);
220 }
221
222 template <size_t N, typename BitsT, typename ParamT>
test(ParamT pos)223 constexpr bool BitSetT<N, BitsT, ParamT>::test(ParamT pos) const
224 {
225 return (mBits & Bit<BitsT>(pos)) != 0;
226 }
227
228 template <size_t N, typename BitsT, typename ParamT>
all()229 constexpr bool BitSetT<N, BitsT, ParamT>::all() const
230 {
231 ASSERT(mBits == (mBits & Mask(N)));
232 return mBits == Mask(N);
233 }
234
235 template <size_t N, typename BitsT, typename ParamT>
any()236 constexpr bool BitSetT<N, BitsT, ParamT>::any() const
237 {
238 ASSERT(mBits == (mBits & Mask(N)));
239 return (mBits != 0);
240 }
241
242 template <size_t N, typename BitsT, typename ParamT>
none()243 constexpr bool BitSetT<N, BitsT, ParamT>::none() const
244 {
245 ASSERT(mBits == (mBits & Mask(N)));
246 return (mBits == 0);
247 }
248
249 template <size_t N, typename BitsT, typename ParamT>
count()250 constexpr std::size_t BitSetT<N, BitsT, ParamT>::count() const
251 {
252 return gl::BitCount(mBits);
253 }
254
255 template <size_t N, typename BitsT, typename ParamT>
256 constexpr BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator&=(const BitSetT &other)
257 {
258 mBits &= other.mBits;
259 return *this;
260 }
261
262 template <size_t N, typename BitsT, typename ParamT>
263 constexpr BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator|=(const BitSetT &other)
264 {
265 mBits |= other.mBits;
266 return *this;
267 }
268
269 template <size_t N, typename BitsT, typename ParamT>
270 constexpr BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator^=(const BitSetT &other)
271 {
272 mBits = mBits ^ other.mBits;
273 return *this;
274 }
275
276 template <size_t N, typename BitsT, typename ParamT>
277 constexpr BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator~() const
278 {
279 return BitSetT<N, BitsT, ParamT>(~mBits & Mask(N));
280 }
281
282 template <size_t N, typename BitsT, typename ParamT>
283 constexpr BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator&=(BitsT value)
284 {
285 mBits &= value;
286 return *this;
287 }
288
289 template <size_t N, typename BitsT, typename ParamT>
290 constexpr BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator|=(BitsT value)
291 {
292 mBits |= value;
293 ASSERT(mBits == (mBits & Mask(N)));
294 return *this;
295 }
296
297 template <size_t N, typename BitsT, typename ParamT>
298 constexpr BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator^=(BitsT value)
299 {
300 mBits ^= value;
301 ASSERT(mBits == (mBits & Mask(N)));
302 return *this;
303 }
304
305 template <size_t N, typename BitsT, typename ParamT>
306 constexpr BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator<<(std::size_t pos) const
307 {
308 return BitSetT<N, BitsT, ParamT>((mBits << pos) & Mask(N));
309 }
310
311 template <size_t N, typename BitsT, typename ParamT>
312 constexpr BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator<<=(std::size_t pos)
313 {
314 mBits = mBits << pos & Mask(N);
315 return *this;
316 }
317
318 template <size_t N, typename BitsT, typename ParamT>
319 constexpr BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator>>(std::size_t pos) const
320 {
321 return BitSetT<N, BitsT, ParamT>(mBits >> pos);
322 }
323
324 template <size_t N, typename BitsT, typename ParamT>
325 constexpr BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator>>=(std::size_t pos)
326 {
327 mBits = (mBits >> pos) & Mask(N);
328 return *this;
329 }
330
331 template <size_t N, typename BitsT, typename ParamT>
set()332 constexpr BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::set()
333 {
334 ASSERT(mBits == (mBits & Mask(N)));
335 mBits = Mask(N);
336 return *this;
337 }
338
339 template <size_t N, typename BitsT, typename ParamT>
set(ParamT pos,bool value)340 constexpr BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::set(ParamT pos, bool value)
341 {
342 ASSERT(static_cast<size_t>(pos) < N);
343 if (value)
344 {
345 mBits |= Bit<BitsT>(pos);
346 }
347 else
348 {
349 reset(pos);
350 }
351 ASSERT(mBits == (mBits & Mask(N)));
352 return *this;
353 }
354
355 template <size_t N, typename BitsT, typename ParamT>
reset()356 constexpr BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::reset()
357 {
358 ASSERT(mBits == (mBits & Mask(N)));
359 mBits = 0;
360 return *this;
361 }
362
363 template <size_t N, typename BitsT, typename ParamT>
reset(ParamT pos)364 constexpr BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::reset(ParamT pos)
365 {
366 ASSERT(static_cast<size_t>(pos) < N);
367 ASSERT(mBits == (mBits & Mask(N)));
368 mBits &= ~Bit<BitsT>(pos);
369 return *this;
370 }
371
372 template <size_t N, typename BitsT, typename ParamT>
flip()373 constexpr BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::flip()
374 {
375 ASSERT(mBits == (mBits & Mask(N)));
376 mBits ^= Mask(N);
377 return *this;
378 }
379
380 template <size_t N, typename BitsT, typename ParamT>
flip(ParamT pos)381 constexpr BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::flip(ParamT pos)
382 {
383 ASSERT(static_cast<size_t>(pos) < N);
384 mBits ^= Bit<BitsT>(pos);
385 ASSERT(mBits == (mBits & Mask(N)));
386 return *this;
387 }
388
389 template <size_t N, typename BitsT, typename ParamT>
first()390 constexpr ParamT BitSetT<N, BitsT, ParamT>::first() const
391 {
392 ASSERT(!none());
393 return static_cast<ParamT>(gl::ScanForward(mBits));
394 }
395
396 template <size_t N, typename BitsT, typename ParamT>
last()397 constexpr ParamT BitSetT<N, BitsT, ParamT>::last() const
398 {
399 ASSERT(!none());
400 return static_cast<ParamT>(gl::ScanReverse(mBits));
401 }
402
403 template <size_t N, typename BitsT, typename ParamT>
Iterator(const BitSetT & bits)404 BitSetT<N, BitsT, ParamT>::Iterator::Iterator(const BitSetT &bits) : mBitsCopy(bits), mCurrentBit(0)
405 {
406 if (bits.any())
407 {
408 mCurrentBit = getNextBit();
409 }
410 }
411
412 template <size_t N, typename BitsT, typename ParamT>
413 ANGLE_INLINE typename BitSetT<N, BitsT, ParamT>::Iterator &
414 BitSetT<N, BitsT, ParamT>::Iterator::operator++()
415 {
416 ASSERT(mBitsCopy.any());
417 mBitsCopy.reset(static_cast<ParamT>(mCurrentBit));
418 mCurrentBit = getNextBit();
419 return *this;
420 }
421
422 template <size_t N, typename BitsT, typename ParamT>
423 bool BitSetT<N, BitsT, ParamT>::Iterator::operator==(const Iterator &other) const
424 {
425 return mBitsCopy == other.mBitsCopy;
426 }
427
428 template <size_t N, typename BitsT, typename ParamT>
429 bool BitSetT<N, BitsT, ParamT>::Iterator::operator!=(const Iterator &other) const
430 {
431 return !(*this == other);
432 }
433
434 template <size_t N, typename BitsT, typename ParamT>
435 ParamT BitSetT<N, BitsT, ParamT>::Iterator::operator*() const
436 {
437 return static_cast<ParamT>(mCurrentBit);
438 }
439
440 template <size_t N, typename BitsT, typename ParamT>
getNextBit()441 std::size_t BitSetT<N, BitsT, ParamT>::Iterator::getNextBit()
442 {
443 if (mBitsCopy.none())
444 {
445 return 0;
446 }
447
448 return gl::ScanForward(mBitsCopy.mBits);
449 }
450
451 template <size_t N>
452 using BitSet8 = BitSetT<N, uint8_t>;
453
454 template <size_t N>
455 using BitSet16 = BitSetT<N, uint16_t>;
456
457 template <size_t N>
458 using BitSet32 = BitSetT<N, uint32_t>;
459
460 template <size_t N>
461 using BitSet64 = BitSetT<N, uint64_t>;
462
463 template <std::size_t N>
464 class BitSetArray;
465
466 namespace priv
467 {
468
469 template <size_t N, typename T>
470 using EnableIfBitsFit = typename std::enable_if<N <= sizeof(T) * 8>::type;
471
472 template <size_t N, typename Enable = void>
473 struct GetBitSet
474 {
475 using Type = BitSetArray<N>;
476 };
477
478 // Prefer 64-bit bitsets on 64-bit CPUs. They seem faster than 32-bit.
479 #if defined(ANGLE_IS_64_BIT_CPU)
480 template <size_t N>
481 struct GetBitSet<N, EnableIfBitsFit<N, uint64_t>>
482 {
483 using Type = BitSet64<N>;
484 };
485 constexpr std::size_t kDefaultBitSetSize = 64;
486 using BaseBitSetType = BitSet64<kDefaultBitSetSize>;
487 #else
488 template <size_t N>
489 struct GetBitSet<N, EnableIfBitsFit<N, uint32_t>>
490 {
491 using Type = BitSet32<N>;
492 };
493 constexpr std::size_t kDefaultBitSetSize = 32;
494 using BaseBitSetType = BitSet32<kDefaultBitSetSize>;
495 #endif // defined(ANGLE_IS_64_BIT_CPU)
496
497 } // namespace priv
498
499 template <size_t N>
500 using BitSet = typename priv::GetBitSet<N>::Type;
501
502 template <std::size_t N>
503 class BitSetArray final
504 {
505 public:
506 using BaseBitSet = priv::BaseBitSetType;
507
508 BitSetArray();
509 BitSetArray(const BitSetArray<N> &other);
510
511 using value_type = BaseBitSet::value_type;
512 using param_type = BaseBitSet::param_type;
513
514 class Reference final
515 {
516 public:
517 ~Reference() {}
518 Reference &operator=(bool x)
519 {
520 mParent.set(mPosition, x);
521 return *this;
522 }
523 explicit operator bool() const { return mParent.test(mPosition); }
524
525 private:
526 friend class BitSetArray;
527
528 Reference(BitSetArray &parent, std::size_t pos) : mParent(parent), mPosition(pos) {}
529
530 BitSetArray &mParent;
531 std::size_t mPosition;
532 };
533 class Iterator final
534 {
535 public:
536 Iterator(const BitSetArray<N> &bitSetArray, std::size_t index);
537 Iterator &operator++();
538 bool operator==(const Iterator &other) const;
539 bool operator!=(const Iterator &other) const;
540 size_t operator*() const;
541
542 // These helper functions allow mutating an iterator in-flight.
543 // They only operate on later bits to ensure we don't iterate the same bit twice.
544 void resetLaterBit(std::size_t pos)
545 {
546 ASSERT(pos > (mIndex * priv::kDefaultBitSetSize) + *mCurrentIterator);
547 prepareCopy();
548 mParentCopy.reset(pos);
549 updateIteratorBit(pos, false);
550 }
551
552 void setLaterBit(std::size_t pos)
553 {
554 ASSERT(pos > (mIndex * priv::kDefaultBitSetSize) + *mCurrentIterator);
555 prepareCopy();
556 mParentCopy.set(pos);
557 updateIteratorBit(pos, true);
558 }
559
560 void setLaterBits(const BitSetArray &bits)
561 {
562 prepareCopy();
563 mParentCopy |= bits;
564 updateIteratorBits(bits);
565 }
566
567 private:
568 ANGLE_INLINE void prepareCopy()
569 {
570 ASSERT(mParent.mBaseBitSetArray[mIndex].end() ==
571 mParentCopy.mBaseBitSetArray[mIndex].end());
572 if (mParentCopy.none())
573 {
574 mParentCopy = mParent;
575 mCurrentParent = &mParentCopy;
576 }
577 }
578
579 ANGLE_INLINE void updateIteratorBit(std::size_t pos, bool setBit)
580 {
581 // Get the index and offset, update current interator if within range
582 size_t index = pos >> kShiftForDivision;
583 size_t offset = pos & kDefaultBitSetSizeMinusOne;
584 if (index == mIndex)
585 {
586 if (setBit)
587 {
588 mCurrentIterator.setLaterBit(offset);
589 }
590 else
591 {
592 mCurrentIterator.resetLaterBit(offset);
593 }
594 }
595 }
596
597 ANGLE_INLINE void updateIteratorBits(const BitSetArray &bits)
598 {
599 mCurrentIterator.setLaterBits(bits.mBaseBitSetArray[mIndex]);
600 }
601
602 // Problem -
603 // We want to provide the fastest path possible for usecases that iterate though the bitset.
604 //
605 // Options -
606 // 1) For non-mutating iterations the const ref <mParent> is set as mCurrentParent and only
607 // for usecases that need to mutate the bitset while iterating we perform a copy of
608 // <mParent> into <mParentCopy> and modify its bits accordingly.
609 // 2) The alternate approach was to perform a copy all the time in the constructor
610 // irrespective of whether it was a mutating usecase or not.
611 //
612 // Experiment -
613 // BitSetIteratorPerfTest was run on a Windows machine with Intel CPU and these were the
614 // results -
615 // 1) Copy only when necessary -
616 // RESULT BitSetIteratorPerf.wall_time: run = 116.1067374961 ns
617 // RESULT BitSetIteratorPerf.trial_steps : run = 8416124 count
618 // RESULT BitSetIteratorPerf.total_steps : run = 16832251 count
619 // 2) Copy always -
620 // RESULT BitSetIteratorPerf.wall_time: run = 242.7446459439 ns
621 // RESULT BitSetIteratorPerf.trial_steps : run = 4171416 count
622 // RESULT BitSetIteratorPerf.total_steps : run = 8342834 count
623 //
624 // Resolution -
625 // We settled on the copy only when necessary path.
626 size_t mIndex;
627 const BitSetArray &mParent;
628 BitSetArray mParentCopy;
629 const BitSetArray *mCurrentParent;
630 typename BaseBitSet::Iterator mCurrentIterator;
631 };
632
633 constexpr std::size_t size() const { return N; }
634 Iterator begin() const { return Iterator(*this, 0); }
635 Iterator end() const { return Iterator(*this, kArraySize); }
636 unsigned long to_ulong() const
637 {
638 // TODO(anglebug.com/5628): Handle serializing more than kDefaultBitSetSize
639 for (std::size_t index = 1; index < kArraySize; index++)
640 {
641 ASSERT(mBaseBitSetArray[index].none());
642 }
643 return static_cast<unsigned long>(mBaseBitSetArray[0].to_ulong());
644 }
645
646 // Assignment operators
647 BitSetArray &operator=(const BitSetArray &other);
648 BitSetArray &operator&=(const BitSetArray &other);
649 BitSetArray &operator|=(const BitSetArray &other);
650 BitSetArray &operator^=(const BitSetArray &other);
651
652 // Bitwise operators
653 BitSetArray<N> operator&(const angle::BitSetArray<N> &other) const;
654 BitSetArray<N> operator|(const angle::BitSetArray<N> &other) const;
655 BitSetArray<N> operator^(const angle::BitSetArray<N> &other) const;
656
657 // Relational Operators
658 bool operator==(const angle::BitSetArray<N> &other) const;
659 bool operator!=(const angle::BitSetArray<N> &other) const;
660
661 // Unary operators
662 BitSetArray operator~() const;
663 bool operator[](std::size_t pos) const;
664 Reference operator[](std::size_t pos)
665 {
666 ASSERT(pos < size());
667 return Reference(*this, pos);
668 }
669
670 // Setter, getters and other helper methods
671 BitSetArray &set();
672 BitSetArray &set(std::size_t pos, bool value = true);
673 BitSetArray &reset();
674 BitSetArray &reset(std::size_t pos);
675 bool test(std::size_t pos) const;
676 bool all() const;
677 bool any() const;
678 bool none() const;
679 std::size_t count() const;
680 bool intersects(const BitSetArray &other) const;
681 BitSetArray<N> &flip();
682 param_type first() const;
683 param_type last() const;
684
685 value_type bits(size_t index) const;
686
687 private:
688 static constexpr std::size_t kDefaultBitSetSizeMinusOne = priv::kDefaultBitSetSize - 1;
689 static constexpr std::size_t kShiftForDivision =
690 static_cast<std::size_t>(rx::Log2(static_cast<unsigned int>(priv::kDefaultBitSetSize)));
691 static constexpr std::size_t kArraySize =
692 ((N + kDefaultBitSetSizeMinusOne) >> kShiftForDivision);
693 constexpr static std::size_t kLastElementCount = (N & kDefaultBitSetSizeMinusOne);
694 constexpr static std::size_t kLastElementMask = priv::BaseBitSetType::Mask(
695 kLastElementCount == 0 ? priv::kDefaultBitSetSize : kLastElementCount);
696
697 std::array<BaseBitSet, kArraySize> mBaseBitSetArray;
698 };
699
700 template <std::size_t N>
701 BitSetArray<N>::BitSetArray()
702 {
703 static_assert(N > priv::kDefaultBitSetSize, "BitSetArray type can't support requested size.");
704 reset();
705 }
706
707 template <size_t N>
708 BitSetArray<N>::BitSetArray(const BitSetArray<N> &other)
709 {
710 for (std::size_t index = 0; index < kArraySize; index++)
711 {
712 mBaseBitSetArray[index] = other.mBaseBitSetArray[index];
713 }
714 }
715
716 template <size_t N>
717 BitSetArray<N>::Iterator::Iterator(const BitSetArray<N> &bitSetArray, std::size_t index)
718 : mIndex(index),
719 mParent(bitSetArray),
720 mCurrentParent(&mParent),
721 mCurrentIterator(mParent.mBaseBitSetArray[0].begin())
722 {
723 while (mIndex < mCurrentParent->kArraySize)
724 {
725 if (mCurrentParent->mBaseBitSetArray[mIndex].any())
726 {
727 break;
728 }
729 mIndex++;
730 }
731
732 if (mIndex < mCurrentParent->kArraySize)
733 {
734 mCurrentIterator = mCurrentParent->mBaseBitSetArray[mIndex].begin();
735 }
736 else
737 {
738 mCurrentIterator = mCurrentParent->mBaseBitSetArray[mCurrentParent->kArraySize - 1].end();
739 }
740 }
741
742 template <std::size_t N>
743 typename BitSetArray<N>::Iterator &BitSetArray<N>::Iterator::operator++()
744 {
745 ++mCurrentIterator;
746 while (mCurrentIterator == mCurrentParent->mBaseBitSetArray[mIndex].end())
747 {
748 mIndex++;
749 if (mIndex >= mCurrentParent->kArraySize)
750 {
751 break;
752 }
753 mCurrentIterator = mCurrentParent->mBaseBitSetArray[mIndex].begin();
754 }
755 return *this;
756 }
757
758 template <std::size_t N>
759 bool BitSetArray<N>::Iterator::operator==(const BitSetArray<N>::Iterator &other) const
760 {
761 return mCurrentIterator == other.mCurrentIterator;
762 }
763
764 template <std::size_t N>
765 bool BitSetArray<N>::Iterator::operator!=(const BitSetArray<N>::Iterator &other) const
766 {
767 return mCurrentIterator != other.mCurrentIterator;
768 }
769
770 template <std::size_t N>
771 std::size_t BitSetArray<N>::Iterator::operator*() const
772 {
773 return (mIndex * priv::kDefaultBitSetSize) + *mCurrentIterator;
774 }
775
776 template <std::size_t N>
777 BitSetArray<N> &BitSetArray<N>::operator=(const BitSetArray<N> &other)
778 {
779 for (std::size_t index = 0; index < kArraySize; index++)
780 {
781 mBaseBitSetArray[index] = other.mBaseBitSetArray[index];
782 }
783 return *this;
784 }
785
786 template <std::size_t N>
787 BitSetArray<N> &BitSetArray<N>::operator&=(const BitSetArray<N> &other)
788 {
789 for (std::size_t index = 0; index < kArraySize; index++)
790 {
791 mBaseBitSetArray[index] &= other.mBaseBitSetArray[index];
792 }
793 return *this;
794 }
795
796 template <std::size_t N>
797 BitSetArray<N> &BitSetArray<N>::operator|=(const BitSetArray<N> &other)
798 {
799 for (std::size_t index = 0; index < kArraySize; index++)
800 {
801 mBaseBitSetArray[index] |= other.mBaseBitSetArray[index];
802 }
803 return *this;
804 }
805
806 template <std::size_t N>
807 BitSetArray<N> &BitSetArray<N>::operator^=(const BitSetArray<N> &other)
808 {
809 for (std::size_t index = 0; index < kArraySize; index++)
810 {
811 mBaseBitSetArray[index] ^= other.mBaseBitSetArray[index];
812 }
813 return *this;
814 }
815
816 template <std::size_t N>
817 BitSetArray<N> BitSetArray<N>::operator&(const angle::BitSetArray<N> &other) const
818 {
819 angle::BitSetArray<N> result(other);
820 result &= *this;
821 return result;
822 }
823
824 template <std::size_t N>
825 BitSetArray<N> BitSetArray<N>::operator|(const angle::BitSetArray<N> &other) const
826 {
827 angle::BitSetArray<N> result(other);
828 result |= *this;
829 return result;
830 }
831
832 template <std::size_t N>
833 BitSetArray<N> BitSetArray<N>::operator^(const angle::BitSetArray<N> &other) const
834 {
835 angle::BitSetArray<N> result(other);
836 result ^= *this;
837 return result;
838 }
839
840 template <std::size_t N>
841 bool BitSetArray<N>::operator==(const angle::BitSetArray<N> &other) const
842 {
843 for (std::size_t index = 0; index < kArraySize; index++)
844 {
845 if (mBaseBitSetArray[index] != other.mBaseBitSetArray[index])
846 {
847 return false;
848 }
849 }
850 return true;
851 }
852
853 template <std::size_t N>
854 bool BitSetArray<N>::operator!=(const angle::BitSetArray<N> &other) const
855 {
856 return !(*this == other);
857 }
858
859 template <std::size_t N>
860 BitSetArray<N> BitSetArray<N>::operator~() const
861 {
862 angle::BitSetArray<N> result;
863 for (std::size_t index = 0; index < kArraySize; index++)
864 {
865 result.mBaseBitSetArray[index] |= ~mBaseBitSetArray[index];
866 }
867 // The last element in result may need special handling
868 result.mBaseBitSetArray[kArraySize - 1] &= kLastElementMask;
869
870 return result;
871 }
872
873 template <std::size_t N>
874 bool BitSetArray<N>::operator[](std::size_t pos) const
875 {
876 ASSERT(pos < size());
877 return test(pos);
878 }
879
880 template <std::size_t N>
881 BitSetArray<N> &BitSetArray<N>::set()
882 {
883 for (BaseBitSet &baseBitSet : mBaseBitSetArray)
884 {
885 baseBitSet.set();
886 }
887 // The last element in mBaseBitSetArray may need special handling
888 mBaseBitSetArray[kArraySize - 1] &= kLastElementMask;
889
890 return *this;
891 }
892
893 template <std::size_t N>
894 BitSetArray<N> &BitSetArray<N>::set(std::size_t pos, bool value)
895 {
896 ASSERT(pos < size());
897 // Get the index and offset, then set the bit
898 size_t index = pos >> kShiftForDivision;
899 size_t offset = pos & kDefaultBitSetSizeMinusOne;
900 mBaseBitSetArray[index].set(offset, value);
901 return *this;
902 }
903
904 template <std::size_t N>
905 BitSetArray<N> &BitSetArray<N>::reset()
906 {
907 for (BaseBitSet &baseBitSet : mBaseBitSetArray)
908 {
909 baseBitSet.reset();
910 }
911 return *this;
912 }
913
914 template <std::size_t N>
915 BitSetArray<N> &BitSetArray<N>::reset(std::size_t pos)
916 {
917 ASSERT(pos < size());
918 return set(pos, false);
919 }
920
921 template <std::size_t N>
922 bool BitSetArray<N>::test(std::size_t pos) const
923 {
924 ASSERT(pos < size());
925 // Get the index and offset, then test the bit
926 size_t index = pos >> kShiftForDivision;
927 size_t offset = pos & kDefaultBitSetSizeMinusOne;
928 return mBaseBitSetArray[index].test(offset);
929 }
930
931 template <std::size_t N>
932 bool BitSetArray<N>::all() const
933 {
934 static priv::BaseBitSetType kLastElementBitSet = priv::BaseBitSetType(kLastElementMask);
935
936 for (std::size_t index = 0; index < kArraySize - 1; index++)
937 {
938 if (!mBaseBitSetArray[index].all())
939 {
940 return false;
941 }
942 }
943
944 // The last element in mBaseBitSetArray may need special handling
945 return mBaseBitSetArray[kArraySize - 1] == kLastElementBitSet;
946 }
947
948 template <std::size_t N>
949 bool BitSetArray<N>::any() const
950 {
951 for (const BaseBitSet &baseBitSet : mBaseBitSetArray)
952 {
953 if (baseBitSet.any())
954 {
955 return true;
956 }
957 }
958 return false;
959 }
960
961 template <std::size_t N>
962 bool BitSetArray<N>::none() const
963 {
964 for (const BaseBitSet &baseBitSet : mBaseBitSetArray)
965 {
966 if (!baseBitSet.none())
967 {
968 return false;
969 }
970 }
971 return true;
972 }
973
974 template <std::size_t N>
975 std::size_t BitSetArray<N>::count() const
976 {
977 size_t count = 0;
978 for (const BaseBitSet &baseBitSet : mBaseBitSetArray)
979 {
980 count += baseBitSet.count();
981 }
982 return count;
983 }
984
985 template <std::size_t N>
986 bool BitSetArray<N>::intersects(const BitSetArray<N> &other) const
987 {
988 for (std::size_t index = 0; index < kArraySize; index++)
989 {
990 if ((mBaseBitSetArray[index].bits() & other.mBaseBitSetArray[index].bits()) != 0)
991 {
992 return true;
993 }
994 }
995 return false;
996 }
997
998 template <std::size_t N>
999 BitSetArray<N> &BitSetArray<N>::flip()
1000 {
1001 for (BaseBitSet &baseBitSet : mBaseBitSetArray)
1002 {
1003 baseBitSet.flip();
1004 }
1005
1006 // The last element in mBaseBitSetArray may need special handling
1007 mBaseBitSetArray[kArraySize - 1] &= kLastElementMask;
1008 return *this;
1009 }
1010
1011 template <std::size_t N>
1012 typename BitSetArray<N>::param_type BitSetArray<N>::first() const
1013 {
1014 ASSERT(any());
1015 for (size_t arrayIndex = 0; arrayIndex < kArraySize; ++arrayIndex)
1016 {
1017 const BaseBitSet &baseBitSet = mBaseBitSetArray[arrayIndex];
1018 if (baseBitSet.any())
1019 {
1020 return baseBitSet.first() + arrayIndex * priv::kDefaultBitSetSize;
1021 }
1022 }
1023 UNREACHABLE();
1024 return 0;
1025 }
1026
1027 template <std::size_t N>
1028 typename BitSetArray<N>::param_type BitSetArray<N>::last() const
1029 {
1030 ASSERT(any());
1031 for (size_t arrayIndex = kArraySize; arrayIndex > 0; --arrayIndex)
1032 {
1033 const BaseBitSet &baseBitSet = mBaseBitSetArray[arrayIndex - 1];
1034 if (baseBitSet.any())
1035 {
1036 return baseBitSet.last() + (arrayIndex - 1) * priv::kDefaultBitSetSize;
1037 }
1038 }
1039 UNREACHABLE();
1040 return 0;
1041 }
1042
1043 template <std::size_t N>
1044 typename BitSetArray<N>::value_type BitSetArray<N>::bits(size_t index) const
1045 {
1046 return mBaseBitSetArray[index].bits();
1047 }
1048 } // namespace angle
1049
1050 template <size_t N, typename BitsT, typename ParamT>
1051 inline constexpr angle::BitSetT<N, BitsT, ParamT> operator&(
1052 const angle::BitSetT<N, BitsT, ParamT> &lhs,
1053 const angle::BitSetT<N, BitsT, ParamT> &rhs)
1054 {
1055 angle::BitSetT<N, BitsT, ParamT> result(lhs);
1056 result &= rhs.bits();
1057 return result;
1058 }
1059
1060 template <size_t N, typename BitsT, typename ParamT>
1061 inline constexpr angle::BitSetT<N, BitsT, ParamT> operator|(
1062 const angle::BitSetT<N, BitsT, ParamT> &lhs,
1063 const angle::BitSetT<N, BitsT, ParamT> &rhs)
1064 {
1065 angle::BitSetT<N, BitsT, ParamT> result(lhs);
1066 result |= rhs.bits();
1067 return result;
1068 }
1069
1070 template <size_t N, typename BitsT, typename ParamT>
1071 inline constexpr angle::BitSetT<N, BitsT, ParamT> operator^(
1072 const angle::BitSetT<N, BitsT, ParamT> &lhs,
1073 const angle::BitSetT<N, BitsT, ParamT> &rhs)
1074 {
1075 angle::BitSetT<N, BitsT, ParamT> result(lhs);
1076 result ^= rhs.bits();
1077 return result;
1078 }
1079
1080 template <size_t N, typename BitsT, typename ParamT>
1081 inline bool operator==(angle::BitSetT<N, BitsT, ParamT> &lhs, angle::BitSetT<N, BitsT, ParamT> &rhs)
1082 {
1083 return lhs.bits() == rhs.bits();
1084 }
1085
1086 template <size_t N, typename BitsT, typename ParamT>
1087 inline bool operator!=(angle::BitSetT<N, BitsT, ParamT> &lhs, angle::BitSetT<N, BitsT, ParamT> &rhs)
1088 {
1089 return !(lhs == rhs);
1090 }
1091
1092 #endif // COMMON_BITSETITERATOR_H_
1093