blob: 6ce56be4d0cf80b811c11706d59fe60ffdc724c6 [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//
12// The size of each Bitset is defined by the macro WORDSIZE.
13//
14// NOTE: The WORDSIZE macro should be made machine-dependent, in order to use
15// 64-bit words or whatever gives most efficient Bitsets on each platform.
16//
17//
18// External functions:
19//
20// bool Disjoint(const BitSetVector& set1, const BitSetVector& set2):
21// Tests if two sets have an empty intersection.
22// This is more efficient than !(set1 & set2).any().
23//
24//===----------------------------------------------------------------------===//
25
26#ifndef LLVM_SUPPORT_BITVECTORSET_H
27#define LLVM_SUPPORT_BITVECTORSET_H
28
29#include <bitset>
30#include <vector>
31#include <functional>
32#include <iostream>
33
John Criswellbe583b92003-06-11 14:01:36 +000034#include <assert.h>
Vikram S. Adve5f760542002-11-06 17:14:14 +000035
36#define WORDSIZE (32U)
37
38
39class BitSetVector {
Vikram S. Adve0e2cf762002-11-27 17:46:38 +000040 // Types used internal to the representation
Vikram S. Adve5f760542002-11-06 17:14:14 +000041 typedef std::bitset<WORDSIZE> bitword;
42 typedef bitword::reference reference;
43 class iterator;
44
Vikram S. Adve0e2cf762002-11-27 17:46:38 +000045 // Data used in the representation
Vikram S. Adve5f760542002-11-06 17:14:14 +000046 std::vector<bitword> bitsetVec;
Chris Lattner45a91162002-11-06 18:34:40 +000047 unsigned maxSize;
Vikram S. Adve5f760542002-11-06 17:14:14 +000048
Vikram S. Adve0e2cf762002-11-27 17:46:38 +000049private:
50 // Utility functions for the representation
Vikram S. Adve5f760542002-11-06 17:14:14 +000051 static unsigned NumWords(unsigned Size) { return (Size+WORDSIZE-1)/WORDSIZE;}
Vikram S. Adve0e2cf762002-11-27 17:46:38 +000052 static unsigned LastWordSize(unsigned Size) { return Size % WORDSIZE; }
53
54 // Clear the unused bits in the last word.
55 // The unused bits are the high (WORDSIZE - LastWordSize()) bits
56 void ClearUnusedBits() {
57 unsigned long usedBits = (1U << LastWordSize(size())) - 1;
58 bitsetVec.back() &= bitword(usedBits);
59 }
Vikram S. Adve5f760542002-11-06 17:14:14 +000060
61 const bitword& getWord(unsigned i) const { return bitsetVec[i]; }
62 bitword& getWord(unsigned i) { return bitsetVec[i]; }
63
64 friend bool Disjoint(const BitSetVector& set1,
65 const BitSetVector& set2);
66
67 BitSetVector(); // do not implement!
68
69public:
Vikram S. Adve5f760542002-11-06 17:14:14 +000070 ///
71 /// Constructor: create a set of the maximum size maxSetSize.
72 /// The set is initialized to empty.
73 ///
74 BitSetVector(unsigned maxSetSize)
Chris Lattner45a91162002-11-06 18:34:40 +000075 : bitsetVec(NumWords(maxSetSize)), maxSize(maxSetSize) { }
76
77 /// size - Return the number of bits tracked by this bit vector...
78 unsigned size() const { return maxSize; }
Vikram S. Adve5f760542002-11-06 17:14:14 +000079
80 ///
81 /// Modifier methods: reset, set for entire set, operator[] for one element.
82 ///
83 void reset() {
Vikram S. Adve0e2cf762002-11-27 17:46:38 +000084 for (unsigned i=0, N = bitsetVec.size(); i < N; ++i)
85 bitsetVec[i].reset();
Vikram S. Adve5f760542002-11-06 17:14:14 +000086 }
87 void set() {
Vikram S. Adve0e2cf762002-11-27 17:46:38 +000088 for (unsigned i=0, N = bitsetVec.size(); i < N; ++i) // skip last word
89 bitsetVec[i].set();
90 ClearUnusedBits();
Vikram S. Adve5f760542002-11-06 17:14:14 +000091 }
Vikram S. Adve0e2cf762002-11-27 17:46:38 +000092 reference operator[](unsigned n) {
93 assert(n < size() && "BitSetVector: Bit number out of range");
Vikram S. Adve5f760542002-11-06 17:14:14 +000094 unsigned ndiv = n / WORDSIZE, nmod = n % WORDSIZE;
Vikram S. Adve5f760542002-11-06 17:14:14 +000095 return bitsetVec[ndiv][nmod];
96 }
97 iterator begin() { return iterator::begin(*this); }
98 iterator end() { return iterator::end(*this); }
99
100 ///
Vikram S. Adve0e2cf762002-11-27 17:46:38 +0000101 /// Comparison operations: equal, not equal
102 ///
103 bool operator == (const BitSetVector& set2) const {
104 assert(maxSize == set2.maxSize && "Illegal == comparison");
105 for (unsigned i = 0; i < bitsetVec.size(); ++i)
106 if (getWord(i) != set2.getWord(i))
107 return false;
108 return true;
109 }
110 bool operator != (const BitSetVector& set2) const {
111 return ! (*this == set2);
112 }
113
114 ///
Vikram S. Adve5f760542002-11-06 17:14:14 +0000115 /// Set membership operations: single element, any, none, count
116 ///
117 bool test(unsigned n) const {
Vikram S. Adve0e2cf762002-11-27 17:46:38 +0000118 assert(n < size() && "BitSetVector: Bit number out of range");
Vikram S. Adve5f760542002-11-06 17:14:14 +0000119 unsigned ndiv = n / WORDSIZE, nmod = n % WORDSIZE;
Vikram S. Adve5f760542002-11-06 17:14:14 +0000120 return bitsetVec[ndiv].test(nmod);
121 }
122 bool any() const {
123 for (unsigned i = 0; i < bitsetVec.size(); ++i)
124 if (bitsetVec[i].any())
125 return true;
126 return false;
127 }
128 bool none() const {
129 return ! any();
130 }
131 unsigned count() const {
132 unsigned n = 0;
133 for (unsigned i = 0; i < bitsetVec.size(); ++i)
134 n += bitsetVec[i].count();
135 return n;
136 }
Vikram S. Adve0e2cf762002-11-27 17:46:38 +0000137 bool all() const {
138 return (count() == size());
139 }
Vikram S. Adve5f760542002-11-06 17:14:14 +0000140
141 ///
142 /// Set operations: intersection, union, disjoint union, complement.
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 BitSetVector& set2) const {
159 assert(maxSize == set2.maxSize && "Illegal intersection");
160 BitSetVector result(maxSize);
161 for (unsigned i = 0; i < bitsetVec.size(); ++i)
162 result.getWord(i) = getWord(i) ^ set2.getWord(i);
163 return result;
164 }
165 BitSetVector operator~ () const {
166 BitSetVector result(maxSize);
167 for (unsigned i = 0; i < bitsetVec.size(); ++i)
168 (result.getWord(i) = getWord(i)).flip();
Vikram S. Adve0e2cf762002-11-27 17:46:38 +0000169 result.ClearUnusedBits();
Vikram S. Adve5f760542002-11-06 17:14:14 +0000170 return result;
171 }
172
173 ///
174 /// Printing and debugging support
175 ///
176 void print(std::ostream &O) const;
177 void dump() const { print(std::cerr); }
178
179public:
180 //
181 // An iterator to enumerate the bits in a BitSetVector.
182 // Eventually, this needs to inherit from bidirectional_iterator.
183 // But this iterator may not be as useful as I once thought and
184 // may just go away.
185 //
186 class iterator {
187 unsigned currentBit;
188 unsigned currentWord;
Vikram S. Adve0e2cf762002-11-27 17:46:38 +0000189 BitSetVector* bitvec;
190 iterator(unsigned B, unsigned W, BitSetVector& _bitvec)
191 : currentBit(B), currentWord(W), bitvec(&_bitvec) { }
Vikram S. Adve5f760542002-11-06 17:14:14 +0000192 public:
193 iterator(BitSetVector& _bitvec)
Vikram S. Adve0e2cf762002-11-27 17:46:38 +0000194 : currentBit(0), currentWord(0), bitvec(&_bitvec) { }
Vikram S. Adve5f760542002-11-06 17:14:14 +0000195 iterator(const iterator& I)
196 : currentBit(I.currentBit),currentWord(I.currentWord),bitvec(I.bitvec) { }
197 iterator& operator=(const iterator& I) {
Chris Lattner8fb1fe12003-03-17 18:11:27 +0000198 currentWord = I.currentWord;
199 currentBit = I.currentBit;
Vikram S. Adve5f760542002-11-06 17:14:14 +0000200 bitvec = I.bitvec;
201 return *this;
202 }
203
204 // Increment and decrement operators (pre and post)
205 iterator& operator++() {
206 if (++currentBit == WORDSIZE)
Chris Lattner8fb1fe12003-03-17 18:11:27 +0000207 { currentBit = 0; if (currentWord < bitvec->size()) ++currentWord; }
Vikram S. Adve5f760542002-11-06 17:14:14 +0000208 return *this;
209 }
210 iterator& operator--() {
211 if (currentBit == 0) {
212 currentBit = WORDSIZE-1;
Chris Lattner8fb1fe12003-03-17 18:11:27 +0000213 currentWord = (currentWord == 0)? bitvec->size() : --currentWord;
Vikram S. Adve5f760542002-11-06 17:14:14 +0000214 }
215 else
216 --currentBit;
217 return *this;
218 }
219 iterator operator++(int) { iterator copy(*this); ++*this; return copy; }
220 iterator operator--(int) { iterator copy(*this); --*this; return copy; }
221
222 // Dereferencing operators
223 reference operator*() {
Chris Lattner8fb1fe12003-03-17 18:11:27 +0000224 assert(currentWord < bitvec->size() &&
Vikram S. Adve5f760542002-11-06 17:14:14 +0000225 "Dereferencing iterator past the end of a BitSetVector");
Vikram S. Adve0e2cf762002-11-27 17:46:38 +0000226 return bitvec->getWord(currentWord)[currentBit];
Vikram S. Adve5f760542002-11-06 17:14:14 +0000227 }
228
229 // Comparison operator
230 bool operator==(const iterator& I) {
Vikram S. Adve0e2cf762002-11-27 17:46:38 +0000231 return (I.bitvec == bitvec &&
Vikram S. Adve5f760542002-11-06 17:14:14 +0000232 I.currentWord == currentWord && I.currentBit == currentBit);
233 }
234
235 protected:
236 static iterator begin(BitSetVector& _bitvec) { return iterator(_bitvec); }
237 static iterator end(BitSetVector& _bitvec) { return iterator(0,
Chris Lattner8fb1fe12003-03-17 18:11:27 +0000238 _bitvec.size(), _bitvec); }
Vikram S. Adve5f760542002-11-06 17:14:14 +0000239 friend class BitSetVector;
240 };
241};
242
243
244inline void BitSetVector::print(std::ostream& O) const
245{
246 for (std::vector<bitword>::const_iterator
247 I=bitsetVec.begin(), E=bitsetVec.end(); I != E; ++I)
248 O << "<" << (*I) << ">" << (I+1 == E? "\n" : ", ");
249}
250
251inline std::ostream& operator<< (std::ostream& O, const BitSetVector& bset)
252{
253 bset.print(O);
254 return O;
255};
256
257
258///
259/// Optimized versions of fundamental comparison operations
260///
261inline bool Disjoint(const BitSetVector& set1,
262 const BitSetVector& set2)
263{
Chris Lattner45a91162002-11-06 18:34:40 +0000264 assert(set1.size() == set2.size() && "Illegal intersection");
Vikram S. Adve5f760542002-11-06 17:14:14 +0000265 for (unsigned i = 0; i < set1.bitsetVec.size(); ++i)
266 if ((set1.getWord(i) & set2.getWord(i)).any())
267 return false;
268 return true;
269}
270
271#endif