blob: 0143413b3d4f222b720ef581a7ad3770e43aded0 [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
34
35#define WORDSIZE (32U)
36
37
38class BitSetVector {
39 typedef std::bitset<WORDSIZE> bitword;
40 typedef bitword::reference reference;
41 class iterator;
42
43 std::vector<bitword> bitsetVec;
44
45 static unsigned NumWords(unsigned Size) { return (Size+WORDSIZE-1)/WORDSIZE;}
46
47 const bitword& getWord(unsigned i) const { return bitsetVec[i]; }
48 bitword& getWord(unsigned i) { return bitsetVec[i]; }
49
50 friend bool Disjoint(const BitSetVector& set1,
51 const BitSetVector& set2);
52
53 BitSetVector(); // do not implement!
54
55public:
56 unsigned maxSize;
57
58 ///
59 /// Constructor: create a set of the maximum size maxSetSize.
60 /// The set is initialized to empty.
61 ///
62 BitSetVector(unsigned maxSetSize)
63 : bitsetVec(BitSetVector::NumWords(maxSetSize)), maxSize(maxSetSize) { }
64
65 ///
66 /// Modifier methods: reset, set for entire set, operator[] for one element.
67 ///
68 void reset() {
69 for(std::vector<bitword>::iterator I=bitsetVec.begin(), E=bitsetVec.end();
70 I != E; ++I)
71 I->reset();
72 }
73 void set() {
74 for(std::vector<bitword>::iterator I=bitsetVec.begin(), E=bitsetVec.end();
75 I != E; ++I)
76 I->set();
77 }
78 std::bitset<32>::reference operator[](unsigned n) {
79 unsigned ndiv = n / WORDSIZE, nmod = n % WORDSIZE;
80 assert(ndiv < bitsetVec.size() && "BitSetVector: Bit number out of range");
81 return bitsetVec[ndiv][nmod];
82 }
83 iterator begin() { return iterator::begin(*this); }
84 iterator end() { return iterator::end(*this); }
85
86 ///
87 /// Set membership operations: single element, any, none, count
88 ///
89 bool test(unsigned n) const {
90 unsigned ndiv = n / WORDSIZE, nmod = n % WORDSIZE;
91 assert(ndiv < bitsetVec.size() && "BitSetVector: Bit number out of range");
92 return bitsetVec[ndiv].test(nmod);
93 }
94 bool any() const {
95 for (unsigned i = 0; i < bitsetVec.size(); ++i)
96 if (bitsetVec[i].any())
97 return true;
98 return false;
99 }
100 bool none() const {
101 return ! any();
102 }
103 unsigned count() const {
104 unsigned n = 0;
105 for (unsigned i = 0; i < bitsetVec.size(); ++i)
106 n += bitsetVec[i].count();
107 return n;
108 }
109
110 ///
111 /// Set operations: intersection, union, disjoint union, complement.
112 ///
113 BitSetVector operator& (const BitSetVector& set2) const {
114 assert(maxSize == set2.maxSize && "Illegal intersection");
115 BitSetVector result(maxSize);
116 for (unsigned i = 0; i < bitsetVec.size(); ++i)
117 result.getWord(i) = getWord(i) & set2.getWord(i);
118 return result;
119 }
120 BitSetVector operator| (const BitSetVector& set2) const {
121 assert(maxSize == set2.maxSize && "Illegal intersection");
122 BitSetVector result(maxSize);
123 for (unsigned i = 0; i < bitsetVec.size(); ++i)
124 result.getWord(i) = getWord(i) | set2.getWord(i);
125 return result;
126 }
127 BitSetVector operator^ (const BitSetVector& set2) const {
128 assert(maxSize == set2.maxSize && "Illegal intersection");
129 BitSetVector result(maxSize);
130 for (unsigned i = 0; i < bitsetVec.size(); ++i)
131 result.getWord(i) = getWord(i) ^ set2.getWord(i);
132 return result;
133 }
134 BitSetVector operator~ () const {
135 BitSetVector result(maxSize);
136 for (unsigned i = 0; i < bitsetVec.size(); ++i)
137 (result.getWord(i) = getWord(i)).flip();
138 return result;
139 }
140
141 ///
142 /// Printing and debugging support
143 ///
144 void print(std::ostream &O) const;
145 void dump() const { print(std::cerr); }
146
147public:
148 //
149 // An iterator to enumerate the bits in a BitSetVector.
150 // Eventually, this needs to inherit from bidirectional_iterator.
151 // But this iterator may not be as useful as I once thought and
152 // may just go away.
153 //
154 class iterator {
155 unsigned currentBit;
156 unsigned currentWord;
157 BitSetVector& bitvec;
158 iterator(unsigned B, unsigned W, BitSetVector _bitvec)
159 : currentBit(B), currentWord(W), bitvec(_bitvec) { }
160 public:
161 iterator(BitSetVector& _bitvec)
162 : currentBit(0), currentWord(0), bitvec(_bitvec) { }
163 iterator(const iterator& I)
164 : currentBit(I.currentBit),currentWord(I.currentWord),bitvec(I.bitvec) { }
165 iterator& operator=(const iterator& I) {
166 currentWord == I.currentWord;
167 currentBit == I.currentBit;
168 bitvec = I.bitvec;
169 return *this;
170 }
171
172 // Increment and decrement operators (pre and post)
173 iterator& operator++() {
174 if (++currentBit == WORDSIZE)
175 { currentBit = 0; if (currentWord < bitvec.maxSize) ++currentWord; }
176 return *this;
177 }
178 iterator& operator--() {
179 if (currentBit == 0) {
180 currentBit = WORDSIZE-1;
181 currentWord = (currentWord == 0)? bitvec.maxSize : --currentWord;
182 }
183 else
184 --currentBit;
185 return *this;
186 }
187 iterator operator++(int) { iterator copy(*this); ++*this; return copy; }
188 iterator operator--(int) { iterator copy(*this); --*this; return copy; }
189
190 // Dereferencing operators
191 reference operator*() {
192 assert(currentWord < bitvec.maxSize &&
193 "Dereferencing iterator past the end of a BitSetVector");
194 return bitvec.getWord(currentWord)[currentBit];
195 }
196
197 // Comparison operator
198 bool operator==(const iterator& I) {
199 return (&I.bitvec == &bitvec &&
200 I.currentWord == currentWord && I.currentBit == currentBit);
201 }
202
203 protected:
204 static iterator begin(BitSetVector& _bitvec) { return iterator(_bitvec); }
205 static iterator end(BitSetVector& _bitvec) { return iterator(0,
206 _bitvec.maxSize, _bitvec); }
207 friend class BitSetVector;
208 };
209};
210
211
212inline void BitSetVector::print(std::ostream& O) const
213{
214 for (std::vector<bitword>::const_iterator
215 I=bitsetVec.begin(), E=bitsetVec.end(); I != E; ++I)
216 O << "<" << (*I) << ">" << (I+1 == E? "\n" : ", ");
217}
218
219inline std::ostream& operator<< (std::ostream& O, const BitSetVector& bset)
220{
221 bset.print(O);
222 return O;
223};
224
225
226///
227/// Optimized versions of fundamental comparison operations
228///
229inline bool Disjoint(const BitSetVector& set1,
230 const BitSetVector& set2)
231{
232 assert(set1.maxSize == set2.maxSize && "Illegal intersection");
233 for (unsigned i = 0; i < set1.bitsetVec.size(); ++i)
234 if ((set1.getWord(i) & set2.getWord(i)).any())
235 return false;
236 return true;
237}
238
239#endif