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