diff options
Diffstat (limited to 'llvm/include/llvm/ADT/BitSetVector.h')
-rw-r--r-- | llvm/include/llvm/ADT/BitSetVector.h | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/llvm/include/llvm/ADT/BitSetVector.h b/llvm/include/llvm/ADT/BitSetVector.h new file mode 100644 index 00000000000..73c5841ad6e --- /dev/null +++ b/llvm/include/llvm/ADT/BitSetVector.h @@ -0,0 +1,272 @@ +//===-- llvm/ADT/BitVectorSet.h - A bit-vector rep. of sets -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is 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. +// +// 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_ADT_BITSETVECTOR_H +#define LLVM_ADT_BITSETVECTOR_H + +#include <bitset> +#include <vector> +#include <functional> +#include <iostream> + +namespace llvm { + +class BitSetVector { + enum { BITSET_WORDSIZE = sizeof(long)*8 }; + + // Types used internal to the representation + typedef std::bitset<BITSET_WORDSIZE> bitword; + typedef bitword::reference reference; + + // Data used in the representation + std::vector<bitword> bitsetVec; + unsigned maxSize; + +private: + // Utility functions for the representation + static unsigned NumWords(unsigned Size) { + return (Size+BITSET_WORDSIZE-1)/BITSET_WORDSIZE; + } + static unsigned LastWordSize(unsigned Size) { return Size % BITSET_WORDSIZE; } + + // Clear the unused bits in the last word. + // The unused bits are the high (BITSET_WORDSIZE - LastWordSize()) bits + void ClearUnusedBits() { + unsigned long usedBits = (1U << LastWordSize(size())) - 1; + bitsetVec.back() &= bitword(usedBits); + } + + 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: + class iterator; + /// + /// Constructor: create a set of the maximum size maxSetSize. + /// The set is initialized to empty. + /// + BitSetVector(unsigned maxSetSize) + : bitsetVec(NumWords(maxSetSize)), maxSize(maxSetSize) { } + + /// size - Return the number of bits tracked by this bit vector... + unsigned size() const { return maxSize; } + + /// + /// Modifier methods: reset, set for entire set, operator[] for one element. + /// + void reset() { + for (unsigned i=0, N = bitsetVec.size(); i < N; ++i) + bitsetVec[i].reset(); + } + void set() { + for (unsigned i=0, N = bitsetVec.size(); i < N; ++i) // skip last word + bitsetVec[i].set(); + ClearUnusedBits(); + } + reference operator[](unsigned n) { + assert(n < size() && "BitSetVector: Bit number out of range"); + unsigned ndiv = n / BITSET_WORDSIZE, nmod = n % BITSET_WORDSIZE; + return bitsetVec[ndiv][nmod]; + } + iterator begin() { return iterator::begin(*this); } + iterator end() { return iterator::end(*this); } + + /// + /// Comparison operations: equal, not equal + /// + bool operator == (const BitSetVector& set2) const { + assert(maxSize == set2.maxSize && "Illegal == comparison"); + for (unsigned i = 0; i < bitsetVec.size(); ++i) + if (getWord(i) != set2.getWord(i)) + return false; + return true; + } + bool operator != (const BitSetVector& set2) const { + return ! (*this == set2); + } + + /// + /// Set membership operations: single element, any, none, count + /// + bool test(unsigned n) const { + assert(n < size() && "BitSetVector: Bit number out of range"); + unsigned ndiv = n / BITSET_WORDSIZE, nmod = n % BITSET_WORDSIZE; + 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; + } + bool all() const { + return (count() == size()); + } + + /// + /// 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(); + result.ClearUnusedBits(); + 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 == BITSET_WORDSIZE) + { currentBit = 0; if (currentWord < bitvec->size()) ++currentWord; } + return *this; + } + iterator& operator--() { + if (currentBit == 0) { + currentBit = BITSET_WORDSIZE-1; + currentWord = (currentWord == 0)? bitvec->size() : --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->size() && + "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.size(), _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.size() == set2.size() && "Illegal intersection"); + for (unsigned i = 0; i < set1.bitsetVec.size(); ++i) + if ((set1.getWord(i) & set2.getWord(i)).any()) + return false; + return true; +} + +} // End llvm namespace +#endif |