xref: /aosp_15_r20/external/pytorch/c10/util/sparse_bitset.h (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1*da0073e9SAndroid Build Coastguard Worker //===- llvm/ADT/SparseBitVector.h - Efficient Sparse BitVector --*- C++ -*-===//
2*da0073e9SAndroid Build Coastguard Worker //
3*da0073e9SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*da0073e9SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
5*da0073e9SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*da0073e9SAndroid Build Coastguard Worker //
7*da0073e9SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*da0073e9SAndroid Build Coastguard Worker //
9*da0073e9SAndroid Build Coastguard Worker // This file defines the SparseBitVector class.  See the doxygen comment for
10*da0073e9SAndroid Build Coastguard Worker // SparseBitVector for more details on the algorithm used.
11*da0073e9SAndroid Build Coastguard Worker //
12*da0073e9SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*da0073e9SAndroid Build Coastguard Worker 
14*da0073e9SAndroid Build Coastguard Worker #pragma once
15*da0073e9SAndroid Build Coastguard Worker #include <c10/macros/Macros.h>
16*da0073e9SAndroid Build Coastguard Worker #include <c10/util/llvmMathExtras.h>
17*da0073e9SAndroid Build Coastguard Worker #include <array>
18*da0073e9SAndroid Build Coastguard Worker #include <cassert>
19*da0073e9SAndroid Build Coastguard Worker #include <climits>
20*da0073e9SAndroid Build Coastguard Worker #include <iterator>
21*da0073e9SAndroid Build Coastguard Worker #include <list>
22*da0073e9SAndroid Build Coastguard Worker #include <ostream>
23*da0073e9SAndroid Build Coastguard Worker 
24*da0073e9SAndroid Build Coastguard Worker namespace c10 {
25*da0073e9SAndroid Build Coastguard Worker 
26*da0073e9SAndroid Build Coastguard Worker /// SparseBitVector is an implementation of a bitvector that is sparse by only
27*da0073e9SAndroid Build Coastguard Worker /// storing the elements that have non-zero bits set.  In order to make this
28*da0073e9SAndroid Build Coastguard Worker /// fast for the most common cases, SparseBitVector is implemented as a linked
29*da0073e9SAndroid Build Coastguard Worker /// list of SparseBitVectorElements.  We maintain a pointer to the last
30*da0073e9SAndroid Build Coastguard Worker /// SparseBitVectorElement accessed (in the form of a list iterator), in order
31*da0073e9SAndroid Build Coastguard Worker /// to make multiple in-order test/set constant time after the first one is
32*da0073e9SAndroid Build Coastguard Worker /// executed.  Note that using vectors to store SparseBitVectorElement's does
33*da0073e9SAndroid Build Coastguard Worker /// not work out very well because it causes insertion in the middle to take
34*da0073e9SAndroid Build Coastguard Worker /// enormous amounts of time with a large amount of bits.  Other structures that
35*da0073e9SAndroid Build Coastguard Worker /// have better worst cases for insertion in the middle (various balanced trees,
36*da0073e9SAndroid Build Coastguard Worker /// etc) do not perform as well in practice as a linked list with this iterator
37*da0073e9SAndroid Build Coastguard Worker /// kept up to date.  They are also significantly more memory intensive.
38*da0073e9SAndroid Build Coastguard Worker 
39*da0073e9SAndroid Build Coastguard Worker template <unsigned ElementSize = 128>
40*da0073e9SAndroid Build Coastguard Worker struct SparseBitVectorElement {
41*da0073e9SAndroid Build Coastguard Worker  public:
42*da0073e9SAndroid Build Coastguard Worker   using BitWord = unsigned long;
43*da0073e9SAndroid Build Coastguard Worker   using size_type = unsigned;
44*da0073e9SAndroid Build Coastguard Worker   enum {
45*da0073e9SAndroid Build Coastguard Worker     BITWORD_SIZE = sizeof(BitWord) * CHAR_BIT,
46*da0073e9SAndroid Build Coastguard Worker     BITWORDS_PER_ELEMENT = (ElementSize + BITWORD_SIZE - 1) / BITWORD_SIZE,
47*da0073e9SAndroid Build Coastguard Worker     BITS_PER_ELEMENT = ElementSize
48*da0073e9SAndroid Build Coastguard Worker   };
49*da0073e9SAndroid Build Coastguard Worker 
50*da0073e9SAndroid Build Coastguard Worker  private:
51*da0073e9SAndroid Build Coastguard Worker   // Index of Element in terms of where first bit starts.
52*da0073e9SAndroid Build Coastguard Worker   unsigned ElementIndex;
53*da0073e9SAndroid Build Coastguard Worker   std::array<BitWord, BITWORDS_PER_ELEMENT> Bits{};
54*da0073e9SAndroid Build Coastguard Worker 
SparseBitVectorElementSparseBitVectorElement55*da0073e9SAndroid Build Coastguard Worker   SparseBitVectorElement() : ElementIndex(~0U) {}
56*da0073e9SAndroid Build Coastguard Worker 
57*da0073e9SAndroid Build Coastguard Worker  public:
SparseBitVectorElementSparseBitVectorElement58*da0073e9SAndroid Build Coastguard Worker   explicit SparseBitVectorElement(unsigned Idx) : ElementIndex(Idx) {}
59*da0073e9SAndroid Build Coastguard Worker 
60*da0073e9SAndroid Build Coastguard Worker   // Comparison.
61*da0073e9SAndroid Build Coastguard Worker   bool operator==(const SparseBitVectorElement& RHS) const {
62*da0073e9SAndroid Build Coastguard Worker     if (ElementIndex != RHS.ElementIndex)
63*da0073e9SAndroid Build Coastguard Worker       return false;
64*da0073e9SAndroid Build Coastguard Worker     for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
65*da0073e9SAndroid Build Coastguard Worker       if (Bits[i] != RHS.Bits[i])
66*da0073e9SAndroid Build Coastguard Worker         return false;
67*da0073e9SAndroid Build Coastguard Worker     return true;
68*da0073e9SAndroid Build Coastguard Worker   }
69*da0073e9SAndroid Build Coastguard Worker 
70*da0073e9SAndroid Build Coastguard Worker   bool operator!=(const SparseBitVectorElement& RHS) const {
71*da0073e9SAndroid Build Coastguard Worker     return !(*this == RHS);
72*da0073e9SAndroid Build Coastguard Worker   }
73*da0073e9SAndroid Build Coastguard Worker 
74*da0073e9SAndroid Build Coastguard Worker   // Return the bits that make up word Idx in our element.
wordSparseBitVectorElement75*da0073e9SAndroid Build Coastguard Worker   BitWord word(unsigned Idx) const {
76*da0073e9SAndroid Build Coastguard Worker     assert(Idx < BITWORDS_PER_ELEMENT);
77*da0073e9SAndroid Build Coastguard Worker     return Bits[Idx];
78*da0073e9SAndroid Build Coastguard Worker   }
79*da0073e9SAndroid Build Coastguard Worker 
indexSparseBitVectorElement80*da0073e9SAndroid Build Coastguard Worker   unsigned index() const {
81*da0073e9SAndroid Build Coastguard Worker     return ElementIndex;
82*da0073e9SAndroid Build Coastguard Worker   }
83*da0073e9SAndroid Build Coastguard Worker 
emptySparseBitVectorElement84*da0073e9SAndroid Build Coastguard Worker   bool empty() const {
85*da0073e9SAndroid Build Coastguard Worker     for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
86*da0073e9SAndroid Build Coastguard Worker       if (Bits[i])
87*da0073e9SAndroid Build Coastguard Worker         return false;
88*da0073e9SAndroid Build Coastguard Worker     return true;
89*da0073e9SAndroid Build Coastguard Worker   }
90*da0073e9SAndroid Build Coastguard Worker 
setSparseBitVectorElement91*da0073e9SAndroid Build Coastguard Worker   void set(unsigned Idx) {
92*da0073e9SAndroid Build Coastguard Worker     Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE);
93*da0073e9SAndroid Build Coastguard Worker   }
94*da0073e9SAndroid Build Coastguard Worker 
test_and_setSparseBitVectorElement95*da0073e9SAndroid Build Coastguard Worker   bool test_and_set(unsigned Idx) {
96*da0073e9SAndroid Build Coastguard Worker     bool old = test(Idx);
97*da0073e9SAndroid Build Coastguard Worker     if (!old) {
98*da0073e9SAndroid Build Coastguard Worker       set(Idx);
99*da0073e9SAndroid Build Coastguard Worker       return true;
100*da0073e9SAndroid Build Coastguard Worker     }
101*da0073e9SAndroid Build Coastguard Worker     return false;
102*da0073e9SAndroid Build Coastguard Worker   }
103*da0073e9SAndroid Build Coastguard Worker 
resetSparseBitVectorElement104*da0073e9SAndroid Build Coastguard Worker   void reset(unsigned Idx) {
105*da0073e9SAndroid Build Coastguard Worker     Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE));
106*da0073e9SAndroid Build Coastguard Worker   }
107*da0073e9SAndroid Build Coastguard Worker 
testSparseBitVectorElement108*da0073e9SAndroid Build Coastguard Worker   bool test(unsigned Idx) const {
109*da0073e9SAndroid Build Coastguard Worker     return Bits[Idx / BITWORD_SIZE] & (1L << (Idx % BITWORD_SIZE));
110*da0073e9SAndroid Build Coastguard Worker   }
111*da0073e9SAndroid Build Coastguard Worker 
countSparseBitVectorElement112*da0073e9SAndroid Build Coastguard Worker   size_type count() const {
113*da0073e9SAndroid Build Coastguard Worker     unsigned NumBits = 0;
114*da0073e9SAndroid Build Coastguard Worker     for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
115*da0073e9SAndroid Build Coastguard Worker       NumBits += llvm::countPopulation(Bits[i]);
116*da0073e9SAndroid Build Coastguard Worker     return NumBits;
117*da0073e9SAndroid Build Coastguard Worker   }
118*da0073e9SAndroid Build Coastguard Worker 
119*da0073e9SAndroid Build Coastguard Worker   /// find_first - Returns the index of the first set bit.
find_firstSparseBitVectorElement120*da0073e9SAndroid Build Coastguard Worker   int find_first() const {
121*da0073e9SAndroid Build Coastguard Worker     for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
122*da0073e9SAndroid Build Coastguard Worker       if (Bits[i] != 0)
123*da0073e9SAndroid Build Coastguard Worker         return i * BITWORD_SIZE + llvm::countTrailingZeros(Bits[i]);
124*da0073e9SAndroid Build Coastguard Worker     throw std::runtime_error("Illegal empty element");
125*da0073e9SAndroid Build Coastguard Worker   }
126*da0073e9SAndroid Build Coastguard Worker 
127*da0073e9SAndroid Build Coastguard Worker   /// find_last - Returns the index of the last set bit.
find_lastSparseBitVectorElement128*da0073e9SAndroid Build Coastguard Worker   int find_last() const {
129*da0073e9SAndroid Build Coastguard Worker     for (unsigned I = 0; I < BITWORDS_PER_ELEMENT; ++I) {
130*da0073e9SAndroid Build Coastguard Worker       unsigned Idx = BITWORDS_PER_ELEMENT - I - 1;
131*da0073e9SAndroid Build Coastguard Worker       if (Bits[Idx] != 0)
132*da0073e9SAndroid Build Coastguard Worker         return Idx * BITWORD_SIZE + BITWORD_SIZE -
133*da0073e9SAndroid Build Coastguard Worker             llvm::countLeadingZeros(Bits[Idx]);
134*da0073e9SAndroid Build Coastguard Worker     }
135*da0073e9SAndroid Build Coastguard Worker     throw std::runtime_error("Illegal empty element");
136*da0073e9SAndroid Build Coastguard Worker   }
137*da0073e9SAndroid Build Coastguard Worker 
138*da0073e9SAndroid Build Coastguard Worker   /// find_next - Returns the index of the next set bit starting from the
139*da0073e9SAndroid Build Coastguard Worker   /// "Curr" bit. Returns -1 if the next set bit is not found.
find_nextSparseBitVectorElement140*da0073e9SAndroid Build Coastguard Worker   int find_next(unsigned Curr) const {
141*da0073e9SAndroid Build Coastguard Worker     if (Curr >= BITS_PER_ELEMENT)
142*da0073e9SAndroid Build Coastguard Worker       return -1;
143*da0073e9SAndroid Build Coastguard Worker 
144*da0073e9SAndroid Build Coastguard Worker     unsigned WordPos = Curr / BITWORD_SIZE;
145*da0073e9SAndroid Build Coastguard Worker     unsigned BitPos = Curr % BITWORD_SIZE;
146*da0073e9SAndroid Build Coastguard Worker     BitWord Copy = Bits[WordPos];
147*da0073e9SAndroid Build Coastguard Worker     assert(
148*da0073e9SAndroid Build Coastguard Worker         WordPos <= BITWORDS_PER_ELEMENT && "Word Position outside of element");
149*da0073e9SAndroid Build Coastguard Worker 
150*da0073e9SAndroid Build Coastguard Worker     // Mask off previous bits.
151*da0073e9SAndroid Build Coastguard Worker     Copy &= ~0UL << BitPos;
152*da0073e9SAndroid Build Coastguard Worker 
153*da0073e9SAndroid Build Coastguard Worker     if (Copy != 0)
154*da0073e9SAndroid Build Coastguard Worker       return WordPos * BITWORD_SIZE + llvm::countTrailingZeros(Copy);
155*da0073e9SAndroid Build Coastguard Worker 
156*da0073e9SAndroid Build Coastguard Worker     // Check subsequent words.
157*da0073e9SAndroid Build Coastguard Worker     for (unsigned i = WordPos + 1; i < BITWORDS_PER_ELEMENT; ++i)
158*da0073e9SAndroid Build Coastguard Worker       if (Bits[i] != 0)
159*da0073e9SAndroid Build Coastguard Worker         return i * BITWORD_SIZE + llvm::countTrailingZeros(Bits[i]);
160*da0073e9SAndroid Build Coastguard Worker     return -1;
161*da0073e9SAndroid Build Coastguard Worker   }
162*da0073e9SAndroid Build Coastguard Worker 
163*da0073e9SAndroid Build Coastguard Worker   // Union this element with RHS and return true if this one changed.
unionWithSparseBitVectorElement164*da0073e9SAndroid Build Coastguard Worker   bool unionWith(const SparseBitVectorElement& RHS) {
165*da0073e9SAndroid Build Coastguard Worker     bool changed = false;
166*da0073e9SAndroid Build Coastguard Worker     for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) {
167*da0073e9SAndroid Build Coastguard Worker       BitWord old = changed ? 0 : Bits[i];
168*da0073e9SAndroid Build Coastguard Worker 
169*da0073e9SAndroid Build Coastguard Worker       Bits[i] |= RHS.Bits[i];
170*da0073e9SAndroid Build Coastguard Worker       if (!changed && old != Bits[i])
171*da0073e9SAndroid Build Coastguard Worker         changed = true;
172*da0073e9SAndroid Build Coastguard Worker     }
173*da0073e9SAndroid Build Coastguard Worker     return changed;
174*da0073e9SAndroid Build Coastguard Worker   }
175*da0073e9SAndroid Build Coastguard Worker 
176*da0073e9SAndroid Build Coastguard Worker   // Return true if we have any bits in common with RHS
intersectsSparseBitVectorElement177*da0073e9SAndroid Build Coastguard Worker   bool intersects(const SparseBitVectorElement& RHS) const {
178*da0073e9SAndroid Build Coastguard Worker     for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) {
179*da0073e9SAndroid Build Coastguard Worker       if (RHS.Bits[i] & Bits[i])
180*da0073e9SAndroid Build Coastguard Worker         return true;
181*da0073e9SAndroid Build Coastguard Worker     }
182*da0073e9SAndroid Build Coastguard Worker     return false;
183*da0073e9SAndroid Build Coastguard Worker   }
184*da0073e9SAndroid Build Coastguard Worker 
185*da0073e9SAndroid Build Coastguard Worker   // Intersect this Element with RHS and return true if this one changed.
186*da0073e9SAndroid Build Coastguard Worker   // BecameZero is set to true if this element became all-zero bits.
intersectWithSparseBitVectorElement187*da0073e9SAndroid Build Coastguard Worker   bool intersectWith(const SparseBitVectorElement& RHS, bool& BecameZero) {
188*da0073e9SAndroid Build Coastguard Worker     bool changed = false;
189*da0073e9SAndroid Build Coastguard Worker     bool allzero = true;
190*da0073e9SAndroid Build Coastguard Worker 
191*da0073e9SAndroid Build Coastguard Worker     for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) {
192*da0073e9SAndroid Build Coastguard Worker       BitWord old = changed ? 0 : Bits[i];
193*da0073e9SAndroid Build Coastguard Worker 
194*da0073e9SAndroid Build Coastguard Worker       Bits[i] &= RHS.Bits[i];
195*da0073e9SAndroid Build Coastguard Worker       if (Bits[i] != 0)
196*da0073e9SAndroid Build Coastguard Worker         allzero = false;
197*da0073e9SAndroid Build Coastguard Worker 
198*da0073e9SAndroid Build Coastguard Worker       if (!changed && old != Bits[i])
199*da0073e9SAndroid Build Coastguard Worker         changed = true;
200*da0073e9SAndroid Build Coastguard Worker     }
201*da0073e9SAndroid Build Coastguard Worker     BecameZero = allzero;
202*da0073e9SAndroid Build Coastguard Worker     return changed;
203*da0073e9SAndroid Build Coastguard Worker   }
204*da0073e9SAndroid Build Coastguard Worker 
205*da0073e9SAndroid Build Coastguard Worker   // Intersect this Element with the complement of RHS and return true if this
206*da0073e9SAndroid Build Coastguard Worker   // one changed.  BecameZero is set to true if this element became all-zero
207*da0073e9SAndroid Build Coastguard Worker   // bits.
intersectWithComplementSparseBitVectorElement208*da0073e9SAndroid Build Coastguard Worker   bool intersectWithComplement(
209*da0073e9SAndroid Build Coastguard Worker       const SparseBitVectorElement& RHS,
210*da0073e9SAndroid Build Coastguard Worker       bool& BecameZero) {
211*da0073e9SAndroid Build Coastguard Worker     bool changed = false;
212*da0073e9SAndroid Build Coastguard Worker     bool allzero = true;
213*da0073e9SAndroid Build Coastguard Worker 
214*da0073e9SAndroid Build Coastguard Worker     for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) {
215*da0073e9SAndroid Build Coastguard Worker       BitWord old = changed ? 0 : Bits[i];
216*da0073e9SAndroid Build Coastguard Worker 
217*da0073e9SAndroid Build Coastguard Worker       Bits[i] &= ~RHS.Bits[i];
218*da0073e9SAndroid Build Coastguard Worker       if (Bits[i] != 0)
219*da0073e9SAndroid Build Coastguard Worker         allzero = false;
220*da0073e9SAndroid Build Coastguard Worker 
221*da0073e9SAndroid Build Coastguard Worker       if (!changed && old != Bits[i])
222*da0073e9SAndroid Build Coastguard Worker         changed = true;
223*da0073e9SAndroid Build Coastguard Worker     }
224*da0073e9SAndroid Build Coastguard Worker     BecameZero = allzero;
225*da0073e9SAndroid Build Coastguard Worker     return changed;
226*da0073e9SAndroid Build Coastguard Worker   }
227*da0073e9SAndroid Build Coastguard Worker 
228*da0073e9SAndroid Build Coastguard Worker   // Three argument version of intersectWithComplement that intersects
229*da0073e9SAndroid Build Coastguard Worker   // RHS1 & ~RHS2 into this element
intersectWithComplementSparseBitVectorElement230*da0073e9SAndroid Build Coastguard Worker   void intersectWithComplement(
231*da0073e9SAndroid Build Coastguard Worker       const SparseBitVectorElement& RHS1,
232*da0073e9SAndroid Build Coastguard Worker       const SparseBitVectorElement& RHS2,
233*da0073e9SAndroid Build Coastguard Worker       bool& BecameZero) {
234*da0073e9SAndroid Build Coastguard Worker     bool allzero = true;
235*da0073e9SAndroid Build Coastguard Worker 
236*da0073e9SAndroid Build Coastguard Worker     for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) {
237*da0073e9SAndroid Build Coastguard Worker       Bits[i] = RHS1.Bits[i] & ~RHS2.Bits[i];
238*da0073e9SAndroid Build Coastguard Worker       if (Bits[i] != 0)
239*da0073e9SAndroid Build Coastguard Worker         allzero = false;
240*da0073e9SAndroid Build Coastguard Worker     }
241*da0073e9SAndroid Build Coastguard Worker     BecameZero = allzero;
242*da0073e9SAndroid Build Coastguard Worker   }
243*da0073e9SAndroid Build Coastguard Worker };
244*da0073e9SAndroid Build Coastguard Worker 
245*da0073e9SAndroid Build Coastguard Worker template <unsigned ElementSize = 128>
246*da0073e9SAndroid Build Coastguard Worker class SparseBitVector {
247*da0073e9SAndroid Build Coastguard Worker   using ElementList = std::list<SparseBitVectorElement<ElementSize>>;
248*da0073e9SAndroid Build Coastguard Worker   using ElementListIter = typename ElementList::iterator;
249*da0073e9SAndroid Build Coastguard Worker   using ElementListConstIter = typename ElementList::const_iterator;
250*da0073e9SAndroid Build Coastguard Worker   enum { BITWORD_SIZE = SparseBitVectorElement<ElementSize>::BITWORD_SIZE };
251*da0073e9SAndroid Build Coastguard Worker 
252*da0073e9SAndroid Build Coastguard Worker   ElementList Elements;
253*da0073e9SAndroid Build Coastguard Worker   // Pointer to our current Element. This has no visible effect on the external
254*da0073e9SAndroid Build Coastguard Worker   // state of a SparseBitVector, it's just used to improve performance in the
255*da0073e9SAndroid Build Coastguard Worker   // common case of testing/modifying bits with similar indices.
256*da0073e9SAndroid Build Coastguard Worker   mutable ElementListIter CurrElementIter;
257*da0073e9SAndroid Build Coastguard Worker 
258*da0073e9SAndroid Build Coastguard Worker   // This is like std::lower_bound, except we do linear searching from the
259*da0073e9SAndroid Build Coastguard Worker   // current position.
FindLowerBoundImpl(unsigned ElementIndex)260*da0073e9SAndroid Build Coastguard Worker   ElementListIter FindLowerBoundImpl(unsigned ElementIndex) const {
261*da0073e9SAndroid Build Coastguard Worker     // We cache a non-const iterator so we're forced to resort to const_cast to
262*da0073e9SAndroid Build Coastguard Worker     // get the begin/end in the case where 'this' is const. To avoid duplication
263*da0073e9SAndroid Build Coastguard Worker     // of code with the only difference being whether the const cast is present
264*da0073e9SAndroid Build Coastguard Worker     // 'this' is always const in this particular function and we sort out the
265*da0073e9SAndroid Build Coastguard Worker     // difference in FindLowerBound and FindLowerBoundConst.
266*da0073e9SAndroid Build Coastguard Worker     ElementListIter Begin =
267*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
268*da0073e9SAndroid Build Coastguard Worker         const_cast<SparseBitVector<ElementSize>*>(this)->Elements.begin();
269*da0073e9SAndroid Build Coastguard Worker     ElementListIter End =
270*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
271*da0073e9SAndroid Build Coastguard Worker         const_cast<SparseBitVector<ElementSize>*>(this)->Elements.end();
272*da0073e9SAndroid Build Coastguard Worker 
273*da0073e9SAndroid Build Coastguard Worker     if (Elements.empty()) {
274*da0073e9SAndroid Build Coastguard Worker       CurrElementIter = Begin;
275*da0073e9SAndroid Build Coastguard Worker       return CurrElementIter;
276*da0073e9SAndroid Build Coastguard Worker     }
277*da0073e9SAndroid Build Coastguard Worker 
278*da0073e9SAndroid Build Coastguard Worker     // Make sure our current iterator is valid.
279*da0073e9SAndroid Build Coastguard Worker     if (CurrElementIter == End)
280*da0073e9SAndroid Build Coastguard Worker       --CurrElementIter;
281*da0073e9SAndroid Build Coastguard Worker 
282*da0073e9SAndroid Build Coastguard Worker     // Search from our current iterator, either backwards or forwards,
283*da0073e9SAndroid Build Coastguard Worker     // depending on what element we are looking for.
284*da0073e9SAndroid Build Coastguard Worker     ElementListIter ElementIter = CurrElementIter;
285*da0073e9SAndroid Build Coastguard Worker     if (CurrElementIter->index() == ElementIndex) {
286*da0073e9SAndroid Build Coastguard Worker       return ElementIter;
287*da0073e9SAndroid Build Coastguard Worker     } else if (CurrElementIter->index() > ElementIndex) {
288*da0073e9SAndroid Build Coastguard Worker       while (ElementIter != Begin && ElementIter->index() > ElementIndex)
289*da0073e9SAndroid Build Coastguard Worker         --ElementIter;
290*da0073e9SAndroid Build Coastguard Worker     } else {
291*da0073e9SAndroid Build Coastguard Worker       while (ElementIter != End && ElementIter->index() < ElementIndex)
292*da0073e9SAndroid Build Coastguard Worker         ++ElementIter;
293*da0073e9SAndroid Build Coastguard Worker     }
294*da0073e9SAndroid Build Coastguard Worker     CurrElementIter = ElementIter;
295*da0073e9SAndroid Build Coastguard Worker     return ElementIter;
296*da0073e9SAndroid Build Coastguard Worker   }
FindLowerBoundConst(unsigned ElementIndex)297*da0073e9SAndroid Build Coastguard Worker   ElementListConstIter FindLowerBoundConst(unsigned ElementIndex) const {
298*da0073e9SAndroid Build Coastguard Worker     return FindLowerBoundImpl(ElementIndex);
299*da0073e9SAndroid Build Coastguard Worker   }
FindLowerBound(unsigned ElementIndex)300*da0073e9SAndroid Build Coastguard Worker   ElementListIter FindLowerBound(unsigned ElementIndex) {
301*da0073e9SAndroid Build Coastguard Worker     return FindLowerBoundImpl(ElementIndex);
302*da0073e9SAndroid Build Coastguard Worker   }
303*da0073e9SAndroid Build Coastguard Worker 
304*da0073e9SAndroid Build Coastguard Worker   // Iterator to walk set bits in the bitmap.  This iterator is a lot uglier
305*da0073e9SAndroid Build Coastguard Worker   // than it would be, in order to be efficient.
306*da0073e9SAndroid Build Coastguard Worker   class SparseBitVectorIterator {
307*da0073e9SAndroid Build Coastguard Worker    private:
308*da0073e9SAndroid Build Coastguard Worker     bool AtEnd{false};
309*da0073e9SAndroid Build Coastguard Worker 
310*da0073e9SAndroid Build Coastguard Worker     const SparseBitVector<ElementSize>* BitVector = nullptr;
311*da0073e9SAndroid Build Coastguard Worker 
312*da0073e9SAndroid Build Coastguard Worker     // Current element inside of bitmap.
313*da0073e9SAndroid Build Coastguard Worker     ElementListConstIter Iter;
314*da0073e9SAndroid Build Coastguard Worker 
315*da0073e9SAndroid Build Coastguard Worker     // Current bit number inside of our bitmap.
316*da0073e9SAndroid Build Coastguard Worker     unsigned BitNumber{0};
317*da0073e9SAndroid Build Coastguard Worker 
318*da0073e9SAndroid Build Coastguard Worker     // Current word number inside of our element.
319*da0073e9SAndroid Build Coastguard Worker     unsigned WordNumber{0};
320*da0073e9SAndroid Build Coastguard Worker 
321*da0073e9SAndroid Build Coastguard Worker     // Current bits from the element.
322*da0073e9SAndroid Build Coastguard Worker     typename SparseBitVectorElement<ElementSize>::BitWord Bits{0};
323*da0073e9SAndroid Build Coastguard Worker 
324*da0073e9SAndroid Build Coastguard Worker     // Move our iterator to the first non-zero bit in the bitmap.
AdvanceToFirstNonZero()325*da0073e9SAndroid Build Coastguard Worker     void AdvanceToFirstNonZero() {
326*da0073e9SAndroid Build Coastguard Worker       if (AtEnd)
327*da0073e9SAndroid Build Coastguard Worker         return;
328*da0073e9SAndroid Build Coastguard Worker       if (BitVector->Elements.empty()) {
329*da0073e9SAndroid Build Coastguard Worker         AtEnd = true;
330*da0073e9SAndroid Build Coastguard Worker         return;
331*da0073e9SAndroid Build Coastguard Worker       }
332*da0073e9SAndroid Build Coastguard Worker       Iter = BitVector->Elements.begin();
333*da0073e9SAndroid Build Coastguard Worker       BitNumber = Iter->index() * ElementSize;
334*da0073e9SAndroid Build Coastguard Worker       unsigned BitPos = Iter->find_first();
335*da0073e9SAndroid Build Coastguard Worker       BitNumber += BitPos;
336*da0073e9SAndroid Build Coastguard Worker       WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE;
337*da0073e9SAndroid Build Coastguard Worker       Bits = Iter->word(WordNumber);
338*da0073e9SAndroid Build Coastguard Worker       Bits >>= BitPos % BITWORD_SIZE;
339*da0073e9SAndroid Build Coastguard Worker     }
340*da0073e9SAndroid Build Coastguard Worker 
341*da0073e9SAndroid Build Coastguard Worker     // Move our iterator to the next non-zero bit.
AdvanceToNextNonZero()342*da0073e9SAndroid Build Coastguard Worker     void AdvanceToNextNonZero() {
343*da0073e9SAndroid Build Coastguard Worker       if (AtEnd)
344*da0073e9SAndroid Build Coastguard Worker         return;
345*da0073e9SAndroid Build Coastguard Worker 
346*da0073e9SAndroid Build Coastguard Worker       while (Bits && !(Bits & 1)) {
347*da0073e9SAndroid Build Coastguard Worker         Bits >>= 1;
348*da0073e9SAndroid Build Coastguard Worker         BitNumber += 1;
349*da0073e9SAndroid Build Coastguard Worker       }
350*da0073e9SAndroid Build Coastguard Worker 
351*da0073e9SAndroid Build Coastguard Worker       // See if we ran out of Bits in this word.
352*da0073e9SAndroid Build Coastguard Worker       if (!Bits) {
353*da0073e9SAndroid Build Coastguard Worker         int NextSetBitNumber = Iter->find_next(BitNumber % ElementSize);
354*da0073e9SAndroid Build Coastguard Worker         // If we ran out of set bits in this element, move to next element.
355*da0073e9SAndroid Build Coastguard Worker         if (NextSetBitNumber == -1 || (BitNumber % ElementSize == 0)) {
356*da0073e9SAndroid Build Coastguard Worker           ++Iter;
357*da0073e9SAndroid Build Coastguard Worker           WordNumber = 0;
358*da0073e9SAndroid Build Coastguard Worker 
359*da0073e9SAndroid Build Coastguard Worker           // We may run out of elements in the bitmap.
360*da0073e9SAndroid Build Coastguard Worker           if (Iter == BitVector->Elements.end()) {
361*da0073e9SAndroid Build Coastguard Worker             AtEnd = true;
362*da0073e9SAndroid Build Coastguard Worker             return;
363*da0073e9SAndroid Build Coastguard Worker           }
364*da0073e9SAndroid Build Coastguard Worker           // Set up for next non-zero word in bitmap.
365*da0073e9SAndroid Build Coastguard Worker           BitNumber = Iter->index() * ElementSize;
366*da0073e9SAndroid Build Coastguard Worker           NextSetBitNumber = Iter->find_first();
367*da0073e9SAndroid Build Coastguard Worker           BitNumber += NextSetBitNumber;
368*da0073e9SAndroid Build Coastguard Worker           WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE;
369*da0073e9SAndroid Build Coastguard Worker           Bits = Iter->word(WordNumber);
370*da0073e9SAndroid Build Coastguard Worker           Bits >>= NextSetBitNumber % BITWORD_SIZE;
371*da0073e9SAndroid Build Coastguard Worker         } else {
372*da0073e9SAndroid Build Coastguard Worker           WordNumber = (NextSetBitNumber % ElementSize) / BITWORD_SIZE;
373*da0073e9SAndroid Build Coastguard Worker           Bits = Iter->word(WordNumber);
374*da0073e9SAndroid Build Coastguard Worker           Bits >>= NextSetBitNumber % BITWORD_SIZE;
375*da0073e9SAndroid Build Coastguard Worker           BitNumber = Iter->index() * ElementSize;
376*da0073e9SAndroid Build Coastguard Worker           BitNumber += NextSetBitNumber;
377*da0073e9SAndroid Build Coastguard Worker         }
378*da0073e9SAndroid Build Coastguard Worker       }
379*da0073e9SAndroid Build Coastguard Worker     }
380*da0073e9SAndroid Build Coastguard Worker 
381*da0073e9SAndroid Build Coastguard Worker    public:
382*da0073e9SAndroid Build Coastguard Worker     SparseBitVectorIterator() = default;
383*da0073e9SAndroid Build Coastguard Worker 
384*da0073e9SAndroid Build Coastguard Worker     SparseBitVectorIterator(
385*da0073e9SAndroid Build Coastguard Worker         const SparseBitVector<ElementSize>* RHS,
386*da0073e9SAndroid Build Coastguard Worker         bool end = false)
AtEnd(end)387*da0073e9SAndroid Build Coastguard Worker         : AtEnd(end),
388*da0073e9SAndroid Build Coastguard Worker           BitVector(RHS),
389*da0073e9SAndroid Build Coastguard Worker           Iter(BitVector->Elements.begin()),
390*da0073e9SAndroid Build Coastguard Worker           WordNumber(~0) {
391*da0073e9SAndroid Build Coastguard Worker       AdvanceToFirstNonZero();
392*da0073e9SAndroid Build Coastguard Worker     }
393*da0073e9SAndroid Build Coastguard Worker 
394*da0073e9SAndroid Build Coastguard Worker     // Preincrement.
395*da0073e9SAndroid Build Coastguard Worker     inline SparseBitVectorIterator& operator++() {
396*da0073e9SAndroid Build Coastguard Worker       ++BitNumber;
397*da0073e9SAndroid Build Coastguard Worker       Bits >>= 1;
398*da0073e9SAndroid Build Coastguard Worker       AdvanceToNextNonZero();
399*da0073e9SAndroid Build Coastguard Worker       return *this;
400*da0073e9SAndroid Build Coastguard Worker     }
401*da0073e9SAndroid Build Coastguard Worker 
402*da0073e9SAndroid Build Coastguard Worker     // Postincrement.
403*da0073e9SAndroid Build Coastguard Worker     inline SparseBitVectorIterator operator++(int) {
404*da0073e9SAndroid Build Coastguard Worker       SparseBitVectorIterator tmp = *this;
405*da0073e9SAndroid Build Coastguard Worker       ++*this;
406*da0073e9SAndroid Build Coastguard Worker       return tmp;
407*da0073e9SAndroid Build Coastguard Worker     }
408*da0073e9SAndroid Build Coastguard Worker 
409*da0073e9SAndroid Build Coastguard Worker     // Return the current set bit number.
410*da0073e9SAndroid Build Coastguard Worker     unsigned operator*() const {
411*da0073e9SAndroid Build Coastguard Worker       return BitNumber;
412*da0073e9SAndroid Build Coastguard Worker     }
413*da0073e9SAndroid Build Coastguard Worker 
414*da0073e9SAndroid Build Coastguard Worker     bool operator==(const SparseBitVectorIterator& RHS) const {
415*da0073e9SAndroid Build Coastguard Worker       // If they are both at the end, ignore the rest of the fields.
416*da0073e9SAndroid Build Coastguard Worker       if (AtEnd && RHS.AtEnd)
417*da0073e9SAndroid Build Coastguard Worker         return true;
418*da0073e9SAndroid Build Coastguard Worker       // Otherwise they are the same if they have the same bit number and
419*da0073e9SAndroid Build Coastguard Worker       // bitmap.
420*da0073e9SAndroid Build Coastguard Worker       return AtEnd == RHS.AtEnd && RHS.BitNumber == BitNumber;
421*da0073e9SAndroid Build Coastguard Worker     }
422*da0073e9SAndroid Build Coastguard Worker 
423*da0073e9SAndroid Build Coastguard Worker     bool operator!=(const SparseBitVectorIterator& RHS) const {
424*da0073e9SAndroid Build Coastguard Worker       return !(*this == RHS);
425*da0073e9SAndroid Build Coastguard Worker     }
426*da0073e9SAndroid Build Coastguard Worker   };
427*da0073e9SAndroid Build Coastguard Worker 
428*da0073e9SAndroid Build Coastguard Worker  public:
429*da0073e9SAndroid Build Coastguard Worker   using iterator = SparseBitVectorIterator;
430*da0073e9SAndroid Build Coastguard Worker 
SparseBitVector()431*da0073e9SAndroid Build Coastguard Worker   SparseBitVector() : Elements(), CurrElementIter(Elements.begin()) {}
432*da0073e9SAndroid Build Coastguard Worker 
SparseBitVector(const SparseBitVector & RHS)433*da0073e9SAndroid Build Coastguard Worker   SparseBitVector(const SparseBitVector& RHS)
434*da0073e9SAndroid Build Coastguard Worker       : Elements(RHS.Elements), CurrElementIter(Elements.begin()) {}
SparseBitVector(SparseBitVector && RHS)435*da0073e9SAndroid Build Coastguard Worker   SparseBitVector(SparseBitVector&& RHS) noexcept
436*da0073e9SAndroid Build Coastguard Worker       : Elements(std::move(RHS.Elements)), CurrElementIter(Elements.begin()) {}
437*da0073e9SAndroid Build Coastguard Worker 
438*da0073e9SAndroid Build Coastguard Worker   // Clear.
clear()439*da0073e9SAndroid Build Coastguard Worker   void clear() {
440*da0073e9SAndroid Build Coastguard Worker     Elements.clear();
441*da0073e9SAndroid Build Coastguard Worker   }
442*da0073e9SAndroid Build Coastguard Worker 
443*da0073e9SAndroid Build Coastguard Worker   // Assignment
444*da0073e9SAndroid Build Coastguard Worker   SparseBitVector& operator=(const SparseBitVector& RHS) {
445*da0073e9SAndroid Build Coastguard Worker     if (this == &RHS)
446*da0073e9SAndroid Build Coastguard Worker       return *this;
447*da0073e9SAndroid Build Coastguard Worker 
448*da0073e9SAndroid Build Coastguard Worker     Elements = RHS.Elements;
449*da0073e9SAndroid Build Coastguard Worker     CurrElementIter = Elements.begin();
450*da0073e9SAndroid Build Coastguard Worker     return *this;
451*da0073e9SAndroid Build Coastguard Worker   }
452*da0073e9SAndroid Build Coastguard Worker   SparseBitVector& operator=(SparseBitVector&& RHS) noexcept {
453*da0073e9SAndroid Build Coastguard Worker     Elements = std::move(RHS.Elements);
454*da0073e9SAndroid Build Coastguard Worker     CurrElementIter = Elements.begin();
455*da0073e9SAndroid Build Coastguard Worker     return *this;
456*da0073e9SAndroid Build Coastguard Worker   }
457*da0073e9SAndroid Build Coastguard Worker 
458*da0073e9SAndroid Build Coastguard Worker   // Test, Reset, and Set a bit in the bitmap.
test(unsigned Idx)459*da0073e9SAndroid Build Coastguard Worker   bool test(unsigned Idx) const {
460*da0073e9SAndroid Build Coastguard Worker     if (Elements.empty())
461*da0073e9SAndroid Build Coastguard Worker       return false;
462*da0073e9SAndroid Build Coastguard Worker 
463*da0073e9SAndroid Build Coastguard Worker     unsigned ElementIndex = Idx / ElementSize;
464*da0073e9SAndroid Build Coastguard Worker     ElementListConstIter ElementIter = FindLowerBoundConst(ElementIndex);
465*da0073e9SAndroid Build Coastguard Worker 
466*da0073e9SAndroid Build Coastguard Worker     // If we can't find an element that is supposed to contain this bit, there
467*da0073e9SAndroid Build Coastguard Worker     // is nothing more to do.
468*da0073e9SAndroid Build Coastguard Worker     if (ElementIter == Elements.end() || ElementIter->index() != ElementIndex)
469*da0073e9SAndroid Build Coastguard Worker       return false;
470*da0073e9SAndroid Build Coastguard Worker     return ElementIter->test(Idx % ElementSize);
471*da0073e9SAndroid Build Coastguard Worker   }
472*da0073e9SAndroid Build Coastguard Worker 
reset(unsigned Idx)473*da0073e9SAndroid Build Coastguard Worker   void reset(unsigned Idx) {
474*da0073e9SAndroid Build Coastguard Worker     if (Elements.empty())
475*da0073e9SAndroid Build Coastguard Worker       return;
476*da0073e9SAndroid Build Coastguard Worker 
477*da0073e9SAndroid Build Coastguard Worker     unsigned ElementIndex = Idx / ElementSize;
478*da0073e9SAndroid Build Coastguard Worker     ElementListIter ElementIter = FindLowerBound(ElementIndex);
479*da0073e9SAndroid Build Coastguard Worker 
480*da0073e9SAndroid Build Coastguard Worker     // If we can't find an element that is supposed to contain this bit, there
481*da0073e9SAndroid Build Coastguard Worker     // is nothing more to do.
482*da0073e9SAndroid Build Coastguard Worker     if (ElementIter == Elements.end() || ElementIter->index() != ElementIndex)
483*da0073e9SAndroid Build Coastguard Worker       return;
484*da0073e9SAndroid Build Coastguard Worker     ElementIter->reset(Idx % ElementSize);
485*da0073e9SAndroid Build Coastguard Worker 
486*da0073e9SAndroid Build Coastguard Worker     // When the element is zeroed out, delete it.
487*da0073e9SAndroid Build Coastguard Worker     if (ElementIter->empty()) {
488*da0073e9SAndroid Build Coastguard Worker       ++CurrElementIter;
489*da0073e9SAndroid Build Coastguard Worker       Elements.erase(ElementIter);
490*da0073e9SAndroid Build Coastguard Worker     }
491*da0073e9SAndroid Build Coastguard Worker   }
492*da0073e9SAndroid Build Coastguard Worker 
set(unsigned Idx)493*da0073e9SAndroid Build Coastguard Worker   void set(unsigned Idx) {
494*da0073e9SAndroid Build Coastguard Worker     unsigned ElementIndex = Idx / ElementSize;
495*da0073e9SAndroid Build Coastguard Worker     ElementListIter ElementIter;
496*da0073e9SAndroid Build Coastguard Worker     if (Elements.empty()) {
497*da0073e9SAndroid Build Coastguard Worker       ElementIter = Elements.emplace(Elements.end(), ElementIndex);
498*da0073e9SAndroid Build Coastguard Worker     } else {
499*da0073e9SAndroid Build Coastguard Worker       ElementIter = FindLowerBound(ElementIndex);
500*da0073e9SAndroid Build Coastguard Worker 
501*da0073e9SAndroid Build Coastguard Worker       if (ElementIter == Elements.end() ||
502*da0073e9SAndroid Build Coastguard Worker           ElementIter->index() != ElementIndex) {
503*da0073e9SAndroid Build Coastguard Worker         // We may have hit the beginning of our SparseBitVector, in which case,
504*da0073e9SAndroid Build Coastguard Worker         // we may need to insert right after this element, which requires moving
505*da0073e9SAndroid Build Coastguard Worker         // the current iterator forward one, because insert does insert before.
506*da0073e9SAndroid Build Coastguard Worker         if (ElementIter != Elements.end() &&
507*da0073e9SAndroid Build Coastguard Worker             ElementIter->index() < ElementIndex)
508*da0073e9SAndroid Build Coastguard Worker           ++ElementIter;
509*da0073e9SAndroid Build Coastguard Worker         ElementIter = Elements.emplace(ElementIter, ElementIndex);
510*da0073e9SAndroid Build Coastguard Worker       }
511*da0073e9SAndroid Build Coastguard Worker     }
512*da0073e9SAndroid Build Coastguard Worker     CurrElementIter = ElementIter;
513*da0073e9SAndroid Build Coastguard Worker 
514*da0073e9SAndroid Build Coastguard Worker     ElementIter->set(Idx % ElementSize);
515*da0073e9SAndroid Build Coastguard Worker   }
516*da0073e9SAndroid Build Coastguard Worker 
test_and_set(unsigned Idx)517*da0073e9SAndroid Build Coastguard Worker   bool test_and_set(unsigned Idx) {
518*da0073e9SAndroid Build Coastguard Worker     bool old = test(Idx);
519*da0073e9SAndroid Build Coastguard Worker     if (!old) {
520*da0073e9SAndroid Build Coastguard Worker       set(Idx);
521*da0073e9SAndroid Build Coastguard Worker       return true;
522*da0073e9SAndroid Build Coastguard Worker     }
523*da0073e9SAndroid Build Coastguard Worker     return false;
524*da0073e9SAndroid Build Coastguard Worker   }
525*da0073e9SAndroid Build Coastguard Worker 
526*da0073e9SAndroid Build Coastguard Worker   bool operator!=(const SparseBitVector& RHS) const {
527*da0073e9SAndroid Build Coastguard Worker     return !(*this == RHS);
528*da0073e9SAndroid Build Coastguard Worker   }
529*da0073e9SAndroid Build Coastguard Worker 
530*da0073e9SAndroid Build Coastguard Worker   bool operator==(const SparseBitVector& RHS) const {
531*da0073e9SAndroid Build Coastguard Worker     ElementListConstIter Iter1 = Elements.begin();
532*da0073e9SAndroid Build Coastguard Worker     ElementListConstIter Iter2 = RHS.Elements.begin();
533*da0073e9SAndroid Build Coastguard Worker 
534*da0073e9SAndroid Build Coastguard Worker     for (; Iter1 != Elements.end() && Iter2 != RHS.Elements.end();
535*da0073e9SAndroid Build Coastguard Worker          ++Iter1, ++Iter2) {
536*da0073e9SAndroid Build Coastguard Worker       if (*Iter1 != *Iter2)
537*da0073e9SAndroid Build Coastguard Worker         return false;
538*da0073e9SAndroid Build Coastguard Worker     }
539*da0073e9SAndroid Build Coastguard Worker     return Iter1 == Elements.end() && Iter2 == RHS.Elements.end();
540*da0073e9SAndroid Build Coastguard Worker   }
541*da0073e9SAndroid Build Coastguard Worker 
542*da0073e9SAndroid Build Coastguard Worker   // Union our bitmap with the RHS and return true if we changed.
543*da0073e9SAndroid Build Coastguard Worker   bool operator|=(const SparseBitVector& RHS) {
544*da0073e9SAndroid Build Coastguard Worker     if (this == &RHS)
545*da0073e9SAndroid Build Coastguard Worker       return false;
546*da0073e9SAndroid Build Coastguard Worker 
547*da0073e9SAndroid Build Coastguard Worker     if (empty()) {
548*da0073e9SAndroid Build Coastguard Worker       *this = RHS;
549*da0073e9SAndroid Build Coastguard Worker       return true;
550*da0073e9SAndroid Build Coastguard Worker     }
551*da0073e9SAndroid Build Coastguard Worker 
552*da0073e9SAndroid Build Coastguard Worker     bool changed = false;
553*da0073e9SAndroid Build Coastguard Worker     ElementListIter Iter1 = Elements.begin();
554*da0073e9SAndroid Build Coastguard Worker     ElementListConstIter Iter2 = RHS.Elements.begin();
555*da0073e9SAndroid Build Coastguard Worker 
556*da0073e9SAndroid Build Coastguard Worker     // If RHS is empty, we are done
557*da0073e9SAndroid Build Coastguard Worker     if (RHS.Elements.empty())
558*da0073e9SAndroid Build Coastguard Worker       return false;
559*da0073e9SAndroid Build Coastguard Worker 
560*da0073e9SAndroid Build Coastguard Worker     while (Iter2 != RHS.Elements.end()) {
561*da0073e9SAndroid Build Coastguard Worker       if (Iter1 == Elements.end() || Iter1->index() > Iter2->index()) {
562*da0073e9SAndroid Build Coastguard Worker         Elements.insert(Iter1, *Iter2);
563*da0073e9SAndroid Build Coastguard Worker         ++Iter2;
564*da0073e9SAndroid Build Coastguard Worker         changed = true;
565*da0073e9SAndroid Build Coastguard Worker       } else if (Iter1->index() == Iter2->index()) {
566*da0073e9SAndroid Build Coastguard Worker         changed |= Iter1->unionWith(*Iter2);
567*da0073e9SAndroid Build Coastguard Worker         ++Iter1;
568*da0073e9SAndroid Build Coastguard Worker         ++Iter2;
569*da0073e9SAndroid Build Coastguard Worker       } else {
570*da0073e9SAndroid Build Coastguard Worker         ++Iter1;
571*da0073e9SAndroid Build Coastguard Worker       }
572*da0073e9SAndroid Build Coastguard Worker     }
573*da0073e9SAndroid Build Coastguard Worker     CurrElementIter = Elements.begin();
574*da0073e9SAndroid Build Coastguard Worker     return changed;
575*da0073e9SAndroid Build Coastguard Worker   }
576*da0073e9SAndroid Build Coastguard Worker 
577*da0073e9SAndroid Build Coastguard Worker   // Intersect our bitmap with the RHS and return true if ours changed.
578*da0073e9SAndroid Build Coastguard Worker   bool operator-=(const SparseBitVector& RHS) {
579*da0073e9SAndroid Build Coastguard Worker     return intersectWithComplement(RHS);
580*da0073e9SAndroid Build Coastguard Worker   }
581*da0073e9SAndroid Build Coastguard Worker 
582*da0073e9SAndroid Build Coastguard Worker   // Intersect our bitmap with the RHS and return true if ours changed.
583*da0073e9SAndroid Build Coastguard Worker   bool operator&=(const SparseBitVector& RHS) {
584*da0073e9SAndroid Build Coastguard Worker     if (this == &RHS)
585*da0073e9SAndroid Build Coastguard Worker       return false;
586*da0073e9SAndroid Build Coastguard Worker 
587*da0073e9SAndroid Build Coastguard Worker     bool changed = false;
588*da0073e9SAndroid Build Coastguard Worker     ElementListIter Iter1 = Elements.begin();
589*da0073e9SAndroid Build Coastguard Worker     ElementListConstIter Iter2 = RHS.Elements.begin();
590*da0073e9SAndroid Build Coastguard Worker 
591*da0073e9SAndroid Build Coastguard Worker     // Check if both bitmaps are empty.
592*da0073e9SAndroid Build Coastguard Worker     if (Elements.empty() && RHS.Elements.empty())
593*da0073e9SAndroid Build Coastguard Worker       return false;
594*da0073e9SAndroid Build Coastguard Worker 
595*da0073e9SAndroid Build Coastguard Worker     // Loop through, intersecting as we go, erasing elements when necessary.
596*da0073e9SAndroid Build Coastguard Worker     while (Iter2 != RHS.Elements.end()) {
597*da0073e9SAndroid Build Coastguard Worker       if (Iter1 == Elements.end()) {
598*da0073e9SAndroid Build Coastguard Worker         CurrElementIter = Elements.begin();
599*da0073e9SAndroid Build Coastguard Worker         return changed;
600*da0073e9SAndroid Build Coastguard Worker       }
601*da0073e9SAndroid Build Coastguard Worker 
602*da0073e9SAndroid Build Coastguard Worker       if (Iter1->index() > Iter2->index()) {
603*da0073e9SAndroid Build Coastguard Worker         ++Iter2;
604*da0073e9SAndroid Build Coastguard Worker       } else if (Iter1->index() == Iter2->index()) {
605*da0073e9SAndroid Build Coastguard Worker         bool BecameZero = false;
606*da0073e9SAndroid Build Coastguard Worker         changed |= Iter1->intersectWith(*Iter2, BecameZero);
607*da0073e9SAndroid Build Coastguard Worker         if (BecameZero) {
608*da0073e9SAndroid Build Coastguard Worker           ElementListIter IterTmp = Iter1;
609*da0073e9SAndroid Build Coastguard Worker           ++Iter1;
610*da0073e9SAndroid Build Coastguard Worker           Elements.erase(IterTmp);
611*da0073e9SAndroid Build Coastguard Worker         } else {
612*da0073e9SAndroid Build Coastguard Worker           ++Iter1;
613*da0073e9SAndroid Build Coastguard Worker         }
614*da0073e9SAndroid Build Coastguard Worker         ++Iter2;
615*da0073e9SAndroid Build Coastguard Worker       } else {
616*da0073e9SAndroid Build Coastguard Worker         ElementListIter IterTmp = Iter1;
617*da0073e9SAndroid Build Coastguard Worker         ++Iter1;
618*da0073e9SAndroid Build Coastguard Worker         Elements.erase(IterTmp);
619*da0073e9SAndroid Build Coastguard Worker         changed = true;
620*da0073e9SAndroid Build Coastguard Worker       }
621*da0073e9SAndroid Build Coastguard Worker     }
622*da0073e9SAndroid Build Coastguard Worker     if (Iter1 != Elements.end()) {
623*da0073e9SAndroid Build Coastguard Worker       Elements.erase(Iter1, Elements.end());
624*da0073e9SAndroid Build Coastguard Worker       changed = true;
625*da0073e9SAndroid Build Coastguard Worker     }
626*da0073e9SAndroid Build Coastguard Worker     CurrElementIter = Elements.begin();
627*da0073e9SAndroid Build Coastguard Worker     return changed;
628*da0073e9SAndroid Build Coastguard Worker   }
629*da0073e9SAndroid Build Coastguard Worker 
630*da0073e9SAndroid Build Coastguard Worker   // Intersect our bitmap with the complement of the RHS and return true
631*da0073e9SAndroid Build Coastguard Worker   // if ours changed.
intersectWithComplement(const SparseBitVector & RHS)632*da0073e9SAndroid Build Coastguard Worker   bool intersectWithComplement(const SparseBitVector& RHS) {
633*da0073e9SAndroid Build Coastguard Worker     if (this == &RHS) {
634*da0073e9SAndroid Build Coastguard Worker       if (!empty()) {
635*da0073e9SAndroid Build Coastguard Worker         clear();
636*da0073e9SAndroid Build Coastguard Worker         return true;
637*da0073e9SAndroid Build Coastguard Worker       }
638*da0073e9SAndroid Build Coastguard Worker       return false;
639*da0073e9SAndroid Build Coastguard Worker     }
640*da0073e9SAndroid Build Coastguard Worker 
641*da0073e9SAndroid Build Coastguard Worker     bool changed = false;
642*da0073e9SAndroid Build Coastguard Worker     ElementListIter Iter1 = Elements.begin();
643*da0073e9SAndroid Build Coastguard Worker     ElementListConstIter Iter2 = RHS.Elements.begin();
644*da0073e9SAndroid Build Coastguard Worker 
645*da0073e9SAndroid Build Coastguard Worker     // If either our bitmap or RHS is empty, we are done
646*da0073e9SAndroid Build Coastguard Worker     if (Elements.empty() || RHS.Elements.empty())
647*da0073e9SAndroid Build Coastguard Worker       return false;
648*da0073e9SAndroid Build Coastguard Worker 
649*da0073e9SAndroid Build Coastguard Worker     // Loop through, intersecting as we go, erasing elements when necessary.
650*da0073e9SAndroid Build Coastguard Worker     while (Iter2 != RHS.Elements.end()) {
651*da0073e9SAndroid Build Coastguard Worker       if (Iter1 == Elements.end()) {
652*da0073e9SAndroid Build Coastguard Worker         CurrElementIter = Elements.begin();
653*da0073e9SAndroid Build Coastguard Worker         return changed;
654*da0073e9SAndroid Build Coastguard Worker       }
655*da0073e9SAndroid Build Coastguard Worker 
656*da0073e9SAndroid Build Coastguard Worker       if (Iter1->index() > Iter2->index()) {
657*da0073e9SAndroid Build Coastguard Worker         ++Iter2;
658*da0073e9SAndroid Build Coastguard Worker       } else if (Iter1->index() == Iter2->index()) {
659*da0073e9SAndroid Build Coastguard Worker         bool BecameZero = false;
660*da0073e9SAndroid Build Coastguard Worker         changed |= Iter1->intersectWithComplement(*Iter2, BecameZero);
661*da0073e9SAndroid Build Coastguard Worker         if (BecameZero) {
662*da0073e9SAndroid Build Coastguard Worker           ElementListIter IterTmp = Iter1;
663*da0073e9SAndroid Build Coastguard Worker           ++Iter1;
664*da0073e9SAndroid Build Coastguard Worker           Elements.erase(IterTmp);
665*da0073e9SAndroid Build Coastguard Worker         } else {
666*da0073e9SAndroid Build Coastguard Worker           ++Iter1;
667*da0073e9SAndroid Build Coastguard Worker         }
668*da0073e9SAndroid Build Coastguard Worker         ++Iter2;
669*da0073e9SAndroid Build Coastguard Worker       } else {
670*da0073e9SAndroid Build Coastguard Worker         ++Iter1;
671*da0073e9SAndroid Build Coastguard Worker       }
672*da0073e9SAndroid Build Coastguard Worker     }
673*da0073e9SAndroid Build Coastguard Worker     CurrElementIter = Elements.begin();
674*da0073e9SAndroid Build Coastguard Worker     return changed;
675*da0073e9SAndroid Build Coastguard Worker   }
676*da0073e9SAndroid Build Coastguard Worker 
intersectWithComplement(const SparseBitVector<ElementSize> * RHS)677*da0073e9SAndroid Build Coastguard Worker   bool intersectWithComplement(const SparseBitVector<ElementSize>* RHS) const {
678*da0073e9SAndroid Build Coastguard Worker     return intersectWithComplement(*RHS);
679*da0073e9SAndroid Build Coastguard Worker   }
680*da0073e9SAndroid Build Coastguard Worker 
681*da0073e9SAndroid Build Coastguard Worker   //  Three argument version of intersectWithComplement.
682*da0073e9SAndroid Build Coastguard Worker   //  Result of RHS1 & ~RHS2 is stored into this bitmap.
intersectWithComplement(const SparseBitVector<ElementSize> & RHS1,const SparseBitVector<ElementSize> & RHS2)683*da0073e9SAndroid Build Coastguard Worker   void intersectWithComplement(
684*da0073e9SAndroid Build Coastguard Worker       const SparseBitVector<ElementSize>& RHS1,
685*da0073e9SAndroid Build Coastguard Worker       const SparseBitVector<ElementSize>& RHS2) {
686*da0073e9SAndroid Build Coastguard Worker     if (this == &RHS1) {
687*da0073e9SAndroid Build Coastguard Worker       intersectWithComplement(RHS2);
688*da0073e9SAndroid Build Coastguard Worker       return;
689*da0073e9SAndroid Build Coastguard Worker     } else if (this == &RHS2) {
690*da0073e9SAndroid Build Coastguard Worker       SparseBitVector RHS2Copy(RHS2);
691*da0073e9SAndroid Build Coastguard Worker       intersectWithComplement(RHS1, RHS2Copy);
692*da0073e9SAndroid Build Coastguard Worker       return;
693*da0073e9SAndroid Build Coastguard Worker     }
694*da0073e9SAndroid Build Coastguard Worker 
695*da0073e9SAndroid Build Coastguard Worker     Elements.clear();
696*da0073e9SAndroid Build Coastguard Worker     CurrElementIter = Elements.begin();
697*da0073e9SAndroid Build Coastguard Worker     ElementListConstIter Iter1 = RHS1.Elements.begin();
698*da0073e9SAndroid Build Coastguard Worker     ElementListConstIter Iter2 = RHS2.Elements.begin();
699*da0073e9SAndroid Build Coastguard Worker 
700*da0073e9SAndroid Build Coastguard Worker     // If RHS1 is empty, we are done
701*da0073e9SAndroid Build Coastguard Worker     // If RHS2 is empty, we still have to copy RHS1
702*da0073e9SAndroid Build Coastguard Worker     if (RHS1.Elements.empty())
703*da0073e9SAndroid Build Coastguard Worker       return;
704*da0073e9SAndroid Build Coastguard Worker 
705*da0073e9SAndroid Build Coastguard Worker     // Loop through, intersecting as we go, erasing elements when necessary.
706*da0073e9SAndroid Build Coastguard Worker     while (Iter2 != RHS2.Elements.end()) {
707*da0073e9SAndroid Build Coastguard Worker       if (Iter1 == RHS1.Elements.end())
708*da0073e9SAndroid Build Coastguard Worker         return;
709*da0073e9SAndroid Build Coastguard Worker 
710*da0073e9SAndroid Build Coastguard Worker       if (Iter1->index() > Iter2->index()) {
711*da0073e9SAndroid Build Coastguard Worker         ++Iter2;
712*da0073e9SAndroid Build Coastguard Worker       } else if (Iter1->index() == Iter2->index()) {
713*da0073e9SAndroid Build Coastguard Worker         bool BecameZero = false;
714*da0073e9SAndroid Build Coastguard Worker         Elements.emplace_back(Iter1->index());
715*da0073e9SAndroid Build Coastguard Worker         Elements.back().intersectWithComplement(*Iter1, *Iter2, BecameZero);
716*da0073e9SAndroid Build Coastguard Worker         if (BecameZero)
717*da0073e9SAndroid Build Coastguard Worker           Elements.pop_back();
718*da0073e9SAndroid Build Coastguard Worker         ++Iter1;
719*da0073e9SAndroid Build Coastguard Worker         ++Iter2;
720*da0073e9SAndroid Build Coastguard Worker       } else {
721*da0073e9SAndroid Build Coastguard Worker         Elements.push_back(*Iter1++);
722*da0073e9SAndroid Build Coastguard Worker       }
723*da0073e9SAndroid Build Coastguard Worker     }
724*da0073e9SAndroid Build Coastguard Worker 
725*da0073e9SAndroid Build Coastguard Worker     // copy the remaining elements
726*da0073e9SAndroid Build Coastguard Worker     std::copy(Iter1, RHS1.Elements.end(), std::back_inserter(Elements));
727*da0073e9SAndroid Build Coastguard Worker   }
728*da0073e9SAndroid Build Coastguard Worker 
intersectWithComplement(const SparseBitVector<ElementSize> * RHS1,const SparseBitVector<ElementSize> * RHS2)729*da0073e9SAndroid Build Coastguard Worker   void intersectWithComplement(
730*da0073e9SAndroid Build Coastguard Worker       const SparseBitVector<ElementSize>* RHS1,
731*da0073e9SAndroid Build Coastguard Worker       const SparseBitVector<ElementSize>* RHS2) {
732*da0073e9SAndroid Build Coastguard Worker     intersectWithComplement(*RHS1, *RHS2);
733*da0073e9SAndroid Build Coastguard Worker   }
734*da0073e9SAndroid Build Coastguard Worker 
intersects(const SparseBitVector<ElementSize> * RHS)735*da0073e9SAndroid Build Coastguard Worker   bool intersects(const SparseBitVector<ElementSize>* RHS) const {
736*da0073e9SAndroid Build Coastguard Worker     return intersects(*RHS);
737*da0073e9SAndroid Build Coastguard Worker   }
738*da0073e9SAndroid Build Coastguard Worker 
739*da0073e9SAndroid Build Coastguard Worker   // Return true if we share any bits in common with RHS
intersects(const SparseBitVector<ElementSize> & RHS)740*da0073e9SAndroid Build Coastguard Worker   bool intersects(const SparseBitVector<ElementSize>& RHS) const {
741*da0073e9SAndroid Build Coastguard Worker     ElementListConstIter Iter1 = Elements.begin();
742*da0073e9SAndroid Build Coastguard Worker     ElementListConstIter Iter2 = RHS.Elements.begin();
743*da0073e9SAndroid Build Coastguard Worker 
744*da0073e9SAndroid Build Coastguard Worker     // Check if both bitmaps are empty.
745*da0073e9SAndroid Build Coastguard Worker     if (Elements.empty() && RHS.Elements.empty())
746*da0073e9SAndroid Build Coastguard Worker       return false;
747*da0073e9SAndroid Build Coastguard Worker 
748*da0073e9SAndroid Build Coastguard Worker     // Loop through, intersecting stopping when we hit bits in common.
749*da0073e9SAndroid Build Coastguard Worker     while (Iter2 != RHS.Elements.end()) {
750*da0073e9SAndroid Build Coastguard Worker       if (Iter1 == Elements.end())
751*da0073e9SAndroid Build Coastguard Worker         return false;
752*da0073e9SAndroid Build Coastguard Worker 
753*da0073e9SAndroid Build Coastguard Worker       if (Iter1->index() > Iter2->index()) {
754*da0073e9SAndroid Build Coastguard Worker         ++Iter2;
755*da0073e9SAndroid Build Coastguard Worker       } else if (Iter1->index() == Iter2->index()) {
756*da0073e9SAndroid Build Coastguard Worker         if (Iter1->intersects(*Iter2))
757*da0073e9SAndroid Build Coastguard Worker           return true;
758*da0073e9SAndroid Build Coastguard Worker         ++Iter1;
759*da0073e9SAndroid Build Coastguard Worker         ++Iter2;
760*da0073e9SAndroid Build Coastguard Worker       } else {
761*da0073e9SAndroid Build Coastguard Worker         ++Iter1;
762*da0073e9SAndroid Build Coastguard Worker       }
763*da0073e9SAndroid Build Coastguard Worker     }
764*da0073e9SAndroid Build Coastguard Worker     return false;
765*da0073e9SAndroid Build Coastguard Worker   }
766*da0073e9SAndroid Build Coastguard Worker 
767*da0073e9SAndroid Build Coastguard Worker   // Return true iff all bits set in this SparseBitVector are
768*da0073e9SAndroid Build Coastguard Worker   // also set in RHS.
contains(const SparseBitVector<ElementSize> & RHS)769*da0073e9SAndroid Build Coastguard Worker   bool contains(const SparseBitVector<ElementSize>& RHS) const {
770*da0073e9SAndroid Build Coastguard Worker     SparseBitVector<ElementSize> Result(*this);
771*da0073e9SAndroid Build Coastguard Worker     Result &= RHS;
772*da0073e9SAndroid Build Coastguard Worker     return (Result == RHS);
773*da0073e9SAndroid Build Coastguard Worker   }
774*da0073e9SAndroid Build Coastguard Worker 
775*da0073e9SAndroid Build Coastguard Worker   // Return the first set bit in the bitmap.  Return -1 if no bits are set.
find_first()776*da0073e9SAndroid Build Coastguard Worker   int find_first() const {
777*da0073e9SAndroid Build Coastguard Worker     if (Elements.empty())
778*da0073e9SAndroid Build Coastguard Worker       return -1;
779*da0073e9SAndroid Build Coastguard Worker     const SparseBitVectorElement<ElementSize>& First = *(Elements.begin());
780*da0073e9SAndroid Build Coastguard Worker     return (First.index() * ElementSize) + First.find_first();
781*da0073e9SAndroid Build Coastguard Worker   }
782*da0073e9SAndroid Build Coastguard Worker 
783*da0073e9SAndroid Build Coastguard Worker   // Return the last set bit in the bitmap.  Return -1 if no bits are set.
find_last()784*da0073e9SAndroid Build Coastguard Worker   int find_last() const {
785*da0073e9SAndroid Build Coastguard Worker     if (Elements.empty())
786*da0073e9SAndroid Build Coastguard Worker       return -1;
787*da0073e9SAndroid Build Coastguard Worker     const SparseBitVectorElement<ElementSize>& Last = *(Elements.rbegin());
788*da0073e9SAndroid Build Coastguard Worker     return (Last.index() * ElementSize) + Last.find_last();
789*da0073e9SAndroid Build Coastguard Worker   }
790*da0073e9SAndroid Build Coastguard Worker 
791*da0073e9SAndroid Build Coastguard Worker   // Return true if the SparseBitVector is empty
empty()792*da0073e9SAndroid Build Coastguard Worker   bool empty() const {
793*da0073e9SAndroid Build Coastguard Worker     return Elements.empty();
794*da0073e9SAndroid Build Coastguard Worker   }
795*da0073e9SAndroid Build Coastguard Worker 
count()796*da0073e9SAndroid Build Coastguard Worker   unsigned count() const {
797*da0073e9SAndroid Build Coastguard Worker     unsigned BitCount = 0;
798*da0073e9SAndroid Build Coastguard Worker     for (ElementListConstIter Iter = Elements.begin(); Iter != Elements.end();
799*da0073e9SAndroid Build Coastguard Worker          ++Iter)
800*da0073e9SAndroid Build Coastguard Worker       BitCount += Iter->count();
801*da0073e9SAndroid Build Coastguard Worker 
802*da0073e9SAndroid Build Coastguard Worker     return BitCount;
803*da0073e9SAndroid Build Coastguard Worker   }
804*da0073e9SAndroid Build Coastguard Worker 
begin()805*da0073e9SAndroid Build Coastguard Worker   iterator begin() const {
806*da0073e9SAndroid Build Coastguard Worker     return iterator(this);
807*da0073e9SAndroid Build Coastguard Worker   }
808*da0073e9SAndroid Build Coastguard Worker 
end()809*da0073e9SAndroid Build Coastguard Worker   iterator end() const {
810*da0073e9SAndroid Build Coastguard Worker     return iterator(this, true);
811*da0073e9SAndroid Build Coastguard Worker   }
812*da0073e9SAndroid Build Coastguard Worker };
813*da0073e9SAndroid Build Coastguard Worker 
814*da0073e9SAndroid Build Coastguard Worker // Convenience functions to allow Or and And without dereferencing in the user
815*da0073e9SAndroid Build Coastguard Worker // code.
816*da0073e9SAndroid Build Coastguard Worker 
817*da0073e9SAndroid Build Coastguard Worker template <unsigned ElementSize>
818*da0073e9SAndroid Build Coastguard Worker inline bool operator|=(
819*da0073e9SAndroid Build Coastguard Worker     SparseBitVector<ElementSize>& LHS,
820*da0073e9SAndroid Build Coastguard Worker     const SparseBitVector<ElementSize>* RHS) {
821*da0073e9SAndroid Build Coastguard Worker   return LHS |= *RHS;
822*da0073e9SAndroid Build Coastguard Worker }
823*da0073e9SAndroid Build Coastguard Worker 
824*da0073e9SAndroid Build Coastguard Worker template <unsigned ElementSize>
825*da0073e9SAndroid Build Coastguard Worker inline bool operator|=(
826*da0073e9SAndroid Build Coastguard Worker     SparseBitVector<ElementSize>* LHS,
827*da0073e9SAndroid Build Coastguard Worker     const SparseBitVector<ElementSize>& RHS) {
828*da0073e9SAndroid Build Coastguard Worker   return LHS->operator|=(RHS);
829*da0073e9SAndroid Build Coastguard Worker }
830*da0073e9SAndroid Build Coastguard Worker 
831*da0073e9SAndroid Build Coastguard Worker template <unsigned ElementSize>
832*da0073e9SAndroid Build Coastguard Worker inline bool operator&=(
833*da0073e9SAndroid Build Coastguard Worker     SparseBitVector<ElementSize>* LHS,
834*da0073e9SAndroid Build Coastguard Worker     const SparseBitVector<ElementSize>& RHS) {
835*da0073e9SAndroid Build Coastguard Worker   return LHS->operator&=(RHS);
836*da0073e9SAndroid Build Coastguard Worker }
837*da0073e9SAndroid Build Coastguard Worker 
838*da0073e9SAndroid Build Coastguard Worker template <unsigned ElementSize>
839*da0073e9SAndroid Build Coastguard Worker inline bool operator&=(
840*da0073e9SAndroid Build Coastguard Worker     SparseBitVector<ElementSize>& LHS,
841*da0073e9SAndroid Build Coastguard Worker     const SparseBitVector<ElementSize>* RHS) {
842*da0073e9SAndroid Build Coastguard Worker   return LHS &= *RHS;
843*da0073e9SAndroid Build Coastguard Worker }
844*da0073e9SAndroid Build Coastguard Worker 
845*da0073e9SAndroid Build Coastguard Worker // Convenience functions for infix union, intersection, difference operators.
846*da0073e9SAndroid Build Coastguard Worker 
847*da0073e9SAndroid Build Coastguard Worker template <unsigned ElementSize>
848*da0073e9SAndroid Build Coastguard Worker inline SparseBitVector<ElementSize> operator|(
849*da0073e9SAndroid Build Coastguard Worker     const SparseBitVector<ElementSize>& LHS,
850*da0073e9SAndroid Build Coastguard Worker     const SparseBitVector<ElementSize>& RHS) {
851*da0073e9SAndroid Build Coastguard Worker   SparseBitVector<ElementSize> Result(LHS);
852*da0073e9SAndroid Build Coastguard Worker   Result |= RHS;
853*da0073e9SAndroid Build Coastguard Worker   return Result;
854*da0073e9SAndroid Build Coastguard Worker }
855*da0073e9SAndroid Build Coastguard Worker 
856*da0073e9SAndroid Build Coastguard Worker template <unsigned ElementSize>
857*da0073e9SAndroid Build Coastguard Worker inline SparseBitVector<ElementSize> operator&(
858*da0073e9SAndroid Build Coastguard Worker     const SparseBitVector<ElementSize>& LHS,
859*da0073e9SAndroid Build Coastguard Worker     const SparseBitVector<ElementSize>& RHS) {
860*da0073e9SAndroid Build Coastguard Worker   SparseBitVector<ElementSize> Result(LHS);
861*da0073e9SAndroid Build Coastguard Worker   Result &= RHS;
862*da0073e9SAndroid Build Coastguard Worker   return Result;
863*da0073e9SAndroid Build Coastguard Worker }
864*da0073e9SAndroid Build Coastguard Worker 
865*da0073e9SAndroid Build Coastguard Worker template <unsigned ElementSize>
866*da0073e9SAndroid Build Coastguard Worker inline SparseBitVector<ElementSize> operator-(
867*da0073e9SAndroid Build Coastguard Worker     const SparseBitVector<ElementSize>& LHS,
868*da0073e9SAndroid Build Coastguard Worker     const SparseBitVector<ElementSize>& RHS) {
869*da0073e9SAndroid Build Coastguard Worker   SparseBitVector<ElementSize> Result;
870*da0073e9SAndroid Build Coastguard Worker   Result.intersectWithComplement(LHS, RHS);
871*da0073e9SAndroid Build Coastguard Worker   return Result;
872*da0073e9SAndroid Build Coastguard Worker }
873*da0073e9SAndroid Build Coastguard Worker 
874*da0073e9SAndroid Build Coastguard Worker template <unsigned ElementSize>
875*da0073e9SAndroid Build Coastguard Worker std::ostream& operator<<(
876*da0073e9SAndroid Build Coastguard Worker     std::ostream& stream,
877*da0073e9SAndroid Build Coastguard Worker     const SparseBitVector<ElementSize>& vec) {
878*da0073e9SAndroid Build Coastguard Worker   bool first = true;
879*da0073e9SAndroid Build Coastguard Worker   stream << "{";
880*da0073e9SAndroid Build Coastguard Worker   for (auto el : vec) {
881*da0073e9SAndroid Build Coastguard Worker     if (first) {
882*da0073e9SAndroid Build Coastguard Worker       first = false;
883*da0073e9SAndroid Build Coastguard Worker     } else {
884*da0073e9SAndroid Build Coastguard Worker       stream << ", ";
885*da0073e9SAndroid Build Coastguard Worker     }
886*da0073e9SAndroid Build Coastguard Worker     stream << el;
887*da0073e9SAndroid Build Coastguard Worker   }
888*da0073e9SAndroid Build Coastguard Worker   stream << "}";
889*da0073e9SAndroid Build Coastguard Worker   return stream;
890*da0073e9SAndroid Build Coastguard Worker }
891*da0073e9SAndroid Build Coastguard Worker 
892*da0073e9SAndroid Build Coastguard Worker } // end namespace c10
893