style: clean up ruby's Set class

Further cleanup should probably be done to make this class be non-Ruby
specific and put it in src/base.

There are probably several cases where this class is used, std::bitset
could be used instead.
This commit is contained in:
Nathan Binkert 2010-06-01 11:38:56 -07:00
parent bb589d463b
commit c1aabe8172
3 changed files with 304 additions and 567 deletions

View file

@ -222,7 +222,7 @@ NetDest::intersectionIsNotEmpty(const NetDest& other_netDest) const
{ {
assert(m_bits.size() == other_netDest.getSize()); assert(m_bits.size() == other_netDest.getSize());
for (int i = 0; i < m_bits.size(); i++) { for (int i = 0; i < m_bits.size(); i++) {
if (m_bits[i].intersectionIsNotEmpty(other_netDest.m_bits[i])) { if (!m_bits[i].intersectionIsEmpty(other_netDest.m_bits[i])) {
return true; return true;
} }
} }

View file

@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@ -27,554 +26,340 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* // modified (rewritten) 05/20/05 by Dan Gibson to accomimdate FASTER
* Set.cc // >32 bit set sizes
*
* Description: See Set.hh
*
* $Id: BigSet.cc 1.9 05/01/19 13:12:25-06:00 mikem@maya.cs.wisc.edu $
*
*/
// modified (rewritten) 05/20/05 by Dan Gibson to accomimdate FASTER >32 bit
// set sizes
#include "mem/ruby/common/Set.hh" #include "mem/ruby/common/Set.hh"
#include "mem/ruby/system/System.hh" #include "mem/ruby/system/System.hh"
#if __amd64__ || __LP64__
#define __64BITS__
#else
#define __32BITS__
#endif
Set::Set() Set::Set()
{ {
m_p_nArray = NULL; m_p_nArray = NULL;
m_nArrayLen = 0; m_nArrayLen = 0;
m_nSize = 0; m_nSize = 0;
} }
// copy constructor Set::Set(const Set& obj)
Set::Set(const Set& obj) { {
m_p_nArray = NULL; m_p_nArray = NULL;
setSize(obj.m_nSize); setSize(obj.m_nSize);
// copy from the host to this array
for(int i=0; i<m_nArrayLen; i++) {
m_p_nArray[i] = obj.m_p_nArray[i];
}
// copy from the host to this array
for (int i = 0; i < m_nArrayLen; i++)
m_p_nArray[i] = obj.m_p_nArray[i];
} }
Set::Set(int size) Set::Set(int size)
{ {
m_p_nArray = NULL; m_p_nArray = NULL;
m_nArrayLen = 0; m_nArrayLen = 0;
m_nSize = 0; m_nSize = 0;
if(size > 0) { if (size > 0)
setSize(size); setSize(size);
}
} }
Set::~Set() { Set::~Set()
if( (m_p_nArray != (&m_p_nArray_Static[0])) && (m_p_nArray != NULL))
delete [] m_p_nArray;
m_p_nArray = NULL;
}
// /*
// * This function should set the bit corresponding to index
// * to 1.
// */
// void Set::add(NodeID index)
// {
// assert(index<m_nSize && index >= 0);
// #ifdef __32BITS__
// m_p_nArray[index>>5] |= (1 << (index & 0x01F));
// #else
// m_p_nArray[index>>6] |= (((unsigned long) 1) << (index & 0x03F));
// #endif // __32BITS__
// }
/*
* This function should set all the bits in the current set
* that are already set in the parameter set
*/
void Set::addSet(const Set& set)
{ {
assert(getSize()==set.getSize()); if (m_p_nArray && m_p_nArray != &m_p_nArray_Static[0])
for(int i=0; i<m_nArrayLen; i++) { delete [] m_p_nArray;
m_p_nArray[i] |= set.m_p_nArray[i]; m_p_nArray = NULL;
}
} }
/* void
* This function should randomly assign 1 to the bits in the set-- Set::clearExcess()
* it should not clear the bits bits first, though?
*/
void Set::addRandom()
{ {
// now just ensure that no bits over the maximum size were set
for(int i=0; i<m_nArrayLen; i++) { #ifdef _LP64
m_p_nArray[i] |= random() ^ (random() << 4); // this ensures that all 32 bits are subject to random effects, long mask = 0x7FFFFFFFFFFFFFFF;
// as RAND_MAX typically = 0x7FFFFFFF
}
// now just ensure that no bits over the maximum size were set
#ifdef __32BITS__
long mask = 0x7FFFFFFF;
// the number of populated spaces in the higest-order array slot is:
// m_nSize % 32, so the uppermost 32 - m_nSize%32 bits should be
// cleared
if((m_nSize % 32) != 0) {
for(int j=0; j<32-(m_nSize&0x01F); j++) {
m_p_nArray[m_nArrayLen-1] &= mask;
mask = mask >> 1;
}
}
#else #else
long mask = 0x7FFFFFFFFFFFFFFF; long mask = 0x7FFFFFFF;
#endif
// the number of populated spaces in the higest-order array slot is: // the number of populated spaces in the higest-order array slot
// m_nSize % 64, so the uppermost 64 - m_nSize%64 bits should be // is: m_nSize % LONG_BITS, so the uppermost LONG_BITS -
// cleared // m_nSize%64 bits should be cleared
if ((m_nSize % LONG_BITS) != 0) {
if((m_nSize % 64) != 0) { for (int j = 0; j < 64 - (m_nSize & INDEX_MASK); j++) {
for(int j=0; j<64-(m_nSize&0x03F); j++) { m_p_nArray[m_nArrayLen - 1] &= mask;
m_p_nArray[m_nArrayLen-1] &= mask; mask = mask >> 1;
mask = mask >> 1; }
} }
}
#endif // __32BITS__
} }
// /*
// * This function unsets the bit associated with index
// */
// void Set::remove(NodeID index)
// {
// assert(index<m_nSize && index>=0);
// #ifdef __32BITS__ /*
// m_p_nArray[index>>5] &= ~(0x00000001 << (index & 0x01F)); * This function should set all the bits in the current set that are
// #else * already set in the parameter set
// m_p_nArray[index>>6] &= ~(((unsigned long) 0x0000000000000001) << (index & 0x03F)); */
// #endif // __32BITS__ void
Set::addSet(const Set& set)
{
assert(getSize()==set.getSize());
for (int i = 0; i < m_nArrayLen; i++)
m_p_nArray[i] |= set.m_p_nArray[i];
}
// } /*
* This function should randomly assign 1 to the bits in the set--it
* should not clear the bits bits first, though?
*/
void
Set::addRandom()
{
for (int i = 0; i < m_nArrayLen; i++) {
// this ensures that all 32 bits are subject to random effects,
// as RAND_MAX typically = 0x7FFFFFFF
m_p_nArray[i] |= random() ^ (random() << 4);
}
clearExcess();
}
/* /*
* This function clears bits that are =1 in the parameter set * This function clears bits that are =1 in the parameter set
*/ */
void Set::removeSet(const Set& set) void
Set::removeSet(const Set& set)
{ {
assert(m_nSize == set.m_nSize);
assert(m_nSize==set.m_nSize); for (int i = 0; i < m_nArrayLen; i++)
for(int i=0; i<m_nArrayLen; i++) { m_p_nArray[i] &= ~set.m_p_nArray[i];
m_p_nArray[i] &= ~(set.m_p_nArray[i]);
}
} }
// /*
// * This function clears all bits in the set
// */
// void Set::clear()
// {
// for(int i=0; i<m_nArrayLen; i++) {
// m_p_nArray[i] = 0;
// }
// }
/* /*
* this function sets all bits in the set * this function sets all bits in the set
*/ */
void Set::broadcast() void
Set::broadcast()
{ {
for (int i = 0; i < m_nArrayLen; i++)
m_p_nArray[i] = -1; // note that -1 corresponds to all 1's in 2's comp.
for(int i=0; i<m_nArrayLen; i++) { clearExcess();
m_p_nArray[i] = -1; // note that -1 corresponds to all 1's in 2's comp.
}
// now just ensure that no bits over the maximum size were set
#ifdef __32BITS__
long mask = 0x7FFFFFFF;
// the number of populated spaces in the higest-order array slot is:
// m_nSize % 32, so the uppermost 32 - m_nSize%32 bits should be
// cleared
if((m_nSize % 32) != 0) {
for(int j=0; j<32-(m_nSize&0x01F); j++) {
m_p_nArray[m_nArrayLen-1] &= mask;
mask = mask >> 1;
}
}
#else
long mask = 0x7FFFFFFFFFFFFFFF;
// the number of populated spaces in the higest-order array slot is:
// m_nSize % 64, so the uppermost 64 - m_nSize%64 bits should be
// cleared
if((m_nSize % 64) != 0) {
for(int j=0; j<64-(m_nSize&0x03F); j++) {
m_p_nArray[m_nArrayLen-1] &= mask;
mask = mask >> 1;
}
}
#endif // __32BITS__
} }
/* /*
* This function returns the population count of 1's in the set * This function returns the population count of 1's in the set
*/ */
int Set::count() const int
Set::count() const
{ {
int counter = 0; int counter = 0;
long mask; long mask;
for( int i=0; i<m_nArrayLen; i++) {
mask = (long) 0x01;
#ifdef __32BITS__ for (int i = 0; i < m_nArrayLen; i++) {
for( int j=0; j<32; j++) { mask = (long)0x01;
if(m_p_nArray[i] & mask) counter++;
mask = mask << 1; for (int j = 0; j < LONG_BITS; j++) {
// FIXME - significant performance loss when array
// population << LONG_BITS
if ((m_p_nArray[i] & mask) != 0) {
counter++;
}
mask = mask << 1;
}
} }
#else return counter;
for( int j=0; j<64; j++) { // FIXME - significant performance loss when array population << 64
if((m_p_nArray[i] & mask) != 0) {
counter++;
}
mask = mask << 1;
}
#endif // __32BITS__
}
return counter;
} }
/* /*
* This function checks for set equality * This function checks for set equality
*/ */
bool
bool Set::isEqual(const Set& set) const Set::isEqual(const Set& set) const
{ {
assert(m_nSize==set.m_nSize); assert(m_nSize == set.m_nSize);
for(int i=0;i<m_nArrayLen;i++) { for (int i = 0; i < m_nArrayLen; i++)
if(m_p_nArray[i] != set.m_p_nArray[i]) { if (m_p_nArray[i] != set.m_p_nArray[i])
return false; return false;
}
}
return true; return true;
} }
/* /*
* This function returns the NodeID (int) of the * This function returns the NodeID (int) of the least set bit
* least set bit
*/ */
NodeID Set::smallestElement() const NodeID
Set::smallestElement() const
{ {
assert(count() > 0); assert(count() > 0);
long x; long x;
for( int i=0; i<m_nArrayLen; i++) { for (int i = 0; i < m_nArrayLen; i++) {
if(m_p_nArray[i]!=0) { if (m_p_nArray[i] != 0) {
// the least-set bit must be in here // the least-set bit must be in here
x = m_p_nArray[i]; x = m_p_nArray[i];
#ifdef __32BITS__ for (int j = 0; j < LONG_BITS; j++) {
for( int j=0; j<32; j++) { if (x & (unsigned long)1) {
if(x & 0x00000001) { return LONG_BITS * i + j;
return 32*i+j; }
x = x >> 1;
}
ERROR_MSG("No smallest element of an empty set.");
} }
x = x >> 1;
}
#else
for( int j=0; j<64; j++) {
if(x & 0x0000000000000001) {
return 64*i+j;
}
x = x >> 1;
}
#endif // __32BITS__
ERROR_MSG("No smallest element of an empty set.");
} }
}
ERROR_MSG("No smallest element of an empty set."); ERROR_MSG("No smallest element of an empty set.");
return 0; return 0;
} }
/* /*
* this function returns true iff all bits are set * this function returns true iff all bits are set
*/ */
bool Set::isBroadcast() const bool
Set::isBroadcast() const
{ {
// check the fully-loaded words by equal to 0xffffffff // check the fully-loaded words by equal to 0xffffffff
// only the last word may not be fully loaded, it is not // only the last word may not be fully loaded, it is not
// fully loaded iff m_nSize % 32 or 64 !=0 => fully loaded iff // fully loaded iff m_nSize % 32 or 64 !=0 => fully loaded iff
// m_nSize % 32 or 64 == 0 // m_nSize % 32 or 64 == 0
#ifdef __32BITS__ int max = (m_nSize % LONG_BITS) == 0 ? m_nArrayLen : m_nArrayLen - 1;
for(int i=0; i< (((m_nSize % 32)==0) ? m_nArrayLen : m_nArrayLen-1); i++) { for (int i = 0; i < max; i++) {
if(m_p_nArray[i]!=-1) { if (m_p_nArray[i] != -1) {
return false; return false;
}
} }
}
// now check the last word, which may not be fully loaded // now check the last word, which may not be fully loaded
long mask = 1; long mask = 1;
for(int j=0; j< (m_nSize % 32); j++) { for (int j = 0; j < (m_nSize % LONG_BITS); j++) {
if((mask & m_p_nArray[m_nArrayLen-1])==0) { if ((mask & m_p_nArray[m_nArrayLen-1]) == 0) {
return false; return false;
}
mask = mask << 1;
} }
mask = mask << 1;
}
#else
for(int i=0; i< (((m_nSize % 64)==0) ? m_nArrayLen : m_nArrayLen-1); i++) {
if(m_p_nArray[i]!=-1) {
return false;
}
}
// now check the last word, which may not be fully loaded return true;
long mask = 1;
for(int j=0; j< (m_nSize % 64); j++) {
if((mask & m_p_nArray[m_nArrayLen-1])==0) {
return false;
}
mask = mask << 1;
}
#endif // __32BITS__
return true;
} }
/* /*
* this function returns true iff no bits are set * this function returns true iff no bits are set
*/ */
bool Set::isEmpty() const bool
Set::isEmpty() const
{ {
// here we can simply check if all = 0, since we ensure
// here we can simply check if all = 0, since we ensure // that "extra slots" are all zero
// that "extra slots" are all zero for (int i = 0; i < m_nArrayLen ; i++)
for(int i=0; i< m_nArrayLen ; i++) { if (m_p_nArray[i])
if(m_p_nArray[i]!=0) {
return false; return false;
}
}
return true; return true;
} }
// returns the logical OR of "this" set and orSet // returns the logical OR of "this" set and orSet
Set Set::OR(const Set& orSet) const Set
Set::OR(const Set& orSet) const
{ {
Set result(m_nSize); Set result(m_nSize);
assert(m_nSize == orSet.m_nSize); assert(m_nSize == orSet.m_nSize);
for(int i=0; i< m_nArrayLen; i++) { for (int i = 0; i < m_nArrayLen; i++)
result.m_p_nArray[i] = m_p_nArray[i] | orSet.m_p_nArray[i]; result.m_p_nArray[i] = m_p_nArray[i] | orSet.m_p_nArray[i];
}
return result;
return result;
} }
// returns the logical AND of "this" set and andSet // returns the logical AND of "this" set and andSet
Set Set::AND(const Set& andSet) const Set
Set::AND(const Set& andSet) const
{ {
Set result(m_nSize); Set result(m_nSize);
assert(m_nSize == andSet.m_nSize); assert(m_nSize == andSet.m_nSize);
for(int i=0; i< m_nArrayLen; i++) { for (int i = 0; i < m_nArrayLen; i++) {
result.m_p_nArray[i] = m_p_nArray[i] & andSet.m_p_nArray[i]; result.m_p_nArray[i] = m_p_nArray[i] & andSet.m_p_nArray[i];
} }
return result; return result;
} }
// // Returns true if the intersection of the two sets is non-empty
// bool Set::intersectionIsNotEmpty(const Set& other_set) const
// {
// assert(m_nSize == other_set.m_nSize);
// for(int i=0; i< m_nArrayLen; i++) {
// if(m_p_nArray[i] & other_set.m_p_nArray[i]) {
// return true;
// }
// }
// return false;
// }
// // Returns true if the intersection of the two sets is empty
// bool Set::intersectionIsEmpty(const Set& other_set) const
// {
// assert(m_nSize == other_set.m_nSize);
// for(int i=0; i< m_nArrayLen; i++) {
// if(m_p_nArray[i] & other_set.m_p_nArray[i]) {
// return false;
// }
// }
// return true;
// }
/* /*
* Returns false if a bit is set in the parameter set that is * Returns false if a bit is set in the parameter set that is NOT set
* NOT set in this set * in this set
*/ */
bool Set::isSuperset(const Set& test) const bool
Set::isSuperset(const Set& test) const
{ {
assert(m_nSize == test.m_nSize); assert(m_nSize == test.m_nSize);
for(int i=0;i<m_nArrayLen;i++) { for (int i = 0; i < m_nArrayLen; i++)
if(((test.m_p_nArray[i] & m_p_nArray[i]) | ~test.m_p_nArray[i]) != -1) { if (((test.m_p_nArray[i] & m_p_nArray[i]) | ~test.m_p_nArray[i]) != -1)
return false; return false;
return true;
}
void
Set::setSize(int size)
{
m_nSize = size;
m_nArrayLen = m_nSize / LONG_BITS + ((m_nSize % LONG_BITS == 0) ? 0 : 1 );
// decide whether to use dynamic or static alloction
if (m_nArrayLen <= NUMBER_WORDS_PER_SET) {
// constant defined in RubySystem.hh
// its OK to use the static allocation, and it will
// probably be faster (as m_nArrayLen is already in the
// cache and they will probably share the same cache line)
// if switching from dyanamic to static allocation (which
// is probably rare, but why not be complete?), must delete
// the dynamically allocated space
if (m_p_nArray && m_p_nArray != &m_p_nArray_Static[0])
delete [] m_p_nArray;
m_p_nArray = &m_p_nArray_Static[0];
} else {
// can't use static allocation...simply not enough room
// so dynamically allocate some space
if (m_p_nArray && m_p_nArray != &m_p_nArray_Static[0])
delete [] m_p_nArray;
m_p_nArray = new long[m_nArrayLen];
} }
}
return true; clear();
} }
// /* Set&
// * Returns true iff this bit is set Set::operator=(const Set& obj)
// */
// bool Set::isElement(NodeID element) const
// {
// bool result;
// #ifdef __32BITS__
// result = ((m_p_nArray[element>>5] & (0x00000001 << (element & 0x01F)))!=0);
// #else
// result = ((m_p_nArray[element>>6] & (((unsigned long) 0x0000000000000001) << (element & 0x03F)))!=0);
// #endif // __32BITS__
// return result;
// }
/*
* "Supposed" to return the node id of the (n+1)th set
* bit, IE n=0 => returns nodeid of first set bit, BUT
* since BigSet.cc behaves strangely, this implementation
* will behave strangely just for reverse compatability.
*
* Was originally implemented for the flight data recorder
* FDR
*/
// NodeID Set::elementAt(int n) const
// {
// if(isElement(n)) return (NodeID) true;
// else return 0;
// /*
// int match = -1;
// for(int i=0;i<m_nSize;i++) {
// if(isElement(i)) match++;
// if(match==n) {
// return i;
// }
// }
// return -1;
// */
// }
void Set::setSize(int size)
{ {
m_nSize = size; if (this != &obj) {
// resize this item
setSize(obj.getSize());
#ifdef __32BITS__ // copy the elements from obj to this
m_nArrayLen = m_nSize/32 + ((m_nSize%32==0) ? 0 : 1 ); for (int i = 0; i < m_nArrayLen; i++)
#else m_p_nArray[i] = obj.m_p_nArray[i];
m_nArrayLen = m_nSize/64 + ((m_nSize%64==0) ? 0 : 1 );
#endif // __32BITS__
// decide whether to use dynamic or static alloction
if(m_nArrayLen<=NUMBER_WORDS_PER_SET) { // constant defined in RubySystem.hh
// its OK to use the static allocation, and it will
// probably be faster (as m_nArrayLen is already in the
// cache and they will probably share the same cache line)
// if switching from dyanamic to static allocation (which
// is probably rare, but why not be complete?), must delete
// the dynamically allocated space
if((m_p_nArray != NULL) && (m_p_nArray != &m_p_nArray_Static[0]))
delete [] m_p_nArray;
m_p_nArray = & m_p_nArray_Static[0];
} else {
// can't use static allocation...simply not enough room
// so dynamically allocate some space
if((m_p_nArray != NULL) && (m_p_nArray != &m_p_nArray_Static[0]))
delete [] m_p_nArray;
m_p_nArray = new long[m_nArrayLen];
}
clear();
}
Set& Set::operator=(const Set& obj) {
if(this == &obj) {
// do nothing
} else {
// resize this item
setSize(obj.getSize());
// copy the elements from obj to this
for(int i=0; i<m_nArrayLen; i++) {
m_p_nArray[i] = obj.m_p_nArray[i];
} }
}
return *this; return *this;
} }
void Set::print(std::ostream& out) const void
Set::print(std::ostream& out) const
{ {
if(m_p_nArray==NULL) { if (!m_p_nArray) {
out << "[Set {Empty}]"; out << "[Set {Empty}]";
return; return;
} }
char buff[24];
out << "[Set (" << m_nSize << ") 0x "; char buff[24];
for (int i=m_nArrayLen-1; i>=0; i--) { out << "[Set (" << m_nSize << ") 0x ";
#ifdef __32BITS__ for (int i = m_nArrayLen - 1; i >= 0; i--) {
sprintf(buff,"%08X ",m_p_nArray[i]); #ifdef _LP64
sprintf(buff,"0x %016llX ", (long long)m_p_nArray[i]);
#else #else
sprintf(buff,"0x %016llX ", (long long)m_p_nArray[i]); sprintf(buff,"%08X ", m_p_nArray[i]);
#endif // __32BITS__ #endif // __32BITS__
out << buff; out << buff;
} }
out << " ]"; out << " ]";
} }

View file

@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@ -27,178 +26,131 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* Set.hh
*
* Description:
*
* $Id: BigSet.hh 1.6 05/01/19 13:12:25-06:00 mikem@maya.cs.wisc.edu $
*
*/
// modified by Dan Gibson on 05/20/05 to accomidate FASTER // modified by Dan Gibson on 05/20/05 to accomidate FASTER
// >32 set lengths, using an array of ints w/ 32 bits/int // >32 set lengths, using an array of ints w/ 32 bits/int
// NOTE: Never include this file directly, this should only be #ifndef __MEM_RUBY_COMMON_SET_HH__
// included from Set.hh #define __MEM_RUBY_COMMON_SET_HH__
#ifndef SET_H
#define SET_H
#include <iostream> #include <iostream>
#include <limits>
#include "mem/ruby/system/System.hh" #include "mem/ruby/system/System.hh"
#include "mem/ruby/common/Global.hh" #include "mem/ruby/common/Global.hh"
#include "mem/gems_common/Vector.hh"
#include "mem/ruby/system/NodeID.hh" #include "mem/ruby/system/NodeID.hh"
// gibson 05/20/05 class Set
// enum PresenceBit {NotPresent, Present}; {
private:
int m_nSize; // the number of bits in this set
int m_nArrayLen; // the number of 32-bit words that are
// held in the array
class Set { // Changed 5/24/05 for static allocation of array
public: // note that "long" corresponds to 32 bits on a 32-bit machine,
// Constructors // 64 bits if the -m64 parameter is passed to g++, which it is
// creates and empty set // for an AMD opteron under our configuration
Set();
Set (int size);
// used during the replay mechanism long *m_p_nArray; // an word array to hold the bits in the set
// Set(const char *str); long m_p_nArray_Static[NUMBER_WORDS_PER_SET];
Set(const Set& obj); static const int LONG_BITS = std::numeric_limits<long>::digits;
Set& operator=(const Set& obj); static const int INDEX_SHIFT = LONG_BITS == 64 ? 6 : 5;
static const int INDEX_MASK = (1 << INDEX_SHIFT) - 1;
// Destructor void clearExcess();
~Set();
// Public Methods public:
Set();
Set(int size);
Set(const Set& obj);
~Set();
inline void add(NodeID index) Set& operator=(const Set& obj);
void
add(NodeID index)
{ {
#ifdef __32BITS__ m_p_nArray[index >> INDEX_SHIFT] |=
m_p_nArray[index>>5] |= (1 << (index & 0x01F)); (((unsigned long) 1) << (index & INDEX_MASK));
#else
m_p_nArray[index>>6] |= (((unsigned long) 1) << (index & 0x03F));
#endif // __32BITS__
} }
void addSet(const Set& set); void addSet(const Set& set);
void addRandom(); void addRandom();
inline void remove(NodeID index) void
remove(NodeID index)
{ {
#ifdef __32BITS__ m_p_nArray[index >> INDEX_SHIFT] &=
m_p_nArray[index>>5] &= ~(0x00000001 << (index & 0x01F)); ~(((unsigned long)1) << (index & INDEX_MASK));
#else
m_p_nArray[index>>6] &= ~(((unsigned long) 0x0000000000000001) << (index & 0x03F));
#endif // __32BITS__
} }
void removeSet(const Set& set);
void removeSet(const Set& set); void
clear()
inline void clear() { for(int i=0; i<m_nArrayLen; i++) m_p_nArray[i] = 0; }
void broadcast();
int count() const;
bool isEqual(const Set& set) const;
Set OR(const Set& orSet) const; // return the logical OR of this set and orSet
Set AND(const Set& andSet) const; // return the logical AND of this set and andSet
// Returns true if the intersection of the two sets is non-empty
inline bool intersectionIsNotEmpty(const Set& other_set) const
{ {
for(int i=0; i< m_nArrayLen; i++) { for (int i = 0; i < m_nArrayLen; i++)
if(m_p_nArray[i] & other_set.m_p_nArray[i]) { m_p_nArray[i] = 0;
return true;
}
}
return false;
} }
// Returns true if the intersection of the two sets is empty void broadcast();
inline bool intersectionIsEmpty(const Set& other_set) const int count() const;
bool isEqual(const Set& set) const;
// return the logical OR of this set and orSet
Set OR(const Set& orSet) const;
// return the logical AND of this set and andSet
Set AND(const Set& andSet) const;
// Returns true if the intersection of the two sets is empty
bool
intersectionIsEmpty(const Set& other_set) const
{ {
for(int i=0; i< m_nArrayLen; i++) { for (int i = 0; i < m_nArrayLen; i++)
if(m_p_nArray[i] & other_set.m_p_nArray[i]) { if (m_p_nArray[i] & other_set.m_p_nArray[i])
return false; return false;
} return true;
}
return true;
} }
bool isSuperset(const Set& test) const; bool isSuperset(const Set& test) const;
bool isSubset(const Set& test) const { return test.isSuperset(*this); } bool isSubset(const Set& test) const { return test.isSuperset(*this); }
inline bool isElement(NodeID element) const bool
isElement(NodeID element) const
{ {
#ifdef __32BITS__ return (m_p_nArray[element>>INDEX_SHIFT] &
return ((m_p_nArray[element>>5] & (0x00000001 << (element & 0x01F)))!=0); (((unsigned long)1) << (element & INDEX_MASK))) != 0;
#else
return ((m_p_nArray[element>>6] & (((unsigned long) 0x0000000000000001) << (element & 0x03F)))!=0);
#endif // __32BITS__
} }
bool isBroadcast() const; bool isBroadcast() const;
bool isEmpty() const; bool isEmpty() const;
NodeID smallestElement() const; NodeID smallestElement() const;
// int size() const; void setSize(int size);
void setSize (int size);
// get element for a index NodeID
inline NodeID elementAt(int index) const elementAt(int index) const
{ {
if(isElement(index)) return (NodeID) true; if (isElement(index))
else return 0; return (NodeID)true;
else
return 0;
} }
// gibson 05/20/05 int getSize() const { return m_nSize; }
int getSize() const { return m_nSize; }
// DEPRECATED METHODS void print(std::ostream& out) const;
void addToSet(NodeID newElement) { add(newElement); } // Deprecated
void removeFromSet(NodeID newElement) { remove(newElement); } // Deprecated
void clearSet() { clear(); } // Deprecated
void setBroadcast() { broadcast(); } // Deprecated
bool presentInSet(NodeID element) const { return isElement(element); } // Deprecated
void print(std::ostream& out) const;
private:
// Private Methods
// Data Members (m_ prefix)
// gibson 05/20/05
// Vector<uint8> m_bits; // This is an vector of uint8 to reduce the size of the set
int m_nSize; // the number of bits in this set
int m_nArrayLen; // the number of 32-bit words that are held in the array
// Changed 5/24/05 for static allocation of array
// note that "long" corresponds to 32 bits on a 32-bit machine,
// 64 bits if the -m64 parameter is passed to g++, which it is
// for an AMD opteron under our configuration
long * m_p_nArray; // an word array to hold the bits in the set
long m_p_nArray_Static[NUMBER_WORDS_PER_SET];
}; };
// Output operator declaration inline std::ostream&
std::ostream& operator<<(std::ostream& out, const Set& obj); operator<<(std::ostream& out, const Set& obj)
// ******************* Definitions *******************
// Output operator definition
extern inline
std::ostream& operator<<(std::ostream& out, const Set& obj)
{ {
obj.print(out); obj.print(out);
out << std::flush; out << std::flush;
return out; return out;
} }
#endif //SET_H #endif // __MEM_RUBY_COMMON_SET_HH__