// Filename: bitArray.I // Created by: drose (20Jan06) // //////////////////////////////////////////////////////////////////// // // 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." // //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// // Function: BitArray::Constructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE BitArray:: BitArray() { _highest_bits = 0; } //////////////////////////////////////////////////////////////////// // Function: BitArray::Constructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE BitArray:: BitArray(WordType init_value) { if (init_value != 0) { _array.push_back(MaskType(init_value)); } _highest_bits = 0; } //////////////////////////////////////////////////////////////////// // Function: BitArray::Copy Constructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE BitArray:: BitArray(const BitArray ©) : _array(copy._array), _highest_bits(copy._highest_bits) { } //////////////////////////////////////////////////////////////////// // Function: BitArray::Copy Assignment Operator // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE BitArray &BitArray:: operator = (const BitArray ©) { _array = copy._array; _highest_bits = copy._highest_bits; return *this; } //////////////////////////////////////////////////////////////////// // Function: BitArray::Named all_on constructor // Access: Published, Static // Description: Returns a BitArray with an infinite array of bits, // all on. //////////////////////////////////////////////////////////////////// INLINE BitArray BitArray:: all_on() { BitArray result; result._highest_bits = 1; return result; } //////////////////////////////////////////////////////////////////// // Function: BitArray::Named all_on constructor // Access: Published, Static // Description: Returns a BitArray whose bits are all off. //////////////////////////////////////////////////////////////////// INLINE BitArray BitArray:: all_off() { return BitArray(); } //////////////////////////////////////////////////////////////////// // Function: BitArray::Named lower_on constructor // Access: Published, Static // Description: Returns a BitArray whose lower on_bits bits are on. //////////////////////////////////////////////////////////////////// INLINE BitArray BitArray:: lower_on(int on_bits) { BitArray result; result.set_range(0, on_bits); return result; } //////////////////////////////////////////////////////////////////// // Function: BitArray::Named bit constructor // Access: Published, Static // Description: Returns a BitArray with only the indicated bit on. //////////////////////////////////////////////////////////////////// INLINE BitArray BitArray:: bit(int index) { BitArray result; result.set_bit(index); return result; } //////////////////////////////////////////////////////////////////// // Function: BitArray::Named range constructor // Access: Published, Static // Description: Returns a BitArray whose size bits, beginning at // low_bit, are on. //////////////////////////////////////////////////////////////////// INLINE BitArray BitArray:: range(int low_bit, int size) { BitArray result; result.set_range(low_bit, size); return result; } //////////////////////////////////////////////////////////////////// // Function: BitArray::Destructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE BitArray:: ~BitArray() { } //////////////////////////////////////////////////////////////////// // Function: BitArray::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 false. The BitArray has // no maximum number of bits. This method is defined so // generic programming algorithms can use BitMask or // BitArray interchangeably. //////////////////////////////////////////////////////////////////// INLINE bool BitArray:: has_max_num_bits() { return false; } //////////////////////////////////////////////////////////////////// // Function: BitArray::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 always an error to call this method. The // BitArray has no maximum number of bits. This method // is defined so generic programming algorithms can use // BitMask or BitArray interchangeably. //////////////////////////////////////////////////////////////////// INLINE int BitArray:: get_max_num_bits() { nassertr(false, 0); return 0; } //////////////////////////////////////////////////////////////////// // Function: BitArray::get_num_bits_per_word // Access: Published, Static // Description: Returns the number of bits stored per word // internally. This is of interest only in that it // limits the maximum number of bits that may be queried // or set at once by extract() and store(). //////////////////////////////////////////////////////////////////// INLINE int BitArray:: get_num_bits_per_word() { return num_bits_per_word; } //////////////////////////////////////////////////////////////////// // Function: BitArray::get_num_bits // Access: Published // Description: Returns the current number of possibly different bits // in this array. There are actually an infinite number // of bits, but every bit higher than this bit will have // the same value, either 0 or 1 (see // get_highest_bits()). // // This number may grow and/or shrink automatically as // needed. //////////////////////////////////////////////////////////////////// INLINE int BitArray:: get_num_bits() const { return get_num_words() * num_bits_per_word; } //////////////////////////////////////////////////////////////////// // Function: BitArray::get_bit // Access: Published // Description: Returns true if the nth bit is set, false if it is // cleared. It is valid for n to increase beyond // get_num_bits(), but the return value get_num_bits() // will always be the same. //////////////////////////////////////////////////////////////////// INLINE bool BitArray:: get_bit(int index) const { nassertr(index >= 0, false); int w = index / num_bits_per_word; int b = index % num_bits_per_word; if (w >= get_num_words()) { return get_highest_bits(); } else { return (_array[w].get_bit(b)); } } //////////////////////////////////////////////////////////////////// // Function: BitArray::set_bit // Access: Published // Description: Sets the nth bit on. If n >= get_num_bits(), this // automatically extends the array. //////////////////////////////////////////////////////////////////// INLINE void BitArray:: set_bit(int index) { nassertv(index >= 0); int w = index / num_bits_per_word; int b = index % num_bits_per_word; if (w >= get_num_words() && _highest_bits) { // All the highest bits are already on. return; } ensure_has_word(w); _array[w].set_bit(b); normalize(); } //////////////////////////////////////////////////////////////////// // Function: BitArray::clear_bit // Access: Published // Description: Sets the nth bit off. If n >= get_num_bits(), this // automatically extends the array. //////////////////////////////////////////////////////////////////// INLINE void BitArray:: clear_bit(int index) { nassertv(index >= 0); int w = index / num_bits_per_word; int b = index % num_bits_per_word; if (w >= get_num_words() && !_highest_bits) { // All the highest bits are already off. return; } ensure_has_word(w); _array[w].clear_bit(b); normalize(); } //////////////////////////////////////////////////////////////////// // Function: BitArray::set_bit_to // Access: Published // Description: Sets the nth bit either on or off, according to the // indicated bool value. //////////////////////////////////////////////////////////////////// INLINE void BitArray:: set_bit_to(int index, bool value) { if (value) { set_bit(index); } else { clear_bit(index); } } //////////////////////////////////////////////////////////////////// // Function: BitArray::get_highest_bits // Access: Published // Description: Returns true if the infinite set of bits beyond // get_num_bits() are all on, or false of they are all // off. //////////////////////////////////////////////////////////////////// INLINE bool BitArray:: get_highest_bits() const { return (_highest_bits != 0); } //////////////////////////////////////////////////////////////////// // Function: BitArray::extract // Access: Published // Description: Returns a word that represents only the indicated // range of bits within this BitArray, shifted to the // least-significant position. size must be <= // get_num_bits_per_word(). //////////////////////////////////////////////////////////////////// INLINE BitArray::WordType BitArray:: extract(int low_bit, int size) const { nassertr(size >= 0 && size <= num_bits_per_word, 0); int w = low_bit / num_bits_per_word; int b = low_bit % num_bits_per_word; if (b + size < num_bits_per_word) { // The whole thing fits within one word of the array. return get_word(w).extract(b, size); } else { // We have to split it across two words. int num_lower_bits = num_bits_per_word - b; int num_higher_bits = size - num_lower_bits; return get_word(w).extract(b, num_lower_bits) | (get_word(w + 1).extract(0, num_higher_bits) << num_lower_bits); } } //////////////////////////////////////////////////////////////////// // Function: BitArray::store // Access: Published // Description: Stores the indicated word into the indicated range of // bits with this BitArray. //////////////////////////////////////////////////////////////////// INLINE void BitArray:: store(WordType value, int low_bit, int size) { nassertv(size >= 0); int w = low_bit / num_bits_per_word; int b = low_bit % num_bits_per_word; if (b + size < num_bits_per_word) { // The whole thing fits within one word of the array. ensure_has_word(w); _array[w].store(value, b, size); } else { // We have to split it across two words. int num_lower_bits = num_bits_per_word - b; int num_higher_bits = size - num_lower_bits; ensure_has_word(w + 1); _array[w].store(value, b, num_lower_bits); _array[w + 1].store(value >> num_lower_bits, 0, num_higher_bits); } normalize(); } //////////////////////////////////////////////////////////////////// // Function: BitArray::set_range_to // Access: Published // Description: Sets the indicated range of bits to either on or off. //////////////////////////////////////////////////////////////////// INLINE void BitArray:: set_range_to(bool value, int low_bit, int size) { if (value) { set_range(low_bit, size); } else { clear_range(low_bit, size); } } //////////////////////////////////////////////////////////////////// // Function: BitArray::get_num_words // Access: Published // Description: Returns the number of possibly-unique words stored in // the array. //////////////////////////////////////////////////////////////////// INLINE int BitArray:: get_num_words() const { return _array.size(); } //////////////////////////////////////////////////////////////////// // Function: BitArray::get_word // Access: Published // Description: Returns the nth word in the array. It is valid for n // to be greater than get_num_words(), but the return // value beyond get_num_words() will always be the same. //////////////////////////////////////////////////////////////////// INLINE BitArray::MaskType BitArray:: get_word(int n) const { nassertr(n >= 0, MaskType::all_off()); if (n < get_num_words()) { return _array[n]; } if (_highest_bits) { return MaskType::all_on(); } else { return MaskType::all_off(); } } //////////////////////////////////////////////////////////////////// // Function: BitArray::set_word // Access: Published // Description: Replaces the nth word in the array. If n >= // get_num_words(), this automatically extends the // array. //////////////////////////////////////////////////////////////////// INLINE void BitArray:: set_word(int n, MaskType value) { nassertv(n >= 0); ensure_has_word(n); _array[n] = value; normalize(); } //////////////////////////////////////////////////////////////////// // Function: BitArray::clear // Access: Published // Description: Sets all the bits in the BitArray off. //////////////////////////////////////////////////////////////////// void BitArray:: clear() { _array.clear(); _highest_bits = 0; } //////////////////////////////////////////////////////////////////// // Function: BitArray::operator == // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE bool BitArray:: operator == (const BitArray &other) const { return compare_to(other) == 0; } //////////////////////////////////////////////////////////////////// // Function: BitArray::operator != // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE bool BitArray:: operator != (const BitArray &other) const { return compare_to(other) != 0; } //////////////////////////////////////////////////////////////////// // Function: BitArray::operator < // Access: Published // Description: Returns true if the unsigned integer which is // represented by this BitArray is less than that of the // other one, false otherwise. //////////////////////////////////////////////////////////////////// INLINE bool BitArray:: operator < (const BitArray &other) const { return compare_to(other) < 0; } //////////////////////////////////////////////////////////////////// // Function: BitArray::operator & // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE BitArray BitArray:: operator & (const BitArray &other) const { BitArray result(*this); result &= other; return result; } //////////////////////////////////////////////////////////////////// // Function: BitArray::operator | // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE BitArray BitArray:: operator | (const BitArray &other) const { BitArray result(*this); result |= other; return result; } //////////////////////////////////////////////////////////////////// // Function: BitArray::operator ^ // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE BitArray BitArray:: operator ^ (const BitArray &other) const { BitArray result(*this); result ^= other; return result; } //////////////////////////////////////////////////////////////////// // Function: BitArray::operator ~ // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE BitArray BitArray:: operator ~ () const { BitArray result(*this); result.invert_in_place(); return result; } //////////////////////////////////////////////////////////////////// // Function: BitArray::operator << // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE BitArray BitArray:: operator << (int shift) const { BitArray result(*this); result <<= shift; return result; } //////////////////////////////////////////////////////////////////// // Function: BitArray::operator >> // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE BitArray BitArray:: operator >> (int shift) const { BitArray result(*this); result >>= shift; return result; } //////////////////////////////////////////////////////////////////// // Function: BitArray::copy_on_write // Access: Private // Description: Called internally just before writing to the _array // member, this makes a new copy of _array if it appears // to be shared with any other objects--thus achieving // copy-on-write. //////////////////////////////////////////////////////////////////// INLINE void BitArray:: copy_on_write() { if (_array.get_ref_count() > 1) { PTA(MaskType) new_array; new_array.v() = _array.v(); _array = new_array; } }