home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume19
/
wacco
/
part01
/
bitset.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-05-19
|
6KB
|
328 lines
// Copyright (c) 1991 by Parag Patel. All Rights Reserved.
// $Header: bitset.C,v 1.3 91/02/22 16:05:27 hmgr Exp $
// A set of ints (or an array of bits) is implemented by matching
// each element in the set with its corresponding bit position in
// a word of infinite size. The word is implemented as an array
// of "long" that is grown in size as necessary. Thus this set of
// ints is not limited in size, like most Pascal implementations.
//
// By Parag Patel
#include <stdio.h>
#include <stdarg.h>
#include "boolean.h"
#include "bitset.h"
// the following are machine-dependant - change them if necessary
// sizeof long == 32 bits == 2**5 --> 5, therefore ...
const int NUM = 32;
const int SHIFT = 5;
const int MASK = 0x1F;
const long EMPTY = 0;
// generic minimum function
static inline int MIN(int i1, int i2)
{
return i1 < i2 ? i1 : i2;
}
// this determines which particular "long" in the array has this element
static inline int ELT(int e)
{
return e >> SHIFT;
}
// this gets the bit position in a "long" for this set element
static inline long BIT(int e)
{
return ((long)(1L << (e & MASK)));
}
// this adds an element to an array of longs
static inline void ADD(long *elts, int e)
{
elts[ELT(e)] |= BIT(e);
}
// return a new set of elts - clear it
static long *newelts(int largest)
{
register long *elts = new long[ELT(largest) + 1];
for (register int i = ELT(largest); i >= 0; i--)
elts[i] = EMPTY;
return elts;
}
// bump the size of a set
void Bitset::bumpsize(int largest)
{
if (largest <= num)
return;
// only re-allocate our array if we are out of ELTs
if (ELT(largest) != ELT(num))
{
register long *ne = newelts(largest);
for (register int i = ELT(num); i >= 0; i--)
ne[i] = elts[i];
delete elts;
elts = ne;
}
num = largest;
}
// various constructors:
// construct a set from a list of elements
Bitset::Bitset(int e1, int e2 ...)
{
// if the first element is < 0, we ignore the rest
if (e1 < 0)
{
elts = new long;
num = 0;
elts[0] = 0L;
return;
}
// the largest element in our list for determining the initial
// Bitset size
register int largest = e1 > e2 ? e1 : e2;
va_list ap;
register int t;
// if we have more than 3 elements, we need to use varargs
if (e2 >= 0)
{
// find the largest element to be put in the set
va_start(ap, e2);
while ((t = va_arg(ap, int)) >= 0)
if (t > largest)
largest = t;
va_end(ap);
}
// allocate the space for this set
elts = newelts(num = largest);
// add all the elements to the set
ADD(elts, e1);
if (e2 >= 0)
{
ADD(elts, e2);
va_start(ap, e2);
while ((t = va_arg(ap, int)) >= 0)
ADD(elts, t);
va_end(ap);
}
}
// make a new set of the specified size
Bitset::Bitset(int size)
{
if (size <= 1)
size = 1;
elts = newelts(num = size - 1);
}
// dup a set
Bitset::Bitset(const Bitset &s)
{
elts = newelts(num = s.num);
for (register int i = ELT(s.num); i >= 0; i--)
elts[i] = s.elts[i];
}
// assign a set to a set - also a dup
Bitset &Bitset::operator=(const Bitset &s)
{
register int i, t;
BUMPSIZE(s.num);
for (i = t = ELT(s.num); i >= 0; i--)
elts[i] = s.elts[i];
for (i = ELT(num); i > t; i--)
elts[i] = EMPTY;
return *this;
}
// add an element to a set
Bitset &Bitset::add(int elt)
{
if (elt < 0)
return *this;
BUMPSIZE(elt);
elts[ELT(elt)] |= BIT(elt);
return *this;
}
// delete an element from a set
Bitset &Bitset::remove(int elt)
{
if (elt < 0)
return *this;
elts[ELT(elt)] &= ~BIT(elt);
return *this;
}
// union with set
Bitset &Bitset::operator|=(const Bitset &s)
{
BUMPSIZE(s.num);
for (register int i = ELT(s.num); i >= 0; i--)
elts[i] |= s.elts[i];
return *this;
}
// intersect with set
Bitset &Bitset::operator&=(const Bitset &s)
{
register int t = ELT(s.num);
BUMPSIZE(s.num);
for (register int i = ELT(num); i >= 0; i--)
elts[i] &= i <= t ? s.elts[i] : EMPTY;
return *this;
}
// difference from set
Bitset &Bitset::operator-=(const Bitset &s)
{
for (register int i = MIN(ELT(num), ELT(s.num)); i >= 0; i--)
elts[i] &= ~s.elts[i];
return *this;
}
// symmetric difference (xor) from set
Bitset &Bitset::operator^=(const Bitset &s)
{
BUMPSIZE(s.num);
for (register int i = ELT(s.num); i >= 0; i--)
elts[i] ^= s.elts[i];
return *this;
}
// complement set
Bitset &Bitset::operator~()
{
register int i = ELT(num);
elts[i] = ((BIT(num) << 1) - 1) & ~elts[i];
for (i--; i >= 0; i--)
elts[i] = ~elts[i];
return *this;
}
// is set a subset of s?
boolean Bitset::operator<=(const Bitset &s) const
{
register int i = MIN(num, s.num);
for (i = ELT(i); i >= 0; i--)
if ((elts[i] & s.elts[i]) != elts[i])
return FALSE;
if (num <= s.num)
return TRUE;
register int t = ELT(s.num);
for (i = ELT(num); i > t; i--)
if (elts[i])
return FALSE;
return TRUE;
}
// is set same as s?
boolean Bitset::operator==(const Bitset &s) const
{
register int i = MIN(num, s.num);
for (i = ELT(i); i >= 0; i--)
if (elts[i] != s.elts[i])
return FALSE;
if (num == s.num)
return TRUE;
register int t;
if (num < s.num)
{
for (t = ELT(num), i = ELT(s.num); i > t; i--)
if (s.elts[i])
return FALSE;
}
else
{
for (t = ELT(s.num), i = ELT(num); i > t; i--)
if (elts[i])
return FALSE;
}
return TRUE;
}
// return the number of elements in the set (cardinality)
int Bitset::size() const
{
register int n = 0;
for (register int i = ELT(num); i >= 0; i--)
for (register long m = 1; m; m <<= 1)
if (elts[i] & m)
n++;
return n;
}
// clear the set of all elements
void Bitset::clear()
{
for (register int i = ELT(num); i >= 0; i--)
elts[i] = EMPTY;
}
// return a hash number for this set
unsigned long Bitset::hash() const
{
register int i = ELT(num);
// skip over null elements in array to make
// hash value independent of size
while (i >= 0 && elts[i] == 0)
i--;
// now we can hash safely...
register unsigned long h = 0;
for (; i >= 0; i--)
{
// "+" moves around the bits a lot better than "^"
h += elts[i];
// rotate "h" left by 3 bits, just to mix things up
h = (h << 3) | (h >> (NUM - 3));
}
return h;
}
// set iterator class:
// creator
Bitsetiter::Bitsetiter(const Bitset &s)
{
int i, e;
int num = 0;
arr = new int[len = s.size()];
int t = ELT(s.num);
for (e = 0, i = 0; i <= t; i++)
for (long m = 1; m; e++, m <<= 1)
if (s.elts[i] & m)
arr[num++] = e;
elt = 0;
}