llvm.org GIT mirror llvm / 2f5d593
Add SparseBitVector implementation git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41790 91177308-0d34-0410-b5e6-96231b3b80d8 Daniel Berlin 12 years ago
2 changed file(s) with 561 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
2828 N: Daniel Berlin
2929 E: dberlin@dberlin.org
3030 D: ET-Forest implementation.
31 D: Sparse bitmap
3132
3233 N: Neil Booth
3334 E: neil@daikokuya.co.uk
0 //===- llvm/ADT/SparseBitVector.h - Efficient Sparse BitVector -*- C++ -*- ===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file was developed by Daniel Berlin and is distributed under
5 // the University of Illinois Open Source License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the SparseBitVector class. See the doxygen comment for
10 // SparseBitVector for more details on the algorithm used.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_ADT_SPARSEBITVECTOR_H
15 #define LLVM_ADT_SPARSEBITVECTOR_H
16
17 #include
18 #include
19 #include
20 #include
21 #include "llvm/Support/DataTypes.h"
22 #include "llvm/ADT/STLExtras.h"
23 #include "llvm/Support/MathExtras.h"
24
25 namespace llvm {
26
27 /// SparseBitVector is an implementation of a bitvector that is sparse by only
28 /// storing the elements that have non-zero bits set. In order to make this
29 /// fast for the most common cases, SparseBitVector is implemented as a linked
30 /// list of SparseBitVectorElements. We maintain a pointer to the last
31 /// SparseBitVectorElement accessed (in the form of a list iterator), in order
32 /// to make multiple in-order test/set constant time after the first one is
33 /// executed. Note that using vectors to store SparseBitVectorElement's does
34 /// not work out very well because it causes insertion in the middle to take
35 /// enormous amounts of time with a large amount of bits. Other structures that
36 /// have better worst cases for insertion in the middle (various balanced trees,
37 /// etc) do not perform as well in practice as a linked list with this iterator
38 /// kept up to date. They are also significantly more memory intensive.
39
40
41 template
42 struct SparseBitVectorElement {
43 public:
44 typedef unsigned long BitWord;
45 enum {
46 BITWORD_SIZE = sizeof(BitWord) * 8,
47 BITWORDS_PER_ELEMENT = (ElementSize + BITWORD_SIZE - 1) / BITWORD_SIZE,
48 BITS_PER_ELEMENT = ElementSize
49 };
50 private:
51 // Index of Element in terms of where first bit starts.
52 unsigned ElementIndex;
53 BitWord Bits[BITWORDS_PER_ELEMENT];
54 SparseBitVectorElement();
55 public:
56 explicit SparseBitVectorElement(unsigned Idx) {
57 ElementIndex = Idx;
58 memset(&Bits[0], 0, sizeof (BitWord) * BITWORDS_PER_ELEMENT);
59 }
60
61 ~SparseBitVectorElement() {
62 }
63
64 // Copy ctor.
65 SparseBitVectorElement(const SparseBitVectorElement &RHS) {
66 ElementIndex = RHS.ElementIndex;
67 std::copy(&RHS.Bits[0], &RHS.Bits[BITWORDS_PER_ELEMENT], Bits);
68 }
69
70 // Comparison.
71 bool operator==(const SparseBitVectorElement &RHS) const {
72 if (ElementIndex != RHS.ElementIndex)
73 return false;
74 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
75 if (Bits[i] != RHS.Bits[i])
76 return false;
77 return true;
78 }
79
80 bool operator!=(const SparseBitVectorElement &RHS) const {
81 return !(*this == RHS);
82 }
83
84 // Return the bits that make up word Idx in our element.
85 BitWord word(unsigned Idx) const {
86 assert (Idx < BITWORDS_PER_ELEMENT);
87 return Bits[Idx];
88 }
89
90 unsigned index() const {
91 return ElementIndex;
92 }
93
94 bool empty() const {
95 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
96 if (Bits[i])
97 return false;
98 return true;
99 }
100
101 void set(unsigned Idx) {
102 Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE);
103 }
104
105 bool test_and_set (unsigned Idx) {
106 bool old = test(Idx);
107 if (!old)
108 set(Idx);
109 return !old;
110 }
111
112 void reset(unsigned Idx) {
113 Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE));
114 }
115
116 bool test(unsigned Idx) const {
117 return Bits[Idx / BITWORD_SIZE] & (1L << (Idx % BITWORD_SIZE));
118 }
119
120 unsigned count() const {
121 unsigned NumBits = 0;
122 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
123 if (sizeof(BitWord) == 4)
124 NumBits += CountPopulation_32(Bits[i]);
125 else if (sizeof(BitWord) == 8)
126 NumBits += CountPopulation_64(Bits[i]);
127 else
128 assert(0 && "Unsupported!");
129 return NumBits;
130 }
131
132 /// find_first - Returns the index of the first set bit.
133 int find_first() const {
134 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
135 if (Bits[i] != 0) {
136 if (sizeof(BitWord) == 4)
137 return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]);
138 else if (sizeof(BitWord) == 8)
139 return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]);
140 else
141 assert(0 && "Unsupported!");
142 }
143 assert(0 && "Illegal empty element");
144 }
145
146 /// find_next - Returns the index of the next set bit following the
147 /// "Prev" bit. Returns -1 if the next set bit is not found.
148 int find_next(unsigned Prev) const {
149 ++Prev;
150 if (Prev >= BITS_PER_ELEMENT)
151 return -1;
152
153 unsigned WordPos = Prev / BITWORD_SIZE;
154 unsigned BitPos = Prev % BITWORD_SIZE;
155 BitWord Copy = Bits[WordPos];
156 assert (WordPos <= BITWORDS_PER_ELEMENT
157 && "Word Position outside of element");
158
159 // Mask off previous bits.
160 Copy &= ~0L << BitPos;
161
162 if (Copy != 0) {
163 if (sizeof(BitWord) == 4)
164 return WordPos * BITWORD_SIZE + CountTrailingZeros_32(Copy);
165 else if (sizeof(BitWord) == 8)
166 return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy);
167 else
168 assert(0 && "Unsupported!");
169 }
170
171 // Check subsequent words.
172 for (unsigned i = WordPos+1; i < BITWORDS_PER_ELEMENT; ++i)
173 if (Bits[i] != 0) {
174 if (sizeof(BitWord) == 4)
175 return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]);
176 else if (sizeof(BitWord) == 8)
177 return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]);
178 else
179 assert(0 && "Unsupported!");
180 }
181 return -1;
182 }
183
184 // Union this element with RHS and return true if this one changed.
185 bool unionWith(const SparseBitVectorElement &RHS) {
186 bool changed = false;
187 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) {
188 BitWord old = changed ? 0 : Bits[i];
189
190 Bits[i] |= RHS.Bits[i];
191 if (old != Bits[i])
192 changed = true;
193 }
194 return changed;
195 }
196
197 // Intersect this Element with RHS and return true if this one changed.
198 // BecameZero is set to true if this element became all-zero bits.
199 bool intersectWith(const SparseBitVectorElement &RHS,
200 bool &BecameZero) {
201 bool changed = false;
202 bool allzero = true;
203
204 BecameZero = false;
205 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) {
206 BitWord old = changed ? 0 : Bits[i];
207
208 Bits[i] &= RHS.Bits[i];
209 if (Bits[i] != 0)
210 allzero = false;
211
212 if (old != Bits[i])
213 changed = true;
214 }
215 BecameZero = !allzero;
216 return changed;
217 }
218 };
219
220 template
221 class SparseBitVector {
222 typedef std::list *> ElementList;
223 typedef typename ElementList::iterator ElementListIter;
224 typedef typename ElementList::const_iterator ElementListConstIter;
225 enum {
226 BITWORD_SIZE = SparseBitVectorElement::BITWORD_SIZE
227 };
228
229 // Pointer to our current Element.
230 ElementListIter CurrElementIter;
231 ElementList Elements;
232
233 // This is like std::lower_bound, except we do linear searching from the
234 // current position.
235 ElementListIter FindLowerBound(unsigned ElementIndex) {
236
237 if (Elements.empty()) {
238 CurrElementIter = Elements.begin();
239 return Elements.begin();
240 }
241
242 // Make sure our current iterator is valid.
243 if (CurrElementIter == Elements.end())
244 --CurrElementIter;
245
246 // Search from our current iterator, either backwards or forwards,
247 // depending on what element we are looking for.
248 ElementListIter ElementIter = CurrElementIter;
249 if ((*CurrElementIter)->index() == ElementIndex) {
250 return ElementIter;
251 } else if ((*CurrElementIter)->index() > ElementIndex) {
252 while (ElementIter != Elements.begin()
253 && (*ElementIter)->index() > ElementIndex)
254 --ElementIter;
255 } else {
256 while (ElementIter != Elements.end() &&
257 (*ElementIter)->index() <= ElementIndex)
258 ++ElementIter;
259 --ElementIter;
260 }
261 CurrElementIter = ElementIter;
262 return ElementIter;
263 }
264
265 // Iterator to walk set bits in the bitmap. This iterator is a lot uglier
266 // than it would be, in order to be efficient.
267 struct SparseBitVectorIterator {
268 private:
269 bool AtEnd;
270
271 SparseBitVector &BitVector;
272
273 // Current element inside of bitmap.
274 ElementListConstIter Iter;
275
276 // Current bit number inside of our bitmap.
277 unsigned BitNumber;
278
279 // Current word number inside of our element.
280 unsigned WordNumber;
281
282 // Current bits from the element.
283 typename SparseBitVectorElement::BitWord Bits;
284
285 // Move our iterator to the first non-zero bit in the bitmap.
286 void AdvanceToFirstNonZero() {
287 if (AtEnd)
288 return;
289 if (BitVector.Elements.empty()) {
290 AtEnd = true;
291 return;
292 }
293 Iter = BitVector.Elements.begin();
294 BitNumber = (*Iter)->index() * ElementSize;
295 unsigned BitPos = (*Iter)->find_first();
296 BitNumber += BitPos;
297 WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE;
298 Bits = (*Iter)->word(WordNumber);
299 Bits >>= BitPos % BITWORD_SIZE;
300 }
301
302 // Move our iterator to the next non-zero bit.
303 void AdvanceToNextNonZero() {
304 if (AtEnd)
305 return;
306
307 while (Bits && !(Bits & 1)) {
308 Bits >>= 1;
309 BitNumber += 1;
310 }
311
312 // See if we ran out of Bits in this word.
313 if (!Bits) {
314 int NextSetBitNumber = (*Iter)->find_next(BitNumber % ElementSize) ;
315 // If we ran out of set bits in this element, move to next element.
316 if (NextSetBitNumber == -1 || (BitNumber % ElementSize == 0)) {
317 Iter++;
318 WordNumber = 0;
319
320 // We may run out of elements in the bitmap.
321 if (Iter == BitVector.Elements.end()) {
322 AtEnd = true;
323 return;
324 }
325 // Set up for next non zero word in bitmap.
326 BitNumber = (*Iter)->index() * ElementSize;
327 NextSetBitNumber = (*Iter)->find_first();
328 BitNumber += NextSetBitNumber;
329 WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE;
330 Bits = (*Iter)->word(WordNumber);
331 Bits >>= NextSetBitNumber % BITWORD_SIZE;
332 } else {
333 WordNumber = (NextSetBitNumber % ElementSize) / BITWORD_SIZE;
334 Bits = (*Iter)->word(WordNumber);
335 Bits >>= NextSetBitNumber % BITWORD_SIZE;
336 }
337 }
338 }
339 public:
340 // Preincrement.
341 inline SparseBitVectorIterator& operator++() {
342 BitNumber++;
343 Bits >>= 1;
344 AdvanceToNextNonZero();
345 return *this;
346 }
347
348 // Postincrement.
349 inline SparseBitVectorIterator operator++(int) {
350 SparseBitVectorIterator tmp = *this;
351 ++*this;
352 return tmp;
353 }
354
355 // Return the current set bit number.
356 unsigned operator*() const {
357 return BitNumber;
358 }
359
360 bool operator==(const SparseBitVectorIterator &RHS) const {
361 // If they are both at the end, ignore the rest of the fields.
362 if (AtEnd == RHS.AtEnd)
363 return true;
364 // Otherwise they are the same if they have the same bit number and
365 // bitmap.
366 return AtEnd == RHS.AtEnd && RHS.BitNumber == BitNumber;
367 }
368 bool operator!=(const SparseBitVectorIterator &RHS) const {
369 return !(*this == RHS);
370 }
371
372 explicit SparseBitVectorIterator(SparseBitVector &RHS,
373 bool end = false):BitVector(RHS) {
374 Iter = BitVector.Elements.begin();
375 BitNumber = 0;
376 Bits = 0;
377 WordNumber = ~0;
378 AtEnd = end;
379 AdvanceToFirstNonZero();
380 }
381 };
382 public:
383 typedef SparseBitVectorIterator iterator;
384 typedef const SparseBitVectorIterator const_iterator;
385
386 SparseBitVector () {
387 CurrElementIter = Elements.begin ();
388 }
389
390 ~SparseBitVector() {
391 for_each(Elements.begin(), Elements.end(),
392 deleter >);
393 }
394
395 // SparseBitVector copy ctor.
396 SparseBitVector(const SparseBitVector &RHS) {
397 ElementListConstIter ElementIter = RHS.Elements.begin();
398 while (ElementIter != RHS.Elements.end()) {
399 SparseBitVectorElement *ElementCopy;
400 ElementCopy = new SparseBitVectorElement(*(*ElementIter));
401 Elements.push_back(ElementCopy);
402 }
403
404 CurrElementIter = Elements.begin ();
405 }
406
407 // Test, Reset, and Set a bit in the bitmap.
408 bool test(unsigned Idx) {
409 if (Elements.empty())
410 return false;
411
412 unsigned ElementIndex = Idx / ElementSize;
413 ElementListIter ElementIter = FindLowerBound(ElementIndex);
414
415 // If we can't find an element that is supposed to contain this bit, there
416 // is nothing more to do.
417 if (ElementIter == Elements.end() ||
418 (*ElementIter)->index() != ElementIndex)
419 return false;
420 return (*ElementIter)->test(Idx % ElementSize);
421 }
422
423 void reset(unsigned Idx) {
424 if (Elements.empty())
425 return;
426
427 unsigned ElementIndex = Idx / ElementSize;
428 ElementListIter ElementIter = FindLowerBound(ElementIndex);
429
430 // If we can't find an element that is supposed to contain this bit, there
431 // is nothing more to do.
432 if (ElementIter == Elements.end() ||
433 (*ElementIter)->index() != ElementIndex)
434 return;
435 (*ElementIter)->reset(Idx % ElementSize);
436
437 // When the element is zeroed out, delete it.
438 if ((*ElementIter)->empty()) {
439 delete (*ElementIter);
440 ++CurrElementIter;
441 Elements.erase(ElementIter);
442 }
443 }
444
445 void set(unsigned Idx) {
446 SparseBitVectorElement *Element;
447 unsigned ElementIndex = Idx / ElementSize;
448
449 if (Elements.empty()) {
450 Element = new SparseBitVectorElement(ElementIndex);
451 Elements.push_back(Element);
452 } else {
453 ElementListIter ElementIter = FindLowerBound(ElementIndex);
454
455 if (ElementIter != Elements.end() &&
456 (*ElementIter)->index() == ElementIndex)
457 Element = *ElementIter;
458 else {
459 Element = new SparseBitVectorElement(ElementIndex);
460 // Insert does insert before, and lower bound gives the one before.
461 Elements.insert(++ElementIter, Element);
462 }
463 }
464 Element->set(Idx % ElementSize);
465 }
466
467 // Union our bitmap with the RHS and return true if we changed.
468 bool operator|=(const SparseBitVector &RHS) {
469 bool changed = false;
470 ElementListIter Iter1 = Elements.begin();
471 ElementListConstIter Iter2 = RHS.Elements.begin();
472
473 // IE They may both be end
474 if (Iter1 == Iter2)
475 return false;
476
477 // See if the first bitmap element is the same in both. This is only
478 // possible if they are the same bitmap.
479 if (Iter1 != Elements.end() && Iter2 != RHS.Elements.end())
480 if (*Iter1 == *Iter2)
481 return false;
482
483 while (Iter2 != RHS.Elements.end()) {
484 if (Iter1 == Elements.end() || (*Iter1)->index() > (*Iter2)->index()) {
485 SparseBitVectorElement *NewElem;
486
487 NewElem = new SparseBitVectorElement(*(*Iter2));
488 Elements.insert(Iter1, NewElem);
489 Iter2++;
490 changed = true;
491 } else if ((*Iter1)->index() == (*Iter2)->index()) {
492 changed |= (*Iter1)->unionWith(*(*Iter2));
493 Iter1++;
494 Iter2++;
495 } else {
496 Iter1++;
497 }
498 }
499 CurrElementIter = Elements.begin();
500 return changed;
501 }
502
503 // Intersect our bitmap with the RHS and return true if ours changed.
504 bool operator&=(const SparseBitVector &RHS) {
505 bool changed = false;
506 ElementListIter Iter1 = Elements.begin();
507 ElementListConstIter Iter2 = RHS.Elements.begin();
508
509 // IE They may both be end.
510 if (Iter1 == Iter2)
511 return false;
512
513 // See if the first bitmap element is the same in both. This is only
514 // possible if they are the same bitmap.
515 if (Iter1 != Elements.end() && Iter2 != RHS.Elements.end())
516 if (*Iter1 == *Iter2)
517 return false;
518
519 // Loop through, intersecting as we go, erasing elements when necessary.
520 while (Iter2 != RHS.Elements.end()) {
521 if (Iter1 == Elements.end())
522 return changed;
523
524 if ((*Iter1)->index() > (*Iter2)->index()) {
525 Iter2++;
526 } else if ((*Iter1)->index() == (*Iter2)->index()) {
527 bool BecameZero;
528 changed |= (*Iter1)->intersectWith(*(*Iter2), BecameZero);
529 if (BecameZero) {
530 ElementListIter IterTmp = Iter1;
531 delete *IterTmp;
532 Elements.erase(IterTmp);
533 Iter1++;
534 } else {
535 Iter1++;
536 }
537 Iter2++;
538 } else {
539 ElementListIter IterTmp = Iter1;
540 Iter1++;
541 delete *IterTmp;
542 Elements.erase(IterTmp);
543 }
544 }
545 CurrElementIter = Elements.begin();
546 return changed;
547 }
548
549 iterator begin() const {
550 return iterator(*this);
551 }
552
553 iterator end() const {
554 return iterator(*this, ~0);
555 }
556 };
557 }
558
559 #endif