Follow this link to skip to the main content

bits.h

Go to the documentation of this file.
00001 // -*-c++-*-
00002 //---------------------------< /-/ CLARAty /-/ >------------------------------
00003 /**
00004  * @file  bits.h
00005  *
00006  * Bit field manipulations. Bits are used for Digital I/O
00007  *
00008  * <br>@b Designer(s):  Issa A.D. Nesnas, Won S. Kim
00009  * <br>@b Author(s):    Won S. Kim, Issa A.D. Nesnas
00010  * <br>@b Date:         August 15, 2002
00011  *
00012  * <b>Software License:</b><br>
00013  * <code> http://claraty.jpl.nasa.gov/license/open_src/  or 
00014  *        file: license/open_src.txt </code> 
00015  *
00016  * &copy; 2006, Jet Propulsion Laboratory, California Institute of Technology<br>
00017  *
00018  * $Revision: 1.7 $
00019  */
00020 //-----------------------------------------------------------------------------
00021 
00022 #ifndef BITS_H
00023 #define BITS_H
00024 
00025 #include "claraty/share.h"
00026 
00027 #include <iostream>
00028 #include <string>               // C++ string
00029 
00030 namespace claraty {
00031 
00032 /**
00033  * @defgroup hardware_io I/O
00034  * @ingroup hardware_pkg
00035  *
00036  * Hardware I/O Module
00037  */
00038 //@{
00039 //@}
00040 
00041 /**
00042  *  @ingroup hardware_io
00043  *
00044  *  Based on the STL bitset source code for the single-word specialization.
00045  */
00046 //@{
00047 //@}
00048 
00049 // maximum number of bits --- machine dependent; mostly 32 bits
00050 //
00051 const size_t MAX_BITS = sizeof(unsigned long) * 8;      // # of bytes * 8 bits
00052 
00053 class Bits {
00054 
00055   //
00056   // based on the STL bitset source code for the single-word specialization
00057   //
00058 
00059 public:
00060   class reference;                              // reference to single bit b[i]
00061   friend class reference;
00062 
00063   /** @{ @name Constructors/Destructors */
00064 
00065   Bits(unsigned long val = 0, size_t n_bits = MAX_BITS);        // constructor
00066   explicit Bits(const std::string& str, size_t n_bits = MAX_BITS);      // constructor
00067 
00068   // copy constructor
00069   // Bits(const Bits&)                          // use default copy constructor
00070 
00071 
00072 
00073   // destructor
00074   // ~Bits()                                    // use default destructor
00075   /** @} */
00076 
00077 
00078   /** @{ @name Assignment/index operations */
00079 
00080   // assignment operator
00081   Bits& operator=(const Bits& rhs);             // assignment operator
00082 
00083   // index operator or subscript operator
00084   reference operator[](size_t pos);             // b[i] as an lvalue temporary
00085   bool operator[](size_t pos) const;            // b[i] as const
00086 
00087   /** @} */
00088 
00089   /** @{ @name Bit manipulation operators  */
00090 
00091   Bits& operator&=(const Bits& rhs);            // bitwise AND
00092   Bits& operator|=(const Bits& rhs);            // bitwise OR
00093   Bits& operator^=(const Bits& rhs);            // bitwise EXCLUSIVE-OR
00094   Bits& operator<<=(size_t n);                  // shift left: fill with zeros
00095   Bits& operator>>=(size_t n);                  // shift right: fill with zeros
00096 
00097   // bit manipulation functions
00098 
00099   Bits& set();                                  // set every bit to 1
00100   Bits& set_bit(size_t pos, bool val = true);   // b[pos] = val (default true)
00101   Bits& set_bits(size_t pos, size_t n);         // b[pos] = ... = b[pos+n-1] = 1
00102   Bits& clr();                                  // set every bit to 0
00103   Bits& clr_bit(size_t pos);                    // b[pos] = 0
00104   Bits& clr_bits(size_t pos, size_t n);         // b[pos] = ... = b[pos+n-1] = 0
00105   Bits& toggle();                               // change the value of every bit
00106   Bits& toggle_bit(size_t pos);                 // change the value of b[pos]
00107 
00108   Bits& unchecked_set(unsigned long data);      // b._data = data
00109                                                 // data is assumed sanitized
00110   /** @} */
00111 
00112   // other bit operations that do not change the object (lhs)
00113 
00114   Bits operator<<(size_t n) const;              // for b2 = b1<<3; b1 unchanged
00115   Bits operator>>(size_t n) const;              // for b2 = b1>>3; b1 unchanged
00116   Bits operator~() const;                       // for b2 = ~b1;   b1 unchanged
00117 
00118 
00119   /** @{ @name Bit testing operations */
00120 
00121   bool operator==(const Bits& rhs) const;       // for b1==b2 and for b1==0x14
00122   bool operator!=(const Bits& rhs) const;       // for b1!=b2 and for b1!=0x14
00123   bool test(size_t pos) const;                  // true if b[pos] is 1
00124   bool is_set(size_t pos) const;                // true if b[pos] is 1
00125   bool get_bit(size_t pos) const;               // retrieves b[pos]
00126 
00127   // bool is_set (int pos) const;               // alias for test()
00128   // bool get_bit(size_t pos) const;            // alias for test()
00129   bool any() const;                             // true if any bit is 1
00130   bool none() const;                            // true if no bit is 1
00131 
00132   /** @} */
00133 
00134   //  bit size
00135 
00136   size_t size() const;                          // number of bits
00137 
00138 
00139   // named conversion instead of conversion operators to avoid confusion
00140 
00141   unsigned long to_ulong() const;               // conversion to unsigned long
00142 
00143   std::string to_str() const;
00144 
00145   // printout
00146 
00147   void  print(const char* msg = "") const;      // specially formatted printing
00148 
00149 private:
00150   void _sanitize();                     // zero out the unused high-order bits
00151 
00152 private:
00153   unsigned long _data;                          // bit data
00154   size_t        _Nbits;                         // number of bits --- bit size
00155 };
00156 
00157 //
00158 // static functions to generate the mask bit patterns
00159 //
00160 static unsigned long _maskbit(size_t pos)
00161 {
00162   // only one mask bit at pos is 1;
00163   // mask[pos]=1; all other bits = 0
00164   //
00165   return (static_cast<unsigned long>(1) << pos);
00166 }
00167 //------------------------------------------------------------------------
00168 
00169 static unsigned long _maskbits(size_t pos, size_t n)
00170 {
00171   // n mask bits starting from pos are 1;
00172   // mask[pos] = ... = mask[pos+n-1] = 1; all other bits = 0
00173   //
00174   return (~(~static_cast<unsigned long>(0) << n)) << pos;
00175 }
00176 //------------------------------------------------------------------------
00177 
00178 
00179 //
00180 //  non-member binary operator functions
00181 //
00182 inline Bits operator&(const Bits& lhs, const Bits& rhs);
00183 inline Bits operator|(const Bits& lhs, const Bits& rhs);
00184 inline Bits operator^(const Bits&, const Bits&);
00185 std::ostream& operator<<(std::ostream& ostr, const Bits& rhs);
00186 
00187 
00188 //
00189 //-------------------<< Bits::reference class declaration>>--------------
00190 //
00191 
00192 class Bits::reference
00193 {
00194   //
00195   // Bits::reference class --- reference to a single bit; b[i]
00196   // this nested class is needed, since there is no built-in pointer
00197   //   to address a single bit diretcly
00198   // see p. 492, C++ Programming Language, 3rd ed., Stroustrup
00199   //
00200   friend class Bits;
00201 
00202   unsigned long* _data_p;       // pointer to _data
00203   size_t _bit_pos;                      // bit position
00204 
00205   reference();                  // left undefined; should never be called
00206 
00207 public:
00208   reference(Bits& b, size_t pos);               // constructor
00209   ~reference() {}                               // empty default destructor
00210 
00211   reference& operator= (bool x);                        // for b[i] = x
00212   reference& operator= (const reference& j);            // for b[i] = b[j];
00213   bool operator~ () const;                              // return ~b[i]
00214   operator bool() const;                                // for x = b[i];
00215   reference& toggle();                                  // for b[i].toggle();
00216 };
00217 //------------------------------------------------------------------------
00218 
00219 inline Bits::reference::reference(Bits& b, size_t pos)
00220   : _data_p(&b._data), _bit_pos(pos)
00221 {
00222   // constructor
00223   //
00224   // initialization is all we need
00225 }
00226 //------------------------------------------------------------------------
00227 
00228 
00229 //
00230 //------------------<< Bits::reference inline Functions >>---------------
00231 //
00232 
00233 //
00234 //  bit manipulations using index of b[i]
00235 //
00236 //  b[1] = 0
00237 //  b[2] = b[3]
00238 //  b[2] = ~b[3]
00239 //  b[2].toggle()
00240 //  b[3] = b[1] & b[2]
00241 //  bool x = b[1]
00242 //  b[3] = b[1] | x;
00243 //  bool y = b[1] ^ 1;
00244 //
00245 
00246 inline Bits::reference& Bits::reference::operator= (bool x)
00247 {
00248   // for b[i] = x
00249   //
00250   if ( x )
00251     *_data_p |= _maskbit(_bit_pos);
00252   else
00253     *_data_p &= ~_maskbit(_bit_pos);
00254 
00255   return *this;
00256 }
00257 
00258 inline Bits::reference& Bits::reference::operator= (const Bits::reference& j)
00259 {
00260   // for b[i] = b[j];
00261   //
00262   if ( *j._data_p & _maskbit(j._bit_pos) )
00263     *_data_p |= _maskbit(_bit_pos);
00264   else
00265     *_data_p &= ~_maskbit(_bit_pos);
00266 
00267   return *this;
00268 }
00269 
00270 inline bool Bits::reference::operator~() const
00271 {
00272   // return ~b[i]
00273   //
00274   return (*_data_p & _maskbit(_bit_pos)) == 0;
00275 }
00276 
00277 inline Bits::reference::operator bool() const
00278 {
00279   // for x = b[i]; conversion operator to a built-in type bool
00280   //
00281   return (*_data_p & _maskbit(_bit_pos)) != 0;  // != has precedence over &
00282 }
00283 
00284 inline Bits::reference& Bits::reference::toggle()
00285 {
00286   // for b[i].toggle();
00287   //
00288   *_data_p ^= _maskbit(_bit_pos);
00289   return *this;
00290 }
00291 
00292 
00293 //
00294 //-------------------------<< Bits inline Functions >>-------------------
00295 //
00296 
00297 //
00298 // Constructors
00299 //
00300 inline Bits::Bits (unsigned long val, size_t n_bits)
00301    : _data(val), _Nbits(n_bits)
00302 {
00303   // Constructor
00304   //
00305   // default args:
00306   //   unsigned long val = 0
00307   //   size_t n_bits = MAX_BITS = sizeof(unsigned long)
00308   //
00309   // input args:
00310   //    unsigned long val --- bit pattern in hexadecimal/octal/decimal number
00311   //    size_t n_bits --- number of bits ( >= MAX_BITS )
00312   //
00313   // Bits b1;                   // b1 = 0000 0000 0000 0000 (_Nbits = MAX_BITS)
00314   // Bits b1(0x14);             // b1 = 0000 0000 0001 0100 (_Nbits = MAX_BITS)
00315   // Bits b1 = 0x14;            // same as above (not using assignment operator)
00316   // Bits b1(0x14, 5);          // b1 = ---- ---- ---1 0100 (_Nbits = 5)
00317   //
00318   // Bits(unsigned long) allows automatic type conversion from "unsigned long"
00319   //   to "Bits" with _Nbits = MAX_BITS
00320   //
00321   if ((int) _Nbits > (int) MAX_BITS) {
00322     // throw out_of_range("Bits::Bits");
00323     // For now, clamp to MAX_BITS and let user check size to see if it worked.
00324     _Nbits = MAX_BITS;
00325     std::cerr << "THROW ERROR: out_of_range - Bits::Bits" << std::endl;
00326   } else {
00327       _sanitize();
00328   }
00329 }
00330 
00331 //------------------------------------------------------------------------
00332 
00333 //
00334 // Bits(0, ...) ambiguity problem between unsigned long and char
00335 //   for input argument 0. To avoid this ambiguity, char* must be
00336 //   replaced by string STL.
00337 inline Bits::Bits (const std::string& str, size_t n_bits)
00338   : _Nbits(n_bits)
00339 {
00340   // Constructor
00341   //
00342   // default args:
00343   //   size_t n_bits = MAX_BITS = sizeof(unsigned long)
00344   //
00345   // input args:
00346   //    unsigned char* str ---binary-format number, e.g, "0100 0111 0000 1010"
00347   //    size_t n_bits --- number of bits ( >= MAX_BITS )
00348   //
00349   // explicit: no implicit automatic conversion allowed from char* str to Bits;
00350   //   Bits(const char* str) must be explicitly used for the conversion
00351   //
00352   // Bits b1("");               // b1 = 0000 0000 0000 0000 (_Nbits = MAX_BITS)
00353   // Bits b2("01 0100");        // b1 = 0000 0000 0001 0100 (_Nbits = MAX_BITS)
00354   // Bits b2("01 0100", 5);     // b1 = ---- ---- ---1 0100 (_Nbits = 5)
00355   //
00356   if ((int) _Nbits > (int) MAX_BITS)
00357     // throw out_of_range("Bits::Bits");
00358     std::cerr << "THROW ERROR: out_of_range - Bits::Bits" << std::endl;
00359 
00360   _data = 0;    // clear all bits initially
00361 
00362   int i = 0;    // bit index
00363 
00364   // for (int j = strlen(str) - 1; j >= 0; j--) {
00365   for (int j = str.length() - 1; j >= 0; j--) {
00366 
00367     switch (str[j]) {
00368     case '0':
00369       i++;
00370       break;
00371     case '1':           // set bit[i] of _data = 1
00372       _data |= _maskbit(i);
00373       i++;
00374       break;
00375     case ' ':           // skip space
00376       break;
00377     default:
00378       // throw invalid_argument("Bits::Bits");
00379       std::cerr << "THROW ERROR: invalid_argument - Bits::Bits" << std::endl;
00380     }
00381 
00382     if (i >= (int) _Nbits) {                    // warning ??????
00383       std::cerr << "Warning: input data too large" << std::endl;
00384       break;
00385     }
00386   }
00387 }
00388 
00389 //
00390 // Copy constructor
00391 //
00392 
00393 // Bits::Bits (const Bits&)
00394 // {
00395   // Copy constructor
00396   //
00397   // Bits b2(b1);       // construct b2 and copy b1 into b2; copy _Nbits too
00398   // Bits b2 = b1;      // performs Bits b2(b1), not the Assignment operator
00399   //
00400   // func (Bits b1);    // passing a Bits object by value to func()
00401   // Bits b2 = func (); // returning a Bits object by value from func()
00402   //
00403   // use the compiler-synthesized default copy constructor --- it simply copies
00404   //   all data members from an existing object into the new object;
00405   //   it could be equivalently written as:
00406   //
00407   //   Bits::Bits (const Bits& b) : _data(b._data), _Nbits(b._Nbits) {}
00408 // }
00409 //------------------------------------------------------------------------
00410 
00411 
00412 //
00413 // Assignment operator
00414 //
00415 
00416 inline Bits& Bits::operator= (const Bits& rhs)
00417 {
00418   // Assignment operator
00419   //
00420   // b2 = b1;           // copies _data, but not _Nbits; zeroes out unused bits
00421   // b2 = 0x14;         // first does automatic conversion using Bits(0x14)
00422   //
00423   // cannot not use the compiler-synthesized default assignment operator that
00424   //   copies both the _data and _Nbits member data; it is desirable to keep
00425   //   _Nbits unchanged and zero out the unused high-order bits accordingly;
00426   //   the idea is similar to the assignment statement that involves
00427   //   automatic type conversion (e.g., between char and int)
00428   //
00429   _data = rhs._data;
00430   _sanitize();          // zero out the unused high-order bits
00431   return *this;
00432 }
00433 //------------------------------------------------------------------------
00434 
00435 
00436 //
00437 // Destructor
00438 //
00439 
00440 // inline ~Bits()
00441 // {
00442   // Destructor
00443   //
00444   // The only work needed is to destroy data members, and the system does
00445   //   the work automatically; Since there is no other work needed,
00446   //   use the compiler-synthesized "empty-body" default destructor, which
00447   //   is equivalently written as:
00448   //
00449   //   ~Bits() {}
00450 // }
00451 //------------------------------------------------------------------------
00452 
00453 
00454 //
00455 // index operator (subscript operator) --- b[i]
00456 //
00457 inline Bits::reference Bits::operator[](size_t pos)
00458 {
00459   // single bit element access using b[i] used as lvalue
00460   // - it sets the member data  _bit_pos = pos first, and then
00461   //   returns an lvalue temporay object of type "reference" not "reference&"
00462   // - the returned temporary object together with the assigment operators
00463   //     Bits::reference& Bits::reference::operator=(const reference&) and
00464   //     Bits::reference& Bits::reference::operator=(bool)
00465   //   enables such statement as
00466   //     b[i] = b[j] = 1;
00467   //   After the execution, the i-th and j-th bits of b (a Bits object) are
00468   //   set to 1, and the temporary "reference" object created by b[i]
00469   //   dissappears.
00470   //
00471   return reference(*this, pos);
00472 }
00473 //------------------------------------------------------------------------
00474 
00475 inline bool Bits::operator[](size_t pos) const
00476 {
00477   // single bit element access using b[i]
00478   // - when returning a built-in type by value, it automatically implies
00479   //   a "const" return; it returns a value not a variable; namely,
00480   //   bool f() is the same as const bool f()
00481   // - the "const" return type cannot be a lvalue
00482   //
00483   return (_data & _maskbit(pos)) != 0;
00484 }
00485 //------------------------------------------------------------------------
00486 
00487 
00488 //
00489 // Bit manipulation operators --- &=, |=, ^=, <<=, >>= (compound-assignment ops)
00490 // - the left operand is updated, and is returned by reference (Bits&)
00491 // - self-reference --- returns the updated self object *this
00492 //   by reference Bits&;
00493 //
00494 //   b1 &= b2;
00495 //   b1 |= 0x14;        // first does the automatic conversion using Bits(0x14)
00496 //   b1 ^= b2;
00497 //   b1 <<= 2;
00498 //   b1 >>= 3;
00499 //
00500 
00501 inline  Bits& Bits::operator&= (const Bits& rhs)
00502 {
00503   // bitwise AND
00504   //
00505   _data &= rhs._data;           // _sanitize unnecessary
00506   return *this;
00507 }
00508 //------------------------------------------------------------------------
00509 
00510 inline  Bits& Bits::operator|= (const Bits& rhs)
00511 {
00512   // bitwise OR
00513   //
00514   _data |= rhs._data;
00515   _sanitize();
00516   return *this;
00517 }
00518 //------------------------------------------------------------------------
00519 
00520 inline  Bits& Bits::operator^= (const Bits& rhs)
00521 {
00522   // bitwise EXCLUSIVE-OR
00523   //
00524   _data ^= rhs._data;
00525   _sanitize();
00526   return *this;
00527 }
00528 //------------------------------------------------------------------------
00529 
00530 inline  Bits& Bits::operator<<= (size_t n)
00531 {
00532   // shift left: fill with zeros
00533   //
00534   _data <<= n;
00535   _sanitize();
00536   return *this;
00537 }
00538 //------------------------------------------------------------------------
00539 
00540 inline  Bits& Bits::operator>>= (size_t n)
00541 {
00542   // shift right: fill with zeros
00543   //
00544   _data >>= n;
00545   _sanitize();
00546   return *this;
00547 }
00548 //------------------------------------------------------------------------
00549 
00550 
00551 //
00552 // Bit manipulation functions --- set, clr, and toggle.
00553 //
00554 // self-reference --- returns the updated self object *this by reference
00555 //   Bits& (not Bits); this enables chaining (concatenation) of functions,
00556 //   for instance,
00557 //
00558 //   b1.set_bit(1).set_bit(3).clr_bit(4)
00559 //
00560 //   b1.set()           // b1 = ~0
00561 //   b1.set_bit(3)      // b[3] = 1
00562 //   b1.set_bits(2,3);  // b1[2] = b1[3] = b[4] = 1
00563 //   b1.clr()           // b1 = 0
00564 //   b1.clr_bit(3)      // b[3] = 0
00565 //   b1.clr_bits(2,3)   // b1[2] = b1[3] = b[4] = 0
00566 //   b1.toggle()        // b1 = ~b1
00567 //   b1.toggle_bit(3)   // b[3] = ~b[3]
00568 //
00569 inline  Bits& Bits::set()
00570 {
00571   // set every bit to 1
00572   //
00573   _data = ~static_cast<unsigned long>(0);
00574   _sanitize();
00575   return *this;
00576 }
00577 //------------------------------------------------------------------------
00578 
00579 // Bits& Bits::set_bit(size_t pos, bool val = true)
00580 inline  Bits& Bits::set_bit(size_t pos, bool val)
00581 {
00582   // b[pos] = val; don't change other bits
00583   // default bool val = true; b[pos] = 1 (set to 1)
00584   //
00585   if (pos >= _Nbits)
00586     // throw out_of_range("Bits::set_bit");
00587     std::cerr << "Bits WARNING: out_of_range - Bits::set_bit" << std::endl;
00588 
00589   if (val)
00590     _data |= _maskbit(pos);
00591   else
00592     _data &= ~_maskbit(pos);
00593 
00594   return *this;
00595 }
00596 //------------------------------------------------------------------------
00597 
00598 inline  Bits& Bits::set_bits(size_t pos, size_t n)
00599 {
00600   // extension from STL bitset
00601   // b[pos] =  ... = b[pos+n-1] = 1; don't change other bits
00602   //
00603   if (pos + n > _Nbits)                 // + has precedence over >=
00604     // throw out_of_range("Bits::set_bits");
00605     std::cerr << "Bits WARNING: out_of_range - Bits::set_bits" << std::endl;
00606 
00607   _data |= _maskbits(pos, n);
00608 
00609   return *this;
00610 }
00611 //------------------------------------------------------------------------
00612 
00613 inline  Bits& Bits::clr()
00614 {
00615   // set every bit to 0 (clear all bits)
00616   //
00617   _data = 0;
00618   return *this;
00619 }
00620 //------------------------------------------------------------------------
00621 
00622 inline  Bits& Bits::clr_bit(size_t pos)
00623 {
00624   // b[pos] = 0 (clear one bit)
00625   //
00626   if (pos >= _Nbits)
00627     // throw out_of_range("Bits::clr_bit");
00628     std::cerr << "Bits WARNING: out_of_range - Bits::clr_bit" << std::endl;
00629 
00630   _data &= ~_maskbit(pos);
00631 
00632   return *this;
00633 }
00634 //------------------------------------------------------------------------
00635 
00636 inline  Bits& Bits::clr_bits(size_t pos, size_t n)
00637 {
00638   // extension from STL bitset
00639   // b[pos] =  ... = b[pos+n-1] = 0; don't change other bits
00640   //
00641   if (pos + n > _Nbits)         // + has precedence over >=
00642     // throw out_of_range("Bits::clr_bits");
00643     std::cerr << "Bits WARNING: out_of_range - Bits::clr_bits" << std::endl;
00644 
00645   _data &= ~_maskbits(pos, n);
00646 
00647   return *this;
00648 }
00649 //------------------------------------------------------------------------
00650 
00651 inline  Bits& Bits::toggle()
00652 {
00653   // change the value of every bit
00654   //
00655   _data = ~_data;
00656   _sanitize();
00657 
00658   return *this;
00659 }
00660 //------------------------------------------------------------------------
00661 
00662 inline  Bits& Bits::toggle_bit(size_t pos)
00663 {
00664   // change the value of b[pos]
00665   //
00666   if (pos >= _Nbits)
00667     // throw out_of_range("Bits::toggle_bit");
00668     std::cerr << "Bits WARNING: out_of_range - Bits::toggle_bit" << std::endl;
00669 
00670   _data ^= _maskbit(pos);
00671   return *this;
00672 }
00673 //------------------------------------------------------------------------
00674 
00675 inline Bits& Bits::unchecked_set(unsigned long data)
00676 {
00677   _data = data;                 // user must ensure data is sanitized
00678   // _sanitize();               // does not do data sanity check
00679 
00680   return *this;
00681 }
00682 //------------------------------------------------------------------------
00683 
00684 
00685 
00686 //
00687 // Access function
00688 //
00689 inline size_t Bits::size() const
00690 {
00691   // get bit size
00692   //
00693   return _Nbits;                                // number of bits
00694 }
00695 //------------------------------------------------------------------------
00696 
00697 // REPLACE WITH OPERATOR
00698 // Type conversion
00699 //
00700 // named conversions are provided instead of conversion operators
00701 //   to avoid conversion confusions between Bits and built-in types
00702 //
00703 inline unsigned long Bits::to_ulong() const
00704 {
00705   // conversion to unsigned long
00706   //
00707   // unsigned long x = b1.to_ulong();
00708   // unsigned short y = b1.to_ulong();
00709   // unsigned char z = b1.to_ulong();
00710   // BYTE z = b1.to_ulong();                    // BYTE = unsigned char
00711   //
00712   return _data;
00713 }
00714 //------------------------------------------------------------------------
00715 
00716 
00717 //
00718 // Other operators:
00719 // - evaluates the expression and retuns by value without changing
00720 //   the original object
00721 //
00722 
00723 inline  bool Bits::operator==(const Bits& rhs) const
00724 {
00725   // for b1==b2 and also for b1==0x14
00726   // compare _data only not _Nbits
00727   //
00728   return _data == rhs._data;
00729 }
00730 //------------------------------------------------------------------------
00731 
00732 inline  bool Bits::operator!=(const Bits& rhs) const
00733 {
00734   // for b1!=b2 and also for b1!=0x14
00735   // compare _data only not _Nbits
00736   //
00737   return _data != rhs._data;
00738 }
00739 //------------------------------------------------------------------------
00740 
00741 inline bool
00742 Bits::test(size_t pos) const
00743 {
00744   // true if b[pos] is 1
00745   //
00746   if (pos >= _Nbits)
00747     // throw out_of_range("Bits::test");
00748     std::cerr << "THROW ERROR: out_of_range - Bits::test" << std::endl;
00749 
00750   return (_data & _maskbit(pos)) != 0;
00751 }
00752 //------------------------------------------------------------------------
00753 
00754 inline bool
00755 Bits::is_set(size_t pos) const
00756 {
00757     return test(pos);
00758 }
00759 //------------------------------------------------------------------------
00760 
00761 inline bool
00762 Bits::get_bit(size_t pos) const
00763 {
00764     return test(pos);
00765 }
00766 //------------------------------------------------------------------------
00767 
00768 inline  bool Bits::any() const
00769 {
00770   // true if any bit is 1
00771   //
00772   return _data != 0;
00773 }
00774 //------------------------------------------------------------------------
00775 
00776 inline  bool Bits::none() const
00777 {
00778   // true if no bit is 1
00779   //
00780   return _data == 0;
00781 }
00782 //------------------------------------------------------------------------
00783 
00784 inline  Bits Bits::operator<<(size_t n) const
00785 {
00786   // for return (b1<<3) and also for b2 = b1<<3; b1 unchanged
00787   // make a left-shifted copy without changing the original object (*this)
00788   // e.g., the statement b2 = b1 << 3 should not change b1.
00789   // returns the updated object by value (Bits), not by reference (Bits&)
00790   //
00791   return Bits(*this) <<= n;
00792 }
00793 //------------------------------------------------------------------------
00794 
00795 inline  Bits Bits::operator>>(size_t n) const
00796 {
00797   // for return (b1>>3) and also for b2 = b1>>3; b1 unchanged
00798   // make right-shifted set
00799   //
00800   return Bits(*this) >>= n;
00801 }
00802 //------------------------------------------------------------------------
00803 
00804 inline  Bits Bits::operator~() const
00805 {
00806   // for return (~b1) and also for b2 = ~b1; b1 unchanged
00807   // make complement set
00808   //
00809   return Bits(*this).toggle();
00810 }
00811 //------------------------------------------------------------------------
00812 
00813 
00814 inline void Bits::_sanitize()
00815 {
00816   // zero out the unused high-order bits
00817   //
00818   if (_Nbits != MAX_BITS)
00819     _data &= ~( ~static_cast<unsigned long>(0) << _Nbits );
00820 }
00821 //------------------------------------------------------------------------
00822 
00823 
00824 //
00825 //  non-member binary operator functions
00826 //
00827 // inline Bits operator&(const Bits& lhs, const Bits& rhs);
00828 // inline Bits operator|(const Bits& lhs, const Bits& rhs);
00829 // inline Bits operator^(const Bits&, const Bits&);
00830 // ostream& operator<<(ostream& ostr, const Bits& rhs);
00831 //
00832 
00833 inline Bits operator&(const Bits& lhs, const Bits& rhs)
00834 {
00835   Bits tmp = lhs;
00836 
00837   tmp &= rhs;
00838   return tmp;
00839 }
00840 
00841 inline Bits operator|(const Bits& lhs, const Bits& rhs)
00842 {
00843   Bits tmp = lhs;
00844 
00845   tmp |= rhs;
00846   return tmp;
00847 }
00848 
00849 inline Bits operator^(const Bits& lhs, const Bits& rhs)
00850 {
00851   Bits tmp = lhs;
00852 
00853   tmp ^= rhs;
00854   return tmp;
00855 }
00856 //-------------------------------------------------------------------------
00857 
00858 //------------------------------------------------------------------------
00859 //-------------------< Auto-Generated Operators >-------------------------
00860 //------------------------------------------------------------------------
00861 // - Need to uncomment and test on all rovers in order to have a complete set
00862 //   of bit functionality - IAN
00863 //#define CL_OP_TYPE Bits
00864 //#define CL_OP_MODE CL_BITS_OP_MODE
00865 //#include "claraty_opgen.h"
00866 
00867 } // namespace claraty
00868 
00869 #endif // __BITS_H