blob: cdcd52d948659e3add170ed806aaaadcc17f1000 [file] [log] [blame]
Vikram S. Adve5f760542002-11-06 17:14:14 +00001//===-- BitVectorSet.h - A bit-vector representation of sets -----*- C++ -*--=//
2//
3// class BitVectorSet --
4//
5// An implementation of the bit-vector representation of sets.
6// Unlike vector<bool>, this allows much more efficient parallel set
7// operations on bits, by using the bitset template . The bitset template
8// unfortunately can only represent sets with a size chosen at compile-time.
9// We therefore use a vector of bitsets. The maxmimum size of our sets
10// (i.e., the size of the universal set) can be chosen at creation time.
11//
Vikram S. Adve5f760542002-11-06 17:14:14 +000012// External functions:
13//
14// bool Disjoint(const BitSetVector& set1, const BitSetVector& set2):
15// Tests if two sets have an empty intersection.
16// This is more efficient than !(set1 & set2).any().
17//
18//===----------------------------------------------------------------------===//
19
Brian Gaekea9f6e4a2003-06-17 00:35:55 +000020#ifndef SUPPORT_BITSETVECTOR_H
21#define SUPPORT_BITSETVECTOR_H
Vikram S. Adve5f760542002-11-06 17:14:14 +000022
23#include <bitset>
24#include <vector>
25#include <functional>
26#include <iostream>
Vikram S. Adve5f760542002-11-06 17:14:14 +000027
Vikram S. Adve5f760542002-11-06 17:14:14 +000028class BitSetVector {
Chris Lattner680a7c22003-06-22 03:09:10 +000029 enum { BITSET_WORDSIZE = sizeof(long)*8 };
30
Vikram S. Adve0e2cf762002-11-27 17:46:38 +000031 // Types used internal to the representation
Chris Lattner680a7c22003-06-22 03:09:10 +000032 typedef std::bitset<BITSET_WORDSIZE> bitword;
Vikram S. Adve5f760542002-11-06 17:14:14 +000033 typedef bitword::reference reference;
34 class iterator;
35
Vikram S. Adve0e2cf762002-11-27 17:46:38 +000036 // Data used in the representation
Vikram S. Adve5f760542002-11-06 17:14:14 +000037 std::vector<bitword> bitsetVec;
Chris Lattner45a91162002-11-06 18:34:40 +000038 unsigned maxSize;
Vikram S. Adve5f760542002-11-06 17:14:14 +000039
Vikram S. Adve0e2cf762002-11-27 17:46:38 +000040private:
41 // Utility functions for the representation
Chris Lattner680a7c22003-06-22 03:09:10 +000042 static unsigned NumWords(unsigned Size) {
43 return (Size+BITSET_WORDSIZE-1)/BITSET_WORDSIZE;
44 }
45 static unsigned LastWordSize(unsigned Size) { return Size % BITSET_WORDSIZE; }
Vikram S. Adve0e2cf762002-11-27 17:46:38 +000046
47 // Clear the unused bits in the last word.
Chris Lattner680a7c22003-06-22 03:09:10 +000048 // The unused bits are the high (BITSET_WORDSIZE - LastWordSize()) bits
Vikram S. Adve0e2cf762002-11-27 17:46:38 +000049 void ClearUnusedBits() {
50 unsigned long usedBits = (1U << LastWordSize(size())) - 1;
51 bitsetVec.back() &= bitword(usedBits);
52 }
Vikram S. Adve5f760542002-11-06 17:14:14 +000053
54 const bitword& getWord(unsigned i) const { return bitsetVec[i]; }
55 bitword& getWord(unsigned i) { return bitsetVec[i]; }
56
57 friend bool Disjoint(const BitSetVector& set1,
58 const BitSetVector& set2);
59
60 BitSetVector(); // do not implement!
61
62public:
Vikram S. Adve5f760542002-11-06 17:14:14 +000063 ///
64 /// Constructor: create a set of the maximum size maxSetSize.
65 /// The set is initialized to empty.
66 ///
67 BitSetVector(unsigned maxSetSize)
Chris Lattner45a91162002-11-06 18:34:40 +000068 : bitsetVec(NumWords(maxSetSize)), maxSize(maxSetSize) { }
69
70 /// size - Return the number of bits tracked by this bit vector...
71 unsigned size() const { return maxSize; }
Vikram S. Adve5f760542002-11-06 17:14:14 +000072
73 ///
74 /// Modifier methods: reset, set for entire set, operator[] for one element.
75 ///
76 void reset() {
Vikram S. Adve0e2cf762002-11-27 17:46:38 +000077 for (unsigned i=0, N = bitsetVec.size(); i < N; ++i)
78 bitsetVec[i].reset();
Vikram S. Adve5f760542002-11-06 17:14:14 +000079 }
80 void set() {
Vikram S. Adve0e2cf762002-11-27 17:46:38 +000081 for (unsigned i=0, N = bitsetVec.size(); i < N; ++i) // skip last word
82 bitsetVec[i].set();
83 ClearUnusedBits();
Vikram S. Adve5f760542002-11-06 17:14:14 +000084 }
Vikram S. Adve0e2cf762002-11-27 17:46:38 +000085 reference operator[](unsigned n) {
86 assert(n < size() && "BitSetVector: Bit number out of range");
Chris Lattner680a7c22003-06-22 03:09:10 +000087 unsigned ndiv = n / BITSET_WORDSIZE, nmod = n % BITSET_WORDSIZE;
Vikram S. Adve5f760542002-11-06 17:14:14 +000088 return bitsetVec[ndiv][nmod];
89 }
90 iterator begin() { return iterator::begin(*this); }
91 iterator end() { return iterator::end(*this); }
92
93 ///
Vikram S. Adve0e2cf762002-11-27 17:46:38 +000094 /// Comparison operations: equal, not equal
95 ///
96 bool operator == (const BitSetVector& set2) const {
97 assert(maxSize == set2.maxSize && "Illegal == comparison");
98 for (unsigned i = 0; i < bitsetVec.size(); ++i)
99 if (getWord(i) != set2.getWord(i))
100 return false;
101 return true;
102 }
103 bool operator != (const BitSetVector& set2) const {
104 return ! (*this == set2);
105 }
106
107 ///
Vikram S. Adve5f760542002-11-06 17:14:14 +0000108 /// Set membership operations: single element, any, none, count
109 ///
110 bool test(unsigned n) const {
Vikram S. Adve0e2cf762002-11-27 17:46:38 +0000111 assert(n < size() && "BitSetVector: Bit number out of range");
Chris Lattner680a7c22003-06-22 03:09:10 +0000112 unsigned ndiv = n / BITSET_WORDSIZE, nmod = n % BITSET_WORDSIZE;
Vikram S. Adve5f760542002-11-06 17:14:14 +0000113 return bitsetVec[ndiv].test(nmod);
114 }
115 bool any() const {
116 for (unsigned i = 0; i < bitsetVec.size(); ++i)
117 if (bitsetVec[i].any())
118 return true;
119 return false;
120 }
121 bool none() const {
122 return ! any();
123 }
124 unsigned count() const {
125 unsigned n = 0;
126 for (unsigned i = 0; i < bitsetVec.size(); ++i)
127 n += bitsetVec[i].count();
128 return n;
129 }
Vikram S. Adve0e2cf762002-11-27 17:46:38 +0000130 bool all() const {
131 return (count() == size());
132 }
Vikram S. Adve5f760542002-11-06 17:14:14 +0000133
134 ///
135 /// Set operations: intersection, union, disjoint union, complement.
136 ///
137 BitSetVector operator& (const BitSetVector& set2) const {
138 assert(maxSize == set2.maxSize && "Illegal intersection");
139 BitSetVector result(maxSize);
140 for (unsigned i = 0; i < bitsetVec.size(); ++i)
141 result.getWord(i) = getWord(i) & set2.getWord(i);
142 return result;
143 }
144 BitSetVector operator| (const BitSetVector& set2) const {
145 assert(maxSize == set2.maxSize && "Illegal intersection");
146 BitSetVector result(maxSize);
147 for (unsigned i = 0; i < bitsetVec.size(); ++i)
148 result.getWord(i) = getWord(i) | set2.getWord(i);
149 return result;
150 }
151 BitSetVector operator^ (const BitSetVector& set2) const {
152 assert(maxSize == set2.maxSize && "Illegal intersection");
153 BitSetVector result(maxSize);
154 for (unsigned i = 0; i < bitsetVec.size(); ++i)
155 result.getWord(i) = getWord(i) ^ set2.getWord(i);
156 return result;
157 }
158 BitSetVector operator~ () const {
159 BitSetVector result(maxSize);
160 for (unsigned i = 0; i < bitsetVec.size(); ++i)
161 (result.getWord(i) = getWord(i)).flip();
Vikram S. Adve0e2cf762002-11-27 17:46:38 +0000162 result.ClearUnusedBits();
Vikram S. Adve5f760542002-11-06 17:14:14 +0000163 return result;
164 }
165
166 ///
167 /// Printing and debugging support
168 ///
169 void print(std::ostream &O) const;
170 void dump() const { print(std::cerr); }
171
172public:
173 //
174 // An iterator to enumerate the bits in a BitSetVector.
175 // Eventually, this needs to inherit from bidirectional_iterator.
176 // But this iterator may not be as useful as I once thought and
177 // may just go away.
178 //
179 class iterator {
180 unsigned currentBit;
181 unsigned currentWord;
Vikram S. Adve0e2cf762002-11-27 17:46:38 +0000182 BitSetVector* bitvec;
183 iterator(unsigned B, unsigned W, BitSetVector& _bitvec)
184 : currentBit(B), currentWord(W), bitvec(&_bitvec) { }
Vikram S. Adve5f760542002-11-06 17:14:14 +0000185 public:
186 iterator(BitSetVector& _bitvec)
Vikram S. Adve0e2cf762002-11-27 17:46:38 +0000187 : currentBit(0), currentWord(0), bitvec(&_bitvec) { }
Vikram S. Adve5f760542002-11-06 17:14:14 +0000188 iterator(const iterator& I)
189 : currentBit(I.currentBit),currentWord(I.currentWord),bitvec(I.bitvec) { }
190 iterator& operator=(const iterator& I) {
Chris Lattner8fb1fe12003-03-17 18:11:27 +0000191 currentWord = I.currentWord;
192 currentBit = I.currentBit;
Vikram S. Adve5f760542002-11-06 17:14:14 +0000193 bitvec = I.bitvec;
194 return *this;
195 }
196
197 // Increment and decrement operators (pre and post)
198 iterator& operator++() {
Chris Lattner680a7c22003-06-22 03:09:10 +0000199 if (++currentBit == BITSET_WORDSIZE)
Chris Lattner8fb1fe12003-03-17 18:11:27 +0000200 { currentBit = 0; if (currentWord < bitvec->size()) ++currentWord; }
Vikram S. Adve5f760542002-11-06 17:14:14 +0000201 return *this;
202 }
203 iterator& operator--() {
204 if (currentBit == 0) {
Chris Lattner680a7c22003-06-22 03:09:10 +0000205 currentBit = BITSET_WORDSIZE-1;
Chris Lattner8fb1fe12003-03-17 18:11:27 +0000206 currentWord = (currentWord == 0)? bitvec->size() : --currentWord;
Vikram S. Adve5f760542002-11-06 17:14:14 +0000207 }
208 else
209 --currentBit;
210 return *this;
211 }
212 iterator operator++(int) { iterator copy(*this); ++*this; return copy; }
213 iterator operator--(int) { iterator copy(*this); --*this; return copy; }
214
215 // Dereferencing operators
216 reference operator*() {
Chris Lattner8fb1fe12003-03-17 18:11:27 +0000217 assert(currentWord < bitvec->size() &&
Vikram S. Adve5f760542002-11-06 17:14:14 +0000218 "Dereferencing iterator past the end of a BitSetVector");
Vikram S. Adve0e2cf762002-11-27 17:46:38 +0000219 return bitvec->getWord(currentWord)[currentBit];
Vikram S. Adve5f760542002-11-06 17:14:14 +0000220 }
221
222 // Comparison operator
223 bool operator==(const iterator& I) {
Vikram S. Adve0e2cf762002-11-27 17:46:38 +0000224 return (I.bitvec == bitvec &&
Vikram S. Adve5f760542002-11-06 17:14:14 +0000225 I.currentWord == currentWord && I.currentBit == currentBit);
226 }
227
228 protected:
229 static iterator begin(BitSetVector& _bitvec) { return iterator(_bitvec); }
230 static iterator end(BitSetVector& _bitvec) { return iterator(0,
Chris Lattner8fb1fe12003-03-17 18:11:27 +0000231 _bitvec.size(), _bitvec); }
Vikram S. Adve5f760542002-11-06 17:14:14 +0000232 friend class BitSetVector;
233 };
234};
235
236
237inline void BitSetVector::print(std::ostream& O) const
238{
239 for (std::vector<bitword>::const_iterator
240 I=bitsetVec.begin(), E=bitsetVec.end(); I != E; ++I)
241 O << "<" << (*I) << ">" << (I+1 == E? "\n" : ", ");
242}
243
244inline std::ostream& operator<< (std::ostream& O, const BitSetVector& bset)
245{
246 bset.print(O);
247 return O;
248};
249
250
251///
252/// Optimized versions of fundamental comparison operations
253///
254inline bool Disjoint(const BitSetVector& set1,
255 const BitSetVector& set2)
256{
Chris Lattner45a91162002-11-06 18:34:40 +0000257 assert(set1.size() == set2.size() && "Illegal intersection");
Vikram S. Adve5f760542002-11-06 17:14:14 +0000258 for (unsigned i = 0; i < set1.bitsetVec.size(); ++i)
259 if ((set1.getWord(i) & set2.getWord(i)).any())
260 return false;
261 return true;
262}
263
264#endif