/*ident "@(#)cls4:src/Bits.c 1.5" */ /******************************************************************************* C++ source for the C++ Language System, Release 3.0. This product is a new release of the original cfront developed in the computer science research center of AT&T Bell Laboratories. Copyright (c) 1993 UNIX System Laboratories, Inc. Copyright (c) 1991, 1992 AT&T and UNIX System Laboratories, Inc. Copyright (c) 1984, 1989, 1990 AT&T. All Rights Reserved. THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of AT&T and UNIX System Laboratories, Inc. The copyright notice above does not evidence any actual or intended publication of such source code. *******************************************************************************/ // Bits.c // The numbering scheme in this library is consistently // ``little-end'' -- bit 0 is the low-order bit of the word // stored in the lowest location of a class. #include "Bits.h" Blockimplement(Bits_chunk) Bits::Bits(register Bits_chunk val, register unsigned ct) { if (ct < Bits_len_ATTLC) { register Bits_chunk mask = ~Bits_chunk(0) << ct; while (val & mask) { ct++; mask <<= 1; } } if (size(ct)) *((Bits_chunk*)b) = val; } unsigned Bits::size(unsigned x) { int newsize = bound(x); if (b.size() != newsize) b.size(newsize); n = b.size()? x: 0; normalize(); return n; } Bits& Bits::operator&= (const Bits& x) { if (size() < x.size()) size(x.size()); register Bits_chunk* p = b; register const Bits_chunk* q = x.b; register const Bits_chunk* lim = x.limit(); while (q < lim) *p++ &= *q++; lim = limit(); while (p < lim) *p++ = 0; return *this; } Bits& Bits::operator|= (const Bits& x) { if (size() < x.size()) size(x.size()); register Bits_chunk* p = b; register const Bits_chunk* q = x.b; register const Bits_chunk* lim = x.limit(); while (q < lim) *p++ |= *q++; return *this; } Bits& Bits::operator^= (const Bits& x) { if (size() < x.size()) size(x.size()); register Bits_chunk* p = b; register const Bits_chunk* q = x.b; register const Bits_chunk* lim = x.limit(); while (q < lim) *p++ ^= *q++; return *this; } Bits& Bits::compl() { register Bits_chunk* p = b; register const Bits_chunk* lim = limit(); while (p < lim) { *p = ~*p; p++; } normalize(); return *this; } unsigned Bits::count() const { register const Bits_chunk* p = b; register const Bits_chunk* lim = limit(); register unsigned r = 0; while (p < lim) { register unsigned long x = *p++; register int i = Bits_len_ATTLC; while (--i >= 0) { if (x & 1) r++; x >>= 1; } } return r; } #if 0 Bits::operator Bits_chunk() const { register const Bits_chunk* p = b; register const Bits_chunk* lim = limit(); while (p < lim) { if (*p++) return p[-1]; } return 0; } Bits operator& (const Bits& x, const Bits& y) { Bits r = x; r &= y; return r; } Bits operator| (const Bits& x, const Bits& y) { Bits r = x; r |= y; return r; } Bits operator^ (const Bits& x, const Bits& y) { Bits r = x; r ^= y; return r; } #endif Bits operator~ (const Bits& x) { Bits r = x; r.compl(); return r; } #if 0 Bits operator<< (const Bits& x, int n) { Bits r = x; r <<= n; return r; } Bits operator>> (const Bits& x, int n) { Bits r = x; r >>= n; return r; } #endif int Bits::compare(const Bits& x) const { int w = bound(size()); int xw = bound(x.size()); int len, r; register const Bits_chunk* p; register const Bits_chunk* q; register const Bits_chunk* lim; // two null strings are equal if (w == 0 && xw == 0) return 0; // a null string is the smallest string if (w == 0) return -1; if (xw == 0) return 1; // if the lengths differ, check the high-order // part of the longer string; leave shorter length // in len if we get out of this if (w != xw) { if (w > xw) { len = xw; p = &b[len]; q = &b[w]; r = 1; } else { len = w; p = &x.b[len]; q = &x.b[xw]; r = -1; } do { if (*p++) return r; } while (p < q); } else len = w; // now compare low-order parts, going from high-order // end to low-order end (the direction is important!) p = (const Bits_chunk*)b + len; q = (const Bits_chunk*)x.b + len; lim = b; while (p > lim) { if (*--p != *--q) return *p < *q? -1: 1; } // the bits are equal -- length determines the result return int(size()) - int(x.size()); } // Are two bit strings identical? int Bits::equal(const Bits& x) const { // two strings of different sizes are not equal if (size() != x.size()) return 0; // two null strings are equal if (size() == 0) return 1; // else go the long route return compare(x) == 0; } // The following routines can surely be made more efficient. // I have not done so for two reasons: // // 1. The function call and memory allocation overhead // will probably dominate for all but the largest of // bit strings. // // 2. This code is tricky. Further optimization would // erode my confidence in getting it right. Bits& Bits::operator<<= (int k) { // Quick test for shift by 0 or negative if (k <= 0) { if (k < 0) operator>>= (-k); return *this; } // Enlarge the structure to contain the result; return on error if (size(size() + k) == 0) return *this; register Bits_chunk* lim = b; // If needed, shift left by chunks int chunkoffset = k >> Bits_shift_ATTLC; if (chunkoffset) { register Bits_chunk* dest = limit(); register Bits_chunk* src = dest - chunkoffset; do *--dest = *--src; while (src > lim); do *--dest = 0; while (dest > lim); } // If needed, shift left by bits register int bitoffset = k & Bits_mask_ATTLC; if (bitoffset) { register Bits_chunk* p = limit(); register int compoffset = Bits_len_ATTLC - bitoffset; while (--p > lim) *p = (*p << bitoffset) | (*(p-1) >> compoffset); // Shift low-order chunk *lim <<= bitoffset; } normalize(); return *this; } Bits& Bits::operator>>= (int k) { // Quick test for shift by 0 or negative if (k <= 0) { if (k < 0) operator<<= (-k); return *this; } // Check for shifting all significance out int newsize = size() - k; if (newsize <= 0) { size(0); return *this; } // If needed, shift right by chunks, leaving high-order // garbage words that will be sized out later int chunkoffset = k >> Bits_shift_ATTLC; if (chunkoffset) { register Bits_chunk* dest = b; register Bits_chunk* src = dest + chunkoffset; register const Bits_chunk* lim = limit(); do *dest++ = *src++; while (src < lim); } // If needed, shift right by bits register int bitoffset = k & Bits_mask_ATTLC; if (bitoffset) { register Bits_chunk* p = b; register Bits_chunk* lim = p + chunk(newsize-1); register int compoffset = Bits_len_ATTLC - bitoffset; while (p < lim) { *p = (*p >> bitoffset) | (*(p+1) << compoffset); p++; } // Shift high-order chunk right *lim >>= bitoffset; if (lim+1 < limit()) *lim |= *(lim+1) << compoffset; } // Finally, make the size right, discarding junk bits size(newsize); return *this; } // How many significant bits? unsigned Bits::signif() const { if (size() == 0) return 0; register const Bits_chunk* p = limit(); register const Bits_chunk* lim = b; while (--p >= lim) { if (*p) { register Bits_chunk x = *p; register int k = Bits_len_ATTLC; while (--k >= 0) { if (x & (Bits_chunk(1) << k)) return k + 1 + Bits_len_ATTLC * (p - lim); } } } return 0; } Bits& Bits::concat(const Bits& x) { operator<<= (x.size()); operator|= (x); return *this; } #if 0 Bits concat(const Bits& x, const Bits& y) { Bits r = x; r.concat(y); return r; } #endif