bitvec.hxx

Go to the documentation of this file.
00001 /*
00002  *   xyzzy
00003  *   Copyright (C) 2007    Karl W. Pfalzer
00004  *
00005  *   This program is free software; you can redistribute it and/or
00006  *   modify it under the terms of the GNU General Public License
00007  *   as published by the Free Software Foundation; either version 2
00008  *   of the License, or (at your option) any later version.
00009  *
00010  *   This program 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
00013  *   GNU General Public License for more details.
00014  *
00015  *   You should have received a copy of the GNU General Public License
00016  *   along with this program; if not, write to the
00017  *   Free Software Foundation, Inc.
00018  *   51 Franklin Street, Fifth Floor
00019  *   Boston, MA  02110-1301, USA.
00020  */
00021 #if !defined(_xyzzy_bitvec_hxx_)
00022 #    define  _xyzzy_bitvec_hxx_
00023 
00024 #include "xyzzy/portable.hxx"
00025 #include "xyzzy/exception.hxx"
00026 #include "xyzzy/assert.hxx"
00027 #include "xyzzy/util.hxx"
00028 
00029 namespace xyzzy
00030 {
00031 
00032 //  Base class
00033 class TBvBase
00034 {
00035 public:
00036     unsigned length() const
00037     {
00038         return length(lb, rb);
00039     }
00040 
00041     bool isDescending() const
00042     {
00043         return isDescending(lb, rb);
00044     }
00045 
00046     unsigned left() const
00047     {
00048         return lb;
00049     }
00050 
00051     unsigned right() const
00052     {
00053         return rb;
00054     }
00055 
00059     unsigned offset(unsigned right) const;
00060 
00064     bool checkBounds(unsigned left, unsigned right) const;
00065 
00066     static unsigned length(unsigned left, unsigned right);
00067 
00068     static bool isDescending(unsigned left, unsigned right)
00069     {
00070         return (left >= right);
00071     }
00072 
00073 protected:
00074     explicit TBvBase(unsigned lb, unsigned rb)
00075     :   lb(lb), rb(rb)
00076     {}
00077 
00078     const unsigned  lb, rb;
00079 
00080 private:
00081 };
00082 
00093 template<typename T>
00094 class PTBitVecMethods
00095 {
00096 public:
00100     static const T& assign(T& lhs);
00104     static const T& assign(T& lhs, const TBvBase& bref, const T v);
00108     static T assign(T& lhs, const TBvBase& bref, const T& v,
00109                     unsigned lb, unsigned rb);
00113     static T valueAt(const T& v, const TBvBase& bref,
00114                      unsigned lb, unsigned rb);
00118     static bool valueAt(const T& v, const TBvBase& bref, unsigned ix);
00122     static unsigned getMaxBits();
00123     
00124     static const unsigned stMaxBits;
00125 
00126     static const T stAllOnes;
00127 
00128 private:
00129     static T onesMask(unsigned lb, unsigned rb);
00130 };
00131 
00132 template<typename T>
00133 class PTBitVec : public TBvBase
00134 {
00135 public:
00136     explicit PTBitVec(unsigned lb, unsigned rb)
00137     :   TBvBase(lb, rb)
00138     {
00139         invariant(PTBitVecMethods<T>::stMaxBits >= length());
00140         PTBitVecMethods<T>::assign(val);
00141     }
00142 
00143     explicit PTBitVec(unsigned len)
00144     :   TBvBase(len - 1, 0)
00145     {
00146         invariant(PTBitVecMethods<T>::stMaxBits >= length());
00147         PTBitVecMethods<T>::assign(val);
00148     }
00149 
00150     explicit PTBitVec(const PTBitVec& r)
00151     :   TBvBase(r.lb, r.rb)
00152     {
00153         invariant(PTBitVecMethods<T>::stMaxBits >= length());
00154         PTBitVecMethods<T>::assign(val, *this, r.val);
00155     }
00156     
00157     const PTBitVec& operator =(const PTBitVec& r)
00158     {
00159         //TODO: range check !
00160         val = r.val;
00161         return *this;
00162     }
00163     
00164     const PTBitVec& operator =(const T& v)
00165     {
00166         //TODO: valid range check
00167         PTBitVecMethods<T>::assign(val, *this, v);
00168         return *this;
00169     }
00170     
00175     class TAccessor
00176     {
00177     private:
00178         explicit TAccessor(PTBitVec &r, unsigned lb, unsigned rb)
00179         :   ref(r), lb(lb), rb(rb)
00180         {}
00181 
00182     public:
00183         operator T() const
00184         {
00185             return PTBitVecMethods<T>::valueAt(ref.val, ref, lb, rb);
00186         }
00187 
00188         T operator =(const TAccessor& v)
00189         {
00190             //T vt = v;
00191             return PTBitVecMethods<T>::assign(ref.val, ref, v, lb, rb);
00192         }
00193 
00194         T operator =(const T& v)
00195         {
00196             return PTBitVecMethods<T>::assign(ref.val, ref, v, lb, rb);
00197         }
00198 
00199     private:
00200         PTBitVec&   ref;
00201         unsigned    lb, rb;
00202 
00203         friend class PTBitVec;
00204     };
00205 
00206     TAccessor operator ()(unsigned l, unsigned r)
00207     {
00208         return TAccessor(*this, l, r);
00209     }
00210 
00211     TAccessor operator ()(unsigned ix)
00212     {
00213         return TAccessor(*this, ix, ix);
00214     }
00215 
00216     TAccessor operator [](unsigned ix)
00217     {
00218         return operator()(ix);
00219     }
00220 
00221     operator T () const
00222     {
00223         return val;
00224     }
00225 
00226 private:
00227     T   val;
00228 
00229     friend class TAccessor;
00230 };
00231 
00232 #define GEN_BOUNDS(lb_, rb_) (rb_ != ~0u) ? lb_ : (lb_-1), (rb_ != ~0u) ? rb_ : 0
00233 
00237 template<unsigned LB, unsigned RB = ~0>
00238 class TBitVec : public PTBitVec<TUint32>
00239 {
00240 public:
00241     explicit TBitVec()
00242     :   PTBitVec<TUint32>(GEN_BOUNDS(LB,RB))
00243     {}
00244 
00249     TBitVec(TUint32 n)
00250     :   PTBitVec<TUint32>(GEN_BOUNDS(LB,RB))
00251     {
00252         PTBitVec<TUint32>::operator =(n);
00253     }
00254     
00255     const TBitVec& operator =(TUint32 v)
00256     {
00257         PTBitVec<TUint32>::operator =(v);
00258         return *this;
00259     }
00260 };
00261 
00265 template<unsigned LB, unsigned RB = ~0>
00266 class TBitVec64 : public PTBitVec<TUint64>
00267 {
00268 public:
00269     explicit TBitVec64()
00270     :   PTBitVec<TUint64>(GEN_BOUNDS(LB,RB))
00271     {}
00272 
00277     TBitVec64(TUint64 n)
00278     :   PTBitVec<TUint64>(GEN_BOUNDS(LB,RB))
00279     {
00280         PTBitVec<TUint64>::operator =(n);
00281     }
00282     
00283     const TBitVec64& operator =(TUint64 v)
00284     {
00285         PTBitVec<TUint64>::operator =(v);
00286         return *this;
00287     }
00288 };
00289 
00290 #undef GEN_BOUNDS
00291 
00292 // BEGIN: template definitions
00293 template<typename T>
00294 const T&
00295 PTBitVecMethods<T>::assign(T& lhs)
00296 {
00297     lhs = 0xdeadbeef;
00298     return lhs;
00299 }
00300 
00301 template<typename T>
00302 T 
00303 PTBitVecMethods<T>::onesMask(unsigned lb, unsigned rb)
00304 {
00305     const unsigned n = TBvBase::length(lb, rb);
00306     return ~((stMaxBits == n) ? 0 : (stAllOnes << n));
00307 }
00308 
00309 template<typename T>
00310 const T&
00311 PTBitVecMethods<T>::assign(T& lhs, const TBvBase& bref, 
00312                            const T v)
00313 {
00314     lhs = v & onesMask(bref.left(), bref.right());
00315     return lhs;
00316 }
00317 
00318 template<typename T>
00319 T
00320 PTBitVecMethods<T>::valueAt(const T& v, const TBvBase& bref,
00321                             unsigned lb, unsigned rb)
00322 {
00323     bref.checkBounds(lb, rb);
00324     T rval = (v >> bref.offset(rb)) & onesMask(lb, rb);
00325     return rval;
00326 }
00327 
00328 template<typename T>
00329 T
00330 PTBitVecMethods<T>::assign(T& lhs, const TBvBase& bref, 
00331                            const T& v,
00332                            unsigned lb, unsigned rb)
00333 {
00334     bref.checkBounds(lb, rb);
00335     T val = lhs;
00336     // zero out bit slots we will set
00337     unsigned offset = bref.offset(rb);
00338     ASSERT_TRUE(offset < stMaxBits);
00339     T mask = onesMask(lb, rb) << offset; // mask <= 1s covering [lb,rb]
00340     val &= ~mask;    // val <= zero out [lb,rb]
00341     T v2 = v;
00342     v2 <<= offset;  // ...v000
00343     v2 &= mask;
00344     val |= v2;
00345     lhs = val;
00346     return valueAt(lhs, bref, lb, rb);
00347 }
00348 
00349 template<typename T>
00350 bool
00351 PTBitVecMethods<T>::valueAt(const T& v, const TBvBase& bref,
00352                             unsigned ix)
00353 {
00354     return (0 != valueAt(v, bref, ix, ix)) ? true : false;
00355 }
00356 // END: template definitions
00357 
00358 };
00359 
00360 #endif //defined(_xyzzy_bitvec_hxx_)

Generated on Thu Mar 22 13:51:07 2007 for anvil by  doxygen 1.5.1