diff options
author | Vikram S. Adve <vadve@cs.uiuc.edu> | 2002-11-06 17:14:14 +0000 |
---|---|---|
committer | Vikram S. Adve <vadve@cs.uiuc.edu> | 2002-11-06 17:14:14 +0000 |
commit | 5f76054a79c5386fcdb6695fa49e9eaa4dfabc19 (patch) | |
tree | 4d0082476e84a10220f9e5a017378093e3201a16 /include/llvm/ADT/BitSetVector.h | |
parent | 895c0bd3fb76938d060cc7596b341d2b9193c21b (diff) |
An implementation of the bit-vector representation of sets.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4568 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/ADT/BitSetVector.h')
-rw-r--r-- | include/llvm/ADT/BitSetVector.h | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/include/llvm/ADT/BitSetVector.h b/include/llvm/ADT/BitSetVector.h new file mode 100644 index 0000000000..0143413b3d --- /dev/null +++ b/include/llvm/ADT/BitSetVector.h @@ -0,0 +1,239 @@ +//===-- BitVectorSet.h - A bit-vector representation of sets -----*- C++ -*--=// +// +// class BitVectorSet -- +// +// An implementation of the bit-vector representation of sets. +// Unlike vector<bool>, this allows much more efficient parallel set +// operations on bits, by using the bitset template . The bitset template +// unfortunately can only represent sets with a size chosen at compile-time. +// We therefore use a vector of bitsets. The maxmimum size of our sets +// (i.e., the size of the universal set) can be chosen at creation time. +// +// The size of each Bitset is defined by the macro WORDSIZE. +// +// NOTE: The WORDSIZE macro should be made machine-dependent, in order to use +// 64-bit words or whatever gives most efficient Bitsets on each platform. +// +// +// External functions: +// +// bool Disjoint(const BitSetVector& set1, const BitSetVector& set2): +// Tests if two sets have an empty intersection. +// This is more efficient than !(set1 & set2).any(). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_BITVECTORSET_H +#define LLVM_SUPPORT_BITVECTORSET_H + +#include <bitset> +#include <vector> +#include <functional> +#include <iostream> + + +#define WORDSIZE (32U) + + +class BitSetVector { + typedef std::bitset<WORDSIZE> bitword; + typedef bitword::reference reference; + class iterator; + + std::vector<bitword> bitsetVec; + + static unsigned NumWords(unsigned Size) { return (Size+WORDSIZE-1)/WORDSIZE;} + + const bitword& getWord(unsigned i) const { return bitsetVec[i]; } + bitword& getWord(unsigned i) { return bitsetVec[i]; } + + friend bool Disjoint(const BitSetVector& set1, + const BitSetVector& set2); + + BitSetVector(); // do not implement! + +public: + unsigned maxSize; + + /// + /// Constructor: create a set of the maximum size maxSetSize. + /// The set is initialized to empty. + /// + BitSetVector(unsigned maxSetSize) + : bitsetVec(BitSetVector::NumWords(maxSetSize)), maxSize(maxSetSize) { } + + /// + /// Modifier methods: reset, set for entire set, operator[] for one element. + /// + void reset() { + for(std::vector<bitword>::iterator I=bitsetVec.begin(), E=bitsetVec.end(); + I != E; ++I) + I->reset(); + } + void set() { + for(std::vector<bitword>::iterator I=bitsetVec.begin(), E=bitsetVec.end(); + I != E; ++I) + I->set(); + } + std::bitset<32>::reference operator[](unsigned n) { + unsigned ndiv = n / WORDSIZE, nmod = n % WORDSIZE; + assert(ndiv < bitsetVec.size() && "BitSetVector: Bit number out of range"); + return bitsetVec[ndiv][nmod]; + } + iterator begin() { return iterator::begin(*this); } + iterator end() { return iterator::end(*this); } + + /// + /// Set membership operations: single element, any, none, count + /// + bool test(unsigned n) const { + unsigned ndiv = n / WORDSIZE, nmod = n % WORDSIZE; + assert(ndiv < bitsetVec.size() && "BitSetVector: Bit number out of range"); + return bitsetVec[ndiv].test(nmod); + } + bool any() const { + for (unsigned i = 0; i < bitsetVec.size(); ++i) + if (bitsetVec[i].any()) + return true; + return false; + } + bool none() const { + return ! any(); + } + unsigned count() const { + unsigned n = 0; + for (unsigned i = 0; i < bitsetVec.size(); ++i) + n += bitsetVec[i].count(); + return n; + } + + /// + /// Set operations: intersection, union, disjoint union, complement. + /// + BitSetVector operator& (const BitSetVector& set2) const { + assert(maxSize == set2.maxSize && "Illegal intersection"); + BitSetVector result(maxSize); + for (unsigned i = 0; i < bitsetVec.size(); ++i) + result.getWord(i) = getWord(i) & set2.getWord(i); + return result; + } + BitSetVector operator| (const BitSetVector& set2) const { + assert(maxSize == set2.maxSize && "Illegal intersection"); + BitSetVector result(maxSize); + for (unsigned i = 0; i < bitsetVec.size(); ++i) + result.getWord(i) = getWord(i) | set2.getWord(i); + return result; + } + BitSetVector operator^ (const BitSetVector& set2) const { + assert(maxSize == set2.maxSize && "Illegal intersection"); + BitSetVector result(maxSize); + for (unsigned i = 0; i < bitsetVec.size(); ++i) + result.getWord(i) = getWord(i) ^ set2.getWord(i); + return result; + } + BitSetVector operator~ () const { + BitSetVector result(maxSize); + for (unsigned i = 0; i < bitsetVec.size(); ++i) + (result.getWord(i) = getWord(i)).flip(); + return result; + } + + /// + /// Printing and debugging support + /// + void print(std::ostream &O) const; + void dump() const { print(std::cerr); } + +public: + // + // An iterator to enumerate the bits in a BitSetVector. + // Eventually, this needs to inherit from bidirectional_iterator. + // But this iterator may not be as useful as I once thought and + // may just go away. + // + class iterator { + unsigned currentBit; + unsigned currentWord; + BitSetVector& bitvec; + iterator(unsigned B, unsigned W, BitSetVector _bitvec) + : currentBit(B), currentWord(W), bitvec(_bitvec) { } + public: + iterator(BitSetVector& _bitvec) + : currentBit(0), currentWord(0), bitvec(_bitvec) { } + iterator(const iterator& I) + : currentBit(I.currentBit),currentWord(I.currentWord),bitvec(I.bitvec) { } + iterator& operator=(const iterator& I) { + currentWord == I.currentWord; + currentBit == I.currentBit; + bitvec = I.bitvec; + return *this; + } + + // Increment and decrement operators (pre and post) + iterator& operator++() { + if (++currentBit == WORDSIZE) + { currentBit = 0; if (currentWord < bitvec.maxSize) ++currentWord; } + return *this; + } + iterator& operator--() { + if (currentBit == 0) { + currentBit = WORDSIZE-1; + currentWord = (currentWord == 0)? bitvec.maxSize : --currentWord; + } + else + --currentBit; + return *this; + } + iterator operator++(int) { iterator copy(*this); ++*this; return copy; } + iterator operator--(int) { iterator copy(*this); --*this; return copy; } + + // Dereferencing operators + reference operator*() { + assert(currentWord < bitvec.maxSize && + "Dereferencing iterator past the end of a BitSetVector"); + return bitvec.getWord(currentWord)[currentBit]; + } + + // Comparison operator + bool operator==(const iterator& I) { + return (&I.bitvec == &bitvec && + I.currentWord == currentWord && I.currentBit == currentBit); + } + + protected: + static iterator begin(BitSetVector& _bitvec) { return iterator(_bitvec); } + static iterator end(BitSetVector& _bitvec) { return iterator(0, + _bitvec.maxSize, _bitvec); } + friend class BitSetVector; + }; +}; + + +inline void BitSetVector::print(std::ostream& O) const +{ + for (std::vector<bitword>::const_iterator + I=bitsetVec.begin(), E=bitsetVec.end(); I != E; ++I) + O << "<" << (*I) << ">" << (I+1 == E? "\n" : ", "); +} + +inline std::ostream& operator<< (std::ostream& O, const BitSetVector& bset) +{ + bset.print(O); + return O; +}; + + +/// +/// Optimized versions of fundamental comparison operations +/// +inline bool Disjoint(const BitSetVector& set1, + const BitSetVector& set2) +{ + assert(set1.maxSize == set2.maxSize && "Illegal intersection"); + for (unsigned i = 0; i < set1.bitsetVec.size(); ++i) + if ((set1.getWord(i) & set2.getWord(i)).any()) + return false; + return true; +} + +#endif |