00001 // Filename: bitMask.I 00002 // Created by: drose (08Jun00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 template<class WordType, int num_bits> 00020 TypeHandle BitMask<WordType, num_bits>::_type_handle; 00021 00022 //////////////////////////////////////////////////////////////////// 00023 // Function: BitMask::Constructor 00024 // Access: Published 00025 // Description: 00026 //////////////////////////////////////////////////////////////////// 00027 template<class WordType, int num_bits> 00028 INLINE BitMask<WordType, num_bits>:: 00029 BitMask() : 00030 _word(0) 00031 { 00032 } 00033 00034 //////////////////////////////////////////////////////////////////// 00035 // Function: BitMask::Constructor 00036 // Access: Published 00037 // Description: 00038 //////////////////////////////////////////////////////////////////// 00039 template<class WordType, int num_bits> 00040 INLINE BitMask<WordType, num_bits>:: 00041 BitMask(WordType init_value) : 00042 _word(init_value) 00043 { 00044 } 00045 00046 //////////////////////////////////////////////////////////////////// 00047 // Function: BitMask::Copy Constructor 00048 // Access: Published 00049 // Description: 00050 //////////////////////////////////////////////////////////////////// 00051 template<class WordType, int num_bits> 00052 INLINE BitMask<WordType, num_bits>:: 00053 BitMask(const BitMask<WordType, num_bits> ©) : 00054 _word(copy._word) 00055 { 00056 } 00057 00058 //////////////////////////////////////////////////////////////////// 00059 // Function: BitMask::Copy Assignment Operator 00060 // Access: Published 00061 // Description: 00062 //////////////////////////////////////////////////////////////////// 00063 template<class WordType, int num_bits> 00064 INLINE void BitMask<WordType, num_bits>:: 00065 operator = (const BitMask<WordType, num_bits> ©) { 00066 _word = copy._word; 00067 } 00068 00069 //////////////////////////////////////////////////////////////////// 00070 // Function: BitMask::Named all_on constructor 00071 // Access: Published, Static 00072 // Description: Returns a BitMask whose bits are all on. 00073 //////////////////////////////////////////////////////////////////// 00074 template<class WordType, int num_bits> 00075 INLINE BitMask<WordType, num_bits> BitMask<WordType, num_bits>:: 00076 all_on() { 00077 BitMask result; 00078 result._word = ~0; 00079 return result; 00080 } 00081 00082 //////////////////////////////////////////////////////////////////// 00083 // Function: BitMask::Named all_on constructor 00084 // Access: Published, Static 00085 // Description: Returns a BitMask whose bits are all off. 00086 //////////////////////////////////////////////////////////////////// 00087 template<class WordType, int num_bits> 00088 INLINE BitMask<WordType, num_bits> BitMask<WordType, num_bits>:: 00089 all_off() { 00090 BitMask result; 00091 result._word = 0; 00092 return result; 00093 } 00094 00095 //////////////////////////////////////////////////////////////////// 00096 // Function: BitMask::Named lower_on constructor 00097 // Access: Published, Static 00098 // Description: Returns a BitMask whose lower num_bits bits are on. 00099 //////////////////////////////////////////////////////////////////// 00100 template<class WordType, int num_bits> 00101 INLINE BitMask<WordType, num_bits> BitMask<WordType, num_bits>:: 00102 lower_on(int on_bits) { 00103 if (on_bits <= 0) { 00104 return all_off(); 00105 } else if (on_bits >= num_bits) { 00106 return all_on(); 00107 } 00108 BitMask result; 00109 result._word = ((WordType)1 << on_bits) - 1; 00110 return result; 00111 } 00112 00113 //////////////////////////////////////////////////////////////////// 00114 // Function: BitMask::Named bit constructor 00115 // Access: Published, Static 00116 // Description: Returns a BitMask with only the indicated bit on. 00117 //////////////////////////////////////////////////////////////////// 00118 template<class WordType, int num_bits> 00119 INLINE BitMask<WordType, num_bits> BitMask<WordType, num_bits>:: 00120 bit(int index) { 00121 BitMask result; 00122 result.set_bit(index); 00123 return result; 00124 } 00125 00126 //////////////////////////////////////////////////////////////////// 00127 // Function: BitMask::Destructor 00128 // Access: Published 00129 // Description: 00130 //////////////////////////////////////////////////////////////////// 00131 template<class WordType, int num_bits> 00132 INLINE BitMask<WordType, num_bits>:: 00133 ~BitMask() { 00134 } 00135 00136 //////////////////////////////////////////////////////////////////// 00137 // Function: BitMask::get_num_bits 00138 // Access: Published 00139 // Description: Returns the number of bits available to set in the 00140 // bitmask. 00141 //////////////////////////////////////////////////////////////////// 00142 template<class WordType, int num_bits> 00143 INLINE int BitMask<WordType, num_bits>:: 00144 get_num_bits() const { 00145 return num_bits; 00146 } 00147 00148 //////////////////////////////////////////////////////////////////// 00149 // Function: BitMask::get_bit 00150 // Access: Published 00151 // Description: Returns true if the nth bit is set, false if it is 00152 // cleared. index must be in the range [0, 00153 // get_num_bits). 00154 //////////////////////////////////////////////////////////////////// 00155 template<class WordType, int num_bits> 00156 INLINE bool BitMask<WordType, num_bits>:: 00157 get_bit(int index) const { 00158 nassertr(index >= 0 && index < num_bits, false); 00159 return (_word & ((WordType)1 << index)) != 0; 00160 } 00161 00162 //////////////////////////////////////////////////////////////////// 00163 // Function: BitMask::set_bit 00164 // Access: Published 00165 // Description: Sets the nth bit on. index must be in the range 00166 // [0, get_num_bits). 00167 //////////////////////////////////////////////////////////////////// 00168 template<class WordType, int num_bits> 00169 INLINE void BitMask<WordType, num_bits>:: 00170 set_bit(int index) { 00171 nassertv(index >= 0 && index < num_bits); 00172 _word |= ((WordType)1 << index); 00173 } 00174 00175 //////////////////////////////////////////////////////////////////// 00176 // Function: BitMask::clear_bit 00177 // Access: Published 00178 // Description: Sets the nth bit off. index must be in the range 00179 // [0, get_num_bits). 00180 //////////////////////////////////////////////////////////////////// 00181 template<class WordType, int num_bits> 00182 INLINE void BitMask<WordType, num_bits>:: 00183 clear_bit(int index) { 00184 nassertv(index >= 0 && index < num_bits); 00185 _word &= ~((WordType)1 << index); 00186 } 00187 00188 //////////////////////////////////////////////////////////////////// 00189 // Function: BitMask::set_bit_to 00190 // Access: Published 00191 // Description: Sets the nth bit either on or off, according to the 00192 // indicated bool value. index must be in the range [0, 00193 // get_num_bits). 00194 //////////////////////////////////////////////////////////////////// 00195 template<class WordType, int num_bits> 00196 INLINE void BitMask<WordType, num_bits>:: 00197 set_bit_to(int index, bool value) { 00198 if (value) { 00199 set_bit(index); 00200 } else { 00201 clear_bit(index); 00202 } 00203 } 00204 00205 //////////////////////////////////////////////////////////////////// 00206 // Function: BitMask::is_zero 00207 // Access: Published 00208 // Description: Returns true if the entire bitmask is zero, false 00209 // otherwise. 00210 //////////////////////////////////////////////////////////////////// 00211 template<class WordType, int num_bits> 00212 INLINE bool BitMask<WordType, num_bits>:: 00213 is_zero() const { 00214 return (_word == 0); 00215 } 00216 00217 //////////////////////////////////////////////////////////////////// 00218 // Function: BitMask::extract 00219 // Access: Published 00220 // Description: Returns a word that represents only the indicated 00221 // range of bits within this BitMask, shifted to the 00222 // least-significant position. 00223 //////////////////////////////////////////////////////////////////// 00224 template<class WordType, int num_bits> 00225 INLINE WordType BitMask<WordType, num_bits>:: 00226 extract(int low_bit, int size) const { 00227 return (_word >> low_bit) & 00228 BitMask<WordType, num_bits>::lower_on(size)._word; 00229 } 00230 00231 //////////////////////////////////////////////////////////////////// 00232 // Function: BitMask::store 00233 // Access: Published 00234 // Description: Stores the indicated word into the indicated range of 00235 // bits with this BitMask. 00236 //////////////////////////////////////////////////////////////////// 00237 template<class WordType, int num_bits> 00238 INLINE void BitMask<WordType, num_bits>:: 00239 store(WordType value, int low_bit, int size) { 00240 WordType mask = 00241 BitMask<WordType, num_bits>::lower_on(size)._word << low_bit; 00242 _word = (_word & ~mask) | ((value << low_bit) & mask); 00243 } 00244 00245 //////////////////////////////////////////////////////////////////// 00246 // Function: BitMask::get_word 00247 // Access: Published 00248 // Description: Returns the entire BitMask as a single word. 00249 //////////////////////////////////////////////////////////////////// 00250 template<class WordType, int num_bits> 00251 INLINE WordType BitMask<WordType, num_bits>:: 00252 get_word() const { 00253 return _word; 00254 } 00255 00256 //////////////////////////////////////////////////////////////////// 00257 // Function: BitMask::set_word 00258 // Access: Published 00259 // Description: Sets the entire BitMask to the value indicated by the 00260 // given word. 00261 //////////////////////////////////////////////////////////////////// 00262 template<class WordType, int num_bits> 00263 INLINE void BitMask<WordType, num_bits>:: 00264 set_word(WordType value) { 00265 _word = value; 00266 } 00267 00268 //////////////////////////////////////////////////////////////////// 00269 // Function: BitMask::invert_in_place 00270 // Access: Published 00271 // Description: Inverts all the bits in the BitMask. 00272 //////////////////////////////////////////////////////////////////// 00273 template<class WordType, int num_bits> 00274 INLINE void BitMask<WordType, num_bits>:: 00275 invert_in_place() { 00276 _word = ~_word; 00277 } 00278 00279 //////////////////////////////////////////////////////////////////// 00280 // Function: BitMask::clear 00281 // Access: Published 00282 // Description: Sets all the bits in the BitMask off. 00283 //////////////////////////////////////////////////////////////////// 00284 template<class WordType, int num_bits> 00285 INLINE void BitMask<WordType, num_bits>:: 00286 clear() { 00287 _word = 0; 00288 } 00289 00290 //////////////////////////////////////////////////////////////////// 00291 // Function: BitMask::output 00292 // Access: Published 00293 // Description: Writes the BitMask out as a binary or a hex number, 00294 // according to the number of bits. 00295 //////////////////////////////////////////////////////////////////// 00296 template<class WordType, int num_bits> 00297 void BitMask<WordType, num_bits>:: 00298 output(ostream &out) const { 00299 if (num_bits >= 40) { 00300 output_hex(out); 00301 } else { 00302 output_binary(out); 00303 } 00304 } 00305 00306 //////////////////////////////////////////////////////////////////// 00307 // Function: BitMask::output_binary 00308 // Access: Published 00309 // Description: Writes the BitMask out as a binary number, with 00310 // spaces every four bits. 00311 //////////////////////////////////////////////////////////////////// 00312 template<class WordType, int num_bits> 00313 void BitMask<WordType, num_bits>:: 00314 output_binary(ostream &out, int spaces_every) const { 00315 for (int i = num_bits - 1; i >= 0; i--) { 00316 if (spaces_every != 0 && ((i % spaces_every) == spaces_every - 1)) { 00317 out << ' '; 00318 } 00319 out << (get_bit(i) ? '1' : '0'); 00320 } 00321 } 00322 00323 //////////////////////////////////////////////////////////////////// 00324 // Function: BitMask::output_hex 00325 // Access: Published 00326 // Description: Writes the BitMask out as a hexadecimal number, with 00327 // spaces every four digits. 00328 //////////////////////////////////////////////////////////////////// 00329 template<class WordType, int num_bits> 00330 void BitMask<WordType, num_bits>:: 00331 output_hex(ostream &out, int spaces_every) const { 00332 int num_digits = (num_bits + 3) / 4; 00333 00334 for (int i = num_digits - 1; i >= 0; i--) { 00335 WordType digit = extract(i * 4, 4); 00336 if (spaces_every != 0 && ((i % spaces_every) == spaces_every - 1)) { 00337 out << ' '; 00338 } 00339 if (digit > 9) { 00340 out << (char)(digit - 10 + 'a'); 00341 } else { 00342 out << (char)(digit + '0'); 00343 } 00344 } 00345 } 00346 00347 //////////////////////////////////////////////////////////////////// 00348 // Function: BitMask::write 00349 // Access: Published 00350 // Description: Writes the BitMask out as a binary or a hex number, 00351 // according to the number of bits. 00352 //////////////////////////////////////////////////////////////////// 00353 template<class WordType, int num_bits> 00354 void BitMask<WordType, num_bits>:: 00355 write(ostream &out, int indent_level) const { 00356 indent(out, indent_level) << *this << "\n"; 00357 } 00358 00359 //////////////////////////////////////////////////////////////////// 00360 // Function: BitMask::operator == 00361 // Access: Published 00362 // Description: 00363 //////////////////////////////////////////////////////////////////// 00364 template<class WordType, int num_bits> 00365 INLINE bool BitMask<WordType, num_bits>:: 00366 operator == (const BitMask<WordType, num_bits> &other) const { 00367 return _word == other._word; 00368 } 00369 00370 //////////////////////////////////////////////////////////////////// 00371 // Function: BitMask::operator != 00372 // Access: Published 00373 // Description: 00374 //////////////////////////////////////////////////////////////////// 00375 template<class WordType, int num_bits> 00376 INLINE bool BitMask<WordType, num_bits>:: 00377 operator != (const BitMask<WordType, num_bits> &other) const { 00378 return _word != other._word; 00379 } 00380 00381 //////////////////////////////////////////////////////////////////// 00382 // Function: BitMask::operator < 00383 // Access: Published 00384 // Description: The ordering operator is of limited usefulness with a 00385 // BitMask, however, it has a definition which places 00386 // all unique BitMasks into a unique ordering. It may 00387 // be useful when defining ordered STL containers of 00388 // BitMasks, for instance; and it's required in order to 00389 // export any STL container (ordered or unordered) of 00390 // BitMask under Windows. 00391 //////////////////////////////////////////////////////////////////// 00392 template<class WordType, int num_bits> 00393 INLINE bool BitMask<WordType, num_bits>:: 00394 operator < (const BitMask<WordType, num_bits> &other) const { 00395 return _word < other._word; 00396 } 00397 00398 //////////////////////////////////////////////////////////////////// 00399 // Function: BitMask::compare_to 00400 // Access: Published 00401 // Description: Returns a number less than zero if this BitMask sorts 00402 // before the indicated other BitMask, greater than zero 00403 // if it sorts after, or 0 if they are equivalent. This 00404 // is based on the same ordering defined by operator <. 00405 //////////////////////////////////////////////////////////////////// 00406 template<class WordType, int num_bits> 00407 INLINE int BitMask<WordType, num_bits>:: 00408 compare_to(const BitMask<WordType, num_bits> &other) const { 00409 if ((*this) < other) { 00410 return -1; 00411 } else if (other < (*this)) { 00412 return 1; 00413 } else { 00414 return 0; 00415 } 00416 } 00417 00418 //////////////////////////////////////////////////////////////////// 00419 // Function: BitMask::operator & 00420 // Access: Published 00421 // Description: 00422 //////////////////////////////////////////////////////////////////// 00423 template<class WordType, int num_bits> 00424 INLINE BitMask<WordType, num_bits> BitMask<WordType, num_bits>:: 00425 operator & (const BitMask<WordType, num_bits> &other) const { 00426 BitMask<WordType, num_bits> result(*this); 00427 result &= other; 00428 return result; 00429 } 00430 00431 //////////////////////////////////////////////////////////////////// 00432 // Function: BitMask::operator | 00433 // Access: Published 00434 // Description: 00435 //////////////////////////////////////////////////////////////////// 00436 template<class WordType, int num_bits> 00437 INLINE BitMask<WordType, num_bits> BitMask<WordType, num_bits>:: 00438 operator | (const BitMask<WordType, num_bits> &other) const { 00439 BitMask<WordType, num_bits> result(*this); 00440 result |= other; 00441 return result; 00442 } 00443 00444 //////////////////////////////////////////////////////////////////// 00445 // Function: BitMask::operator ^ 00446 // Access: Published 00447 // Description: 00448 //////////////////////////////////////////////////////////////////// 00449 template<class WordType, int num_bits> 00450 INLINE BitMask<WordType, num_bits> BitMask<WordType, num_bits>:: 00451 operator ^ (const BitMask<WordType, num_bits> &other) const { 00452 BitMask<WordType, num_bits> result(*this); 00453 result ^= other; 00454 return result; 00455 } 00456 00457 //////////////////////////////////////////////////////////////////// 00458 // Function: BitMask::operator ~ 00459 // Access: Published 00460 // Description: 00461 //////////////////////////////////////////////////////////////////// 00462 template<class WordType, int num_bits> 00463 INLINE BitMask<WordType, num_bits> BitMask<WordType, num_bits>:: 00464 operator ~ () const { 00465 BitMask<WordType, num_bits> result(*this); 00466 result._word = ~result._word; 00467 return result; 00468 } 00469 00470 //////////////////////////////////////////////////////////////////// 00471 // Function: BitMask::operator << 00472 // Access: Published 00473 // Description: 00474 //////////////////////////////////////////////////////////////////// 00475 template<class WordType, int num_bits> 00476 INLINE BitMask<WordType, num_bits> BitMask<WordType, num_bits>:: 00477 operator << (int shift) const { 00478 BitMask<WordType, num_bits> result(*this); 00479 result <<= shift; 00480 return result; 00481 } 00482 00483 //////////////////////////////////////////////////////////////////// 00484 // Function: BitMask::operator >> 00485 // Access: Published 00486 // Description: 00487 //////////////////////////////////////////////////////////////////// 00488 template<class WordType, int num_bits> 00489 INLINE BitMask<WordType, num_bits> BitMask<WordType, num_bits>:: 00490 operator >> (int shift) const { 00491 BitMask<WordType, num_bits> result(*this); 00492 result >>= shift; 00493 return result; 00494 } 00495 00496 //////////////////////////////////////////////////////////////////// 00497 // Function: BitMask::operator &= 00498 // Access: Published 00499 // Description: 00500 //////////////////////////////////////////////////////////////////// 00501 template<class WordType, int num_bits> 00502 INLINE void BitMask<WordType, num_bits>:: 00503 operator &= (const BitMask<WordType, num_bits> &other) { 00504 _word &= other._word; 00505 } 00506 00507 //////////////////////////////////////////////////////////////////// 00508 // Function: BitMask::operator |= 00509 // Access: Published 00510 // Description: 00511 //////////////////////////////////////////////////////////////////// 00512 template<class WordType, int num_bits> 00513 INLINE void BitMask<WordType, num_bits>:: 00514 operator |= (const BitMask<WordType, num_bits> &other) { 00515 _word |= other._word; 00516 } 00517 00518 //////////////////////////////////////////////////////////////////// 00519 // Function: BitMask::operator ^= 00520 // Access: Published 00521 // Description: 00522 //////////////////////////////////////////////////////////////////// 00523 template<class WordType, int num_bits> 00524 INLINE void BitMask<WordType, num_bits>:: 00525 operator ^= (const BitMask<WordType, num_bits> &other) { 00526 _word ^= other._word; 00527 } 00528 00529 //////////////////////////////////////////////////////////////////// 00530 // Function: BitMask::operator <<= 00531 // Access: Published 00532 // Description: 00533 //////////////////////////////////////////////////////////////////// 00534 template<class WordType, int num_bits> 00535 INLINE void BitMask<WordType, num_bits>:: 00536 operator <<= (int shift) { 00537 _word <<= shift; 00538 } 00539 00540 //////////////////////////////////////////////////////////////////// 00541 // Function: BitMask::operator >>= 00542 // Access: Published 00543 // Description: 00544 //////////////////////////////////////////////////////////////////// 00545 template<class WordType, int num_bits> 00546 INLINE void BitMask<WordType, num_bits>:: 00547 operator >>= (int shift) { 00548 _word >>= shift; 00549 } 00550 00551 //////////////////////////////////////////////////////////////////// 00552 // Function: BitMask::generate_hash 00553 // Access: Public 00554 // Description: Adds the bitmask to the indicated hash generator. 00555 //////////////////////////////////////////////////////////////////// 00556 template<class WordType, int num_bits> 00557 INLINE void BitMask<WordType, num_bits>:: 00558 generate_hash(ChecksumHashGenerator &hashgen) const { 00559 hashgen.add_int(_word); 00560 } 00561 00562 //////////////////////////////////////////////////////////////////// 00563 // Function: BitMask::init_type 00564 // Access: Public 00565 // Description: 00566 //////////////////////////////////////////////////////////////////// 00567 template<class WordType, int num_bits> 00568 void BitMask<WordType, num_bits>:: 00569 init_type() { 00570 ostringstream str; 00571 str << "BitMask" << num_bits; 00572 register_type(_type_handle, str.str()); 00573 }