// Filename: bitMask.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 BitMask::_type_handle; //////////////////////////////////////////////////////////////////// // Function: BitMask::Constructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE BitMask:: BitMask() : _word(0) { } //////////////////////////////////////////////////////////////////// // Function: BitMask::Constructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE BitMask:: BitMask(WordType init_value) : _word(init_value) { } //////////////////////////////////////////////////////////////////// // Function: BitMask::Copy Constructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE BitMask:: BitMask(const BitMask ©) : _word(copy._word) { } //////////////////////////////////////////////////////////////////// // Function: BitMask::Copy Assignment Operator // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE BitMask &BitMask:: operator = (const BitMask ©) { _word = copy._word; return *this; } //////////////////////////////////////////////////////////////////// // Function: BitMask::Named all_on constructor // Access: Published, Static // Description: Returns a BitMask whose bits are all on. //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: all_on() { BitMask result; result._word = (WordType)~0; return result; } //////////////////////////////////////////////////////////////////// // Function: BitMask::Named all_on constructor // Access: Published, Static // Description: Returns a BitMask whose bits are all off. //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: all_off() { BitMask result; result._word = 0; return result; } //////////////////////////////////////////////////////////////////// // Function: BitMask::Named lower_on constructor // Access: Published, Static // Description: Returns a BitMask whose lower on_bits bits are on. //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: lower_on(int on_bits) { if (on_bits <= 0) { return all_off(); } else if (on_bits >= num_bits) { return all_on(); } BitMask result; result._word = ((WordType)1 << on_bits) - 1; return result; } //////////////////////////////////////////////////////////////////// // Function: BitMask::Named bit constructor // Access: Published, Static // Description: Returns a BitMask with only the indicated bit on. //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: bit(int index) { BitMask result; result.set_bit(index); return result; } //////////////////////////////////////////////////////////////////// // Function: BitMask::Named range constructor // Access: Published, Static // Description: Returns a BitMask whose size bits, beginning at // low_bit, are on. //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: range(int low_bit, int size) { BitMask result; if (size <= 0) { result._word = 0; } else if (size >= num_bits) { result._word = (WordType)~0; } else { result._word = ((WordType)1 << size) - 1; } result._word <<= low_bit; return result; } //////////////////////////////////////////////////////////////////// // Function: BitMask::Destructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE BitMask:: ~BitMask() { } //////////////////////////////////////////////////////////////////// // Function: BitMask::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 // BitMask or BitArray interchangeably. //////////////////////////////////////////////////////////////////// template INLINE bool BitMask:: has_max_num_bits() { return true; } //////////////////////////////////////////////////////////////////// // Function: BitMask::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 BitMask or BitArray interchangeably. //////////////////////////////////////////////////////////////////// template INLINE int BitMask:: get_max_num_bits() { return num_bits; } //////////////////////////////////////////////////////////////////// // Function: BitMask::get_num_bits // Access: Published, Static // Description: Returns the number of bits available to set in the // bitmask. //////////////////////////////////////////////////////////////////// template INLINE int BitMask:: get_num_bits() { return num_bits; } //////////////////////////////////////////////////////////////////// // Function: BitMask::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 BitMask:: get_bit(int index) const { nassertr(index >= 0 && index < num_bits, false); return (_word & ((WordType)1 << index)) != 0; } //////////////////////////////////////////////////////////////////// // Function: BitMask::set_bit // Access: Published // Description: Sets the nth bit on. index must be in the range // [0, num_bits). //////////////////////////////////////////////////////////////////// template INLINE void BitMask:: set_bit(int index) { nassertv(index >= 0 && index < num_bits); _word |= ((WordType)1 << index); } //////////////////////////////////////////////////////////////////// // Function: BitMask::clear_bit // Access: Published // Description: Sets the nth bit off. index must be in the range // [0, num_bits). //////////////////////////////////////////////////////////////////// template INLINE void BitMask:: clear_bit(int index) { nassertv(index >= 0 && index < num_bits); _word &= ~((WordType)1 << index); } //////////////////////////////////////////////////////////////////// // Function: BitMask::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 BitMask:: set_bit_to(int index, bool value) { if (value) { set_bit(index); } else { clear_bit(index); } } //////////////////////////////////////////////////////////////////// // Function: BitMask::is_zero // Access: Published // Description: Returns true if the entire bitmask is zero, false // otherwise. //////////////////////////////////////////////////////////////////// template INLINE bool BitMask:: is_zero() const { return (_word == 0); } //////////////////////////////////////////////////////////////////// // Function: BitMask::is_all_on // Access: Published // Description: Returns true if the entire bitmask is one, false // otherwise. //////////////////////////////////////////////////////////////////// template INLINE bool BitMask:: is_all_on() const { return (~_word == 0); } //////////////////////////////////////////////////////////////////// // Function: BitMask::extract // Access: Published // Description: Returns a word that represents only the indicated // range of bits within this BitMask, shifted to the // least-significant position. //////////////////////////////////////////////////////////////////// template INLINE TYPENAME BitMask::WordType BitMask:: extract(int low_bit, int size) const { return (_word >> low_bit) & BitMask::lower_on(size)._word; } //////////////////////////////////////////////////////////////////// // Function: BitMask::store // Access: Published // Description: Stores the indicated word into the indicated range of // bits with this BitMask. //////////////////////////////////////////////////////////////////// template INLINE void BitMask:: store(WordType value, int low_bit, int size) { WordType mask = BitMask::range(low_bit, size)._word; _word = (_word & ~mask) | ((value << low_bit) & mask); } //////////////////////////////////////////////////////////////////// // Function: BitMask::has_any_of // Access: Published // Description: Returns true if any bit in the indicated range is // set, false otherwise. //////////////////////////////////////////////////////////////////// template INLINE bool BitMask:: has_any_of(int low_bit, int size) const { WordType mask = BitMask::range(low_bit, size)._word; return (_word & mask) != 0; } //////////////////////////////////////////////////////////////////// // Function: BitMask::has_all_of // Access: Published // Description: Returns true if all bits in the indicated range are // set, false otherwise. //////////////////////////////////////////////////////////////////// template INLINE bool BitMask:: has_all_of(int low_bit, int size) const { WordType mask = BitMask::range(low_bit, size)._word; return (_word & mask) == mask; } //////////////////////////////////////////////////////////////////// // Function: BitMask::set_range // Access: Published // Description: Sets the indicated range of bits on. //////////////////////////////////////////////////////////////////// template INLINE void BitMask:: set_range(int low_bit, int size) { WordType mask = BitMask::range(low_bit, size)._word; _word |= mask; } //////////////////////////////////////////////////////////////////// // Function: BitMask::clear_range // Access: Published // Description: Sets the indicated range of bits off. //////////////////////////////////////////////////////////////////// template INLINE void BitMask:: clear_range(int low_bit, int size) { WordType mask = BitMask::range(low_bit, size)._word; _word &= ~mask; } //////////////////////////////////////////////////////////////////// // Function: BitMask::set_range_to // Access: Published // Description: Sets the indicated range of bits to either on or off. //////////////////////////////////////////////////////////////////// template INLINE void BitMask:: set_range_to(bool value, int low_bit, int size) { if (value) { set_range(low_bit, size); } else { clear_range(low_bit, size); } } //////////////////////////////////////////////////////////////////// // Function: BitMask::get_word // Access: Published // Description: Returns the entire BitMask as a single word. //////////////////////////////////////////////////////////////////// template INLINE TYPENAME BitMask::WordType BitMask:: get_word() const { return _word; } //////////////////////////////////////////////////////////////////// // Function: BitMask::set_word // Access: Published // Description: Sets the entire BitMask to the value indicated by the // given word. //////////////////////////////////////////////////////////////////// template INLINE void BitMask:: set_word(WordType value) { _word = value; } //////////////////////////////////////////////////////////////////// // Function: BitMask::get_num_on_bits // Access: Published // Description: Returns the number of bits that are set to 1 in the // mask. //////////////////////////////////////////////////////////////////// template INLINE int BitMask:: get_num_on_bits() const { return count_bits_in_word((WType)_word); } //////////////////////////////////////////////////////////////////// // Function: BitMask::get_num_off_bits // Access: Published // Description: Returns the number of bits that are set to 0 in the // mask. //////////////////////////////////////////////////////////////////// template INLINE int BitMask:: get_num_off_bits() const { return count_bits_in_word((WType)(~_word)); } //////////////////////////////////////////////////////////////////// // Function: BitMask::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 BitMask:: get_lowest_on_bit() const { return ::get_lowest_on_bit(_word); } //////////////////////////////////////////////////////////////////// // Function: BitMask::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 BitMask:: get_lowest_off_bit() const { return (~(*this)).get_lowest_on_bit(); } //////////////////////////////////////////////////////////////////// // Function: BitMask::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 BitMask:: get_highest_on_bit() const { return ::get_highest_on_bit(_word); } //////////////////////////////////////////////////////////////////// // Function: BitMask::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 BitMask:: get_highest_off_bit() const { return (~(*this)).get_highest_on_bit(); } //////////////////////////////////////////////////////////////////// // Function: BitMask::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 BitMask:: get_next_higher_different_bit(int low_bit) const { // We are allowed to call this method with low_bit == num_bits, // which is the highest value this method will return. nassertr(low_bit >= 0, low_bit); if (low_bit >= num_bits) { return low_bit; } WordType is_on = (_word & ((WordType)1 << low_bit)); WordType w; if (is_on) { // low_bit is 1. Get the next higher 0 bit. To do this, invert // the word and the get the next higher 1 bit. w = ~_word; } else { // low_bit is 0. Get the next higher 1 bit. w = _word; } // Mask out all of the bits below low_bit. Since we already know // that low_bit is 0, we can use (1 << low_bit) instead of (1 << // (low_bit + 1)), which becomes undefined when (low_bit + 1) == 32. w &= ~((1 << low_bit) - 1); if (w == 0) { // All higher bits in the word have the same value. Since every // bit after the topmost bit is 0, we either return the topmost // bit + 1 to indicate the next 0 bit, or low_bit to indicate we // have reached the end of the number of bits. return is_on ? num_bits : low_bit; } else { // Now determine the lowest 1 bit in the remaining word. This // operation will clear out all bits except for the lowest 1 bit. w = (w & (~w + 1)); // And the answer is the number of bits in (w - 1). return count_bits_in_word((WType)(w - 1)); } } //////////////////////////////////////////////////////////////////// // Function: BitMask::invert_in_place // Access: Published // Description: Inverts all the bits in the BitMask. This is // equivalent to mask = ~mask. //////////////////////////////////////////////////////////////////// template INLINE void BitMask:: invert_in_place() { _word = ~_word; } //////////////////////////////////////////////////////////////////// // Function: BitMask::has_bits_in_common // Access: Published // Description: Returns true if this BitMask 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 BitMask:: has_bits_in_common(const BitMask &other) const { return (_word & other._word) != 0; } //////////////////////////////////////////////////////////////////// // Function: BitMask::clear // Access: Published // Description: Sets all the bits in the BitMask off. //////////////////////////////////////////////////////////////////// template INLINE void BitMask:: clear() { _word = 0; } //////////////////////////////////////////////////////////////////// // Function: BitMask::output // Access: Published // Description: Writes the BitMask out as a binary or a hex number, // according to the number of bits. //////////////////////////////////////////////////////////////////// template void BitMask:: output(ostream &out) const { if (num_bits >= 40) { output_hex(out); } else { output_binary(out); } } //////////////////////////////////////////////////////////////////// // Function: BitMask::output_binary // Access: Published // Description: Writes the BitMask out as a binary number, with // spaces every four bits. //////////////////////////////////////////////////////////////////// template void BitMask:: output_binary(ostream &out, int spaces_every) const { for (int i = num_bits - 1; i >= 0; i--) { if (spaces_every != 0 && ((i % spaces_every) == spaces_every - 1)) { out << ' '; } out << (get_bit(i) ? '1' : '0'); } } //////////////////////////////////////////////////////////////////// // Function: BitMask::output_hex // Access: Published // Description: Writes the BitMask out as a hexadecimal number, with // spaces every four digits. //////////////////////////////////////////////////////////////////// template void BitMask:: output_hex(ostream &out, int spaces_every) const { int num_digits = (num_bits + 3) / 4; for (int i = num_digits - 1; i >= 0; i--) { WordType digit = extract(i * 4, 4); if (spaces_every != 0 && ((i % spaces_every) == spaces_every - 1)) { out << ' '; } if (digit > 9) { out << (char)(digit - 10 + 'a'); } else { out << (char)(digit + '0'); } } } //////////////////////////////////////////////////////////////////// // Function: BitMask::write // Access: Published // Description: Writes the BitMask out as a binary or a hex number, // according to the number of bits. //////////////////////////////////////////////////////////////////// template void BitMask:: write(ostream &out, int indent_level) const { indent(out, indent_level) << *this << "\n"; } //////////////////////////////////////////////////////////////////// // Function: BitMask::operator == // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE bool BitMask:: operator == (const BitMask &other) const { return _word == other._word; } //////////////////////////////////////////////////////////////////// // Function: BitMask::operator != // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE bool BitMask:: operator != (const BitMask &other) const { return _word != other._word; } //////////////////////////////////////////////////////////////////// // Function: BitMask::operator < // Access: Published // Description: The ordering operator is of limited usefulness with a // BitMask, however, it has a definition which places // all unique BitMasks into a unique ordering. It may // be useful when defining ordered STL containers of // BitMasks, for instance; and it's required in order to // export any STL container (ordered or unordered) of // BitMask under Windows. //////////////////////////////////////////////////////////////////// template INLINE bool BitMask:: operator < (const BitMask &other) const { return _word < other._word; } //////////////////////////////////////////////////////////////////// // Function: BitMask::compare_to // Access: Published // Description: Returns a number less than zero if this BitMask sorts // before the indicated other BitMask, 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 BitMask:: compare_to(const BitMask &other) const { if ((*this) < other) { return -1; } else if (other < (*this)) { return 1; } else { return 0; } } //////////////////////////////////////////////////////////////////// // Function: BitMask::operator & // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: operator & (const BitMask &other) const { BitMask result(*this); result &= other; return result; } //////////////////////////////////////////////////////////////////// // Function: BitMask::operator | // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: operator | (const BitMask &other) const { BitMask result(*this); result |= other; return result; } //////////////////////////////////////////////////////////////////// // Function: BitMask::operator ^ // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: operator ^ (const BitMask &other) const { BitMask result(*this); result ^= other; return result; } //////////////////////////////////////////////////////////////////// // Function: BitMask::operator ~ // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: operator ~ () const { return BitMask(~_word); } //////////////////////////////////////////////////////////////////// // Function: BitMask::operator << // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: operator << (int shift) const { BitMask result(*this); result <<= shift; return result; } //////////////////////////////////////////////////////////////////// // Function: BitMask::operator >> // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: operator >> (int shift) const { BitMask result(*this); result >>= shift; return result; } //////////////////////////////////////////////////////////////////// // Function: BitMask::operator &= // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE void BitMask:: operator &= (const BitMask &other) { _word &= other._word; } //////////////////////////////////////////////////////////////////// // Function: BitMask::operator |= // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE void BitMask:: operator |= (const BitMask &other) { _word |= other._word; } //////////////////////////////////////////////////////////////////// // Function: BitMask::operator ^= // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE void BitMask:: operator ^= (const BitMask &other) { _word ^= other._word; } //////////////////////////////////////////////////////////////////// // Function: BitMask::operator <<= // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE void BitMask:: operator <<= (int shift) { _word <<= shift; } //////////////////////////////////////////////////////////////////// // Function: BitMask::operator >>= // Access: Published // Description: //////////////////////////////////////////////////////////////////// template INLINE void BitMask:: operator >>= (int shift) { _word >>= shift; } //////////////////////////////////////////////////////////////////// // Function: BitMask::get_key // Access: Published // Description: Returns a mostly unique integer key per unique // bitmask, suitable for using in a hash table. //////////////////////////////////////////////////////////////////// template INLINE int BitMask:: get_key() const { return (int)_word; } //////////////////////////////////////////////////////////////////// // Function: BitMask::generate_hash // Access: Public // Description: Adds the bitmask to the indicated hash generator. //////////////////////////////////////////////////////////////////// template INLINE void BitMask:: generate_hash(ChecksumHashGenerator &hashgen) const { hashgen.add_int(_word); } //////////////////////////////////////////////////////////////////// // Function: BitMask::init_type // Access: Public // Description: //////////////////////////////////////////////////////////////////// template void BitMask:: init_type() { ostringstream str; str << "BitMask" << num_bits; register_type(_type_handle, str.str()); } //////////////////////////////////////////////////////////////////// // Function: BitMask::flood_up_in_place // Access: Published // Description: Floods this bitmask's bits upwards. //////////////////////////////////////////////////////////////////// template INLINE void BitMask:: flood_up_in_place() { _word = ::flood_bits_up(_word); } //////////////////////////////////////////////////////////////////// // Function: BitMask::flood_down_in_place // Access: Published // Description: Floods this bitmask's bits downwards. //////////////////////////////////////////////////////////////////// template INLINE void BitMask:: flood_down_in_place() { _word = ::flood_bits_down(_word); } //////////////////////////////////////////////////////////////////// // Function: BitMask::flood_bits_up // Access: Published // Description: Returns a BitMask with the bits flooded upwards. //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: flood_bits_up() const { BitMask result(::flood_bits_up(_word)); return result; } //////////////////////////////////////////////////////////////////// // Function: BitMask::flood_bits_down // Access: Published // Description: Returns a BitMask with the bits flooded down. //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: flood_bits_down() const { BitMask result(::flood_bits_down(_word)); return result; } //////////////////////////////////////////////////////////////////// // Function: BitMask::keep_next_highest_bit // Access: Published // Description: Returns a BitMask with only the next highest // bit above the indicated bit on, or all_off. //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: keep_next_highest_bit() const { int low_bit = get_lowest_on_bit(); if (low_bit >= 0) { return BitMask::bit(low_bit); } else { return BitMask::all_off(); } } //////////////////////////////////////////////////////////////////// // Function: BitMask::keep_next_lowest_bit // Access: Published // Description: Returns a BitMask with only the next lower // bit below the indicated bit on, or all_off. //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: keep_next_lowest_bit() const { int high_bit = get_highest_on_bit(); if (high_bit >= 0) { return BitMask::bit(high_bit); } else { return BitMask::all_off(); } } //////////////////////////////////////////////////////////////////// // Function: BitMask::keep_next_highest_bit // Access: Published // Description: Returns a BitMask with only the next highest // bit above the indicated bit on, or all. //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: keep_next_highest_bit(int index) const { BitMask mask,temp; nassertr(index >= 0 && index < num_bits, mask); mask.set_bit(index); mask.flood_down_in_place(); mask.invert_in_place(); mask &= *this; temp = mask; mask <<= 1; mask.flood_up_in_place(); mask.invert_in_place(); mask &= temp; return mask; } //////////////////////////////////////////////////////////////////// // Function: BitMask::keep_next_lowest_bit // Access: Published // Description: Returns a BitMask with only the next lower // bit below the indicated bit on, or all_off. //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: keep_next_lowest_bit(int index) const { BitMask mask, temp; nassertr(index >= 0 && index < num_bits, mask); mask.set_bit(index); mask.flood_up_in_place(); mask.invert_in_place(); mask &= *this; temp = mask; mask >>= 1; mask.flood_down_in_place(); mask.invert_in_place(); mask &= temp; return mask; } //////////////////////////////////////////////////////////////////// // Function: BitMask::keep_next_highest_bit // Access: Published // Description: Returns a BitMask with only the next highest "on" // bit above all "on" bits in the passed in bitmask, or // all_off. If there are no "on" bits in the passed in // bitmask, it will return keep_next_highest_bit(). //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: keep_next_highest_bit(const BitMask &other) const { int high_bit = other.get_highest_on_bit(); if (high_bit >= 0) { return keep_next_highest_bit(high_bit); } else { return keep_next_highest_bit(); } } //////////////////////////////////////////////////////////////////// // Function: BitMask::keep_next_lowest_bit // Access: Published // Description: Returns a BitMask with only the next lowest "on" // bit below all "on" bits in the passed in bitmask, or // all_off. If there are no "on" bits in the passed in // bitmask, it will return keep_next_lowest_bit(). //////////////////////////////////////////////////////////////////// template INLINE BitMask BitMask:: keep_next_lowest_bit(const BitMask &other) const { int low_bit = other.get_lowest_on_bit(); if (low_bit >= 0) { return keep_next_lowest_bit(low_bit); } else { return keep_next_lowest_bit(); } }