blob: 7febb78e52f8eab7997c1fd133b2ccb730ea2334 [file] [log] [blame]
Jamie Madill6b2a0b02015-08-03 14:15:08 -04001//
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//
Jamie Madill20e005b2017-04-07 14:19:22 -04006// bitset_utils:
7// Bitset-related helper classes, such as a fast iterator to scan for set bits.
Jamie Madill6b2a0b02015-08-03 14:15:08 -04008//
9
10#ifndef COMMON_BITSETITERATOR_H_
11#define COMMON_BITSETITERATOR_H_
12
13#include <stdint.h>
14
15#include <bitset>
16
17#include "common/angleutils.h"
18#include "common/debug.h"
19#include "common/mathutil.h"
20#include "common/platform.h"
21
22namespace angle
23{
Jamie Madill6de51852017-04-12 09:53:01 -040024
Corentin Walleze4477002017-12-01 14:39:58 -050025template <size_t N, typename BitsT, typename ParamT = std::size_t>
Jamie Madill6de51852017-04-12 09:53:01 -040026class BitSetT final
Jamie Madill6b2a0b02015-08-03 14:15:08 -040027{
28 public:
Jamie Madill6de51852017-04-12 09:53:01 -040029 class Reference final
30 {
31 public:
32 ~Reference() {}
Shao37219c82017-04-26 10:59:48 +080033 Reference &operator=(bool x)
34 {
35 mParent->set(mBit, x);
36 return *this;
37 }
Jeff Gilbert5e5438f2017-10-31 14:44:06 -070038 explicit operator bool() const { return mParent->test(mBit); }
Jamie Madill6de51852017-04-12 09:53:01 -040039
40 private:
41 friend class BitSetT;
42
43 Reference(BitSetT *parent, std::size_t bit) : mParent(parent), mBit(bit) {}
44
45 BitSetT *mParent;
46 std::size_t mBit;
47 };
48
49 class Iterator final
50 {
51 public:
52 Iterator(const BitSetT &bits);
53 Iterator &operator++();
54
55 bool operator==(const Iterator &other) const;
56 bool operator!=(const Iterator &other) const;
57 std::size_t operator*() const;
58
59 private:
60 std::size_t getNextBit();
61
62 BitSetT mBitsCopy;
63 std::size_t mCurrentBit;
64 };
65
66 BitSetT();
67 BitSetT(BitsT value);
68 ~BitSetT();
69
70 BitSetT(const BitSetT &other);
71 BitSetT &operator=(const BitSetT &other);
72
73 bool operator==(const BitSetT &other) const;
74 bool operator!=(const BitSetT &other) const;
75
Corentin Walleze4477002017-12-01 14:39:58 -050076 constexpr bool operator[](ParamT pos) const;
77 Reference operator[](ParamT pos) { return Reference(this, pos); }
Jamie Madill6de51852017-04-12 09:53:01 -040078
Corentin Walleze4477002017-12-01 14:39:58 -050079 bool test(ParamT pos) const;
Jamie Madill6de51852017-04-12 09:53:01 -040080
81 bool all() const;
82 bool any() const;
83 bool none() const;
84 std::size_t count() const;
85
86 constexpr std::size_t size() const { return N; }
87
88 BitSetT &operator&=(const BitSetT &other);
89 BitSetT &operator|=(const BitSetT &other);
90 BitSetT &operator^=(const BitSetT &other);
91 BitSetT operator~() const;
92
93 BitSetT operator<<(std::size_t pos) const;
94 BitSetT &operator<<=(std::size_t pos);
95 BitSetT operator>>(std::size_t pos) const;
96 BitSetT &operator>>=(std::size_t pos);
97
98 BitSetT &set();
Corentin Walleze4477002017-12-01 14:39:58 -050099 BitSetT &set(ParamT pos, bool value = true);
Jamie Madill6de51852017-04-12 09:53:01 -0400100
101 BitSetT &reset();
Corentin Walleze4477002017-12-01 14:39:58 -0500102 BitSetT &reset(ParamT pos);
Jamie Madill6de51852017-04-12 09:53:01 -0400103
104 BitSetT &flip();
Corentin Walleze4477002017-12-01 14:39:58 -0500105 BitSetT &flip(ParamT pos);
Jamie Madill6de51852017-04-12 09:53:01 -0400106
107 unsigned long to_ulong() const { return static_cast<unsigned long>(mBits); }
108 BitsT bits() const { return mBits; }
109
110 Iterator begin() const { return Iterator(*this); }
111 Iterator end() const { return Iterator(BitSetT()); }
112
113 private:
Corentin Walleze4477002017-12-01 14:39:58 -0500114 constexpr static BitsT Bit(ParamT x)
115 {
116 return (static_cast<BitsT>(1) << static_cast<size_t>(x));
117 }
Jamie Madill6de51852017-04-12 09:53:01 -0400118 constexpr static BitsT Mask(std::size_t x) { return ((Bit(x - 1) - 1) << 1) + 1; }
119
120 BitsT mBits;
121};
122
123template <size_t N>
124class IterableBitSet : public std::bitset<N>
125{
126 public:
127 IterableBitSet() {}
128 IterableBitSet(const std::bitset<N> &implicitBitSet) : std::bitset<N>(implicitBitSet) {}
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400129
130 class Iterator final
131 {
132 public:
133 Iterator(const std::bitset<N> &bits);
134 Iterator &operator++();
135
136 bool operator==(const Iterator &other) const;
137 bool operator!=(const Iterator &other) const;
138 unsigned long operator*() const { return mCurrentBit; }
139
140 private:
141 unsigned long getNextBit();
142
Jamie Madill6de51852017-04-12 09:53:01 -0400143 static constexpr size_t BitsPerWord = sizeof(uint32_t) * 8;
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400144 std::bitset<N> mBits;
145 unsigned long mCurrentBit;
146 unsigned long mOffset;
147 };
148
Jamie Madill6de51852017-04-12 09:53:01 -0400149 Iterator begin() const { return Iterator(*this); }
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400150 Iterator end() const { return Iterator(std::bitset<N>(0)); }
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400151};
152
153template <size_t N>
Jamie Madill6de51852017-04-12 09:53:01 -0400154IterableBitSet<N>::Iterator::Iterator(const std::bitset<N> &bitset)
155 : mBits(bitset), mCurrentBit(0), mOffset(0)
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400156{
Jamie Madill6de51852017-04-12 09:53:01 -0400157 if (mBits.any())
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400158 {
159 mCurrentBit = getNextBit();
160 }
161 else
162 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700163 mOffset = static_cast<unsigned long>(rx::roundUp(N, BitsPerWord));
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400164 }
165}
166
167template <size_t N>
Jamie Madill6de51852017-04-12 09:53:01 -0400168typename IterableBitSet<N>::Iterator &IterableBitSet<N>::Iterator::operator++()
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400169{
170 ASSERT(mBits.any());
171 mBits.set(mCurrentBit - mOffset, 0);
172 mCurrentBit = getNextBit();
173 return *this;
174}
175
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400176template <size_t N>
Jamie Madill6de51852017-04-12 09:53:01 -0400177bool IterableBitSet<N>::Iterator::operator==(const Iterator &other) const
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400178{
179 return mOffset == other.mOffset && mBits == other.mBits;
180}
181
182template <size_t N>
Jamie Madill6de51852017-04-12 09:53:01 -0400183bool IterableBitSet<N>::Iterator::operator!=(const Iterator &other) const
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400184{
185 return !(*this == other);
186}
187
188template <size_t N>
Jamie Madill6de51852017-04-12 09:53:01 -0400189unsigned long IterableBitSet<N>::Iterator::getNextBit()
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400190{
Jamie Madill6de51852017-04-12 09:53:01 -0400191 // TODO(jmadill): Use 64-bit scan when possible.
192 static constexpr std::bitset<N> wordMask(std::numeric_limits<uint32_t>::max());
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400193
194 while (mOffset < N)
195 {
Jamie Madill6de51852017-04-12 09:53:01 -0400196 uint32_t wordBits = static_cast<uint32_t>((mBits & wordMask).to_ulong());
197 if (wordBits != 0)
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400198 {
Olli Etuaho9250cb22017-01-21 10:51:27 +0000199 return gl::ScanForward(wordBits) + mOffset;
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400200 }
201
202 mBits >>= BitsPerWord;
203 mOffset += BitsPerWord;
204 }
205 return 0;
206}
207
Corentin Walleze4477002017-12-01 14:39:58 -0500208template <size_t N, typename BitsT, typename ParamT>
209BitSetT<N, BitsT, ParamT>::BitSetT() : mBits(0)
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400210{
Jamie Madill6de51852017-04-12 09:53:01 -0400211 static_assert(N > 0, "Bitset type cannot support zero bits.");
212 static_assert(N <= sizeof(BitsT) * 8, "Bitset type cannot support a size this large.");
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400213}
214
Corentin Walleze4477002017-12-01 14:39:58 -0500215template <size_t N, typename BitsT, typename ParamT>
216BitSetT<N, BitsT, ParamT>::BitSetT(BitsT value) : mBits(value & Mask(N))
Jamie Madill6de51852017-04-12 09:53:01 -0400217{
218}
219
Corentin Walleze4477002017-12-01 14:39:58 -0500220template <size_t N, typename BitsT, typename ParamT>
221BitSetT<N, BitsT, ParamT>::~BitSetT()
Jamie Madill6de51852017-04-12 09:53:01 -0400222{
223}
224
Corentin Walleze4477002017-12-01 14:39:58 -0500225template <size_t N, typename BitsT, typename ParamT>
226BitSetT<N, BitsT, ParamT>::BitSetT(const BitSetT &other) : mBits(other.mBits)
Jamie Madill6de51852017-04-12 09:53:01 -0400227{
228}
229
Corentin Walleze4477002017-12-01 14:39:58 -0500230template <size_t N, typename BitsT, typename ParamT>
231BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator=(const BitSetT &other)
Jamie Madill6de51852017-04-12 09:53:01 -0400232{
233 mBits = other.mBits;
234 return *this;
235}
236
Corentin Walleze4477002017-12-01 14:39:58 -0500237template <size_t N, typename BitsT, typename ParamT>
238bool BitSetT<N, BitsT, ParamT>::operator==(const BitSetT &other) const
Jamie Madill6de51852017-04-12 09:53:01 -0400239{
240 return mBits == other.mBits;
241}
242
Corentin Walleze4477002017-12-01 14:39:58 -0500243template <size_t N, typename BitsT, typename ParamT>
244bool BitSetT<N, BitsT, ParamT>::operator!=(const BitSetT &other) const
Jamie Madill6de51852017-04-12 09:53:01 -0400245{
246 return mBits != other.mBits;
247}
248
Corentin Walleze4477002017-12-01 14:39:58 -0500249template <size_t N, typename BitsT, typename ParamT>
250constexpr bool BitSetT<N, BitsT, ParamT>::operator[](ParamT pos) const
Jamie Madill6de51852017-04-12 09:53:01 -0400251{
252 return test(pos);
253}
254
Corentin Walleze4477002017-12-01 14:39:58 -0500255template <size_t N, typename BitsT, typename ParamT>
256bool BitSetT<N, BitsT, ParamT>::test(ParamT pos) const
Jamie Madill6de51852017-04-12 09:53:01 -0400257{
258 return (mBits & Bit(pos)) != 0;
259}
260
Corentin Walleze4477002017-12-01 14:39:58 -0500261template <size_t N, typename BitsT, typename ParamT>
262bool BitSetT<N, BitsT, ParamT>::all() const
Jamie Madill6de51852017-04-12 09:53:01 -0400263{
264 ASSERT(mBits == (mBits & Mask(N)));
265 return mBits == Mask(N);
266}
267
Corentin Walleze4477002017-12-01 14:39:58 -0500268template <size_t N, typename BitsT, typename ParamT>
269bool BitSetT<N, BitsT, ParamT>::any() const
Jamie Madill6de51852017-04-12 09:53:01 -0400270{
271 ASSERT(mBits == (mBits & Mask(N)));
272 return (mBits != 0);
273}
274
Corentin Walleze4477002017-12-01 14:39:58 -0500275template <size_t N, typename BitsT, typename ParamT>
276bool BitSetT<N, BitsT, ParamT>::none() const
Jamie Madill6de51852017-04-12 09:53:01 -0400277{
278 ASSERT(mBits == (mBits & Mask(N)));
279 return (mBits == 0);
280}
281
Corentin Walleze4477002017-12-01 14:39:58 -0500282template <size_t N, typename BitsT, typename ParamT>
283std::size_t BitSetT<N, BitsT, ParamT>::count() const
Jamie Madill6de51852017-04-12 09:53:01 -0400284{
285 return gl::BitCount(mBits);
286}
287
Corentin Walleze4477002017-12-01 14:39:58 -0500288template <size_t N, typename BitsT, typename ParamT>
289BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator&=(const BitSetT &other)
Jamie Madill6de51852017-04-12 09:53:01 -0400290{
291 mBits &= other.mBits;
292 return *this;
293}
294
Corentin Walleze4477002017-12-01 14:39:58 -0500295template <size_t N, typename BitsT, typename ParamT>
296BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator|=(const BitSetT &other)
Jamie Madill6de51852017-04-12 09:53:01 -0400297{
298 mBits |= other.mBits;
299 return *this;
300}
301
Corentin Walleze4477002017-12-01 14:39:58 -0500302template <size_t N, typename BitsT, typename ParamT>
303BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator^=(const BitSetT &other)
Jamie Madill6de51852017-04-12 09:53:01 -0400304{
305 mBits = (mBits ^ other.mBits) & Mask(N);
306 return *this;
307}
308
Corentin Walleze4477002017-12-01 14:39:58 -0500309template <size_t N, typename BitsT, typename ParamT>
310BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator~() const
Jamie Madill6de51852017-04-12 09:53:01 -0400311{
Corentin Walleze4477002017-12-01 14:39:58 -0500312 return BitSetT<N, BitsT, ParamT>(~mBits & Mask(N));
Jamie Madill6de51852017-04-12 09:53:01 -0400313}
314
Corentin Walleze4477002017-12-01 14:39:58 -0500315template <size_t N, typename BitsT, typename ParamT>
316BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator<<(std::size_t pos) const
Jamie Madill6de51852017-04-12 09:53:01 -0400317{
Corentin Walleze4477002017-12-01 14:39:58 -0500318 return BitSetT<N, BitsT, ParamT>((mBits << pos) & Mask(N));
Jamie Madill6de51852017-04-12 09:53:01 -0400319}
320
Corentin Walleze4477002017-12-01 14:39:58 -0500321template <size_t N, typename BitsT, typename ParamT>
322BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator<<=(std::size_t pos)
Jamie Madill6de51852017-04-12 09:53:01 -0400323{
324 mBits = (mBits << pos & Mask(N));
325 return *this;
326}
327
Corentin Walleze4477002017-12-01 14:39:58 -0500328template <size_t N, typename BitsT, typename ParamT>
329BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator>>(std::size_t pos) const
Jamie Madill6de51852017-04-12 09:53:01 -0400330{
Corentin Walleze4477002017-12-01 14:39:58 -0500331 return BitSetT<N, BitsT, ParamT>(mBits >> pos);
Jamie Madill6de51852017-04-12 09:53:01 -0400332}
333
Corentin Walleze4477002017-12-01 14:39:58 -0500334template <size_t N, typename BitsT, typename ParamT>
335BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator>>=(std::size_t pos)
Jamie Madill6de51852017-04-12 09:53:01 -0400336{
337 mBits = ((mBits >> pos) & Mask(N));
338 return *this;
339}
340
Corentin Walleze4477002017-12-01 14:39:58 -0500341template <size_t N, typename BitsT, typename ParamT>
342BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::set()
Jamie Madill6de51852017-04-12 09:53:01 -0400343{
344 mBits = Mask(N);
345 return *this;
346}
347
Corentin Walleze4477002017-12-01 14:39:58 -0500348template <size_t N, typename BitsT, typename ParamT>
349BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::set(ParamT pos, bool value)
Jamie Madill6de51852017-04-12 09:53:01 -0400350{
351 if (value)
352 {
353 mBits |= Bit(pos);
354 }
355 else
356 {
357 reset(pos);
358 }
359 return *this;
360}
361
Corentin Walleze4477002017-12-01 14:39:58 -0500362template <size_t N, typename BitsT, typename ParamT>
363BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::reset()
Jamie Madill6de51852017-04-12 09:53:01 -0400364{
365 mBits = 0;
366 return *this;
367}
368
Corentin Walleze4477002017-12-01 14:39:58 -0500369template <size_t N, typename BitsT, typename ParamT>
370BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::reset(ParamT pos)
Jamie Madill6de51852017-04-12 09:53:01 -0400371{
372 mBits &= ~Bit(pos);
373 return *this;
374}
375
Corentin Walleze4477002017-12-01 14:39:58 -0500376template <size_t N, typename BitsT, typename ParamT>
377BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::flip()
Jamie Madill6de51852017-04-12 09:53:01 -0400378{
379 mBits ^= Mask(N);
380 return *this;
381}
382
Corentin Walleze4477002017-12-01 14:39:58 -0500383template <size_t N, typename BitsT, typename ParamT>
384BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::flip(ParamT pos)
Jamie Madill6de51852017-04-12 09:53:01 -0400385{
386 mBits ^= Bit(pos);
387 return *this;
388}
389
Corentin Walleze4477002017-12-01 14:39:58 -0500390template <size_t N, typename BitsT, typename ParamT>
391BitSetT<N, BitsT, ParamT>::Iterator::Iterator(const BitSetT &bits) : mBitsCopy(bits), mCurrentBit(0)
Jamie Madill6de51852017-04-12 09:53:01 -0400392{
393 if (bits.any())
394 {
395 mCurrentBit = getNextBit();
396 }
397}
398
Corentin Walleze4477002017-12-01 14:39:58 -0500399template <size_t N, typename BitsT, typename ParamT>
400typename BitSetT<N, BitsT, ParamT>::Iterator &BitSetT<N, BitsT, ParamT>::Iterator::operator++()
Jamie Madill6de51852017-04-12 09:53:01 -0400401{
402 ASSERT(mBitsCopy.any());
403 mBitsCopy.reset(mCurrentBit);
404 mCurrentBit = getNextBit();
405 return *this;
406}
407
Corentin Walleze4477002017-12-01 14:39:58 -0500408template <size_t N, typename BitsT, typename ParamT>
409bool BitSetT<N, BitsT, ParamT>::Iterator::operator==(const Iterator &other) const
Jamie Madill6de51852017-04-12 09:53:01 -0400410{
411 return mBitsCopy == other.mBitsCopy;
412}
413
Corentin Walleze4477002017-12-01 14:39:58 -0500414template <size_t N, typename BitsT, typename ParamT>
415bool BitSetT<N, BitsT, ParamT>::Iterator::operator!=(const Iterator &other) const
Jamie Madill6de51852017-04-12 09:53:01 -0400416{
417 return !(*this == other);
418}
419
Corentin Walleze4477002017-12-01 14:39:58 -0500420template <size_t N, typename BitsT, typename ParamT>
421std::size_t BitSetT<N, BitsT, ParamT>::Iterator::operator*() const
Jamie Madill6de51852017-04-12 09:53:01 -0400422{
423 return mCurrentBit;
424}
425
Corentin Walleze4477002017-12-01 14:39:58 -0500426template <size_t N, typename BitsT, typename ParamT>
427std::size_t BitSetT<N, BitsT, ParamT>::Iterator::getNextBit()
Jamie Madill6de51852017-04-12 09:53:01 -0400428{
429 if (mBitsCopy.none())
430 {
431 return 0;
432 }
433
434 return gl::ScanForward(mBitsCopy.mBits);
435}
436
437template <size_t N>
438using BitSet32 = BitSetT<N, uint32_t>;
439
440// ScanForward for 64-bits requires a 64-bit implementation.
Yuly Novikovc4f1dd82017-10-25 17:02:29 -0400441#if defined(ANGLE_IS_64_BIT_CPU)
Jamie Madill6de51852017-04-12 09:53:01 -0400442template <size_t N>
443using BitSet64 = BitSetT<N, uint64_t>;
Yuly Novikovc4f1dd82017-10-25 17:02:29 -0400444#endif // defined(ANGLE_IS_64_BIT_CPU)
Jamie Madill6de51852017-04-12 09:53:01 -0400445
446namespace priv
447{
448
449template <size_t N, typename T>
450using EnableIfBitsFit = typename std::enable_if<N <= sizeof(T) * 8>::type;
451
452template <size_t N, typename Enable = void>
453struct GetBitSet
454{
455 using Type = IterableBitSet<N>;
456};
457
458// Prefer 64-bit bitsets on 64-bit CPUs. They seem faster than 32-bit.
Yuly Novikovc4f1dd82017-10-25 17:02:29 -0400459#if defined(ANGLE_IS_64_BIT_CPU)
Jamie Madill6de51852017-04-12 09:53:01 -0400460template <size_t N>
461struct GetBitSet<N, EnableIfBitsFit<N, uint64_t>>
462{
463 using Type = BitSet64<N>;
464};
465#else
466template <size_t N>
467struct GetBitSet<N, EnableIfBitsFit<N, uint32_t>>
468{
469 using Type = BitSet32<N>;
470};
Yuly Novikovc4f1dd82017-10-25 17:02:29 -0400471#endif // defined(ANGLE_IS_64_BIT_CPU)
Jamie Madill6de51852017-04-12 09:53:01 -0400472
473} // namespace priv
474
475template <size_t N>
476using BitSet = typename priv::GetBitSet<N>::Type;
477
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400478} // angle
479
Corentin Walleze4477002017-12-01 14:39:58 -0500480template <size_t N, typename BitsT, typename ParamT>
481inline angle::BitSetT<N, BitsT, ParamT> operator&(const angle::BitSetT<N, BitsT, ParamT> &lhs,
482 const angle::BitSetT<N, BitsT, ParamT> &rhs)
Jamie Madill6de51852017-04-12 09:53:01 -0400483{
Corentin Walleze4477002017-12-01 14:39:58 -0500484 return angle::BitSetT<N, BitsT, ParamT>(lhs.bits() & rhs.bits());
Jamie Madill6de51852017-04-12 09:53:01 -0400485}
486
Corentin Walleze4477002017-12-01 14:39:58 -0500487template <size_t N, typename BitsT, typename ParamT>
488inline angle::BitSetT<N, BitsT, ParamT> operator|(const angle::BitSetT<N, BitsT, ParamT> &lhs,
489 const angle::BitSetT<N, BitsT, ParamT> &rhs)
Jamie Madill6de51852017-04-12 09:53:01 -0400490{
Corentin Walleze4477002017-12-01 14:39:58 -0500491 return angle::BitSetT<N, BitsT, ParamT>(lhs.bits() | rhs.bits());
Jamie Madill6de51852017-04-12 09:53:01 -0400492}
493
Corentin Walleze4477002017-12-01 14:39:58 -0500494template <size_t N, typename BitsT, typename ParamT>
495inline angle::BitSetT<N, BitsT, ParamT> operator^(const angle::BitSetT<N, BitsT, ParamT> &lhs,
496 const angle::BitSetT<N, BitsT, ParamT> &rhs)
Jamie Madill6de51852017-04-12 09:53:01 -0400497{
Corentin Walleze4477002017-12-01 14:39:58 -0500498 return angle::BitSetT<N, BitsT, ParamT>(lhs.bits() ^ rhs.bits());
Jamie Madill6de51852017-04-12 09:53:01 -0400499}
500
Jamie Madill6b2a0b02015-08-03 14:15:08 -0400501#endif // COMMON_BITSETITERATOR_H_