home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 7
/
FreshFishVol7.bin
/
bbs
/
gnu
/
libg++-2.6-fsf.lha
/
libg++-2.6
/
libg++
/
src
/
BitSet.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1994-05-11
|
20KB
|
1,007 lines
/*
Copyright (C) 1988 Free Software Foundation
written by Doug Lea (dl@rocky.oswego.edu)
This file is part of the GNU C++ Library. This library is free
software; you can redistribute it and/or modify it under the terms of
the GNU Library General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version. This library is distributed in the hope
that it will be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
BitSet class implementation
*/
#ifdef __GNUG__
#pragma implementation
#endif
#include <BitSet.h>
#include <std.h>
#include <limits.h>
#include <Obstack.h>
#include <AllocRing.h>
#include <new.h>
#include <builtin.h>
#include <string.h>
#include <strstream.h>
void BitSet::error(const char* msg) const
{
(*lib_error_handler)("BitSet", msg);
}
// globals & constants
BitSetRep _nilBitSetRep = { 0, 1, 0, {0} }; // nil BitSets point here
#define ONES ((unsigned short)(~0L))
#define MAXBitSetRep_SIZE ((1 << (sizeof(short)*CHAR_BIT - 1)) - 1)
#define MINBitSetRep_SIZE 16
#ifndef MALLOC_MIN_OVERHEAD
#define MALLOC_MIN_OVERHEAD 4
#endif
// break things up into .s indices and positions
// mask out bits from left
static inline unsigned short lmask(int p)
{
return ONES << p;
}
// mask out high bits
static inline unsigned short rmask(int p)
{
return ONES >> (BITSETBITS - 1 - p);
}
inline static BitSetRep* BSnew(int newlen)
{
unsigned int siz = sizeof(BitSetRep) + newlen * sizeof(short)
+ MALLOC_MIN_OVERHEAD;
unsigned int allocsiz = MINBitSetRep_SIZE;;
while (allocsiz < siz) allocsiz <<= 1;
allocsiz -= MALLOC_MIN_OVERHEAD;
if (allocsiz >= MAXBitSetRep_SIZE * sizeof(short))
(*lib_error_handler)("BitSet", "Requested length out of range");
BitSetRep* rep = (BitSetRep *) new char[allocsiz];
memset(rep, 0, allocsiz);
rep->sz = (allocsiz - sizeof(BitSetRep) + sizeof(short)) / sizeof(short);
return rep;
}
BitSetRep* BitSetalloc(BitSetRep* old, const unsigned short* src, int srclen,
int newvirt, int newlen)
{
if (old == &_nilBitSetRep) old = 0;
BitSetRep* rep;
if (old == 0 || newlen >= old->sz)
rep = BSnew(newlen);
else
rep = old;
rep->len = newlen;
rep->virt = newvirt;
if (srclen != 0 && src != rep->s)
memcpy(rep->s, src, srclen * sizeof(short));
// BUG fix: extend virtual bit! 20 Oct 1992 Kevin Karplus
if (rep->virt)
memset(&rep->s[srclen], ONES, (newlen - srclen) * sizeof(short));
if (old != rep && old != 0) delete old;
return rep;
}
BitSetRep* BitSetresize(BitSetRep* old, int newlen)
{
BitSetRep* rep;
if (old == 0 || old == &_nilBitSetRep)
{
rep = BSnew(newlen);
rep->virt = 0;
}
else if (newlen >= old->sz)
{
rep = BSnew(newlen);
memcpy(rep->s, old->s, old->len * sizeof(short));
rep->virt = old->virt;
// BUG fix: extend virtual bit! 20 Oct 1992 Kevin Karplus
if (rep->virt)
memset(&rep->s[old->len], ONES, (newlen - old->len) * sizeof(short));
delete old;
}
else
{
rep = old;
if (rep->len < newlen)
memset(&rep->s[rep->len],
rep->virt ? ONES : 0,
(newlen - rep->len) * sizeof(short));
}
rep->len = newlen;
return rep;
}
// same, for straight copy
BitSetRep* BitSetcopy(BitSetRep* old, const BitSetRep* src)
{
BitSetRep* rep;
if (old == &_nilBitSetRep) old = 0;
if (src == 0 || src == &_nilBitSetRep)
{
if (old == 0)
rep = BSnew(0);
else
rep = old;
rep->len = 0;
rep->virt = 0;
}
else if (old == src)
return old;
else
{
int newlen = src->len;
if (old == 0 || newlen > old->sz)
{
rep = BSnew(newlen);
if (old != 0) delete old;
}
else
rep = old;
memcpy(rep->s, src->s, newlen * sizeof(short));
rep->len = newlen;
rep->virt = src->virt;
}
return rep;
}
// remove unneeded top bits
inline static void trim(BitSetRep* rep)
{
int l = rep->len;
unsigned short* s = &(rep->s[l - 1]);
if (rep->virt == 0)
while (l > 0 && *s-- == 0) --l;
else
while (l > 0 && *s-- == ONES) --l;
rep->len = l;
}
int operator == (const BitSet& x, const BitSet& y)
{
if (x.rep->virt != y.rep->virt)
return 0;
int xl = x.rep->len;
int yl = y.rep->len;
unsigned short* xs = x.rep->s;
unsigned short* ys = y.rep->s;
if (xl<=yl)
{
if (memcmp((void*)xs, (void*)ys, xl * sizeof(short)))
return 0;
for (register int i=xl; i<yl; i++)
if (ys[i])
return 0;
return 1;
}
else
{
if (memcmp((void*)xs, (void*)ys, yl * sizeof(short)))
return 0;
for (register int i=yl; i<xl; i++)
if (xs[i])
return 0;
return 1;
}
}
int operator <= (const BitSet& x, const BitSet& y)
{
if (x.rep->virt > y.rep->virt)
return 0;
int xl = x.rep->len;
int yl = y.rep->len;
unsigned short* xs = x.rep->s;
unsigned short* ys = y.rep->s;
unsigned short* topx = &(xs[xl]);
unsigned short* topy = &(ys[yl]);
while (xs < topx && ys < topy)
{
unsigned short a = *xs++;
unsigned short b = *ys++;
if ((a | b) != b)
return 0;
}
if (xl == yl)
return x.rep->virt <= y.rep->virt;
else if (xl < yl)
return !x.rep->virt;
else
return y.rep->virt;
}
int operator < (const BitSet& x, const BitSet& y)
{
if (x.rep->virt > y.rep->virt)
return 0;
int xl = x.rep->len;
int yl = y.rep->len;
unsigned short* xs = x.rep->s;
unsigned short* ys = y.rep->s;
unsigned short* topx = &(xs[xl]);
unsigned short* topy = &(ys[yl]);
int one_diff = 0;
while (xs < topx && ys < topy)
{
unsigned short a = *xs++;
unsigned short b = *ys++;
unsigned short c = a | b;
if (c != b)
return 0;
else if (c != a)
one_diff = 1;
}
if (xl == yl)
return x.rep->virt < y.rep->virt ||
(one_diff && x.rep->virt == y.rep->virt);
else if (xl < yl)
return !x.rep->virt;
else
return y.rep->virt;
}
int BitSet::empty() const
{
if (rep->virt == 1)
return 0;
unsigned short* bots = rep->s;
unsigned short* s = &(bots[rep->len - 1]);
while (s >= bots) if (*s-- != 0) return 0;
return 1;
}
int BitSet::count(int b) const
{
if (b == rep->virt)
return -1;
int l = 0;
unsigned short* s = rep->s;
unsigned short* tops = &(s[rep->len]);
if (b == 1)
{
while (s < tops)
{
unsigned short a = *s++;
for (int i = 0; i < BITSETBITS && a != 0; ++i)
{
if (a & 1)
++l;
a >>= 1;
}
}
}
else
{
unsigned short maxbit = 1 << (BITSETBITS - 1);
while (s < tops)
{
unsigned short a = *s++;
for (int i = 0; i < BITSETBITS; ++i)
{
if ((a & maxbit) == 0)
++l;
a <<= 1;
}
}
}
return l;
}
BitSetRep* BitSetcmpl(const BitSetRep* src, BitSetRep* r)
{
r = BitSetcopy(r, src);
r->virt = !src->virt;
unsigned short* rs = r->s;
unsigned short* topr = &(rs[r->len]);
if (r->len == 0)
*rs = ONES;
else
{
while (rs < topr)
{
unsigned short cmp = ~(*rs);
*rs++ = cmp;
}
}
trim(r);
return r;
}
BitSetRep* BitSetop(const BitSetRep* x, const BitSetRep* y,
BitSetRep* r, char op)
{
int xrsame = x == r;
int yrsame = y == r;
int xv = x->virt;
int yv = y->virt;
int xl = x->len;
int yl = y->len;
int rl = (xl >= yl)? xl : yl;
r = BitSetresize(r, rl);
unsigned short* rs = r->s;
unsigned short* topr = &(rs[rl]);
int av, bv;
const unsigned short* as;
const unsigned short* topa;
const unsigned short* bs;
const unsigned short* topb;
if (xl <= yl)
{
as = (xrsame)? r->s : x->s;
av = xv;
topa = &(as[xl]);
bs = (yrsame)? r->s : y->s;
bv = yv;
topb = &(bs[yl]);
}
else
{
as = (yrsame)? r->s : y->