00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
00160 val = r.val;
00161 return *this;
00162 }
00163
00164 const PTBitVec& operator =(const T& v)
00165 {
00166
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
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
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
00337 unsigned offset = bref.offset(rb);
00338 ASSERT_TRUE(offset < stMaxBits);
00339 T mask = onesMask(lb, rb) << offset;
00340 val &= ~mask;
00341 T v2 = v;
00342 v2 <<= offset;
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
00357
00358 };
00359
00360 #endif //defined(_xyzzy_bitvec_hxx_)