📄 bitset.cc
字号:
/* 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 freesoftware; you can redistribute it and/or modify it under the terms ofthe GNU Library General Public License as published by the FreeSoftware Foundation; either version 2 of the License, or (at youroption) any later version. This library is distributed in the hopethat it will be useful, but WITHOUT ANY WARRANTY; without even theimplied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULARPURPOSE. See the GNU Library General Public License for more details.You should have received a copy of the GNU Library General PublicLicense along with this library; if not, write to the Free SoftwareFoundation, 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 & constantsBitSetRep _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 leftstatic inline unsigned short lmask(int p){ return ONES << p;}// mask out high bitsstatic 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; rep->len = newlen; return rep;}// same, for straight copyBitSetRep* 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 bitsinline 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->s; av = yv; topa = &(as[yl]); bs = (xrsame)? r->s : x->s; bv = xv; topb = &(bs[xl]); if (op == '-') // reverse sense of difference op = 'D'; } switch (op) { case '&': r->virt = av & bv; while (as < topa) *rs++ = *as++ & *bs++; if (av) while (rs < topr) *rs++ = *bs++; else while (rs < topr) *rs++ = 0; break; case '|': r->virt = av | bv; while (as < topa) *rs++ = *as++ | *bs++; if (av) while (rs < topr) *rs++ = ONES; else while (rs < topr) *rs++ = *bs++; break; case '^': r->virt = av ^ bv; while (as < topa) *rs++ = *as++ ^ *bs++; if (av) while (rs < topr) *rs++ = ~(*bs++); else while (rs < topr) *rs++ = *bs++; break; case '-': r->virt = av & ~(bv); while (as < topa) *rs++ = *as++ & ~(*bs++); if (av) while (rs < topr) *rs++ = ~(*bs++); else while (rs < topr) *rs++ = 0; break; case 'D': r->virt = ~(av) & (bv); while (as < topa) *rs++ = ~(*as++) & (*bs++); if (av) while (rs < topr) *rs++ = 0; else while (rs < topr) *rs++ = *bs++; break; } trim(r); return r;}void BitSet::set(int p){ if (p < 0) error("Illegal bit index"); int index = BitSet_index(p); int pos = BitSet_pos(p); if (index >= rep->len) { if (rep->virt) return; else rep = BitSetresize(rep, index+1); } rep->s[index] |= (1 << pos);}void BitSet::clear(){ if (rep->len > 0) memset(rep->s, 0, rep->sz * sizeof(short)); rep->len = rep->virt = 0;}void BitSet::clear(int p){ if (p < 0) error("Illegal bit index"); int index = BitSet_index(p); if (index >= rep->len) { if (rep->virt == 0) return; else rep = BitSetresize(rep, index+1); } rep->s[index] &= ~(1 << BitSet_pos(p));}void BitSet::invert(int p){ if (p < 0) error("Illegal bit index"); int index = BitSet_index(p); if (index >= rep->len) rep = BitSetresize(rep, index+1); rep->s[index] ^= (1 << BitSet_pos(p));}void BitSet::set(int from, int to){ if (from < 0 || from > to) error("Illegal bit index"); int index1 = BitSet_index(from); int pos1 = BitSet_pos(from); if (rep->virt && index1 >= rep->len) return; int index2 = BitSet_index(to); int pos2 = BitSet_pos(to); if (index2 >= rep->len) rep = BitSetresize(rep, index2+1); unsigned short* s = &(rep->s[index1]); unsigned short m1 = lmask(pos1); unsigned short m2 = rmask(pos2); if (index2 == index1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -