• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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