home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright (C) 1988 Free Software Foundation
- written by Doug Lea (dl@rocky.oswego.edu)
-
- This file is part of GNU CC.
-
- GNU CC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY. No author or distributor
- accepts responsibility to anyone for the consequences of using it
- or for whether it serves any particular purpose or works at all,
- unless he says so in writing. Refer to the GNU CC General Public
- License for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- GNU CC, but only under the conditions described in the
- GNU CC General Public License. A copy of this license is
- supposed to have been given to you along with GNU CC so you
- can know your rights and responsibilities. It should be in a
- file named COPYING. Among other things, the copyright notice
- and this notice must be preserved on all copies.
- */
-
- /*
- BitString class implementation
- */
-
- #include <BitString.h>
- #include <std.h>
- #include "libconfig.h"
- #include <Obstack.h>
-
- // error handling
-
-
- void default_BitString_error_handler(char* msg)
- {
- cerr << "Fatal BitString error. " << msg << "\n";
- exit(1);
- }
-
- one_arg_error_handler_t BitString_error_handler = default_BitString_error_handler;
-
- one_arg_error_handler_t set_BitString_error_handler(one_arg_error_handler_t f)
- {
- one_arg_error_handler_t old = BitString_error_handler;
- BitString_error_handler = f;
- return old;
- }
-
- void BitString::error(char* msg)
- {
- (*BitString_error_handler)(msg);
- }
-
- // globals
-
- _BitStringrep _nil_BitStringrep = { 0, 1, -1, {0} };
-
- static BitString _nil_BitString;
-
-
- #define MIN_BITSTRING_SIZE 2
- #define MAX_BITSTRING_SIZE (1 << (SHORTBITS - 1) - 1)
-
- //static unsigned long ones = ~(0L); // g++/vax bug workaround
- #define ONES ((unsigned long)(~0L))
- #define MAXBIT (1 << (B_SHIFT - 1))
-
- /*
- * bit manipulation utilities
- */
-
- // break things up into .s indices and positions
-
- inline static int word_length(int l)
- {
- return (unsigned)(l) / B_SHIFT + 1;
- }
-
- inline static int word_index(int l)
- {
- return (unsigned)(l) / B_SHIFT;
- }
-
- inline static int bit_position(int l)
- {
- return l & (B_SHIFT - 1);
- }
-
- // mask out low bits
-
- static inline unsigned long lmask(int p)
- {
- if (p <= 0)
- return ONES;
- else
- return ONES << p;
- }
-
- // mask out high bits
-
- static inline unsigned long rmask(int p)
- {
- int s = B_SHIFT - 1 - p;
- if (s <= 0)
- return ONES;
- else
- return ONES >> s;
- }
-
-
- // mask out unused bits in last word of rep
-
- inline static void check_last(_BitStringrep* r)
- {
- r->s[r->len / B_SHIFT] &= ONES >> (B_SHIFT - (r->len & (B_SHIFT - 1)));
- }
-
- // merge bits from next word
-
- static inline unsigned long borrow_hi(unsigned long a[], int ind,
- int maxind, int p)
- {
- if (ind < maxind)
- return (a[ind] >> p) | (a[ind+1] << (B_SHIFT - p));
- else
- return (a[ind] >> p);
- }
-
- // merge bits from prev word
-
- static inline unsigned long borrow_lo(unsigned long a[], int ind,
- int minind, int p)
- {
- if (ind > minind)
- return (a[ind] << (B_SHIFT - 1 - p)) | (a[ind-1] >> (p + 1));
- else
- return (a[ind] << (B_SHIFT - 1 - p));
- }
-
- // same with bounds check (for masks shorter than patterns)
-
- static inline unsigned long safe_borrow_hi(unsigned long a[], int ind,
- int maxind, int p)
- {
- if (ind > maxind)
- return 0;
- else if (ind == maxind)
- return(a[ind] >> p);
- else
- return (a[ind] >> p) | (a[ind+1] << (B_SHIFT - p));
- }
-
-
- static inline unsigned long safe_borrow_lo(unsigned long a[], int ind,
- int minind, int p)
- {
- if (ind < minind)
- return 0;
- else if (ind == minind)
- return (a[ind] << (B_SHIFT - 1 - p));
- else
- return (a[ind] << (B_SHIFT - 1 - p)) | (a[ind-1] >> (p + 1));
- }
-
- // copy bits from a word boundary
-
- static inline void bit_copy(unsigned long* ss, unsigned long* ds, int nbits)
- {
- if (ss != ds)
- {
- int n = (unsigned)(nbits) / B_SHIFT;
- if (n > 0) bcopy((void*)ss, (void*)ds, n * sizeof(long));
- unsigned long m = ONES << (nbits & (B_SHIFT - 1));
- ds[n] = (ss[n] & ~m) | (ds[n] & m);
- }
- }
-
- // clear bits from a word boundary
-
- static inline void bit_clear(unsigned long* ds, int nbits)
- {
- int n = (unsigned)(nbits) / B_SHIFT;
- if (n > 0) bzero((void*)ds, n * sizeof(long));
- ds[n] &= ONES << (nbits & (B_SHIFT - 1));
- }
-
-
- // allocate a new rep
-
- static _BitStringrep* new_BitStringrep(unsigned long l)
- {
- int siz = word_length(l);
- if (siz < MIN_BITSTRING_SIZE)
- siz = MIN_BITSTRING_SIZE;
- else if (siz >= MAX_BITSTRING_SIZE)
- (*BitString_error_handler)("Requested length out of range");
-
- unsigned allocsiz = sizeof(_BitStringrep) + (siz - 1) * sizeof(long);
-
- _BitStringrep* z = (_BitStringrep *) (malloc(allocsiz));
- if (z == 0)
- (*BitString_error_handler)("Out of memory.");
-
- z->len = l;
- z->sz = siz;
- z->ref = 1;
- return z;
- }
-
- // expand a rep via realloc
-
- static _BitStringrep* expand_BitStringrep(_BitStringrep* p, unsigned long l)
- {
- int siz = word_length(l);
- if (siz < MIN_BITSTRING_SIZE)
- siz = MIN_BITSTRING_SIZE;
- else if (siz >= MAX_BITSTRING_SIZE)
- (*BitString_error_handler)("Requested length out of range");
-
- unsigned allocsiz = sizeof(_BitStringrep) + (siz - 1) * sizeof(long);
-
- #ifdef SHOULD_FREE_TO_REALLOC
- free((void*)p);
- #endif
-
- _BitStringrep* z = (_BitStringrep *) (realloc((void*)p, allocsiz));
- if (z == 0)
- (*BitString_error_handler)("Out of memory.");
- z->len = l;
- z->sz = siz;
- z->ref = 1;
- return z;
- }
-
-
- // copy ss from starts to lengths-1 into ds starting at startd
- // this will work even if ss & ds are the same
- // The g++ optimizer does very good things with the messy shift expressions!
-
- static void bit_transfer(unsigned long* ss, int starts, int lengths,
- unsigned long* ds, int startd)
- {
- int ends = lengths - 1;
- if (starts > ends)
- return;
-
- int sind = word_index(starts);
- int spos = bit_position(starts);
- int dind = word_index(startd);
- int dpos = bit_position(startd);
-
- if (spos == 0 && dpos == 0)
- {
- bit_copy(&ss[sind], &ds[dind], ends - starts + 1);
- return;
- }
-
- int endsind = word_index(ends);
- int endspos = bit_position(ends);
- int endd = startd + (ends - starts);
- int enddind = word_index(endd);
- int enddpos = bit_position(endd);
-
- if (dind == enddind)
- {
- if (sind == endsind)
- ds[dind] = (ds[dind] & ((ONES >> (B_SHIFT - dpos)) |
- (ONES << (enddpos + 1)))) |
- (((ss[sind] >> spos) << dpos) &
- ~((ONES >> (B_SHIFT - dpos)) | (ONES << (enddpos + 1))));
- else
- ds[dind] = (ds[dind] & ((ONES >> (B_SHIFT - dpos)) |
- (ONES << (enddpos + 1)))) |
- ((((ss[sind] >> spos) | (ss[sind+1] << (B_SHIFT - spos))) << dpos) &
- ~((ONES >> (B_SHIFT - dpos)) | (ONES << (enddpos + 1))));
- return;
- }
- else if (sind == endsind)
- {
- unsigned long saveend = (ds[enddind] & (ONES << (enddpos + 1))) |
- (((ss[sind] << (B_SHIFT - 1 - endspos)) >>
- (B_SHIFT - 1 - enddpos)) & ~(ONES << (enddpos + 1)));
- ds[dind] = (ds[dind] & (ONES >> (B_SHIFT - dpos))) |
- (((ss[sind] >> spos) << dpos) & ~(ONES >> (B_SHIFT - dpos)));
- ds[enddind] = saveend;
- return;
- }
-
- unsigned long saveend = (ds[enddind] & (ONES << (enddpos + 1))) |
- ((((ss[endsind] << (B_SHIFT - 1 - endspos)) |
- (ss[endsind-1] >> (endspos + 1))) >>
- (B_SHIFT - 1 - enddpos)) & ~(ONES << (enddpos + 1)));
- unsigned long savestart = (ds[dind] & (ONES >> (B_SHIFT - dpos))) |
- ((((ss[sind] >> spos) | (ss[sind+1] << (B_SHIFT - spos))) << dpos)
- & ~(ONES >> (B_SHIFT - dpos)));
-
-
- if (ds != ss || startd < starts)
- {
- int pos = spos - dpos;
- if (pos < 0)
- pos += B_SHIFT;
- else
- ++sind;
-
- for (;;) // lag by one in case of overlaps
- {
- if (dind == enddind - 1)
- {
- ds[dind] = savestart;
- ds[enddind] = saveend;
- return;
- }
- else
- {
- unsigned long tmp = borrow_hi(ss, sind++, endsind, pos);
- ds[dind++] = savestart;
- savestart = tmp;
- }
- }
- }
- else
- {
- int pos = endspos - enddpos;
- if (pos <= 0)
- {
- pos += B_SHIFT - 1;
- --endsind;
- }
- for (;;)
- {
- if (enddind == dind + 1)
- {
- ds[enddind] = saveend;
- ds[dind] = savestart;
- return;
- }
- else
- {
- unsigned long tmp = borrow_lo(ss, endsind--, sind, pos);
- ds[enddind--] = saveend;
- saveend = tmp;
- }
- }
- }
- }
-
-
- // set up or expand a rep
-
- void BitString::setlength(int newlen, int prefill = 0)
- {
- check_last(rep);
- unsigned long oldlen = rep->len;
-
- if (rep->ref != 1)
- {
- if (rep->ref > 0) rep->ref--;
- _BitStringrep* newrep = new_BitStringrep(newlen);
- bit_copy(rep->s, newrep->s, oldlen);
- rep = newrep;
- }
- else if (newlen >= rep->sz * B_SHIFT)
- rep = expand_BitStringrep(rep, newlen);
- else
- rep->len = newlen;
-
- if (prefill && newlen > oldlen)
- {
- int ol = word_length(oldlen);
- int nl = word_length(newlen);
- bzero((void*)&(rep->s[ol]), (nl - ol) * sizeof(long));
- check_last(rep);
- }
- }
-
-
- // copy one rep to another; expand & dereference as necessary
-
- void BitString::copy(unsigned long* news, int startpos, int endp)
- {
- int newlen = endp - startpos;
- if (newlen <= 0)
- {
- if (rep->ref > 0 && --rep->ref == 0)
- delete rep;
- rep = &_nil_BitStringrep;
- return;
- }
-
- if (rep->ref != 1)
- {
- if (rep->ref > 0) rep->ref--;
- rep = new_BitStringrep(newlen);
- }
- else if (newlen >= rep->sz * B_SHIFT)
- rep = expand_BitStringrep(rep, newlen);
-
- bit_transfer(news, startpos, endp, rep->s, 0);
- rep->len = newlen;
- check_last(rep);
- }
-
- int operator == (BitString& x, BitString& y)
- {
- return x.rep->len == y.rep->len &&
- bcmp((void*)x.rep->s, (void*)y.rep->s,
- word_length(x.rep->len) * sizeof(long)) == 0;
- }
-
- int operator <= (BitString& x, BitString& y)
- {
- unsigned long xl = x.rep->len;
- unsigned long yl = y.rep->len;
- if (xl > yl)
- return 0;
-
- unsigned long* xs = x.rep->s;
- unsigned long* ys = y.rep->s;
- unsigned long* topx = &(xs[word_length(xl)]);
-
- while (xs < topx)
- {
- unsigned long a = *xs++;
- unsigned long b = *ys++;
- if ((a | b) != b)
- return 0;
- }
- return 1;
- }
-
- int operator < (BitString& x, BitString& y)
- {
- unsigned long xl = x.rep->len;
- unsigned long yl = y.rep->len;
- if (xl >= yl)
- return 0;
-
- unsigned long* xs = x.rep->s;
- unsigned long* ys = y.rep->s;
- unsigned long* topx = &(xs[word_length(xl)]);
- unsigned long* topy = &(xs[word_length(yl)]);
- int one_diff = 0;
- while (xs < topx)
- {
- unsigned long a = *xs++;
- unsigned long b = *ys++;
- unsigned long c = a | b;
- if (c != b)
- return 0;
- else if (c != a)
- one_diff = 1;
- }
- if (one_diff)
- return 1;
- else
- {
- while (ys < topy)
- if (*ys++ != 0)
- return 1;
- return 0;
- }
- }
-
- int lcompare(BitString& x, BitString& y)
- {
- unsigned long xl = x.rep->len;
- unsigned long yl = y.rep->len;
-
- unsigned long* xs = x.rep->s;
- unsigned long* topx = &(xs[word_length(xl)]);
- unsigned long* ys = y.rep->s;
- unsigned long* topy = &(ys[word_length(yl)]);
-
- while (xs < topx && ys < topy)
- {
- unsigned long a = *xs++;
- unsigned long b = *ys++;
- if (a != b)
- {
- unsigned long mask = 1;
- for (;;)
- {
- unsigned long abit = (a & mask) != 0;
- unsigned long bbit = (b & mask) != 0;
- int diff = abit - bbit;
- if (diff != 0)
- return diff;
- else
- mask <<= 1;
- }
- }
- }
- return xl - yl;
- }
-
- int BitString::count(int b = 1)
- {
- check_last(rep);
- int xwds = word_length(rep->len);
- int xlast = bit_position(rep->len);
- int l = 0;
- unsigned long* s = rep->s;
- unsigned long* tops = &(s[xwds - 1]);
- unsigned long a;
- int i;
- if (b != 0)
- {
- while (s < tops)
- {
- a = *s++;
- for (i = 0; i < B_SHIFT && a != 0; ++i)
- {
- if (a & 1)
- ++l;
- a >>= 1;
- }
- }
- a = *s;
- for (i = 0; i < xlast && a != 0; ++i)
- {
- if (a & 1)
- ++l;
- a >>= 1;
- }
- }
- else
- {
- unsigned long maxbit = 1 << (B_SHIFT - 1);
- while (s < tops)
- {
- a = *s++;
- for (i = 0; i < B_SHIFT; ++i)
- {
- if ((a & maxbit) == 0)
- ++l;
- a <<= 1;
- }
- }
- maxbit = 1 << (xlast - 1);
- a = *s;
- for (i = 0; i < xlast; ++i)
- {
- if ((a & maxbit) == 0)
- ++l;
- a <<= 1;
- }
- }
- return l;
- }
-
-
- BitString BitString:: operator ~()
- {
- BitString r;
- r.setlength(rep->len);
- unsigned long* xs = rep->s;
- unsigned long* rs = r.rep->s;
- unsigned long* topr = &(rs[word_length(rep->len)]);
- while (rs < topr) *rs++ = ~(*xs++);
- check_last(r.rep);
- return r;
- }
-
-
- BitString& BitString::complement()
- {
- make_unique();
- unsigned long* rs = rep->s;
- unsigned long* topr = &(rs[word_length(rep->len)]);
- while (rs < topr)
- {
- unsigned long cmp = ~(*rs);
- *rs++ = cmp;
- }
- check_last(rep);
- return *this;
- }
-
- void and(BitString& x, BitString& y, BitString& r)
- {
- int xrsame = x.rep == r.rep;
- int yrsame = y.rep == r.rep;
-
- unsigned long rl = x.rep->len <? y.rep->len;
- r.setlength(rl);
-
- unsigned long* rs = r.rep->s;
- unsigned long* topr = &(rs[word_length(rl)]);
- unsigned long* xs = (xrsame)? rs : x.rep->s;
- unsigned long* ys = (yrsame)? rs : y.rep->s;
-
- while (rs < topr) *rs++ = *xs++ & *ys++;
- check_last(r.rep);
- }
-
- void or(BitString& x, BitString& y, BitString& r)
- {
- unsigned long xl = x.rep->len;
- unsigned long yl = y.rep->len;
- unsigned long rl = xl >? yl;
- int xrsame = x.rep == r.rep;
- int yrsame = y.rep == r.rep;
-
- r.setlength(rl);
-
- unsigned long* rs = r.rep->s;
- unsigned long* xs = (xrsame)? rs : x.rep->s;
- unsigned long* topx = &(xs[word_length(xl)]);
- unsigned long* ys = (yrsame)? rs : y.rep->s;
- unsigned long* topy = &(ys[word_length(yl)]);
-
- if (xl <= yl)
- {
- while (xs < topx) *rs++ = *xs++ | *ys++;
- if (rs != ys) while (ys < topy) *rs++ = *ys++;
- }
- else
- {
- while (ys < topy) *rs++ = *xs++ | *ys++;
- if (rs != xs) while (xs < topx) *rs++ = *xs++;
- }
- check_last(r.rep);
- }
-
-
- void xor(BitString& x, BitString& y, BitString& r)
- {
- unsigned long xl = x.rep->len;
- unsigned long yl = y.rep->len;
- unsigned long rl = xl >? yl;
- int xrsame = x.rep == r.rep;
- int yrsame = y.rep == r.rep;
-
- r.setlength(rl);
-
- unsigned long* rs = r.rep->s;
- unsigned long* xs = (xrsame)? rs : x.rep->s;
- unsigned long* topx = &(xs[word_length(xl)]);
- unsigned long* ys = (yrsame)? rs : y.rep->s;
- unsigned long* topy = &(ys[word_length(yl)]);
-
- if (xl <= yl)
- {
- while (xs < topx) *rs++ = *xs++ ^ *ys++;
- if (rs != ys) while (ys < topy) *rs++ = *ys++;
- }
- else
- {
- while (ys < topy) *rs++ = *xs++ ^ *ys++;
- if (rs != xs) while (xs < topx) *rs++ = *xs++;
- }
- check_last(r.rep);
- }
-
-
- void difference(BitString& x, BitString& y, BitString& r)
- {
- unsigned long xl = x.rep->len;
- unsigned long yl = y.rep->len;
- int xrsame = x.rep == y.rep;
- int yrsame = y.rep == r.rep;
-
- r.setlength(xl);
-
- unsigned long* rs = r.rep->s;
- unsigned long* xs = (xrsame)? rs : x.rep->s;
- unsigned long* topx = &(xs[word_length(xl)]);
- unsigned long* ys = (yrsame)? rs : y.rep->s;
- unsigned long* topy = &(ys[word_length(yl)]);
-
- if (xl <= yl)
- {
- while (xs < topx) *rs++ = *xs++ & ~(*ys++);
- }
- else
- {
- while (ys < topy) *rs++ = *xs++ & ~(*ys++);
- if (rs != xs) while (xs < topx) *rs++ = *xs++;
- }
- check_last(r.rep);
- }
-
-
- void concat(BitString& x, BitString& y, BitString& r)
- {
- unsigned long xl = x.rep->len;
- unsigned long yl = y.rep->len;
- unsigned long rl = xl + yl;
- int xrsame = x.rep == r.rep;
- int yrsame = y.rep == r.rep;
-
- if (yrsame)
- {
- BitString tmp = y;
- r.setlength(rl);
- bit_copy(x.rep->s, r.rep->s, xl);
- bit_transfer(tmp.rep->s, 0, yl, r.rep->s, xl);
- }
- else
- {
- r.setlength(rl);
- bit_copy(x.rep->s, r.rep->s, xl);
- bit_transfer(y.rep->s, 0, yl, r.rep->s, xl);
- }
- check_last(r.rep);
- }
-
- void rshift(BitString& x, int s, BitString& r)
- {
- if (s == 0)
- {
- r = x;
- return;
- }
-
- int xl = x.rep->len;
- int rl = xl + s;
- if (rl <= 0)
- {
- r.nullify();
- return;
- }
-
- int xrsame = x.rep == r.rep;
- r.setlength(rl);
- unsigned long* xs = (xrsame)? r.rep->s : x.rep->s;
-
- if (s < 0)
- bit_transfer(xs, -s, xl, r.rep->s, 0);
- else
- {
- bit_transfer(xs, 0, xl, r.rep->s, s);
- bit_clear(r.rep->s, s);
- }
- check_last(r.rep);
- }
-
-
- void BitString::set(int p)
- {
- if (p < 0)
- {
- error("Illegal bit index");
- return;
- }
-
- if (p >= rep->len)
- setlength(p + 1, 1);
- else
- make_unique();
-
- rep->s[word_index(p)] |= (1 << (bit_position(p)));
- }
-
- void BitString::clear(int p)
- {
- if (p < 0)
- {
- error("Illegal bit index");
- return;
- }
-
- if (p >= rep->len)
- setlength(p + 1, 1);
- else
- make_unique();
-
- rep->s[word_index(p)] &= ~(1 << (bit_position(p)));
- }
-
- void BitString::invert(int p)
- {
- if (p < 0)
- {
- error("Illegal bit index");
- return;
- }
-
- if (p >= rep->len)
- setlength(p + 1, 1);
- else
- make_unique();
-
- rep->s[word_index(p)] ^= (1 << (bit_position(p)));
- }
-
- int BitString::test(int p)
- {
- if (p < 0 || p >= rep->len)
- return 0;
- else
- return (rep->s[word_index(p)] & (1 << (bit_position(p)))) != 0;
- }
-
-
- void BitString::set(int from, int to)
- {
- if (from < 0 || from > to)
- {
- error("Illegal bit index");
- return;
- }
-
-
- if (to >= rep->len)
- setlength(to+1, 1);
- else
- make_unique();
-
- int ind1 = word_index(from);
- int pos1 = bit_position(from);
- int ind2 = word_index(to);
- int pos2 = bit_position(to);
- unsigned long* s = &(rep->s[ind1]);
- unsigned long m1 = lmask(pos1);
- unsigned long m2 = rmask(pos2);
- if (ind2 == ind1)
- *s |= m1 & m2;
- else
- {
- *s++ |= m1;
- unsigned long* top = &(rep->s[ind2]);
- *top |= m2;
- while (s < top)
- *s++ = ONES;
- }
- }
-
- void BitString::clear(int from, int to)
- {
- if (from < 0 || from > to)
- {
- error("Illegal bit index");
- return;
- }
-
- if (to >= rep->len)
- setlength(to+1, 1);
- else
- make_unique();
-
- int ind1 = word_index(from);
- int pos1 = bit_position(from);
- int ind2 = word_index(to);
- int pos2 = bit_position(to);
- unsigned long* s = &(rep->s[ind1]);
- unsigned long m1 = lmask(pos1);
- unsigned long m2 = rmask(pos2);
- if (ind2 == ind1)
- *s &= ~(m1 & m2);
- else
- {
- *s++ &= ~m1;
- unsigned long* top = &(rep->s[ind2]);
- *top &= ~m2;
- while (s < top)
- *s++ = 0;
- }
- }
-
- void BitString::invert(int from, int to)
- {
- if (from < 0 || from > to)
- {
- error("Illegal bit index");
- return;
- }
-
- if (to >= rep->len)
- setlength(to+1, 1);
- else
- make_unique();
-
- int ind1 = word_index(from);
- int pos1 = bit_position(from);
- int ind2 = word_index(to);
- int pos2 = bit_position(to);
- unsigned long* s = &(rep->s[ind1]);
- unsigned long m1 = lmask(pos1);
- unsigned long m2 = rmask(pos2);
- if (ind2 == ind1)
- *s ^= m1 & m2;
- else
- {
- *s++ ^= m1;
- unsigned long* top = &(rep->s[ind2]);
- *top ^= m2;
- while (s < top)
- {
- unsigned long cmp = ~(*s);
- *s++ = cmp;
- }
- }
- }
-
-
- int BitString::test(int from, int to)
- {
- if (from < 0 || from > to || from >= rep->len)
- return 0;
-
- int ind1 = word_index(from);
- int pos1 = bit_position(from);
- int ind2 = word_index(to);
- int pos2 = bit_position(to);
-
- if (to >= rep->len)
- {
- ind2 = word_index(rep->len - 1);
- pos2 = bit_position(rep->len - 1);
- }
-
- unsigned long* s = &(rep->s[ind1]);
- unsigned long m1 = lmask(pos1);
- unsigned long m2 = rmask(pos2);
-
- if (ind2 == ind1)
- return (*s & m1 & m2) != 0;
- else
- {
- if (*s++ & m1)
- return 1;
- unsigned long* top = &(rep->s[ind2]);
- if (*top & m2)
- return 1;
- while (s < top)
- if (*s++ != 0)
- return 1;
- return 0;
- }
- }
-
- int BitString::next(int p, int b = 1)
- {
- if (++p >= rep->len)
- return -1;
-
- int ind = word_index(p);
- int pos = bit_position(p);
- int l = word_length(rep->len);
-
- int j = ind;
- unsigned long* s = rep->s;
- unsigned long a = s[j] >> pos;
- int i = pos;
-
- if (b != 0)
- {
- for (; i < B_SHIFT && a != 0; ++i)
- {
- if (a & 1)
- return j * B_SHIFT + i;
- a >>= 1;
- }
- for (++j; j < l; ++j)
- {
- a = s[j];
- for (i = 0; i < B_SHIFT && a != 0; ++i)
- {
- if (a & 1)
- return j * B_SHIFT + i;
- a >>= 1;
- }
- }
- return -1;
- }
- else
- {
- int last = bit_position(rep->len);
- if (j == l - 1)
- {
- for (; i < last; ++i)
- {
- if ((a & 1) == 0)
- return j * B_SHIFT + i;
- a >>= 1;
- }
- return -1;
- }
-
- for (; i < B_SHIFT; ++i)
- {
- if ((a & 1) == 0)
- return j * B_SHIFT + i;
- a >>= 1;
- }
- for (++j; j < l - 1; ++j)
- {
- a = s[j];
- if (a != ONES)
- {
- for (i = 0; i < B_SHIFT; ++i)
- {
- if ((a & 1) == 0)
- return j * B_SHIFT + i;
- a >>= 1;
- }
- }
- }
- a = s[j];
- for (i = 0; i < last; ++i)
- {
- if ((a & 1) == 0)
- return j * B_SHIFT + i;
- a >>= 1;
- }
- return -1;
- }
- }
-
- int BitString::previous(int p, int b = 1)
- {
- if (--p < 0)
- return -1;
-
- int ind = word_index(p);
- int pos = bit_position(p);
-
- unsigned long* s = rep->s;
- int l = word_length(rep->len);
-
- if (p >= rep->len)
- {
- ind = word_index(rep->len - 1);
- pos = bit_position(rep->len - 1);
- }
-
- int j = ind;
- unsigned long a = s[j];
-
- int i = pos;
- unsigned long maxbit = 1 << pos;
-
- if (b != 0)
- {
- for (; i >= 0 && a != 0; --i)
- {
- if (a & maxbit)
- return j * B_SHIFT + i;
- a <<= 1;
- }
- maxbit = 1 << (B_SHIFT - 1);
- for (--j; j >= 0; --j)
- {
- a = s[j];
- for (i = B_SHIFT - 1; i >= 0 && a != 0; --i)
- {
- if (a & maxbit)
- return j * B_SHIFT + i;
- a <<= 1;
- }
- }
- return -1;
- }
- else
- {
- if (a != ONES)
- {
- for (; i >= 0; --i)
- {
- if ((a & maxbit) == 0)
- return j * B_SHIFT + i;
- a <<= 1;
- }
- }
- maxbit = 1 << (B_SHIFT - 1);
- for (--j; j >= 0; --j)
- {
- a = s[j];
- if (a != ONES)
- {
- for (i = B_SHIFT - 1; i >= 0; --i)
- {
- if ((a & maxbit) == 0)
- return j * B_SHIFT + i;
- a <<= 1;
- }
- }
- }
- return -1;
- }
- }
-
-
- int BitString::search(int startx, int lengthx,
- unsigned long* ys, int starty, int lengthy)
- {
- unsigned long* xs = rep->s;
- int ylen = lengthy - starty;
- int righty = lengthy - 1;
- int leftx, rightx;
- int rev = startx < 0;
- if (rev)
- {
- leftx = 0;
- rightx = lengthx + startx;
- startx = rightx - ylen + 1;
- }
- else
- {
- leftx = startx;
- rightx = lengthx - 1;
- }
-
- if (starty < 0 || righty < 0 || startx < 0 || startx >= lengthx)
- return -1;
-
- int xind = word_index(startx);
- int xpos = bit_position(startx);
- int yind = word_index(starty);
- int ypos = bit_position(starty);
-
- int rightxind = word_index(rightx);
- int leftxind = word_index(leftx);
- unsigned long x = borrow_hi(xs, xind, rightxind, xpos);
- unsigned long nextx;
- if (rev)
- nextx = xs[xind] << (B_SHIFT - xpos);
- else
- nextx = (xind >= rightxind) ? 0 : (xs[xind+1] >> xpos);
-
- int rightyind = word_index(righty);
- int rightypos = bit_position(righty);
- unsigned long y = borrow_hi(ys, yind, rightyind, ypos);
- unsigned long ymask;
- if (yind == rightyind)
- ymask = rmask(rightypos);
- else if (yind+1 == rightyind)
- ymask = rmask(ypos + rightypos + 1);
- else
- ymask = ONES;
-
- int p = startx;
- for (;;)
- {
- if ((x & ymask) == y)
- {
- int xi = xind;
- int yi = yind;
- for (;;)
- {
- if (++yi > rightyind || ++xi > rightxind)
- return p;
- unsigned long tx = borrow_hi(xs, xi, rightxind, xpos);
- unsigned long ty = borrow_hi(ys, yi, rightyind, ypos);
- if (yi == rightyind)
- tx &= rmask(rightypos);
- else if (yi+1 == rightyind)
- tx &= rmask(ypos + rightypos + 1);
- if (tx != ty)
- break;
- }
- }
- if (rev)
- {
- if (--p < leftx)
- return -1;
- if (--xpos < 0)
- {
- xpos = B_SHIFT - 1;
- x = xs[--xind];
- nextx = (xind <= leftxind) ? 0 : xs[xind-1];
- }
- else
- {
- x <<= 1;
- if (nextx & MAXBIT)
- x |= 1;
- nextx <<= 1;
- }
- }
- else
- {
- if (++p > rightx)
- return -1;
- if (++xpos == B_SHIFT)
- {
- xpos = 0;
- x = xs[++xind];
- nextx = (xind >= rightxind) ? 0 : xs[xind+1];
- }
- else
- {
- x >>= 1;
- if (nextx & 1)
- x |= MAXBIT;
- nextx >>= 1;
- }
- }
- }
- }
-
-
- int BitPattern::search(unsigned long* xs, int startx, int lengthx)
- {
- unsigned long* ys = pattern.rep->s;
- unsigned long* ms = mask.rep->s;
- int righty = pattern.rep->len - 1;
- int rightm = mask.rep->len - 1;
-
- int leftx, rightx;
- int rev = startx < 0;
- if (rev)
- {
- leftx = 0;
- rightx = lengthx + startx;
- startx = rightx - righty;
- }
- else
- {
- leftx = startx;
- rightx = lengthx - 1;
- }
-
- if (righty < 0 || startx < 0 || startx >= lengthx)
- return -1;
-
- int xind = word_index(startx);
- int xpos = bit_position(startx);
-
- int rightxind = word_index(rightx);
- int leftxind = word_index(leftx);
- int rightmind = word_index(rightm);
- int rightyind = word_index(righty);
-
- unsigned long x = safe_borrow_hi(xs, xind, rightxind, xpos);
- unsigned long m = safe_borrow_hi(ms, 0, rightmind, 0);
- unsigned long y = safe_borrow_hi(ys, 0, rightyind, 0) & m;
-
- unsigned long nextx;
- if (rev)
- nextx = xs[xind] << (B_SHIFT - xpos);
- else
- nextx = (xind >= rightxind) ? 0 : (xs[xind+1] >> xpos);
-
- int p = startx;
- for (;;)
- {
- if ((x & m) == y)
- {
- int xi = xind;
- int yi = 0;
- for (;;)
- {
- if (++yi > rightyind || ++xi > rightxind)
- return p;
- unsigned long tm = safe_borrow_hi(ms, yi, rightmind, 0);
- unsigned long ty = safe_borrow_hi(ys, yi, rightyind, 0);
- unsigned long tx = safe_borrow_hi(xs, xi, rightxind, xpos);
- if ((tx & tm) != (ty & tm))
- break;
- }
- }
- if (rev)
- {
- if (--p < leftx)
- return -1;
- if (--xpos < 0)
- {
- xpos = B_SHIFT - 1;
- x = xs[--xind];
- nextx = (xind <= leftxind) ? 0 : xs[xind-1];
- }
- else
- {
- x <<= 1;
- if (nextx & MAXBIT)
- x |= 1;
- nextx <<= 1;
- }
- }
- else
- {
- if (++p > rightx)
- return -1;
- if (++xpos == B_SHIFT)
- {
- xpos = 0;
- x = xs[++xind];
- nextx = (xind >= rightxind) ? 0 : xs[xind+1];
- }
- else
- {
- x >>= 1;
- if (nextx & 1)
- x |= MAXBIT;
- nextx >>= 1;
- }
- }
- }
- }
-
- int BitString::match(int startx, int lengthx, int exact,
- unsigned long* ys, int starty, int yl)
- {
- unsigned long* xs = rep->s;
- int ylen = yl - starty;
- int righty = yl - 1;
-
- int rightx;
- int rev = startx < 0;
- if (rev)
- {
- rightx = lengthx + startx;
- startx = rightx - ylen + 1;
- if (exact && startx != 0)
- return 0;
- }
- else
- {
- rightx = lengthx - 1;
- if (exact && rightx - startx != righty)
- return 0;
- }
-
- if (righty < 0 || startx < 0 || startx >= lengthx)
- return 0;
-
- int xi = word_index(startx);
- int xpos = bit_position(startx);
- int yi = word_index(starty);
- int ypos = bit_position(starty);
-
- int rightxind = word_index(rightx);
- int rightyind = word_index(righty);
- int rightypos = bit_position(righty);
-
- for (;;)
- {
- unsigned long x = borrow_hi(xs, xi, rightxind, xpos);
- unsigned long y = borrow_hi(ys, yi, rightyind, ypos);
- if (yi == rightyind)
- x &= rmask(rightypos);
- else if (yi+1 == rightyind)
- x &= rmask(ypos + rightypos + 1);
- if (x != y)
- return 0;
- else if (++yi > rightyind || ++xi > rightxind)
- return 1;
- }
- }
-
- int BitPattern::match(unsigned long* xs, int startx, int lengthx, int exact)
- {
- unsigned long* ys = pattern.rep->s;
- int righty = pattern.rep->len - 1;
- unsigned long* ms = mask.rep->s;
- int rightm = mask.rep->len - 1;
-
- int rightx;
- int rev = startx < 0;
- if (rev)
- {
- rightx = lengthx + startx;
- startx = rightx - righty;
- if (exact && startx != 0)
- return 0;
- }
- else
- {
- rightx = lengthx - 1;
- if (exact && rightx - startx != righty)
- return 0;
- }
-
- if (righty < 0 || startx < 0 || startx >= lengthx)
- return 0;
-
- int xind = word_index(startx);
- int xpos = bit_position(startx);
- int yind = 0;
-
- int rightxind = word_index(rightx);
- int rightyind = word_index(righty);
- int rightmind = word_index(rightm);
-
- for(;;)
- {
- unsigned long m = safe_borrow_hi(ms, yind, rightmind, 0);
- unsigned long x = safe_borrow_hi(xs, xind, rightxind, xpos) & m;
- unsigned long y = safe_borrow_hi(ys, yind, rightyind, 0) & m;
- if (x != y)
- return 0;
- else if (++yind > rightyind || ++xind > rightxind)
- return 1;
- }
- }
-
- BitSubString::BitSubString(BitString* x, int first, int l)
- {
- if (first < 0 || l <= 0 || first + l > x->rep->len)
- {
- S = &_nil_BitString; pos = len = 0;
- }
- else
- {
- S = x; pos = first; len = l;
- }
- }
-
-
-
- void BitSubString::operator = (BitString& y)
- {
- int ylen = y.rep->len;
- _BitStringrep* targ = S->rep;
-
- if (len == 0 || pos >= targ->len)
- return;
-
- int sl = targ->len - len + ylen;
-
- if (targ->ref != 1)
- {
- if (targ->ref > 0) targ->ref--;
- _BitStringrep* oldtarg = targ;
- targ = new_BitStringrep(sl);
- bit_transfer(oldtarg->s, 0, pos, targ->s, 0);
- bit_transfer(y.rep->s, 0, ylen, targ->s, pos);
- bit_transfer(oldtarg->s, pos+len, oldtarg->len, targ->s, pos + ylen);
- }
- else if (y.rep == targ || ylen > len)
- {
- _BitStringrep* oldtarg = targ;
- targ = new_BitStringrep(sl);
- bit_transfer(oldtarg->s, 0, pos, targ->s, 0);
- bit_transfer(y.rep->s, 0, ylen, targ->s, pos);
- bit_transfer(oldtarg->s, pos+len, oldtarg->len, targ->s, pos + ylen);
- delete oldtarg;
- }
- else if (len == ylen)
- bit_transfer(y.rep->s, 0, len, targ->s, pos);
- else if (ylen < len)
- {
- bit_transfer(y.rep->s, 0, ylen, targ->s, pos);
- bit_transfer(targ->s, pos+len, targ->len, targ->s, pos + ylen);
- targ->len = sl;
- }
- check_last(targ);
- S->rep = targ;
- }
-
- void BitSubString::operator = (BitSubString& y)
- {
- _BitStringrep* targ = S->rep;
-
- if (len == 0 || pos >= targ->len)
- return;
-
- int sl = targ->len - len + y.len;
-
- if (targ->ref != 1)
- {
- if (targ->ref > 0) targ->ref--;
- _BitStringrep* oldtarg = targ;
- targ = new_BitStringrep(sl);
- bit_copy(oldtarg->s, targ->s, pos);
- bit_transfer(y.S->rep->s, y.pos, y.pos+y.len, targ->s, pos);
- bit_transfer(oldtarg->s, pos+len, oldtarg->len, targ->s, pos + y.len);
- }
- else if (y.S->rep == targ || y.len > len)
- {
- _BitStringrep* oldtarg = targ;
- targ = new_BitStringrep(sl);
- bit_copy(oldtarg->s, targ->s, pos);
- bit_transfer(y.S->rep->s, y.pos, y.pos+y.len, targ->s, pos);
- bit_transfer(oldtarg->s, pos+len, oldtarg->len, targ->s, pos + y.len);
- delete oldtarg;
- }
- else if (len == y.len)
- bit_transfer(y.S->rep->s, y.pos, y.pos+y.len, targ->s, pos);
- else if (y.len < len)
- {
- bit_transfer(y.S->rep->s, y.pos, y.pos+y.len, targ->s, pos);
- bit_transfer(targ->s, pos+len, targ->len, targ->s, pos + y.len);
- targ->len = sl;
- }
- check_last(targ);
- S->rep = targ;
- }
-
- BitSubString BitString::at(int first, int len)
- {
- return BitSubString(this, first, len);
- }
-
- BitSubString BitString::before(int pos)
- {
- return BitSubString(this, 0, pos);
- }
-
- BitSubString BitString::after(int pos)
- {
- return BitSubString(this, pos + 1, rep->len - (pos + 1));
- }
-
- BitSubString BitString::at(BitString& y, int startpos = 0)
- {
- int first = search(startpos, rep->len, y.rep->s, 0, y.rep->len);
- return BitSubString(this, first, y.rep->len);
- }
-
- BitSubString BitString::before(BitString& y, int startpos = 0)
- {
- int last = search(startpos, rep->len, y.rep->s, 0, y.rep->len);
- return BitSubString(this, 0, last);
- }
-
- BitSubString BitString::after(BitString& y, int startpos = 0)
- {
- int first = search(startpos, rep->len, y.rep->s, 0, y.rep->len);
- return BitSubString(this, first + y.rep->len, rep->len - (first+y.rep->len));
- }
-
-
- BitSubString BitString::at(BitSubString& y, int startpos = 0)
- {
- int first = search(startpos, rep->len, y.S->rep->s, y.pos, y.len);
- return BitSubString(this, first, y.len);
- }
-
- BitSubString BitString::before(BitSubString& y, int startpos = 0)
- {
- int last = search(startpos, rep->len, y.S->rep->s, y.pos, y.len);
- return BitSubString(this, 0, last);
- }
-
- BitSubString BitString::after(BitSubString& y, int startpos = 0)
- {
- int first = search(startpos, rep->len, y.S->rep->s, y.pos, y.len);
- return BitSubString(this, first + y.len, rep->len - (first + y.len));
- }
-
- BitSubString BitString::at(BitPattern& r, int startpos = 0)
- {
- int first = r.search(rep->s, startpos, rep->len);
- return BitSubString(this, first, r.pattern.rep->len);
- }
-
-
- BitSubString BitString::before(BitPattern& r, int startpos = 0)
- {
- int first = r.search(rep->s, startpos, rep->len);
- return BitSubString(this, 0, first);
- }
-
- BitSubString BitString::after(BitPattern& r, int startpos = 0)
- {
- int first = r.search(rep->s, startpos, rep->len);
- int last;
- if (first < 0)
- last = -1;
- else
- last = first + r.pattern.rep->len;
- return BitSubString(this, last, rep->len - last);
- }
-
- BitString common_prefix(BitString& x, BitString& y, int startpos = 0)
- {
- BitString r;
- unsigned long xl = x.rep->len;
- unsigned long yl = y.rep->len;
-
- int startx, starty;
- if (startpos < 0)
- {
- startx = xl + startpos;
- starty = yl + startpos;
- }
- else
- startx = starty = startpos;
-
- if (startx < 0 || startx >= xl || starty < 0 || starty >= yl)
- return r;
-
- unsigned long* xs = &(x.rep->s[word_index(startx)]);
- unsigned long a = *xs++;
- int xp = startx;
-
- unsigned long* ys = &(y.rep->s[word_index(starty)]);
- unsigned long b = *ys++;
- int yp = starty;
-
- for(; xp < xl && yp < yl; ++xp, ++yp)
- {
- unsigned long xbit = 1 << (bit_position(xp));
- unsigned long ybit = 1 << (bit_position(yp));
- if (((a & xbit) == 0) != ((b & ybit) == 0))
- break;
- if (xbit == MAXBIT)
- a = *xs++;
- if (ybit == MAXBIT)
- b = *ys++;
- }
- if (xp > startx)
- r.copy(x.rep->s, startx, xp);
- return r;
- }
-
-
- BitString common_suffix(BitString& x, BitString& y, int startpos = -1)
- {
- BitString r;
- unsigned long xl = x.rep->len;
- unsigned long yl = y.rep->len;
-
- int startx, starty;
- if (startpos < 0)
- {
- startx = xl + startpos;
- starty = yl + startpos;
- }
- else
- startx = starty = startpos;
-
- if (startx < 0 || startx >= xl || starty < 0 || starty >= yl)
- return r;
-
- unsigned long* xs = &(x.rep->s[word_index(startx)]);
- unsigned long a = *xs--;
- int xp = startx;
-
- unsigned long* ys = &(y.rep->s[word_index(starty)]);
- unsigned long b = *ys--;
- int yp = starty;
-
- for(; xp >= 0 && yp >= 0; --xp, --yp)
- {
- unsigned long xbit = 1 << (bit_position(xp));
- unsigned long ybit = 1 << (bit_position(yp));
- if (((a & xbit) == 0) != ((b & ybit) == 0))
- break;
- if (xbit == 1)
- a = *xs--;
- if (ybit == 1)
- b = *ys--;
- }
- if (xp < startx)
- r.copy(x.rep->s, xp+1, startx+1);
- return r;
- }
-
- BitString reverse(BitString& x)
- {
- BitString y = x;
- y.make_unique();
- unsigned long yl = y.rep->len;
- if (yl > 0)
- {
- int l = 0;
- int r = yl - 1;
- unsigned long* ls = y.rep->s;
- unsigned long* rs = &(ls[word_length(yl) - 1]);
- unsigned long lm = 1 << (bit_position(l));
- unsigned long rm = 1 << (bit_position(r));
- for (; l < r; ++l, --r)
- {
- if (((*ls & lm) != 0) != ((*rs & rm) != 0))
- {
- *rs ^= rm;
- *ls ^= lm;
- }
- if (lm == MAXBIT)
- {
- ++ls;
- lm = 1;
- }
- else
- lm <<= 1;
- if (rm == 1)
- {
- --rs;
- rm = MAXBIT;
- }
- else
- rm = (rm >> 1) & ~(MAXBIT);
- }
- }
- return y;
- }
-
- extern Obstack _libgxx_io_ob;
- extern char* _libgxx_io_oblast;
-
-
- const char* BitStringtoa(BitString& x, char f = '0', char t = '1')
- {
- if (_libgxx_io_oblast) _libgxx_io_ob.free(_libgxx_io_oblast);
- unsigned long xl = x.rep->len;
- unsigned long* s = x.rep->s;
- unsigned long a;
-
- for (unsigned long i = 0; i < xl; ++i)
- {
- if (i % B_SHIFT == 0)
- a = *s++;
- _libgxx_io_ob.grow((a & 1)? t : f);
- a >>= 1;
- }
-
- return _libgxx_io_oblast = (char*)(_libgxx_io_ob.finish(0));
- }
-
- BitString atoBitString(const char* s, char f = '0', char t = '1')
- {
- BitString r;
- int sl = strlen(s);
- if (sl != 0)
- {
- unsigned long rl = 0;
- r.setlength(sl);
- unsigned long* rs = r.rep->s;
- unsigned long a = 0;
- unsigned long m = 1;
- unsigned long i = 0;
- for(;;)
- {
- char ch = s[i];
- if (ch != t && ch != f)
- {
- *rs = a;
- break;
- }
- ++rl;
- if (ch == t)
- a |= m;
- if (++i == sl)
- {
- *rs = a;
- break;
- }
- else if (i % B_SHIFT == 0)
- {
- *rs++ = a;
- a = 0;
- m = 1;
- }
- else
- m <<= 1;
- }
- r.setlength(rl);
- }
- return r;
- }
-
- ostream& operator << (ostream& s, BitString& x)
- {
- return s << BitStringtoa(x);
- }
-
-
- const char* BitPatterntoa(BitPattern& p, char f = '0',char t = '1',char x='X')
- {
- if (_libgxx_io_oblast) _libgxx_io_ob.free(_libgxx_io_oblast);
- unsigned long pl = p.pattern.rep->len;
- unsigned long ml = p.mask.rep->len;
- unsigned long l = pl <? ml;
- unsigned long* ps = p.pattern.rep->s;
- unsigned long* ms = p.mask.rep->s;
- unsigned long a;
- unsigned long m;
-
- for (unsigned long i = 0; i < l; ++i)
- {
- if (i % B_SHIFT == 0)
- {
- a = *ps++;
- m = *ms++;
- }
- if (m & 1)
- _libgxx_io_ob.grow((a & 1)? t : f);
- else
- _libgxx_io_ob.grow(x);
- a >>= 1;
- m >>= 1;
- }
-
- return _libgxx_io_oblast = (char*)(_libgxx_io_ob.finish(0));
- }
-
- BitPattern atoBitPattern(const char* s,char f = '0',char t = '1',char x = 'X')
- {
- BitPattern r;
- int sl = strlen(s);
- if (sl != 0)
- {
- unsigned long rl = 0;
- r.pattern.setlength(sl);
- r.mask.setlength(sl);
- unsigned long* rs = r.pattern.rep->s;
- unsigned long* ms = r.mask.rep->s;
- unsigned long a = 0;
- unsigned long b = 0;
- unsigned long m = 1;
- unsigned long i = 0;
- for(;;)
- {
- char ch = s[i];
- if (ch != t && ch != f && ch != x)
- {
- *rs = a;
- *ms = b;
- break;
- }
- ++rl;
- if (ch == t)
- {
- a |= m;
- b |= m;
- }
- else if (ch == f)
- {
- b |= m;
- }
- if (++i == sl)
- {
- *rs = a;
- *ms = b;
- break;
- }
- else if (i % B_SHIFT == 0)
- {
- *rs++ = a;
- *ms++ = b;
- a = 0;
- b = 0;
- m = 1;
- }
- else
- m <<= 1;
- }
- r.pattern.setlength(rl);
- r.mask.setlength(rl);
- }
- return r;
- }
-
- ostream& operator << (ostream& s, BitPattern& x)
- {
- return s << BitPatterntoa(x);
- }
-