From ecec0779f01152f3c625ea0f7e2f04a0a5f48275 Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 20 Jan 2006 18:02:11 +0000 Subject: [PATCH] BitArray (first pass) --- panda/src/putil/Sources.pp | 13 +- panda/src/putil/bitArray.I | 518 ++++++++++++++++++++++ panda/src/putil/bitArray.cxx | 626 +++++++++++++++++++++++++++ panda/src/putil/bitArray.h | 152 +++++++ panda/src/putil/bitMask.I | 325 +++++++++----- panda/src/putil/bitMask.h | 63 +-- panda/src/putil/config_util.cxx | 4 + panda/src/putil/putil_composite1.cxx | 1 + 8 files changed, 1555 insertions(+), 147 deletions(-) create mode 100755 panda/src/putil/bitArray.I create mode 100755 panda/src/putil/bitArray.cxx create mode 100755 panda/src/putil/bitArray.h diff --git a/panda/src/putil/Sources.pp b/panda/src/putil/Sources.pp index 26520d5e50..6a752a9403 100644 --- a/panda/src/putil/Sources.pp +++ b/panda/src/putil/Sources.pp @@ -11,8 +11,9 @@ animInterface.h animInterface.I \ bam.h bamEndian.h \ bamReader.I bamReader.N bamReader.h bamReaderParam.I \ - bamReaderParam.h bamWriter.I bamWriter.h bitMask.I \ - bitMask.h \ + bamReaderParam.h bamWriter.I bamWriter.h \ + bitArray.I bitArray.h \ + bitMask.I bitMask.h \ buttonHandle.I \ buttonHandle.h buttonRegistry.I buttonRegistry.h \ cachedTypedWritableReferenceCount.h cachedTypedWritableReferenceCount.I \ @@ -62,7 +63,9 @@ #define INCLUDED_SOURCES \ animInterface.cxx \ bamEndian.cxx \ - bamReader.cxx bamReaderParam.cxx bamWriter.cxx bitMask.cxx \ + bamReader.cxx bamReaderParam.cxx bamWriter.cxx \ + bitArray.cxx \ + bitMask.cxx \ buttonHandle.cxx buttonRegistry.cxx \ cachedTypedWritableReferenceCount.cxx \ config_util.cxx configurable.cxx \ @@ -99,7 +102,9 @@ animInterface.h animInterface.I \ bam.h bamEndian.h \ bamReader.I bamReader.h bamReaderParam.I bamReaderParam.h \ - bamWriter.I bamWriter.h bitMask.I bitMask.h \ + bamWriter.I bamWriter.h \ + bitArray.I bitArray.h \ + bitMask.I bitMask.h \ buttonHandle.I buttonHandle.h buttonRegistry.I \ buttonRegistry.h \ cachedTypedWritableReferenceCount.h cachedTypedWritableReferenceCount.I \ diff --git a/panda/src/putil/bitArray.I b/panda/src/putil/bitArray.I new file mode 100755 index 0000000000..7aca49d615 --- /dev/null +++ b/panda/src/putil/bitArray.I @@ -0,0 +1,518 @@ +// Filename: bitArray.I +// Created by: drose (20Jan06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// 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 void BitArray:: +operator = (const BitArray ©) { + _array = copy._array; +} + +//////////////////////////////////////////////////////////////////// +// 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; +} diff --git a/panda/src/putil/bitArray.cxx b/panda/src/putil/bitArray.cxx new file mode 100755 index 0000000000..b1cc146f70 --- /dev/null +++ b/panda/src/putil/bitArray.cxx @@ -0,0 +1,626 @@ +// Filename: bitArray.cxx +// Created by: drose (20Jan06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "bitArray.h" + +TypeHandle BitArray::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::is_zero +// Access: Published +// Description: Returns true if the entire bitmask is zero, false +// otherwise. +//////////////////////////////////////////////////////////////////// +bool BitArray:: +is_zero() const { + if (_highest_bits) { + // If all the infinite highest bits are set, certainly the bitmask + // is nonzero. + return false; + } + + // Start from the high end, since that's more likely to be nonzero. + Array::const_reverse_iterator ai; + for (ai = _array.rbegin(); ai != _array.rend(); ++ai) { + if ((*ai) != 0) { + return false; + } + } + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::set_range +// Access: Published +// Description: Sets the indicated range of bits on. +//////////////////////////////////////////////////////////////////// +void BitArray:: +set_range(int low_bit, int size) { + int w = low_bit / num_bits_per_word; + int b = low_bit % num_bits_per_word; + + if (w >= get_num_words() && _highest_bits) { + // All the highest bits are already on. + return; + } + if (b + size <= num_bits_per_word) { + // The whole thing fits within one word of the array. + ensure_has_word(w); + _array[w].set_range(b, size); + normalize(); + return; + } + + while (size > 0) { + if (size <= num_bits_per_word) { + // The remainder fits within one word of the array. + ensure_has_word(w); + _array[w].set_range(0, size); + normalize(); + return; + } + + // Keep going. + ensure_has_word(w); + _array[w] = MaskType::all_on(); + size -= num_bits_per_word; + ++w; + + if (w >= get_num_words() && _highest_bits) { + // All the highest bits are already on. + normalize(); + return; + } + } + normalize(); +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::clear_range +// Access: Published +// Description: Sets the indicated range of bits off. +//////////////////////////////////////////////////////////////////// +void BitArray:: +clear_range(int low_bit, int size) { + int w = low_bit / num_bits_per_word; + int b = low_bit % num_bits_per_word; + + if (w >= get_num_words() && !_highest_bits) { + // All the highest bits are already off. + return; + } + if (b + size <= num_bits_per_word) { + // The whole thing fits within one word of the array. + ensure_has_word(w); + _array[w].clear_range(b, size); + normalize(); + return; + } + + while (size > 0) { + if (size <= num_bits_per_word) { + // The remainder fits within one word of the array. + ensure_has_word(w); + _array[w].clear_range(0, size); + normalize(); + return; + } + + // Keep going. + ensure_has_word(w); + _array[w] = MaskType::all_on(); + size -= num_bits_per_word; + ++w; + + if (w >= get_num_words() && !_highest_bits) { + // All the highest bits are already off. + normalize(); + return; + } + } + normalize(); +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::invert_in_place +// Access: Published +// Description: Inverts all the bits in the BitArray. This is +// equivalent to array = ~array. +//////////////////////////////////////////////////////////////////// +void BitArray:: +invert_in_place() { + _highest_bits = !_highest_bits; + Array::iterator ai; + for (ai = _array.begin(); ai != _array.end(); ++ai) { + (*ai) = ~(*ai); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::has_bits_in_common +// Access: Published +// Description: Returns true if this BitArray has any "one" bits in +// common with the other one, false otherwise. +// +// This is equivalent to (array & other) != 0, but may +// be faster. +//////////////////////////////////////////////////////////////////// +bool BitArray:: +has_bits_in_common(const BitArray &other) const { + if (_highest_bits && other._highest_bits) { + // Yup, in fact we have an infinite number of bits in common. + return true; + } + + size_t num_common_words = min(_array.size(), other._array.size()); + + // Consider the words that are on top of either array. + if (other._array.size() < _array.size() && other._highest_bits) { + // The other array has fewer actual words, and the top n words of + // the other array are all ones. We have bits in common if any of + // our top n words are nonzero. + Array::const_iterator ai; + for (ai = _array.begin() + other._array.size(); + ai != _array.end(); + ++ai) { + if (!(*ai).is_zero()) { + return true; + } + } + + } else if (_array.size() < other._array.size() && _highest_bits) { + // This array has fewer actual words, and the top n words of this + // array are all ones. We have bits in common if any of the the + // other's top n words are nonzero. + Array::const_iterator ai; + for (ai = other._array.begin() + _array.size(); + ai != other._array.end(); + ++ai) { + if (!(*ai).is_zero()) { + return true; + } + } + } + + // Consider the words that both arrays have in common. + for (size_t i = 0; i < num_common_words; ++i) { + if (!(_array[i] & other._array[i]).is_zero()) { + return true; + } + } + + // Nope, nothing. + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::output +// Access: Published +// Description: Writes the BitArray out as a binary or a hex number, +// according to the number of bits. +//////////////////////////////////////////////////////////////////// +void BitArray:: +output(ostream &out) const { + if (get_num_bits() >= 40) { + output_hex(out); + } else { + output_binary(out); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::output_binary +// Access: Published +// Description: Writes the BitArray out as a binary number, with +// spaces every four bits. +//////////////////////////////////////////////////////////////////// +void BitArray:: +output_binary(ostream &out, int spaces_every) const { + if (_highest_bits) { + out << "...1 "; + } + int num_bits = max(get_num_bits(), spaces_every); + 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: BitArray::output_hex +// Access: Published +// Description: Writes the BitArray out as a hexadecimal number, with +// spaces every four digits. +//////////////////////////////////////////////////////////////////// +void BitArray:: +output_hex(ostream &out, int spaces_every) const { + int num_bits = get_num_bits(); + int num_digits = max((num_bits + 3) / 4, spaces_every); + + if (_highest_bits) { + out << "...f "; + } + + 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: BitArray::write +// Access: Published +// Description: Writes the BitArray out as a binary or a hex number, +// according to the number of bits. +//////////////////////////////////////////////////////////////////// +void BitArray:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) << *this << "\n"; +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::compare_to +// Access: Published +// Description: Returns a number less than zero if this BitArray sorts +// before the indicated other BitArray, greater than zero +// if it sorts after, or 0 if they are equivalent. This +// is based on the same ordering defined by operator <. +//////////////////////////////////////////////////////////////////// +int BitArray:: +compare_to(const BitArray &other) const { + if (_highest_bits != other._highest_bits) { + return _highest_bits ? 1 : -1; + } + + int num_words = max(get_num_words(), other.get_num_words()); + + // Compare from highest-order to lowest-order word. + for (int i = num_words - 1; i >= 0; --i) { + int compare = get_word(i).compare_to(other.get_word(i)); + if (compare != 0) { + return compare; + } + } + + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::operator &= +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void BitArray:: +operator &= (const BitArray &other) { + size_t num_common_words = min(_array.size(), other._array.size()); + + // Consider the words that are on top of either array. + if (other._array.size() < _array.size() && !other._highest_bits) { + // The other array has fewer actual words, and the top n words of + // the other array are all zeroes. "mask off" the top n words of + // this array. + _array.erase(_array.begin() + other._array.size(), _array.end()); + + } else if (_array.size() < other._array.size() && _highest_bits) { + // This array has fewer actual words, and the top n words of this + // array are all ones. "mask on" the top n words of the other + // array. + Array::const_iterator ai; + for (ai = other._array.begin() + _array.size(); + ai != other._array.end(); + ++ai) { + _array.push_back(*ai); + } + } + + // Consider the words that both arrays have in common. + for (size_t i = 0; i < num_common_words; ++i) { + _array[i] &= other._array[i]; + } + + _highest_bits &= other._highest_bits; + normalize(); +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::operator |= +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void BitArray:: +operator |= (const BitArray &other) { + size_t num_common_words = min(_array.size(), other._array.size()); + + // Consider the words that are on top of either array. + if (other._array.size() < _array.size() && other._highest_bits) { + // The other array has fewer actual words, and the top n words of + // the other array are all ones. The top n words of this array + // become ones too (which means we can drop them out). + _array.erase(_array.begin() + other._array.size(), _array.end()); + + } else if (_array.size() < other._array.size() && !_highest_bits) { + // This array has fewer actual words, and the top n words of this + // array are all zeros. Copy in the top n words of the other + // array. + Array::const_iterator ai; + for (ai = other._array.begin() + _array.size(); + ai != other._array.end(); + ++ai) { + _array.push_back(*ai); + } + } + + // Consider the words that both arrays have in common. + for (size_t i = 0; i < num_common_words; ++i) { + _array[i] |= other._array[i]; + } + + _highest_bits |= other._highest_bits; + normalize(); +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::operator ^= +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void BitArray:: +operator ^= (const BitArray &other) { + size_t num_common_words = min(_array.size(), other._array.size()); + + // Consider the words that are on top of either array. + if (other._array.size() < _array.size() && other._highest_bits) { + // The other array has fewer actual words, and the top n words of + // the other array are all ones. The top n words of this array + // get inverted. + Array::iterator ai; + for (ai = _array.begin() + other._array.size(); + ai != _array.end(); + ++ai) { + (*ai).invert_in_place(); + } + + } else if (_array.size() < other._array.size()) { + if (!_highest_bits) { + // This array has fewer actual words, and the top n words of this + // array are all zeros. Copy in the top n words of the other + // array. + Array::const_iterator ai; + for (ai = other._array.begin() + _array.size(); + ai != other._array.end(); + ++ai) { + _array.push_back(*ai); + } + } else { + // This array has fewer actual words, and the top n words of this + // array are all ones. Copy in the top n words of the other + // array, inverted. + Array::const_iterator ai; + for (ai = other._array.begin() + _array.size(); + ai != other._array.end(); + ++ai) { + _array.push_back(~(*ai)); + } + } + } + + // Consider the words that both arrays have in common. + for (size_t i = 0; i < num_common_words; ++i) { + _array[i] ^= other._array[i]; + } + + _highest_bits ^= other._highest_bits; + normalize(); +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::operator <<= +// Access: Published +// Description: Logical left shift. The rightmost bits are filled in +// with zeroes. Since this is an infinite bit array, +// none of the bits on the left are lost. +//////////////////////////////////////////////////////////////////// +void BitArray:: +operator <<= (int shift) { + if (shift == 0 || _array.empty()) { + return; + } + if (shift < 0) { + operator >>= (-shift); + return; + } + + int w = shift / num_bits_per_word; + int b = shift % num_bits_per_word; + + if (b == 0) { + // Easy case--word-at-a-time. + Array new_array; + new_array.reserve(_array.size() + w); + for (int i = 0; i < w; ++i) { + new_array.push_back(MaskType::all_off()); + } + Array::const_iterator ai; + for (ai = _array.begin(); ai != _array.end(); ++ai) { + new_array.push_back(*ai); + } + _array.swap(new_array); + + } else { + // Harder case--we have to shuffle bits between words. + Array new_array; + new_array.reserve(_array.size() + w + 1); + for (int i = 0; i < w; ++i) { + new_array.push_back(MaskType::all_off()); + } + + int downshift_count = num_bits_per_word - b; + MaskType lower_mask = MaskType::lower_on(downshift_count); + MaskType upper_mask = ~lower_mask; + + Array::const_iterator ai = _array.begin(); + nassertv(ai != _array.end()); + MaskType next_bits = ((*ai) & upper_mask) >> downshift_count; + new_array.push_back(((*ai) & lower_mask) << b); + ++ai; + while (ai != _array.end()) { + new_array.push_back((((*ai) & lower_mask) << b) | next_bits); + next_bits = ((*ai) & upper_mask) >> downshift_count; + ++ai; + } + + // Finally, the top n bits. + if (_highest_bits) { + next_bits |= upper_mask; + } + new_array.push_back(next_bits); + _array.swap(new_array); + } + + normalize(); +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::operator >>= +// Access: Published +// Description: Logical right shift. The rightmost bits are lost. +// Since this is an infinite bit array, there is no +// question of sign extension; there is no need to +// synthesize bits on the left. +//////////////////////////////////////////////////////////////////// +void BitArray:: +operator >>= (int shift) { + if (shift == 0 || _array.empty()) { + return; + } + if (shift < 0) { + operator <<= (-shift); + return; + } + + int w = shift / num_bits_per_word; + int b = shift % num_bits_per_word; + + if (w >= (int)_array.size()) { + // Trivial case--shift to nothing. + _array.clear(); + return; + } + + if (b == 0) { + // Easy case--word-at-a-time. + Array new_array; + new_array.reserve(_array.size() - w); + Array::const_iterator ai; + for (ai = _array.begin() + w; ai != _array.end(); ++ai) { + new_array.push_back(*ai); + } + _array.swap(new_array); + + } else { + // Harder case--we have to shuffle bits between words. + Array new_array; + new_array.reserve(_array.size() - w); + + int upshift_count = num_bits_per_word - b; + MaskType lower_mask = MaskType::lower_on(b); + MaskType upper_mask = ~lower_mask; + + Array::const_iterator ai = _array.begin() + w; + nassertv(ai < _array.end()); + MaskType next_bits = ((*ai) & upper_mask) >> b; + + ++ai; + while (ai != _array.end()) { + new_array.push_back((((*ai) & lower_mask) << upshift_count) | next_bits); + next_bits = ((*ai) & upper_mask) >> b; + ++ai; + } + + // Finally, the top n bits. + if (_highest_bits) { + next_bits |= upper_mask; + } + new_array.push_back(next_bits); + _array.swap(new_array); + } + + normalize(); +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::generate_hash +// Access: Public +// Description: Adds the bitmask to the indicated hash generator. +//////////////////////////////////////////////////////////////////// +void BitArray:: +generate_hash(ChecksumHashGenerator &hashgen) const { + hashgen.add_int(_highest_bits); + Array::const_iterator ai; + for (ai = _array.begin(); ai != _array.end(); ++ai) { + hashgen.add_int((*ai).get_word()); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::ensure_has_word +// Access: Private +// Description: Ensures that at least word n has been allocated into +// the array. +//////////////////////////////////////////////////////////////////// +void BitArray:: +ensure_has_word(int n) { + if (_highest_bits) { + while (n >= (int)_array.size()) { + _array.push_back(MaskType::all_on()); + } + } else { + while (n >= (int)_array.size()) { + _array.push_back(MaskType::all_off()); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::normalize +// Access: Private +// Description: Ensures that the array is the smallest array that +// represents this same value, by removing the topmost +// words that are all bits off (or on). +//////////////////////////////////////////////////////////////////// +void BitArray:: +normalize() { + if (_highest_bits) { + while (!_array.empty() && _array.back() == MaskType::all_on()) { + _array.pop_back(); + } + } else { + while (!_array.empty() && _array.back().is_zero()) { + _array.pop_back(); + } + } +} diff --git a/panda/src/putil/bitArray.h b/panda/src/putil/bitArray.h new file mode 100755 index 0000000000..0a6bde1d55 --- /dev/null +++ b/panda/src/putil/bitArray.h @@ -0,0 +1,152 @@ +// Filename: bitArray.h +// Created by: drose (20Jan06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef BITARRAY_H +#define BITARRAY_H + +#include "pandabase.h" + +#include "bitMask.h" +#include "numeric_types.h" +#include "typedObject.h" +#include "indent.h" + +#include "checksumHashGenerator.h" + +//////////////////////////////////////////////////////////////////// +// Class : BitArray +// Description : A dynamic array with an unlimited number of bits. +// +// This is similar to a BitMask, except it appears to +// contain an infinite number of bits. You can use it +// very much as you would use a BitMask. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA BitArray { +public: + typedef BitMask32 MaskType; + typedef MaskType::WordType WordType; + enum { num_bits_per_word = MaskType::num_bits }; + +PUBLISHED: + + INLINE BitArray(); + INLINE BitArray(WordType init_value); + INLINE BitArray(const BitArray ©); + INLINE void operator = (const BitArray ©); + + INLINE static BitArray all_on(); + INLINE static BitArray all_off(); + INLINE static BitArray lower_on(int on_bits); + INLINE static BitArray bit(int index); + INLINE static BitArray range(int low_bit, int size); + + INLINE ~BitArray(); + + INLINE static bool has_max_num_bits(); + INLINE static int get_max_num_bits(); + + INLINE static int get_num_bits_per_word(); + INLINE int get_num_bits() const; + INLINE bool get_bit(int index) const; + INLINE void set_bit(int index); + INLINE void clear_bit(int index); + INLINE void set_bit_to(int index, bool value); + INLINE bool get_highest_bits() const; + bool is_zero() const; + + INLINE WordType extract(int low_bit, int size) const; + INLINE void store(WordType value, int low_bit, int size); + void set_range(int low_bit, int size); + void clear_range(int low_bit, int size); + INLINE void set_range_to(bool value, int low_bit, int size); + + INLINE int get_num_words() const; + INLINE MaskType get_word(int n) const; + INLINE void set_word(int n, MaskType value); + + void invert_in_place(); + bool has_bits_in_common(const BitArray &other) const; + INLINE void clear(); + + void output(ostream &out) const; + void output_binary(ostream &out, int spaces_every = 4) const; + void output_hex(ostream &out, int spaces_every = 4) const; + void write(ostream &out, int indent_level = 0) const; + + INLINE bool operator == (const BitArray &other) const; + INLINE bool operator != (const BitArray &other) const; + INLINE bool operator < (const BitArray &other) const; + int compare_to(const BitArray &other) const; + + INLINE BitArray + operator & (const BitArray &other) const; + + INLINE BitArray + operator | (const BitArray &other) const; + + INLINE BitArray + operator ^ (const BitArray &other) const; + + INLINE BitArray + operator ~ () const; + + INLINE BitArray + operator << (int shift) const; + + INLINE BitArray + operator >> (int shift) const; + + void operator &= (const BitArray &other); + void operator |= (const BitArray &other); + void operator ^= (const BitArray &other); + void operator <<= (int shift); + void operator >>= (int shift); + +public: + void generate_hash(ChecksumHashGenerator &hashgen) const; + +private: + void ensure_has_word(int n); + void normalize(); + +private: + typedef pvector Array; + Array _array; + int _highest_bits; // Either 0 or 1. + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + register_type(_type_handle, "BitArray"); + } + +private: + static TypeHandle _type_handle; +}; + +#include "bitArray.I" + +INLINE ostream & +operator << (ostream &out, const BitArray &array) { + array.output(out); + return out; +} + +#endif diff --git a/panda/src/putil/bitMask.I b/panda/src/putil/bitMask.I index 1e2eedf597..4547c64552 100644 --- a/panda/src/putil/bitMask.I +++ b/panda/src/putil/bitMask.I @@ -16,16 +16,16 @@ // //////////////////////////////////////////////////////////////////// -template -TypeHandle BitMask::_type_handle; +template +TypeHandle BitMask::_type_handle; //////////////////////////////////////////////////////////////////// // Function: BitMask::Constructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE BitMask:: +template +INLINE BitMask:: BitMask() : _word(0) { @@ -36,8 +36,8 @@ BitMask() : // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE BitMask:: +template +INLINE BitMask:: BitMask(WordType init_value) : _word(init_value) { @@ -48,9 +48,9 @@ BitMask(WordType init_value) : // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE BitMask:: -BitMask(const BitMask ©) : +template +INLINE BitMask:: +BitMask(const BitMask ©) : _word(copy._word) { } @@ -60,9 +60,9 @@ BitMask(const BitMask ©) : // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE void BitMask:: -operator = (const BitMask ©) { +template +INLINE void BitMask:: +operator = (const BitMask ©) { _word = copy._word; } @@ -71,8 +71,8 @@ operator = (const BitMask ©) { // Access: Published, Static // Description: Returns a BitMask whose bits are all on. //////////////////////////////////////////////////////////////////// -template -INLINE BitMask BitMask:: +template +INLINE BitMask BitMask:: all_on() { BitMask result; result._word = ~0; @@ -84,8 +84,8 @@ all_on() { // Access: Published, Static // Description: Returns a BitMask whose bits are all off. //////////////////////////////////////////////////////////////////// -template -INLINE BitMask BitMask:: +template +INLINE BitMask BitMask:: all_off() { BitMask result; result._word = 0; @@ -95,10 +95,10 @@ all_off() { //////////////////////////////////////////////////////////////////// // Function: BitMask::Named lower_on constructor // Access: Published, Static -// Description: Returns a BitMask whose lower num_bits bits are on. +// Description: Returns a BitMask whose lower on_bits bits are on. //////////////////////////////////////////////////////////////////// -template -INLINE BitMask BitMask:: +template +INLINE BitMask BitMask:: lower_on(int on_bits) { if (on_bits <= 0) { return all_off(); @@ -115,8 +115,8 @@ lower_on(int on_bits) { // Access: Published, Static // Description: Returns a BitMask with only the indicated bit on. //////////////////////////////////////////////////////////////////// -template -INLINE BitMask BitMask:: +template +INLINE BitMask BitMask:: bit(int index) { BitMask result; result.set_bit(index); @@ -129,8 +129,8 @@ bit(int index) { // Description: Returns a BitMask whose size bits, beginning at // low_bit, are on. //////////////////////////////////////////////////////////////////// -template -INLINE BitMask BitMask:: +template +INLINE BitMask BitMask:: range(int low_bit, int size) { BitMask result; if (size <= 0) { @@ -149,19 +149,56 @@ range(int low_bit, int size) { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE BitMask:: +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:: +template +INLINE int BitMask:: get_num_bits() { return num_bits; } @@ -171,10 +208,10 @@ get_num_bits() { // Access: Published // Description: Returns true if the nth bit is set, false if it is // cleared. index must be in the range [0, -// get_num_bits). +// num_bits). //////////////////////////////////////////////////////////////////// -template -INLINE bool BitMask:: +template +INLINE bool BitMask:: get_bit(int index) const { nassertr(index >= 0 && index < num_bits, false); return (_word & ((WordType)1 << index)) != 0; @@ -184,10 +221,10 @@ get_bit(int index) const { // Function: BitMask::set_bit // Access: Published // Description: Sets the nth bit on. index must be in the range -// [0, get_num_bits). +// [0, num_bits). //////////////////////////////////////////////////////////////////// -template -INLINE void BitMask:: +template +INLINE void BitMask:: set_bit(int index) { nassertv(index >= 0 && index < num_bits); _word |= ((WordType)1 << index); @@ -197,10 +234,10 @@ set_bit(int index) { // Function: BitMask::clear_bit // Access: Published // Description: Sets the nth bit off. index must be in the range -// [0, get_num_bits). +// [0, num_bits). //////////////////////////////////////////////////////////////////// -template -INLINE void BitMask:: +template +INLINE void BitMask:: clear_bit(int index) { nassertv(index >= 0 && index < num_bits); _word &= ~((WordType)1 << index); @@ -211,10 +248,10 @@ clear_bit(int index) { // Access: Published // Description: Sets the nth bit either on or off, according to the // indicated bool value. index must be in the range [0, -// get_num_bits). +// num_bits). //////////////////////////////////////////////////////////////////// -template -INLINE void BitMask:: +template +INLINE void BitMask:: set_bit_to(int index, bool value) { if (value) { set_bit(index); @@ -229,8 +266,8 @@ set_bit_to(int index, bool value) { // Description: Returns true if the entire bitmask is zero, false // otherwise. //////////////////////////////////////////////////////////////////// -template -INLINE bool BitMask:: +template +INLINE bool BitMask:: is_zero() const { return (_word == 0); } @@ -242,11 +279,11 @@ is_zero() const { // range of bits within this BitMask, shifted to the // least-significant position. //////////////////////////////////////////////////////////////////// -template -INLINE WordType BitMask:: +template +INLINE TYPENAME BitMask::WordType BitMask:: extract(int low_bit, int size) const { return (_word >> low_bit) & - BitMask::lower_on(size)._word; + BitMask::lower_on(size)._word; } //////////////////////////////////////////////////////////////////// @@ -255,21 +292,59 @@ extract(int low_bit, int size) const { // Description: Stores the indicated word into the indicated range of // bits with this BitMask. //////////////////////////////////////////////////////////////////// -template -INLINE void BitMask:: +template +INLINE void BitMask:: store(WordType value, int low_bit, int size) { - WordType mask = - BitMask::lower_on(size)._word << low_bit; + WordType mask = BitMask::range(low_bit, size)._word; _word = (_word & ~mask) | ((value << low_bit) & 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 WordType BitMask:: +template +INLINE TYPENAME BitMask::WordType BitMask:: get_word() const { return _word; } @@ -280,8 +355,8 @@ get_word() const { // Description: Sets the entire BitMask to the value indicated by the // given word. //////////////////////////////////////////////////////////////////// -template -INLINE void BitMask:: +template +INLINE void BitMask:: set_word(WordType value) { _word = value; } @@ -289,21 +364,39 @@ set_word(WordType value) { //////////////////////////////////////////////////////////////////// // Function: BitMask::invert_in_place // Access: Published -// Description: Inverts all the bits in the BitMask. +// Description: Inverts all the bits in the BitMask. This is +// equivalent to mask = ~mask. //////////////////////////////////////////////////////////////////// -template -INLINE void BitMask:: +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:: +template +INLINE void BitMask:: clear() { _word = 0; } @@ -314,8 +407,8 @@ clear() { // Description: Writes the BitMask out as a binary or a hex number, // according to the number of bits. //////////////////////////////////////////////////////////////////// -template -void BitMask:: +template +void BitMask:: output(ostream &out) const { if (num_bits >= 40) { output_hex(out); @@ -330,8 +423,8 @@ output(ostream &out) const { // Description: Writes the BitMask out as a binary number, with // spaces every four bits. //////////////////////////////////////////////////////////////////// -template -void BitMask:: +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)) { @@ -347,8 +440,8 @@ output_binary(ostream &out, int spaces_every) const { // Description: Writes the BitMask out as a hexadecimal number, with // spaces every four digits. //////////////////////////////////////////////////////////////////// -template -void BitMask:: +template +void BitMask:: output_hex(ostream &out, int spaces_every) const { int num_digits = (num_bits + 3) / 4; @@ -371,8 +464,8 @@ output_hex(ostream &out, int spaces_every) const { // Description: Writes the BitMask out as a binary or a hex number, // according to the number of bits. //////////////////////////////////////////////////////////////////// -template -void BitMask:: +template +void BitMask:: write(ostream &out, int indent_level) const { indent(out, indent_level) << *this << "\n"; } @@ -382,9 +475,9 @@ write(ostream &out, int indent_level) const { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE bool BitMask:: -operator == (const BitMask &other) const { +template +INLINE bool BitMask:: +operator == (const BitMask &other) const { return _word == other._word; } @@ -393,9 +486,9 @@ operator == (const BitMask &other) const { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE bool BitMask:: -operator != (const BitMask &other) const { +template +INLINE bool BitMask:: +operator != (const BitMask &other) const { return _word != other._word; } @@ -410,9 +503,9 @@ operator != (const BitMask &other) const { // export any STL container (ordered or unordered) of // BitMask under Windows. //////////////////////////////////////////////////////////////////// -template -INLINE bool BitMask:: -operator < (const BitMask &other) const { +template +INLINE bool BitMask:: +operator < (const BitMask &other) const { return _word < other._word; } @@ -424,9 +517,9 @@ operator < (const BitMask &other) const { // 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 { +template +INLINE int BitMask:: +compare_to(const BitMask &other) const { if ((*this) < other) { return -1; } else if (other < (*this)) { @@ -441,10 +534,10 @@ compare_to(const BitMask &other) const { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE BitMask BitMask:: -operator & (const BitMask &other) const { - BitMask result(*this); +template +INLINE BitMask BitMask:: +operator & (const BitMask &other) const { + BitMask result(*this); result &= other; return result; } @@ -454,10 +547,10 @@ operator & (const BitMask &other) const { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE BitMask BitMask:: -operator | (const BitMask &other) const { - BitMask result(*this); +template +INLINE BitMask BitMask:: +operator | (const BitMask &other) const { + BitMask result(*this); result |= other; return result; } @@ -467,10 +560,10 @@ operator | (const BitMask &other) const { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE BitMask BitMask:: -operator ^ (const BitMask &other) const { - BitMask result(*this); +template +INLINE BitMask BitMask:: +operator ^ (const BitMask &other) const { + BitMask result(*this); result ^= other; return result; } @@ -480,12 +573,10 @@ operator ^ (const BitMask &other) const { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE BitMask BitMask:: +template +INLINE BitMask BitMask:: operator ~ () const { - BitMask result(*this); - result._word = ~result._word; - return result; + return BitMask(~_word); } //////////////////////////////////////////////////////////////////// @@ -493,10 +584,10 @@ operator ~ () const { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE BitMask BitMask:: +template +INLINE BitMask BitMask:: operator << (int shift) const { - BitMask result(*this); + BitMask result(*this); result <<= shift; return result; } @@ -506,10 +597,10 @@ operator << (int shift) const { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE BitMask BitMask:: +template +INLINE BitMask BitMask:: operator >> (int shift) const { - BitMask result(*this); + BitMask result(*this); result >>= shift; return result; } @@ -519,9 +610,9 @@ operator >> (int shift) const { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE void BitMask:: -operator &= (const BitMask &other) { +template +INLINE void BitMask:: +operator &= (const BitMask &other) { _word &= other._word; } @@ -530,9 +621,9 @@ operator &= (const BitMask &other) { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE void BitMask:: -operator |= (const BitMask &other) { +template +INLINE void BitMask:: +operator |= (const BitMask &other) { _word |= other._word; } @@ -541,9 +632,9 @@ operator |= (const BitMask &other) { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE void BitMask:: -operator ^= (const BitMask &other) { +template +INLINE void BitMask:: +operator ^= (const BitMask &other) { _word ^= other._word; } @@ -552,8 +643,8 @@ operator ^= (const BitMask &other) { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE void BitMask:: +template +INLINE void BitMask:: operator <<= (int shift) { _word <<= shift; } @@ -563,8 +654,8 @@ operator <<= (int shift) { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -template -INLINE void BitMask:: +template +INLINE void BitMask:: operator >>= (int shift) { _word >>= shift; } @@ -574,8 +665,8 @@ operator >>= (int shift) { // Access: Public // Description: Adds the bitmask to the indicated hash generator. //////////////////////////////////////////////////////////////////// -template -INLINE void BitMask:: +template +INLINE void BitMask:: generate_hash(ChecksumHashGenerator &hashgen) const { hashgen.add_int(_word); } @@ -585,8 +676,8 @@ generate_hash(ChecksumHashGenerator &hashgen) const { // Access: Public // Description: //////////////////////////////////////////////////////////////////// -template -void BitMask:: +template +void BitMask:: init_type() { ostringstream str; str << "BitMask" << num_bits; diff --git a/panda/src/putil/bitMask.h b/panda/src/putil/bitMask.h index 6311d75b3f..b171aabdb6 100644 --- a/panda/src/putil/bitMask.h +++ b/panda/src/putil/bitMask.h @@ -34,22 +34,29 @@ // bits of some length that must fit within a given word // of the indicated type. See also BitArray. //////////////////////////////////////////////////////////////////// -template +template class BitMask { +public: + typedef WType WordType; + enum { num_bits = nbits }; + PUBLISHED: INLINE BitMask(); INLINE BitMask(WordType init_value); - INLINE BitMask(const BitMask ©); - INLINE void operator = (const BitMask ©); + INLINE BitMask(const BitMask ©); + INLINE void operator = (const BitMask ©); - INLINE static BitMask all_on(); - INLINE static BitMask all_off(); - INLINE static BitMask lower_on(int on_bits); - INLINE static BitMask bit(int index); - INLINE static BitMask range(int low_bit, int size); + INLINE static BitMask all_on(); + INLINE static BitMask all_off(); + INLINE static BitMask lower_on(int on_bits); + INLINE static BitMask bit(int index); + INLINE static BitMask range(int low_bit, int size); INLINE ~BitMask(); + INLINE static bool has_max_num_bits(); + INLINE static int get_max_num_bits(); + INLINE static int get_num_bits(); INLINE bool get_bit(int index) const; INLINE void set_bit(int index); @@ -59,10 +66,14 @@ PUBLISHED: INLINE WordType extract(int low_bit, int size) const; INLINE void store(WordType value, int low_bit, int size); + INLINE void set_range(int low_bit, int size); + INLINE void clear_range(int low_bit, int size); + INLINE void set_range_to(bool value, int low_bit, int size); INLINE WordType get_word() const; INLINE void set_word(WordType value); INLINE void invert_in_place(); + INLINE bool has_bits_in_common(const BitMask &other) const; INLINE void clear(); void output(ostream &out) const; @@ -70,32 +81,32 @@ PUBLISHED: void output_hex(ostream &out, int spaces_every = 4) const; void write(ostream &out, int indent_level = 0) const; - INLINE bool operator == (const BitMask &other) const; - INLINE bool operator != (const BitMask &other) const; - INLINE bool operator < (const BitMask &other) const; - INLINE int compare_to(const BitMask &other) const; + INLINE bool operator == (const BitMask &other) const; + INLINE bool operator != (const BitMask &other) const; + INLINE bool operator < (const BitMask &other) const; + INLINE int compare_to(const BitMask &other) const; - INLINE BitMask - operator & (const BitMask &other) const; + INLINE BitMask + operator & (const BitMask &other) const; - INLINE BitMask - operator | (const BitMask &other) const; + INLINE BitMask + operator | (const BitMask &other) const; - INLINE BitMask - operator ^ (const BitMask &other) const; + INLINE BitMask + operator ^ (const BitMask &other) const; - INLINE BitMask + INLINE BitMask operator ~ () const; - INLINE BitMask + INLINE BitMask operator << (int shift) const; - INLINE BitMask + INLINE BitMask operator >> (int shift) const; - INLINE void operator &= (const BitMask &other); - INLINE void operator |= (const BitMask &other); - INLINE void operator ^= (const BitMask &other); + INLINE void operator &= (const BitMask &other); + INLINE void operator |= (const BitMask &other); + INLINE void operator ^= (const BitMask &other); INLINE void operator <<= (int shift); INLINE void operator >>= (int shift); @@ -117,8 +128,8 @@ private: #include "bitMask.I" -template -INLINE ostream &operator << (ostream &out, const BitMask &bitmask) { +template +INLINE ostream &operator << (ostream &out, const BitMask &bitmask) { bitmask.output(out); return out; } diff --git a/panda/src/putil/config_util.cxx b/panda/src/putil/config_util.cxx index 2626e24ffd..2543e4ffb4 100644 --- a/panda/src/putil/config_util.cxx +++ b/panda/src/putil/config_util.cxx @@ -19,6 +19,8 @@ #include "config_util.h" #include "animInterface.h" #include "bamReaderParam.h" +#include "bitArray.h" +#include "bitMask.h" #include "cachedTypedWritableReferenceCount.h" #include "clockObject.h" #include "configurable.h" @@ -70,6 +72,8 @@ ConfigVariableSearchPath sound_path ConfigureFn(config_util) { AnimInterface::init_type(); BamReaderParam::init_type(); + BitArray::init_type(); + BitMask32::init_type(); CachedTypedWritableReferenceCount::init_type(); Configurable::init_type(); Datagram::init_type(); diff --git a/panda/src/putil/putil_composite1.cxx b/panda/src/putil/putil_composite1.cxx index e584bca871..9d3c2f3c51 100644 --- a/panda/src/putil/putil_composite1.cxx +++ b/panda/src/putil/putil_composite1.cxx @@ -3,6 +3,7 @@ #include "bamReader.cxx" #include "bamReaderParam.cxx" #include "bamWriter.cxx" +#include "bitArray.cxx" #include "bitMask.cxx" #include "buttonHandle.cxx" #include "buttonRegistry.cxx"