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 * © 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