Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

BitVector.H

Go to the documentation of this file.
00001 // Copyright (C) 2001, Compaq Computer Corporation
00002 // 
00003 // This file is part of Vesta.
00004 // 
00005 // Vesta is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 // 
00010 // Vesta is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with Vesta; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 // Last modified on Tue Aug  3 13:08:10 EDT 2004 by ken@xorian.net
00020 //      modified on Mon Apr 12 08:56:33 PDT 1999 by heydon
00021 
00022 // BitVector -- a zero-based indexable vector of bits
00023 //
00024 // A bit vector is a (zero-based) vector of Boolean values. There is no limit
00025 // to the size of a bit vector, but their implementation was not designed to
00026 // represent sparse vectors efficiently. In particular, the memory
00027 // requirements for a bit vector "bv" are "O(sz)", where "sz" is the result
00028 // returned by the method call "bv.Size()".
00029 //
00030 // Every bit in a bit vector has an index; the index of the least significant
00031 // bit is 0. There are operations for reading the value of a bit at a given
00032 // index, and for setting or resetting a bit at a specified index.
00033 //
00034 // The set bit with largest index is called the vector's most-significant bit.
00035 // A bit is "valid" if its index is at most that of the most-significant bit.
00036 // Setting a bit at an index larger than that of the vector's current
00037 // most-significant bit automatically grows the vector, and resets any bits
00038 // between the old and new most-significant bits.
00039 //
00040 // The methods of a "BitVector" are unmonitored. The read-only methods are
00041 // denoted "const".
00042 
00043 #ifndef _BIT_VECTOR_H
00044 #define _BIT_VECTOR_H
00045 
00046 #include <Basics.H>
00047 #include <FS.H>
00048 #include <SRPC.H>
00049 #include <VestaLog.H>
00050 #include <Recovery.H>
00051 
00052 class BVIter;
00053 
00054 class BitVector {
00055   public:
00056     BitVector(int sizeHint = 0) throw ()
00057         : numWords(0), sz(0), firstAvailWd(0), word((Word *)NULL)
00058         { Init(sizeHint, /*doZero =*/ true); }
00059     /* Initialize a new bit vector. If supplied, "sizeHint" is a hint for the
00060        number of bits the vector is expected to contain. It is a checked
00061        run-time error for "sizeHint < 0". */
00062 
00063     BitVector(const BitVector *bv) throw ();
00064     /* Initialize a new bit vector to be a copy of "*bv". Notice that this is
00065        different from a copy constructor, but it provides a similar
00066        functionality. The true copy constructor is still private, so clients
00067        will not have it invisibly invoked by accident. */
00068 
00069     BitVector(RecoveryReader &rd) throw (VestaLog::Error, VestaLog::Eof)
00070         { Recover(rd); }
00071 
00072     BitVector(std::istream &ifs) throw (FS::EndOfFile, FS::Failure)
00073         { Read(ifs); }
00074 
00075     BitVector(SRPC &srpc) throw (SRPC::failure)
00076         { Recv(srpc); }
00077 
00078     ~BitVector() throw () { if (word != (Word *)NULL) delete word; }
00079     /* De-allocate any space used by the bit vector. */
00080 
00081     bool IsEmpty() const throw ();
00082     /* Return "true" iff the bit vector has no set bits. */
00083 
00084     int Size() const throw () { return this->sz; }
00085     /* Return an upper bound on the bit vector's number of valid bits. Reading
00086        any bit with an index at least as large as the result is guaranteed to
00087        return "false". This operation takes O(1) time. */
00088 
00089     int Cardinality() const throw ();
00090     /* Return the number of set bits in this bit vector. This operation takes
00091        "O(sz)" time, where "sz" is the result returned by the "Size" method. */
00092 
00093     bool Read(int i) const throw ();
00094     /* Return the state of the vector's "i"'th bit. If the "i"th bit is
00095        invalid, return "false". If "i" is negative, the result is undefined,
00096        and a run-time error may result. This operation takes O(1) time. */ 
00097 
00098     inline bool Write(int i, bool val) throw ()
00099         { if (val) return Set(i); else return Reset(i); }
00100     /* Set the value of the "i"'th bit to "val". If the "i"'th bit was
00101        previously invalid and "val" is "true", extend the vector so that "i"
00102        is the new index of the vector's most-significant bit, and so that all
00103        of the other new bits are reset. Returns the value of bit "i" before
00104        it was written to "val".
00105 
00106        It is an unchecked run-time error for "i" to be negative. This
00107        operation takes O(1) time. */
00108 
00109     bool Set(int i) throw ();
00110     bool Reset(int i) throw ();
00111     /* These are equivalent to "Write(i, true)" and "Write(i, false)",
00112        respectively, but may be implemented more efficiently. */
00113 
00114     Word ReadWord(int start, short len) const throw ();
00115     /* Read the "len" consecutive bits starting at index "start", and return
00116        them as the low-order "len" bits of a "Word". It is a checked run-time
00117        error for "len" to exceed the number of bits in a "Word". */
00118 
00119     void WriteWord(int start, short len, Word val) throw ();
00120     /* Write the "len" low-order bits of "val" to the bit vector starting at
00121        index "start". It is a checked run-time error for "len" to exceed the
00122        number of bits in a "Word". */
00123 
00124     void WriteInterval(int lo, int hi, bool val) throw ()
00125         { if (val) SetInterval(lo, hi); else ResetInterval(lo, hi); }
00126     /* Set all of the bits in the closed interval "[lo, hi]" to the value
00127        "val". It is an unchecked run-time error for "hi < lo" or for "lo" or
00128        "hi" to be negative. */
00129 
00130     void SetInterval(int lo, int hi) throw ();
00131     void ResetInterval(int lo, int hi) throw ();
00132     /* These are equivalent to "WriteInterval(lo, hi, true)" and
00133        "WriteInterval(lo, hi, false)", respectively, but may be implemented
00134        more efficiently. */
00135 
00136     void ResetAll(bool freeMem = false) throw ();
00137     /* Reset all the bits in the bit vector. If "freeMem" is true, then any
00138        memory allocated for the current bit vector will be freed. This is
00139        worthwhile if the current bit vector is large and is not expected to
00140        grow so large in the future. */
00141 
00142     int NextAvailExcept(BitVector *except = (BitVector *)NULL,
00143       bool setIt = true) throw ();
00144     /* Return the index of the least significant unset bit that is also unset
00145        in "except"; if "setIt" is true (the default), then also set that bit
00146        in this bit vector. If "except" is "NULL" (the default), it is as if it
00147        is a bit vector of all unset bits. */
00148 
00149     int NextAvail(bool setIt = true) throw ()
00150         { return NextAvailExcept((BitVector *)NULL, setIt); }
00151     /* Return the index of the least significant unset bit; if "setIt" is
00152        "true" (the default), then also set that bit in this bit vector. */
00153 
00154     int MSB() const throw ();
00155     /* Return the index of this bit vector's most-significant bit,
00156        or -1 if it is empty. */
00157 
00158     void Pack(const BitVector &mask) throw ();
00159     /* REQUIRES SELF <= mask */
00160     /* to be written */
00161 
00162     void Pack(const BitVector *mask) throw ()
00163         { if (mask != (BitVector *)NULL) Pack(*mask); }
00164     /* REQUIRES (mask != NULL) => (SELF <= *mask) */
00165     /* If "mask" is non-NULL, pack this bit vector according to "mask"; see
00166         the other "Pack" method above. */
00167 
00168     void Log(VestaLog &log) const throw (VestaLog::Error);
00169     /* Append this bit vector to "log", which must be in the "logging"
00170        state. */
00171 
00172     void Recover(RecoveryReader &rd) throw (VestaLog::Error, VestaLog::Eof);
00173     /* Recover this bit vector from "rd". */
00174 
00175     // write/read
00176     void Write(std::ostream &ofs) const throw (FS::Failure);
00177     void Read(std::istream &ifs) throw (FS::EndOfFile, FS::Failure);
00178 
00179     // send/recv
00180     void Send(SRPC &srpc) const throw (SRPC::failure);
00181     void Recv(SRPC &srpc) throw (SRPC::failure);
00182 
00183     // print
00184     friend std::ostream& operator << (std::ostream &os, const BitVector &fv) throw ()
00185       { fv.Print(os); return os; }
00186     void Print(std::ostream &s, int maxWidth = 64) const throw ();
00187     /* Write a (partial) representation of the bit vector to "s". If writing
00188        the complete representation would take more than "maxWidth" characters,
00189        "..." is written to indicate that the output is only partial. */
00190     void PrintAll(std::ostream &s, int indent = 0, int maxWidth = 70) const throw ();
00191     /* Write the complete contents of this bit vector to "s", indenting each
00192        output line by "indent" spaces. Each line is wrapped at a total of at
00193        most "maxWidth" characters. */
00194 
00195     // assignment operator
00196     BitVector& operator = (const BitVector& bv) throw ();
00197 
00198     // bitwise comparisons
00199     friend bool operator == (const BitVector& bv1, const BitVector& bv2)
00200       throw ();
00201     friend bool operator != (const BitVector& bv1, const BitVector& bv2)
00202       throw () { return !(bv1 == bv2); }
00203     friend bool operator <= (const BitVector& bv1, const BitVector& bv2)
00204       throw ();
00205     friend bool operator >= (const BitVector& bv1, const BitVector& bv2)
00206       throw () { return (bv2 <= bv1); }
00207     friend bool operator < (const BitVector& bv1, const BitVector& bv2)
00208       throw ();
00209     friend bool operator > (const BitVector& bv1, const BitVector& bv2)
00210       throw () { return (bv2 < bv1); }
00211 
00212     // bitwise operations
00213     friend BitVector* operator & (const BitVector& bv1, const BitVector& bv2)
00214       throw ();
00215     friend BitVector* operator | (const BitVector& bv1, const BitVector& bv2)
00216       throw ();
00217     friend BitVector* operator ^ (const BitVector& bv1, const BitVector& bv2)
00218       throw ();
00219     friend BitVector* operator - (const BitVector& bv1, const BitVector& bv2)
00220       throw ();
00221     /* These routines allocate and return a pointer to a new bit vector whose
00222        bits are the bitwise AND, OR, XOR, and difference of "bv1" and "bv2",
00223        respectively. */
00224 
00225     // destructive bitwise operations
00226     BitVector& operator &= (const BitVector& bv) throw ();
00227     BitVector& operator |= (const BitVector& bv) throw ();
00228     BitVector& operator ^= (const BitVector& bv) throw ();
00229     BitVector& operator -= (const BitVector& bv) throw ();
00230 
00231     friend class BVIter;
00232 
00233   private:
00234     Basics::int16 numWords;     // size of "word" array
00235     Basics::int16 firstAvailWd; // see I4 below
00236     Basics::int32 sz;           // upper bound on number of valid bits
00237     Word *word;                 // array of words
00238 
00239     /* A newly constructed bit vector has "sz == 0". The following
00240        invariants hold for an initialized bit vector:  
00241 
00242 |      I0. numWords >= 0
00243 |      I1. numWords > 0 <==> word != NULL <==> numWords == NUMBER(*word)
00244 |      I2. 0 <= sz <= (numWords * bitsPerWd)
00245 |      I3. (forall i: sz <= i < (numWords * bitsPerWd): !bit(word, i))
00246 |      I4. (forall i: 0 <= i < (firstAvailWd * bitsPerWd): bit(word, i))
00247 |      I5. 0 <= firstAvailWd <= numWords
00248 
00249        where "bitsPerWd" is the number of bits per Word, and "bit(word, i)"
00250        is "true" iff the "i"th bit of the "word" array is set (where the
00251        index of the least significant bit is 0).
00252 
00253        By I1, the only words that can be read/written are those with indices
00254        in the interval "[0, numWords-1]".
00255 
00256        By I3, the bits in the "word" array that can possibly be non-zero are
00257        those with indices in the interval "[0, sz-1]".
00258 
00259        By I4, "firstAvailWd" is the index of the first word that may possibly
00260        contain bits that are not all set. Notice, however, that I4 does not
00261        in any way require "firstAvailWd" to be maximal. For example, I4 is
00262        satisfied trivially when "firstAvailWd == 0".
00263 
00264        By I3 and I4, we have: "firstAvailWd * bitsPerWd <= sz". */
00265 
00266     BitVector(int sizeHint, bool doZero) throw ()
00267         : numWords(0U), firstAvailWd(0U), sz(0U), word((Word *)NULL)
00268         { Init(sizeHint, doZero); }
00269     /* See "Init" below. */
00270 
00271     void Init(int sizeHint, bool doZero) throw ();
00272     /* Initialize a new bit vector. If supplied, "sizeHint" is a hint for the
00273        number of bits the vector is expected to contain. It is a checked
00274        run-time error for "sizeHint < 0". If "doZero" is "false", then the
00275        words of the bit vector are not zeroed; it is the client's
00276        responsibility to ensure that all invariants (especially I3) are
00277        satisfied. */ 
00278 
00279     void Extend(short wordCnt, bool doPreserve = true) throw ();
00280     /* REQUIRES wordCnt > this->numWords */
00281     /* Extend the bit vector to include at least a total of "wordCnt"
00282        words. If "doPreserve" is "true", the contents of the bit vector
00283        are preserved, and all bits in the new words above the significant
00284        ones are guaranteed to be reset according to I3. Otherwise, the
00285        contents of the words are unspecified.
00286 
00287        This method may be called on a vector for which "numWords == 0" and
00288        "word == NULL", in which case it does the necessary allocation. */
00289 
00290     void ExpandSz(int i, short wx) throw ();
00291     /* Augment "sz" (and "word" if necessary) so as to contain bit "i"; "wx"
00292        must be the word containing that bit. */
00293 
00294     void ReduceSz() throw ();
00295     /* Reduce "sz" if any of the high-order words of the "word" array are
00296        zero. It's wise to perform this operation after possibly resetting
00297        some of the high-order bits of a bit-vector. */
00298 
00299     // make copy constructor inaccessible to clients
00300     BitVector(const BitVector& bv);
00301 };
00302 
00303 // BVIter -- An object for iterating over the set bits of a BitVector
00304 //
00305 // A "BVIter" object can be used to iterate over the set bits of a
00306 // "BitVector". If "bv" is a "BitVector", then "BVIter(bv)" is a new
00307 // iterator on the bit vector "bv"; it's "Next()" method can be used
00308 // to return the indices of the set bits in "bv" in increasing order.
00309 // The result of the "Next()" method is undefined if the iterator's
00310 // underlying bit vector is changed after the iterator was constructed.
00311 
00312 class BVIter {
00313   public:
00314     BVIter(const BitVector& bv) throw ()
00315         : bv(&bv), bitIndex(0), wordIndex(0), mask(1UL) { /*SKIP*/ }
00316     /* Initialize a new iterator on the bit vector "bv". */
00317 
00318     bool Next(/*OUT*/ int& res) throw ();
00319     /* Set "res" to the index of the next set bit in the iterator's bit vector
00320        if one exists, and return "true". Otherwise, leave "res" unchanged and
00321        return "false". */
00322 
00323   private:
00324     const BitVector *bv;        // the underlying bit vector
00325     int bitIndex;               // overall bit index
00326     int wordIndex;              // index into BitVector "word" array
00327     Word mask;                  // bit mask
00328 };
00329 
00330 #endif // _BIT_VECTOR_H

Generated on Mon May 8 00:48:31 2006 for Vesta by  doxygen 1.4.2