2003-09-30 18:37:50 +00:00
|
|
|
//===-- BitVectorSet.h - A bit-vector representation of sets ----*- C++ -*-===//
|
2003-10-20 19:46:57 +00:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2002-11-06 17:14:14 +00:00
|
|
|
//
|
2003-09-30 18:37:50 +00:00
|
|
|
// 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.
|
2002-11-06 17:14:14 +00:00
|
|
|
//
|
|
|
|
// 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().
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2003-06-17 00:35:55 +00:00
|
|
|
#ifndef SUPPORT_BITSETVECTOR_H
|
|
|
|
#define SUPPORT_BITSETVECTOR_H
|
2002-11-06 17:14:14 +00:00
|
|
|
|
|
|
|
#include <bitset>
|
|
|
|
#include <vector>
|
|
|
|
#include <functional>
|
|
|
|
#include <iostream>
|
|
|
|
|
2003-11-11 22:41:34 +00:00
|
|
|
namespace llvm {
|
|
|
|
|
2002-11-06 17:14:14 +00:00
|
|
|
class BitSetVector {
|
2003-06-22 03:09:10 +00:00
|
|
|
enum { BITSET_WORDSIZE = sizeof(long)*8 };
|
|
|
|
|
2002-11-27 17:46:38 +00:00
|
|
|
// Types used internal to the representation
|
2003-06-22 03:09:10 +00:00
|
|
|
typedef std::bitset<BITSET_WORDSIZE> bitword;
|
2002-11-06 17:14:14 +00:00
|
|
|
typedef bitword::reference reference;
|
|
|
|
|
2002-11-27 17:46:38 +00:00
|
|
|
// Data used in the representation
|
2002-11-06 17:14:14 +00:00
|
|
|
std::vector<bitword> bitsetVec;
|
2002-11-06 18:34:40 +00:00
|
|
|
unsigned maxSize;
|
2002-11-06 17:14:14 +00:00
|
|
|
|
2002-11-27 17:46:38 +00:00
|
|
|
private:
|
|
|
|
// Utility functions for the representation
|
2003-06-22 03:09:10 +00:00
|
|
|
static unsigned NumWords(unsigned Size) {
|
|
|
|
return (Size+BITSET_WORDSIZE-1)/BITSET_WORDSIZE;
|
|
|
|
}
|
|
|
|
static unsigned LastWordSize(unsigned Size) { return Size % BITSET_WORDSIZE; }
|
2002-11-27 17:46:38 +00:00
|
|
|
|
|
|
|
// Clear the unused bits in the last word.
|
2003-06-22 03:09:10 +00:00
|
|
|
// The unused bits are the high (BITSET_WORDSIZE - LastWordSize()) bits
|
2002-11-27 17:46:38 +00:00
|
|
|
void ClearUnusedBits() {
|
|
|
|
unsigned long usedBits = (1U << LastWordSize(size())) - 1;
|
|
|
|
bitsetVec.back() &= bitword(usedBits);
|
|
|
|
}
|
2002-11-06 17:14:14 +00:00
|
|
|
|
|
|
|
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:
|
2004-04-21 16:10:40 +00:00
|
|
|
class iterator;
|
2002-11-06 17:14:14 +00:00
|
|
|
///
|
|
|
|
/// Constructor: create a set of the maximum size maxSetSize.
|
|
|
|
/// The set is initialized to empty.
|
|
|
|
///
|
|
|
|
BitSetVector(unsigned maxSetSize)
|
2002-11-06 18:34:40 +00:00
|
|
|
: bitsetVec(NumWords(maxSetSize)), maxSize(maxSetSize) { }
|
|
|
|
|
|
|
|
/// size - Return the number of bits tracked by this bit vector...
|
|
|
|
unsigned size() const { return maxSize; }
|
2002-11-06 17:14:14 +00:00
|
|
|
|
|
|
|
///
|
|
|
|
/// Modifier methods: reset, set for entire set, operator[] for one element.
|
|
|
|
///
|
|
|
|
void reset() {
|
2002-11-27 17:46:38 +00:00
|
|
|
for (unsigned i=0, N = bitsetVec.size(); i < N; ++i)
|
|
|
|
bitsetVec[i].reset();
|
2002-11-06 17:14:14 +00:00
|
|
|
}
|
|
|
|
void set() {
|
2002-11-27 17:46:38 +00:00
|
|
|
for (unsigned i=0, N = bitsetVec.size(); i < N; ++i) // skip last word
|
|
|
|
bitsetVec[i].set();
|
|
|
|
ClearUnusedBits();
|
2002-11-06 17:14:14 +00:00
|
|
|
}
|
2002-11-27 17:46:38 +00:00
|
|
|
reference operator[](unsigned n) {
|
|
|
|
assert(n < size() && "BitSetVector: Bit number out of range");
|
2003-06-22 03:09:10 +00:00
|
|
|
unsigned ndiv = n / BITSET_WORDSIZE, nmod = n % BITSET_WORDSIZE;
|
2002-11-06 17:14:14 +00:00
|
|
|
return bitsetVec[ndiv][nmod];
|
|
|
|
}
|
|
|
|
iterator begin() { return iterator::begin(*this); }
|
|
|
|
iterator end() { return iterator::end(*this); }
|
|
|
|
|
2002-11-27 17:46:38 +00:00
|
|
|
///
|
|
|
|
/// 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);
|
|
|
|
}
|
|
|
|
|
2002-11-06 17:14:14 +00:00
|
|
|
///
|
|
|
|
/// Set membership operations: single element, any, none, count
|
|
|
|
///
|
|
|
|
bool test(unsigned n) const {
|
2002-11-27 17:46:38 +00:00
|
|
|
assert(n < size() && "BitSetVector: Bit number out of range");
|
2003-06-22 03:09:10 +00:00
|
|
|
unsigned ndiv = n / BITSET_WORDSIZE, nmod = n % BITSET_WORDSIZE;
|
2002-11-06 17:14:14 +00:00
|
|
|
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;
|
|
|
|
}
|
2002-11-27 17:46:38 +00:00
|
|
|
bool all() const {
|
|
|
|
return (count() == size());
|
|
|
|
}
|
2002-11-06 17:14:14 +00:00
|
|
|
|
|
|
|
///
|
|
|
|
/// 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();
|
2002-11-27 17:46:38 +00:00
|
|
|
result.ClearUnusedBits();
|
2002-11-06 17:14:14 +00:00
|
|
|
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;
|
2002-11-27 17:46:38 +00:00
|
|
|
BitSetVector* bitvec;
|
|
|
|
iterator(unsigned B, unsigned W, BitSetVector& _bitvec)
|
|
|
|
: currentBit(B), currentWord(W), bitvec(&_bitvec) { }
|
2002-11-06 17:14:14 +00:00
|
|
|
public:
|
|
|
|
iterator(BitSetVector& _bitvec)
|
2002-11-27 17:46:38 +00:00
|
|
|
: currentBit(0), currentWord(0), bitvec(&_bitvec) { }
|
2002-11-06 17:14:14 +00:00
|
|
|
iterator(const iterator& I)
|
|
|
|
: currentBit(I.currentBit),currentWord(I.currentWord),bitvec(I.bitvec) { }
|
|
|
|
iterator& operator=(const iterator& I) {
|
2003-03-17 18:11:27 +00:00
|
|
|
currentWord = I.currentWord;
|
|
|
|
currentBit = I.currentBit;
|
2002-11-06 17:14:14 +00:00
|
|
|
bitvec = I.bitvec;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Increment and decrement operators (pre and post)
|
|
|
|
iterator& operator++() {
|
2003-06-22 03:09:10 +00:00
|
|
|
if (++currentBit == BITSET_WORDSIZE)
|
2003-03-17 18:11:27 +00:00
|
|
|
{ currentBit = 0; if (currentWord < bitvec->size()) ++currentWord; }
|
2002-11-06 17:14:14 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
iterator& operator--() {
|
|
|
|
if (currentBit == 0) {
|
2003-06-22 03:09:10 +00:00
|
|
|
currentBit = BITSET_WORDSIZE-1;
|
2003-03-17 18:11:27 +00:00
|
|
|
currentWord = (currentWord == 0)? bitvec->size() : --currentWord;
|
2002-11-06 17:14:14 +00:00
|
|
|
}
|
|
|
|
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*() {
|
2003-03-17 18:11:27 +00:00
|
|
|
assert(currentWord < bitvec->size() &&
|
2002-11-06 17:14:14 +00:00
|
|
|
"Dereferencing iterator past the end of a BitSetVector");
|
2002-11-27 17:46:38 +00:00
|
|
|
return bitvec->getWord(currentWord)[currentBit];
|
2002-11-06 17:14:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Comparison operator
|
|
|
|
bool operator==(const iterator& I) {
|
2002-11-27 17:46:38 +00:00
|
|
|
return (I.bitvec == bitvec &&
|
2002-11-06 17:14:14 +00:00
|
|
|
I.currentWord == currentWord && I.currentBit == currentBit);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
static iterator begin(BitSetVector& _bitvec) { return iterator(_bitvec); }
|
|
|
|
static iterator end(BitSetVector& _bitvec) { return iterator(0,
|
2003-03-17 18:11:27 +00:00
|
|
|
_bitvec.size(), _bitvec); }
|
2002-11-06 17:14:14 +00:00
|
|
|
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)
|
|
|
|
{
|
2002-11-06 18:34:40 +00:00
|
|
|
assert(set1.size() == set2.size() && "Illegal intersection");
|
2002-11-06 17:14:14 +00:00
|
|
|
for (unsigned i = 0; i < set1.bitsetVec.size(); ++i)
|
|
|
|
if ((set1.getWord(i) & set2.getWord(i)).any())
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2003-11-11 22:41:34 +00:00
|
|
|
} // End llvm namespace
|
2002-11-06 17:14:14 +00:00
|
|
|
#endif
|