// Filename: doubleBitMask.I // Created by: drose (08Jun00) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) Carnegie Mellon University. All rights reserved. // // All use of this software is subject to the terms of the revised BSD // license. You should have received a copy of this license along // with this source code in a file named "LICENSE." // //////////////////////////////////////////////////////////////////// template TypeHandle DoubleBitMask::_type_handle; //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::Constructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE DoubleBitMask:: DoubleBitMask() { } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::Copy Constructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE DoubleBitMask:: DoubleBitMask(const DoubleBitMask ©) : _lo(copy._lo), _hi(copy._hi) { } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::Copy Assignment Operator // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE DoubleBitMask &DoubleBitMask:: operator = (const DoubleBitMask ©) { _lo = copy._lo; _hi = copy._hi; return *this; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::Named all_on constructor // Access: Published, Static // Description: Returns a DoubleBitMask whose bits are all on. //////////////////////////////////////////////////////////////////// template INLINE DoubleBitMask DoubleBitMask:: all_on() { DoubleBitMask result; result._lo = BitMaskType::all_on(); result._hi = BitMaskType::all_on(); return result; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::Named all_on constructor // Access: Published, Static // Description: Returns a DoubleBitMask whose bits are all off. //////////////////////////////////////////////////////////////////// template INLINE DoubleBitMask DoubleBitMask:: all_off() { DoubleBitMask result; result._lo.clear(); result._hi.clear(); return result; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::Named lower_on constructor // Access: Published, Static // Description: Returns a DoubleBitMask whose lower on_bits bits are on. //////////////////////////////////////////////////////////////////// template INLINE DoubleBitMask DoubleBitMask:: lower_on(int on_bits) { if (on_bits <= 0) { return all_off(); } else if (on_bits >= num_bits) { return all_on(); } DoubleBitMask result; if (on_bits <= half_bits) { result._lo = BitMaskType::lower_on(on_bits); } else { result._lo = BitMaskType::all_on(); result._hi = BitMaskType::lower_on(on_bits - half_bits); } return result; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::Named bit constructor // Access: Published, Static // Description: Returns a DoubleBitMask with only the indicated bit on. //////////////////////////////////////////////////////////////////// template INLINE DoubleBitMask DoubleBitMask:: bit(int index) { DoubleBitMask result; result.set_bit(index); return result; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::Named range constructor // Access: Published, Static // Description: Returns a DoubleBitMask whose size bits, beginning at // low_bit, are on. //////////////////////////////////////////////////////////////////// template INLINE DoubleBitMask DoubleBitMask:: range(int low_bit, int size) { DoubleBitMask result; result.set_range(low_bit, size); return result; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::Destructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE DoubleBitMask:: ~DoubleBitMask() { } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::has_max_num_bits // Access: Published, Static // Description: Returns true if there is a maximum number of bits // that may be stored in this structure, false // otherwise. If this returns true, the number may be // queried in get_max_num_bits(). // // This method always returns true. This method is // defined so generic programming algorithms can use // DoubleBitMask or BitArray interchangeably. //////////////////////////////////////////////////////////////////// template INLINE bool DoubleBitMask:: has_max_num_bits() { return true; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::get_max_num_bits // Access: Published, Static // Description: If get_max_num_bits() returned true, this method may // be called to return the maximum number of bits that // may be stored in this structure. It is an error to // call this if get_max_num_bits() return false. // // It is never an error to call this method. This // returns the same thing as get_num_bits(). This // method is defined so generic programming algorithms // can use DoubleBitMask or BitArray interchangeably. //////////////////////////////////////////////////////////////////// template INLINE int DoubleBitMask:: get_max_num_bits() { return num_bits; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::get_num_bits // Access: Published, Static // Description: Returns the number of bits available to set in the // doubleBitMask. //////////////////////////////////////////////////////////////////// template INLINE int DoubleBitMask:: get_num_bits() { return num_bits; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::get_bit // Access: Published // Description: Returns true if the nth bit is set, false if it is // cleared. index must be in the range [0, // num_bits). //////////////////////////////////////////////////////////////////// template INLINE bool DoubleBitMask:: get_bit(int index) const { if (index < half_bits) { return _lo.get_bit(index); } else { return _hi.get_bit(index - half_bits); } } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::set_bit // Access: Published // Description: Sets the nth bit on. index must be in the range // [0, num_bits). //////////////////////////////////////////////////////////////////// template INLINE void DoubleBitMask:: set_bit(int index) { if (index < half_bits) { _lo.set_bit(index); } else { _hi.set_bit(index - half_bits); } } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::clear_bit // Access: Published // Description: Sets the nth bit off. index must be in the range // [0, num_bits). //////////////////////////////////////////////////////////////////// template INLINE void DoubleBitMask:: clear_bit(int index) { if (index < half_bits) { _lo.clear_bit(index); } else { _hi.clear_bit(index - half_bits); } } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::set_bit_to // Access: Published // Description: Sets the nth bit either on or off, according to the // indicated bool value. index must be in the range [0, // num_bits). //////////////////////////////////////////////////////////////////// template INLINE void DoubleBitMask:: set_bit_to(int index, bool value) { if (index < half_bits) { _lo.set_bit_to(index, value); } else { _hi.set_bit_to(index - half_bits, value); } } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::is_zero // Access: Published // Description: Returns true if the entire doubleBitMask is zero, false // otherwise. //////////////////////////////////////////////////////////////////// template INLINE bool DoubleBitMask:: is_zero() const { return (_lo.is_zero() && _hi.is_zero()); } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::is_all_on // Access: Published // Description: Returns true if the entire doubleBitMask is one, false // otherwise. //////////////////////////////////////////////////////////////////// template INLINE bool DoubleBitMask:: is_all_on() const { return (_lo.is_all_on() && _hi.is_all_on()); } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::extract // Access: Published // Description: Returns a word that represents only the indicated // range of bits within this DoubleBitMask, shifted to the // least-significant position. //////////////////////////////////////////////////////////////////// template INLINE TYPENAME DoubleBitMask::WordType DoubleBitMask:: extract(int low_bit, int size) const { if (low_bit >= half_bits) { return _hi.extract(low_bit - half_bits, size); } else if (low_bit + size < half_bits) { return _lo.extract(low_bit, size); } else { int hi_portion = low_bit + size - half_bits; int lo_portion = size - hi_portion; return (_hi.extract(0, hi_portion) << lo_portion) | _lo.extract(low_bit, lo_portion); } } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::store // Access: Published // Description: Stores the indicated word into the indicated range of // bits with this DoubleBitMask. //////////////////////////////////////////////////////////////////// template INLINE void DoubleBitMask:: store(WordType value, int low_bit, int size) { if (low_bit >= half_bits) { _hi.store(value, low_bit - half_bits, size); } else if (low_bit + size < half_bits) { _lo.store(value, low_bit, size); } else { int hi_portion = low_bit + size - half_bits; int lo_portion = size - hi_portion; _hi.store(value >> lo_portion, 0, hi_portion); _lo.store(value, low_bit, lo_portion); } } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::has_any_of // Access: Published // Description: Returns true if any bit in the indicated range is // set, false otherwise. //////////////////////////////////////////////////////////////////// template INLINE bool DoubleBitMask:: has_any_of(int low_bit, int size) const { if (low_bit >= half_bits) { return _hi.has_any_of(low_bit - half_bits, size); } else if (low_bit + size < half_bits) { return _lo.has_any_of(low_bit, size); } else { int hi_portion = low_bit + size - half_bits; int lo_portion = size - hi_portion; return (_hi.has_any_of(0, hi_portion) << lo_portion) || _lo.has_any_of(low_bit, lo_portion); } } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::has_all_of // Access: Published // Description: Returns true if all bits in the indicated range are // set, false otherwise. //////////////////////////////////////////////////////////////////// template INLINE bool DoubleBitMask:: has_all_of(int low_bit, int size) const { if (low_bit >= half_bits) { return _hi.has_all_of(low_bit - half_bits, size); } else if (low_bit + size < half_bits) { return _lo.has_all_of(low_bit, size); } else { int hi_portion = low_bit + size - half_bits; int lo_portion = size - hi_portion; return (_hi.has_all_of(0, hi_portion) << lo_portion) && _lo.has_all_of(low_bit, lo_portion); } } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::set_range // Access: Published // Description: Sets the indicated range of bits on. //////////////////////////////////////////////////////////////////// template INLINE void DoubleBitMask:: set_range(int low_bit, int size) { if (low_bit >= half_bits) { _hi.set_range(low_bit - half_bits, size); } else if (low_bit + size < half_bits) { _lo.set_range(low_bit, size); } else { int hi_portion = low_bit + size - half_bits; int lo_portion = size - hi_portion; _hi.set_range(0, hi_portion); _lo.set_range(low_bit, lo_portion); } } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::clear_range // Access: Published // Description: Sets the indicated range of bits off. //////////////////////////////////////////////////////////////////// template INLINE void DoubleBitMask:: clear_range(int low_bit, int size) { if (low_bit >= half_bits) { _hi.clear_range(low_bit - half_bits, size); } else if (low_bit + size < half_bits) { _lo.clear_range(low_bit, size); } else { int hi_portion = low_bit + size - half_bits; int lo_portion = size - hi_portion; _hi.clear_range(0, hi_portion); _lo.clear_range(low_bit, lo_portion); } } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::set_range_to // Access: Published // Description: Sets the indicated range of bits to either on or off. //////////////////////////////////////////////////////////////////// template INLINE void DoubleBitMask:: set_range_to(bool value, int low_bit, int size) { if (value) { set_range(low_bit, size); } else { clear_range(low_bit, size); } } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::get_num_on_bits // Access: Published // Description: Returns the number of bits that are set to 1 in the // mask. //////////////////////////////////////////////////////////////////// template INLINE int DoubleBitMask:: get_num_on_bits() const { return _lo.get_num_on_bits() + _hi.get_num_on_bits(); } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::get_num_off_bits // Access: Published // Description: Returns the number of bits that are set to 0 in the // mask. //////////////////////////////////////////////////////////////////// template INLINE int DoubleBitMask:: get_num_off_bits() const { return _lo.get_num_off_bits() + _hi.get_num_off_bits(); } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::get_lowest_on_bit // Access: Published // Description: Returns the index of the lowest 1 bit in the mask. // Returns -1 if there are no 1 bits. //////////////////////////////////////////////////////////////////// template INLINE int DoubleBitMask:: get_lowest_on_bit() const { int result = _lo.get_lowest_on_bit(); if (result == -1) { result = _hi.get_lowest_on_bit(); if (result != -1) { result += half_bits; } } return result; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::get_lowest_off_bit // Access: Published // Description: Returns the index of the lowest 0 bit in the mask. // Returns -1 if there are no 0 bits. //////////////////////////////////////////////////////////////////// template INLINE int DoubleBitMask:: get_lowest_off_bit() const { int result = _lo.get_lowest_off_bit(); if (result == -1) { result = _hi.get_lowest_off_bit(); if (result != -1) { result += half_bits; } } return result; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::get_highest_on_bit // Access: Published // Description: Returns the index of the highest 1 bit in the mask. // Returns -1 if there are no 1 bits. //////////////////////////////////////////////////////////////////// template INLINE int DoubleBitMask:: get_highest_on_bit() const { int result = _hi.get_highest_on_bit(); if (result == -1) { result = _lo.get_highest_on_bit(); } else { result += half_bits; } return result; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::get_highest_off_bit // Access: Published // Description: Returns the index of the highest 0 bit in the mask. // Returns -1 if there are no 0 bits. //////////////////////////////////////////////////////////////////// template INLINE int DoubleBitMask:: get_highest_off_bit() const { int result = _hi.get_highest_off_bit(); if (result == -1) { result = _lo.get_highest_off_bit(); } else { result += half_bits; } return result; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::get_next_higher_different_bit // Access: Published // Description: Returns the index of the next bit in the mask, above // low_bit, whose value is different that the value of // low_bit. Returns low_bit again if all bits higher // than low_bit have the same value. // // This can be used to quickly iterate through all of // the bits in the mask. //////////////////////////////////////////////////////////////////// template INLINE int DoubleBitMask:: get_next_higher_different_bit(int low_bit) const { if (low_bit > half_bits) { return _hi.get_next_higher_different_bit(low_bit - half_bits) + half_bits; } int result = _lo.get_next_higher_different_bit(low_bit); if (result != low_bit) { return result; } if (_lo.get_bit(low_bit)) { result = _hi.get_lowest_off_bit(); } else { result = _hi.get_lowest_on_bit(); } if (result == -1) { return low_bit; } return result + half_bits; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::invert_in_place // Access: Published // Description: Inverts all the bits in the DoubleBitMask. This is // equivalent to mask = ~mask. //////////////////////////////////////////////////////////////////// template INLINE void DoubleBitMask:: invert_in_place() { _lo.invert_in_place(); _hi.invert_in_place(); } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::has_bits_in_common // Access: Published // Description: Returns true if this DoubleBitMask has any "one" bits in // common with the other one, false otherwise. // // This is equivalent to (mask & other) != 0, but may be // faster. (Actually, it should only be faster in the // BitArray case, but this method is provided for the // benefit of generic programming algorithms). //////////////////////////////////////////////////////////////////// template INLINE bool DoubleBitMask:: has_bits_in_common(const DoubleBitMask &other) const { return _lo.has_bits_in_common(other._lo) || _hi.has_bits_in_common(other._hi); } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::clear // Access: Published // Description: Sets all the bits in the DoubleBitMask off. //////////////////////////////////////////////////////////////////// template INLINE void DoubleBitMask:: clear() { _lo.clear(); _hi.clear(); } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::output // Access: Published // Description: Writes the DoubleBitMask out as a binary or a hex number, // according to the number of bits. //////////////////////////////////////////////////////////////////// template void DoubleBitMask:: output(ostream &out) const { output_hex(out); } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::output_binary // Access: Published // Description: Writes the DoubleBitMask out as a binary number, with // spaces every four bits. //////////////////////////////////////////////////////////////////// template void DoubleBitMask:: output_binary(ostream &out, int spaces_every) const { _hi.output_binary(out); out << ' '; _lo.output_binary(out); } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::output_hex // Access: Published // Description: Writes the DoubleBitMask out as a hexadecimal number, with // spaces every four digits. //////////////////////////////////////////////////////////////////// template void DoubleBitMask:: output_hex(ostream &out, int spaces_every) const { _hi.output_hex(out); out << ' '; _lo.output_hex(out); } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::write // Access: Published // Description: Writes the DoubleBitMask out as a binary or a hex number, // according to the number of bits. //////////////////////////////////////////////////////////////////// template void DoubleBitMask:: write(ostream &out, int indent_level) const { indent(out, indent_level) << *this << "\n"; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::operator == // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE bool DoubleBitMask:: operator == (const DoubleBitMask &other) const { return _lo == other._lo && _hi == other._hi; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::operator != // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE bool DoubleBitMask:: operator != (const DoubleBitMask &other) const { return _lo != other._lo && _hi != other._hi; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::operator < // Access: Published // Description: The ordering operator is of limited usefulness with a // DoubleBitMask, however, it has a definition which places // all unique DoubleBitMasks into a unique ordering. It may // be useful when defining ordered STL containers of // DoubleBitMasks, for instance; and it's required in order to // export any STL container (ordered or unordered) of // DoubleBitMask under Windows. //////////////////////////////////////////////////////////////////// template INLINE bool DoubleBitMask:: operator < (const DoubleBitMask &other) const { int cmp = _hi.compare_to(other._hi); if (cmp != 0) { return cmp < 0; } return _lo < other._lo; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::compare_to // Access: Published // Description: Returns a number less than zero if this DoubleBitMask sorts // before the indicated other DoubleBitMask, greater than zero // if it sorts after, or 0 if they are equivalent. This // is based on the same ordering defined by operator <. //////////////////////////////////////////////////////////////////// template INLINE int DoubleBitMask:: compare_to(const DoubleBitMask &other) const { int cmp = _hi.compare_to(other._hi); if (cmp != 0) { return cmp; } return _lo.compare_to(other._lo); } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::operator & // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE DoubleBitMask DoubleBitMask:: operator & (const DoubleBitMask &other) const { DoubleBitMask result(*this); result &= other; return result; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::operator | // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE DoubleBitMask DoubleBitMask:: operator | (const DoubleBitMask &other) const { DoubleBitMask result(*this); result |= other; return result; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::operator ^ // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE DoubleBitMask DoubleBitMask:: operator ^ (const DoubleBitMask &other) const { DoubleBitMask result(*this); result ^= other; return result; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::operator ~ // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE DoubleBitMask DoubleBitMask:: operator ~ () const { DoubleBitMask result(*this); result.invert_in_place(); return result; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::operator << // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE DoubleBitMask DoubleBitMask:: operator << (int shift) const { DoubleBitMask result(*this); result <<= shift; return result; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::operator >> // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE DoubleBitMask DoubleBitMask:: operator >> (int shift) const { DoubleBitMask result(*this); result >>= shift; return result; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::operator &= // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE void DoubleBitMask:: operator &= (const DoubleBitMask &other) { _lo &= other._lo; _hi &= other._hi; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::operator |= // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE void DoubleBitMask:: operator |= (const DoubleBitMask &other) { _lo |= other._lo; _hi |= other._hi; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::operator ^= // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE void DoubleBitMask:: operator ^= (const DoubleBitMask &other) { _lo ^= other._lo; _hi ^= other._hi; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::operator <<= // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE void DoubleBitMask:: operator <<= (int shift) { _hi = (_hi << shift) | ((_lo >> half_bits - shift) & BitMaskType::lower_on(shift)); _lo <<= shift; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::operator >>= // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE void DoubleBitMask:: operator >>= (int shift) { _lo = (_lo >> shift) | ((_hi & BitMaskType::lower_on(shift)) << half_bits - shift); _hi >>= shift; } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::generate_hash // Access: Public // Description: Adds the doubleBitMask to the indicated hash generator. //////////////////////////////////////////////////////////////////// template INLINE void DoubleBitMask:: generate_hash(ChecksumHashGenerator &hashgen) const { _hi.generate_hash(hashgen); _lo.generate_hash(hashgen); } //////////////////////////////////////////////////////////////////// // Function: DoubleBitMask::init_type // Access: Public // Description: //////////////////////////////////////////////////////////////////// template void DoubleBitMask:: init_type() { ostringstream str; str << "DoubleBitMask" << num_bits; register_type(_type_handle, str.str()); }