LLVM API Documentation
00001 //===- llvm/ADT/SparseBitVector.h - Efficient Sparse BitVector -*- C++ -*- ===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the SparseBitVector class. See the doxygen comment for 00011 // SparseBitVector for more details on the algorithm used. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_ADT_SPARSEBITVECTOR_H 00016 #define LLVM_ADT_SPARSEBITVECTOR_H 00017 00018 #include <cassert> 00019 #include <cstring> 00020 #include "llvm/Support/DataTypes.h" 00021 #include "llvm/ADT/STLExtras.h" 00022 #include "llvm/Support/MathExtras.h" 00023 #include "llvm/ADT/ilist.h" 00024 00025 namespace llvm { 00026 00027 /// SparseBitVector is an implementation of a bitvector that is sparse by only 00028 /// storing the elements that have non-zero bits set. In order to make this 00029 /// fast for the most common cases, SparseBitVector is implemented as a linked 00030 /// list of SparseBitVectorElements. We maintain a pointer to the last 00031 /// SparseBitVectorElement accessed (in the form of a list iterator), in order 00032 /// to make multiple in-order test/set constant time after the first one is 00033 /// executed. Note that using vectors to store SparseBitVectorElement's does 00034 /// not work out very well because it causes insertion in the middle to take 00035 /// enormous amounts of time with a large amount of bits. Other structures that 00036 /// have better worst cases for insertion in the middle (various balanced trees, 00037 /// etc) do not perform as well in practice as a linked list with this iterator 00038 /// kept up to date. They are also significantly more memory intensive. 00039 00040 00041 template <unsigned ElementSize = 128> 00042 struct SparseBitVectorElement 00043 : ilist_node<SparseBitVectorElement<ElementSize> > { 00044 public: 00045 typedef unsigned long BitWord; 00046 enum { 00047 BITWORD_SIZE = sizeof(BitWord) * 8, 00048 BITWORDS_PER_ELEMENT = (ElementSize + BITWORD_SIZE - 1) / BITWORD_SIZE, 00049 BITS_PER_ELEMENT = ElementSize 00050 }; 00051 00052 private: 00053 // Index of Element in terms of where first bit starts. 00054 unsigned ElementIndex; 00055 BitWord Bits[BITWORDS_PER_ELEMENT]; 00056 // Needed for sentinels 00057 friend class ilist_sentinel_traits<SparseBitVectorElement>; 00058 SparseBitVectorElement() { 00059 ElementIndex = ~0U; 00060 memset(&Bits[0], 0, sizeof (BitWord) * BITWORDS_PER_ELEMENT); 00061 } 00062 00063 public: 00064 explicit SparseBitVectorElement(unsigned Idx) { 00065 ElementIndex = Idx; 00066 memset(&Bits[0], 0, sizeof (BitWord) * BITWORDS_PER_ELEMENT); 00067 } 00068 00069 // Comparison. 00070 bool operator==(const SparseBitVectorElement &RHS) const { 00071 if (ElementIndex != RHS.ElementIndex) 00072 return false; 00073 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) 00074 if (Bits[i] != RHS.Bits[i]) 00075 return false; 00076 return true; 00077 } 00078 00079 bool operator!=(const SparseBitVectorElement &RHS) const { 00080 return !(*this == RHS); 00081 } 00082 00083 // Return the bits that make up word Idx in our element. 00084 BitWord word(unsigned Idx) const { 00085 assert (Idx < BITWORDS_PER_ELEMENT); 00086 return Bits[Idx]; 00087 } 00088 00089 unsigned index() const { 00090 return ElementIndex; 00091 } 00092 00093 bool empty() const { 00094 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) 00095 if (Bits[i]) 00096 return false; 00097 return true; 00098 } 00099 00100 void set(unsigned Idx) { 00101 Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE); 00102 } 00103 00104 bool test_and_set (unsigned Idx) { 00105 bool old = test(Idx); 00106 if (!old) { 00107 set(Idx); 00108 return true; 00109 } 00110 return false; 00111 } 00112 00113 void reset(unsigned Idx) { 00114 Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE)); 00115 } 00116 00117 bool test(unsigned Idx) const { 00118 return Bits[Idx / BITWORD_SIZE] & (1L << (Idx % BITWORD_SIZE)); 00119 } 00120 00121 unsigned count() const { 00122 unsigned NumBits = 0; 00123 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) 00124 if (sizeof(BitWord) == 4) 00125 NumBits += CountPopulation_32(Bits[i]); 00126 else if (sizeof(BitWord) == 8) 00127 NumBits += CountPopulation_64(Bits[i]); 00128 else 00129 assert(0 && "Unsupported!"); 00130 return NumBits; 00131 } 00132 00133 /// find_first - Returns the index of the first set bit. 00134 int find_first() const { 00135 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) 00136 if (Bits[i] != 0) { 00137 if (sizeof(BitWord) == 4) 00138 return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]); 00139 else if (sizeof(BitWord) == 8) 00140 return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); 00141 else 00142 assert(0 && "Unsupported!"); 00143 } 00144 assert(0 && "Illegal empty element"); 00145 return 0; // Not reached 00146 } 00147 00148 /// find_next - Returns the index of the next set bit starting from the 00149 /// "Curr" bit. Returns -1 if the next set bit is not found. 00150 int find_next(unsigned Curr) const { 00151 if (Curr >= BITS_PER_ELEMENT) 00152 return -1; 00153 00154 unsigned WordPos = Curr / BITWORD_SIZE; 00155 unsigned BitPos = Curr % BITWORD_SIZE; 00156 BitWord Copy = Bits[WordPos]; 00157 assert (WordPos <= BITWORDS_PER_ELEMENT 00158 && "Word Position outside of element"); 00159 00160 // Mask off previous bits. 00161 Copy &= ~0L << BitPos; 00162 00163 if (Copy != 0) { 00164 if (sizeof(BitWord) == 4) 00165 return WordPos * BITWORD_SIZE + CountTrailingZeros_32(Copy); 00166 else if (sizeof(BitWord) == 8) 00167 return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy); 00168 else 00169 assert(0 && "Unsupported!"); 00170 } 00171 00172 // Check subsequent words. 00173 for (unsigned i = WordPos+1; i < BITWORDS_PER_ELEMENT; ++i) 00174 if (Bits[i] != 0) { 00175 if (sizeof(BitWord) == 4) 00176 return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]); 00177 else if (sizeof(BitWord) == 8) 00178 return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); 00179 else 00180 assert(0 && "Unsupported!"); 00181 } 00182 return -1; 00183 } 00184 00185 // Union this element with RHS and return true if this one changed. 00186 bool unionWith(const SparseBitVectorElement &RHS) { 00187 bool changed = false; 00188 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { 00189 BitWord old = changed ? 0 : Bits[i]; 00190 00191 Bits[i] |= RHS.Bits[i]; 00192 if (!changed && old != Bits[i]) 00193 changed = true; 00194 } 00195 return changed; 00196 } 00197 00198 // Return true if we have any bits in common with RHS 00199 bool intersects(const SparseBitVectorElement &RHS) const { 00200 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { 00201 if (RHS.Bits[i] & Bits[i]) 00202 return true; 00203 } 00204 return false; 00205 } 00206 00207 // Intersect this Element with RHS and return true if this one changed. 00208 // BecameZero is set to true if this element became all-zero bits. 00209 bool intersectWith(const SparseBitVectorElement &RHS, 00210 bool &BecameZero) { 00211 bool changed = false; 00212 bool allzero = true; 00213 00214 BecameZero = false; 00215 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { 00216 BitWord old = changed ? 0 : Bits[i]; 00217 00218 Bits[i] &= RHS.Bits[i]; 00219 if (Bits[i] != 0) 00220 allzero = false; 00221 00222 if (!changed && old != Bits[i]) 00223 changed = true; 00224 } 00225 BecameZero = allzero; 00226 return changed; 00227 } 00228 // Intersect this Element with the complement of RHS and return true if this 00229 // one changed. BecameZero is set to true if this element became all-zero 00230 // bits. 00231 bool intersectWithComplement(const SparseBitVectorElement &RHS, 00232 bool &BecameZero) { 00233 bool changed = false; 00234 bool allzero = true; 00235 00236 BecameZero = false; 00237 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { 00238 BitWord old = changed ? 0 : Bits[i]; 00239 00240 Bits[i] &= ~RHS.Bits[i]; 00241 if (Bits[i] != 0) 00242 allzero = false; 00243 00244 if (!changed && old != Bits[i]) 00245 changed = true; 00246 } 00247 BecameZero = allzero; 00248 return changed; 00249 } 00250 // Three argument version of intersectWithComplement that intersects 00251 // RHS1 & ~RHS2 into this element 00252 void intersectWithComplement(const SparseBitVectorElement &RHS1, 00253 const SparseBitVectorElement &RHS2, 00254 bool &BecameZero) { 00255 bool allzero = true; 00256 00257 BecameZero = false; 00258 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { 00259 Bits[i] = RHS1.Bits[i] & ~RHS2.Bits[i]; 00260 if (Bits[i] != 0) 00261 allzero = false; 00262 } 00263 BecameZero = allzero; 00264 } 00265 00266 // Get a hash value for this element; 00267 uint64_t getHashValue() const { 00268 uint64_t HashVal = 0; 00269 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { 00270 HashVal ^= Bits[i]; 00271 } 00272 return HashVal; 00273 } 00274 }; 00275 00276 template <unsigned ElementSize = 128> 00277 class SparseBitVector { 00278 typedef ilist<SparseBitVectorElement<ElementSize> > ElementList; 00279 typedef typename ElementList::iterator ElementListIter; 00280 typedef typename ElementList::const_iterator ElementListConstIter; 00281 enum { 00282 BITWORD_SIZE = SparseBitVectorElement<ElementSize>::BITWORD_SIZE 00283 }; 00284 00285 // Pointer to our current Element. 00286 ElementListIter CurrElementIter; 00287 ElementList Elements; 00288 00289 // This is like std::lower_bound, except we do linear searching from the 00290 // current position. 00291 ElementListIter FindLowerBound(unsigned ElementIndex) { 00292 00293 if (Elements.empty()) { 00294 CurrElementIter = Elements.begin(); 00295 return Elements.begin(); 00296 } 00297 00298 // Make sure our current iterator is valid. 00299 if (CurrElementIter == Elements.end()) 00300 --CurrElementIter; 00301 00302 // Search from our current iterator, either backwards or forwards, 00303 // depending on what element we are looking for. 00304 ElementListIter ElementIter = CurrElementIter; 00305 if (CurrElementIter->index() == ElementIndex) { 00306 return ElementIter; 00307 } else if (CurrElementIter->index() > ElementIndex) { 00308 while (ElementIter != Elements.begin() 00309 && ElementIter->index() > ElementIndex) 00310 --ElementIter; 00311 } else { 00312 while (ElementIter != Elements.end() && 00313 ElementIter->index() < ElementIndex) 00314 ++ElementIter; 00315 } 00316 CurrElementIter = ElementIter; 00317 return ElementIter; 00318 } 00319 00320 // Iterator to walk set bits in the bitmap. This iterator is a lot uglier 00321 // than it would be, in order to be efficient. 00322 class SparseBitVectorIterator { 00323 private: 00324 bool AtEnd; 00325 00326 const SparseBitVector<ElementSize> *BitVector; 00327 00328 // Current element inside of bitmap. 00329 ElementListConstIter Iter; 00330 00331 // Current bit number inside of our bitmap. 00332 unsigned BitNumber; 00333 00334 // Current word number inside of our element. 00335 unsigned WordNumber; 00336 00337 // Current bits from the element. 00338 typename SparseBitVectorElement<ElementSize>::BitWord Bits; 00339 00340 // Move our iterator to the first non-zero bit in the bitmap. 00341 void AdvanceToFirstNonZero() { 00342 if (AtEnd) 00343 return; 00344 if (BitVector->Elements.empty()) { 00345 AtEnd = true; 00346 return; 00347 } 00348 Iter = BitVector->Elements.begin(); 00349 BitNumber = Iter->index() * ElementSize; 00350 unsigned BitPos = Iter->find_first(); 00351 BitNumber += BitPos; 00352 WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE; 00353 Bits = Iter->word(WordNumber); 00354 Bits >>= BitPos % BITWORD_SIZE; 00355 } 00356 00357 // Move our iterator to the next non-zero bit. 00358 void AdvanceToNextNonZero() { 00359 if (AtEnd) 00360 return; 00361 00362 while (Bits && !(Bits & 1)) { 00363 Bits >>= 1; 00364 BitNumber += 1; 00365 } 00366 00367 // See if we ran out of Bits in this word. 00368 if (!Bits) { 00369 int NextSetBitNumber = Iter->find_next(BitNumber % ElementSize) ; 00370 // If we ran out of set bits in this element, move to next element. 00371 if (NextSetBitNumber == -1 || (BitNumber % ElementSize == 0)) { 00372 ++Iter; 00373 WordNumber = 0; 00374 00375 // We may run out of elements in the bitmap. 00376 if (Iter == BitVector->Elements.end()) { 00377 AtEnd = true; 00378 return; 00379 } 00380 // Set up for next non zero word in bitmap. 00381 BitNumber = Iter->index() * ElementSize; 00382 NextSetBitNumber = Iter->find_first(); 00383 BitNumber += NextSetBitNumber; 00384 WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE; 00385 Bits = Iter->word(WordNumber); 00386 Bits >>= NextSetBitNumber % BITWORD_SIZE; 00387 } else { 00388 WordNumber = (NextSetBitNumber % ElementSize) / BITWORD_SIZE; 00389 Bits = Iter->word(WordNumber); 00390 Bits >>= NextSetBitNumber % BITWORD_SIZE; 00391 BitNumber = Iter->index() * ElementSize; 00392 BitNumber += NextSetBitNumber; 00393 } 00394 } 00395 } 00396 public: 00397 // Preincrement. 00398 inline SparseBitVectorIterator& operator++() { 00399 ++BitNumber; 00400 Bits >>= 1; 00401 AdvanceToNextNonZero(); 00402 return *this; 00403 } 00404 00405 // Postincrement. 00406 inline SparseBitVectorIterator operator++(int) { 00407 SparseBitVectorIterator tmp = *this; 00408 ++*this; 00409 return tmp; 00410 } 00411 00412 // Return the current set bit number. 00413 unsigned operator*() const { 00414 return BitNumber; 00415 } 00416 00417 bool operator==(const SparseBitVectorIterator &RHS) const { 00418 // If they are both at the end, ignore the rest of the fields. 00419 if (AtEnd && RHS.AtEnd) 00420 return true; 00421 // Otherwise they are the same if they have the same bit number and 00422 // bitmap. 00423 return AtEnd == RHS.AtEnd && RHS.BitNumber == BitNumber; 00424 } 00425 bool operator!=(const SparseBitVectorIterator &RHS) const { 00426 return !(*this == RHS); 00427 } 00428 SparseBitVectorIterator(): BitVector(NULL) { 00429 } 00430 00431 00432 SparseBitVectorIterator(const SparseBitVector<ElementSize> *RHS, 00433 bool end = false):BitVector(RHS) { 00434 Iter = BitVector->Elements.begin(); 00435 BitNumber = 0; 00436 Bits = 0; 00437 WordNumber = ~0; 00438 AtEnd = end; 00439 AdvanceToFirstNonZero(); 00440 } 00441 }; 00442 public: 00443 typedef SparseBitVectorIterator iterator; 00444 00445 SparseBitVector () { 00446 CurrElementIter = Elements.begin (); 00447 } 00448 00449 ~SparseBitVector() { 00450 } 00451 00452 // SparseBitVector copy ctor. 00453 SparseBitVector(const SparseBitVector &RHS) { 00454 ElementListConstIter ElementIter = RHS.Elements.begin(); 00455 while (ElementIter != RHS.Elements.end()) { 00456 Elements.push_back(SparseBitVectorElement<ElementSize>(*ElementIter)); 00457 ++ElementIter; 00458 } 00459 00460 CurrElementIter = Elements.begin (); 00461 } 00462 00463 // Assignment 00464 SparseBitVector& operator=(const SparseBitVector& RHS) { 00465 Elements.clear(); 00466 00467 ElementListConstIter ElementIter = RHS.Elements.begin(); 00468 while (ElementIter != RHS.Elements.end()) { 00469 Elements.push_back(SparseBitVectorElement<ElementSize>(*ElementIter)); 00470 ++ElementIter; 00471 } 00472 00473 CurrElementIter = Elements.begin (); 00474 00475 return *this; 00476 } 00477 00478 // Test, Reset, and Set a bit in the bitmap. 00479 bool test(unsigned Idx) { 00480 if (Elements.empty()) 00481 return false; 00482 00483 unsigned ElementIndex = Idx / ElementSize; 00484 ElementListIter ElementIter = FindLowerBound(ElementIndex); 00485 00486 // If we can't find an element that is supposed to contain this bit, there 00487 // is nothing more to do. 00488 if (ElementIter == Elements.end() || 00489 ElementIter->index() != ElementIndex) 00490 return false; 00491 return ElementIter->test(Idx % ElementSize); 00492 } 00493 00494 void reset(unsigned Idx) { 00495 if (Elements.empty()) 00496 return; 00497 00498 unsigned ElementIndex = Idx / ElementSize; 00499 ElementListIter ElementIter = FindLowerBound(ElementIndex); 00500 00501 // If we can't find an element that is supposed to contain this bit, there 00502 // is nothing more to do. 00503 if (ElementIter == Elements.end() || 00504 ElementIter->index() != ElementIndex) 00505 return; 00506 ElementIter->reset(Idx % ElementSize); 00507 00508 // When the element is zeroed out, delete it. 00509 if (ElementIter->empty()) { 00510 ++CurrElementIter; 00511 Elements.erase(ElementIter); 00512 } 00513 } 00514 00515 void set(unsigned Idx) { 00516 unsigned ElementIndex = Idx / ElementSize; 00517 SparseBitVectorElement<ElementSize> *Element; 00518 ElementListIter ElementIter; 00519 if (Elements.empty()) { 00520 Element = new SparseBitVectorElement<ElementSize>(ElementIndex); 00521 ElementIter = Elements.insert(Elements.end(), Element); 00522 00523 } else { 00524 ElementIter = FindLowerBound(ElementIndex); 00525 00526 if (ElementIter == Elements.end() || 00527 ElementIter->index() != ElementIndex) { 00528 Element = new SparseBitVectorElement<ElementSize>(ElementIndex); 00529 // We may have hit the beginning of our SparseBitVector, in which case, 00530 // we may need to insert right after this element, which requires moving 00531 // the current iterator forward one, because insert does insert before. 00532 if (ElementIter != Elements.end() && 00533 ElementIter->index() < ElementIndex) 00534 ElementIter = Elements.insert(++ElementIter, Element); 00535 else 00536 ElementIter = Elements.insert(ElementIter, Element); 00537 } 00538 } 00539 CurrElementIter = ElementIter; 00540 00541 ElementIter->set(Idx % ElementSize); 00542 } 00543 00544 bool test_and_set (unsigned Idx) { 00545 bool old = test(Idx); 00546 if (!old) { 00547 set(Idx); 00548 return true; 00549 } 00550 return false; 00551 } 00552 00553 bool operator!=(const SparseBitVector &RHS) const { 00554 return !(*this == RHS); 00555 } 00556 00557 bool operator==(const SparseBitVector &RHS) const { 00558 ElementListConstIter Iter1 = Elements.begin(); 00559 ElementListConstIter Iter2 = RHS.Elements.begin(); 00560 00561 for (; Iter1 != Elements.end() && Iter2 != RHS.Elements.end(); 00562 ++Iter1, ++Iter2) { 00563 if (*Iter1 != *Iter2) 00564 return false; 00565 } 00566 return Iter1 == Elements.end() && Iter2 == RHS.Elements.end(); 00567 } 00568 00569 // Union our bitmap with the RHS and return true if we changed. 00570 bool operator|=(const SparseBitVector &RHS) { 00571 bool changed = false; 00572 ElementListIter Iter1 = Elements.begin(); 00573 ElementListConstIter Iter2 = RHS.Elements.begin(); 00574 00575 // If RHS is empty, we are done 00576 if (RHS.Elements.empty()) 00577 return false; 00578 00579 while (Iter2 != RHS.Elements.end()) { 00580 if (Iter1 == Elements.end() || Iter1->index() > Iter2->index()) { 00581 Elements.insert(Iter1, 00582 new SparseBitVectorElement<ElementSize>(*Iter2)); 00583 ++Iter2; 00584 changed = true; 00585 } else if (Iter1->index() == Iter2->index()) { 00586 changed |= Iter1->unionWith(*Iter2); 00587 ++Iter1; 00588 ++Iter2; 00589 } else { 00590 ++Iter1; 00591 } 00592 } 00593 CurrElementIter = Elements.begin(); 00594 return changed; 00595 } 00596 00597 // Intersect our bitmap with the RHS and return true if ours changed. 00598 bool operator&=(const SparseBitVector &RHS) { 00599 bool changed = false; 00600 ElementListIter Iter1 = Elements.begin(); 00601 ElementListConstIter Iter2 = RHS.Elements.begin(); 00602 00603 // Check if both bitmaps are empty. 00604 if (Elements.empty() && RHS.Elements.empty()) 00605 return false; 00606 00607 // Loop through, intersecting as we go, erasing elements when necessary. 00608 while (Iter2 != RHS.Elements.end()) { 00609 if (Iter1 == Elements.end()) { 00610 CurrElementIter = Elements.begin(); 00611 return changed; 00612 } 00613 00614 if (Iter1->index() > Iter2->index()) { 00615 ++Iter2; 00616 } else if (Iter1->index() == Iter2->index()) { 00617 bool BecameZero; 00618 changed |= Iter1->intersectWith(*Iter2, BecameZero); 00619 if (BecameZero) { 00620 ElementListIter IterTmp = Iter1; 00621 ++Iter1; 00622 Elements.erase(IterTmp); 00623 } else { 00624 ++Iter1; 00625 } 00626 ++Iter2; 00627 } else { 00628 ElementListIter IterTmp = Iter1; 00629 ++Iter1; 00630 Elements.erase(IterTmp); 00631 } 00632 } 00633 Elements.erase(Iter1, Elements.end()); 00634 CurrElementIter = Elements.begin(); 00635 return changed; 00636 } 00637 00638 // Intersect our bitmap with the complement of the RHS and return true if ours 00639 // changed. 00640 bool intersectWithComplement(const SparseBitVector &RHS) { 00641 bool changed = false; 00642 ElementListIter Iter1 = Elements.begin(); 00643 ElementListConstIter Iter2 = RHS.Elements.begin(); 00644 00645 // If either our bitmap or RHS is empty, we are done 00646 if (Elements.empty() || RHS.Elements.empty()) 00647 return false; 00648 00649 // Loop through, intersecting as we go, erasing elements when necessary. 00650 while (Iter2 != RHS.Elements.end()) { 00651 if (Iter1 == Elements.end()) { 00652 CurrElementIter = Elements.begin(); 00653 return changed; 00654 } 00655 00656 if (Iter1->index() > Iter2->index()) { 00657 ++Iter2; 00658 } else if (Iter1->index() == Iter2->index()) { 00659 bool BecameZero; 00660 changed |= Iter1->intersectWithComplement(*Iter2, BecameZero); 00661 if (BecameZero) { 00662 ElementListIter IterTmp = Iter1; 00663 ++Iter1; 00664 Elements.erase(IterTmp); 00665 } else { 00666 ++Iter1; 00667 } 00668 ++Iter2; 00669 } else { 00670 ++Iter1; 00671 } 00672 } 00673 CurrElementIter = Elements.begin(); 00674 return changed; 00675 } 00676 00677 bool intersectWithComplement(const SparseBitVector<ElementSize> *RHS) const { 00678 return intersectWithComplement(*RHS); 00679 } 00680 00681 00682 // Three argument version of intersectWithComplement. Result of RHS1 & ~RHS2 00683 // is stored into this bitmap. 00684 void intersectWithComplement(const SparseBitVector<ElementSize> &RHS1, 00685 const SparseBitVector<ElementSize> &RHS2) 00686 { 00687 Elements.clear(); 00688 CurrElementIter = Elements.begin(); 00689 ElementListConstIter Iter1 = RHS1.Elements.begin(); 00690 ElementListConstIter Iter2 = RHS2.Elements.begin(); 00691 00692 // If RHS1 is empty, we are done 00693 // If RHS2 is empty, we still have to copy RHS1 00694 if (RHS1.Elements.empty()) 00695 return; 00696 00697 // Loop through, intersecting as we go, erasing elements when necessary. 00698 while (Iter2 != RHS2.Elements.end()) { 00699 if (Iter1 == RHS1.Elements.end()) 00700 return; 00701 00702 if (Iter1->index() > Iter2->index()) { 00703 ++Iter2; 00704 } else if (Iter1->index() == Iter2->index()) { 00705 bool BecameZero = false; 00706 SparseBitVectorElement<ElementSize> *NewElement = 00707 new SparseBitVectorElement<ElementSize>(Iter1->index()); 00708 NewElement->intersectWithComplement(*Iter1, *Iter2, BecameZero); 00709 if (!BecameZero) { 00710 Elements.push_back(NewElement); 00711 } 00712 else 00713 delete NewElement; 00714 ++Iter1; 00715 ++Iter2; 00716 } else { 00717 SparseBitVectorElement<ElementSize> *NewElement = 00718 new SparseBitVectorElement<ElementSize>(*Iter1); 00719 Elements.push_back(NewElement); 00720 ++Iter1; 00721 } 00722 } 00723 00724 // copy the remaining elements 00725 while (Iter1 != RHS1.Elements.end()) { 00726 SparseBitVectorElement<ElementSize> *NewElement = 00727 new SparseBitVectorElement<ElementSize>(*Iter1); 00728 Elements.push_back(NewElement); 00729 ++Iter1; 00730 } 00731 00732 return; 00733 } 00734 00735 void intersectWithComplement(const SparseBitVector<ElementSize> *RHS1, 00736 const SparseBitVector<ElementSize> *RHS2) { 00737 intersectWithComplement(*RHS1, *RHS2); 00738 } 00739 00740 bool intersects(const SparseBitVector<ElementSize> *RHS) const { 00741 return intersects(*RHS); 00742 } 00743 00744 // Return true if we share any bits in common with RHS 00745 bool intersects(const SparseBitVector<ElementSize> &RHS) const { 00746 ElementListConstIter Iter1 = Elements.begin(); 00747 ElementListConstIter Iter2 = RHS.Elements.begin(); 00748 00749 // Check if both bitmaps are empty. 00750 if (Elements.empty() && RHS.Elements.empty()) 00751 return false; 00752 00753 // Loop through, intersecting stopping when we hit bits in common. 00754 while (Iter2 != RHS.Elements.end()) { 00755 if (Iter1 == Elements.end()) 00756 return false; 00757 00758 if (Iter1->index() > Iter2->index()) { 00759 ++Iter2; 00760 } else if (Iter1->index() == Iter2->index()) { 00761 if (Iter1->intersects(*Iter2)) 00762 return true; 00763 ++Iter1; 00764 ++Iter2; 00765 } else { 00766 ++Iter1; 00767 } 00768 } 00769 return false; 00770 } 00771 00772 // Return the first set bit in the bitmap. Return -1 if no bits are set. 00773 int find_first() const { 00774 if (Elements.empty()) 00775 return -1; 00776 const SparseBitVectorElement<ElementSize> &First = *(Elements.begin()); 00777 return (First.index() * ElementSize) + First.find_first(); 00778 } 00779 00780 // Return true if the SparseBitVector is empty 00781 bool empty() const { 00782 return Elements.empty(); 00783 } 00784 00785 unsigned count() const { 00786 unsigned BitCount = 0; 00787 for (ElementListConstIter Iter = Elements.begin(); 00788 Iter != Elements.end(); 00789 ++Iter) 00790 BitCount += Iter->count(); 00791 00792 return BitCount; 00793 } 00794 iterator begin() const { 00795 return iterator(this); 00796 } 00797 00798 iterator end() const { 00799 return iterator(this, true); 00800 } 00801 00802 // Get a hash value for this bitmap. 00803 uint64_t getHashValue() const { 00804 uint64_t HashVal = 0; 00805 for (ElementListConstIter Iter = Elements.begin(); 00806 Iter != Elements.end(); 00807 ++Iter) { 00808 HashVal ^= Iter->index(); 00809 HashVal ^= Iter->getHashValue(); 00810 } 00811 return HashVal; 00812 } 00813 }; 00814 00815 // Convenience functions to allow Or and And without dereferencing in the user 00816 // code. 00817 00818 template <unsigned ElementSize> 00819 inline bool operator |=(SparseBitVector<ElementSize> &LHS, 00820 const SparseBitVector<ElementSize> *RHS) { 00821 return LHS |= *RHS; 00822 } 00823 00824 template <unsigned ElementSize> 00825 inline bool operator |=(SparseBitVector<ElementSize> *LHS, 00826 const SparseBitVector<ElementSize> &RHS) { 00827 return LHS->operator|=(RHS); 00828 } 00829 00830 template <unsigned ElementSize> 00831 inline bool operator &=(SparseBitVector<ElementSize> *LHS, 00832 const SparseBitVector<ElementSize> &RHS) { 00833 return LHS->operator&=(RHS); 00834 } 00835 00836 template <unsigned ElementSize> 00837 inline bool operator &=(SparseBitVector<ElementSize> &LHS, 00838 const SparseBitVector<ElementSize> *RHS) { 00839 return LHS &= (*RHS); 00840 } 00841 00842 00843 // Dump a SparseBitVector to a stream 00844 template <unsigned ElementSize> 00845 void dump(const SparseBitVector<ElementSize> &LHS, llvm::OStream &out) { 00846 out << "[ "; 00847 00848 typename SparseBitVector<ElementSize>::iterator bi; 00849 for (bi = LHS.begin(); bi != LHS.end(); ++bi) { 00850 out << *bi << " "; 00851 } 00852 out << " ]\n"; 00853 } 00854 } 00855 00856 00857 00858 #endif