From 8cfcf69cbefd77c81ddcc0673f059ab084560317 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 26 Jun 2007 19:40:32 +0000 Subject: [PATCH] add get_lowest_on_bit(), etc --- panda/src/putil/bitArray.cxx | 116 ++++++++++++++++++++++++++++---- panda/src/putil/bitArray.h | 4 ++ panda/src/putil/bitMask.I | 88 ++++++++++++++++++++++++ panda/src/putil/bitMask.h | 6 ++ panda/src/putil/sparseArray.cxx | 80 ++++++++++++++++++++++ panda/src/putil/sparseArray.h | 4 ++ 6 files changed, 284 insertions(+), 14 deletions(-) diff --git a/panda/src/putil/bitArray.cxx b/panda/src/putil/bitArray.cxx index d79ebc1da9..391bc15a9e 100755 --- a/panda/src/putil/bitArray.cxx +++ b/panda/src/putil/bitArray.cxx @@ -347,6 +347,94 @@ get_num_off_bits() const { return result; } +//////////////////////////////////////////////////////////////////// +// Function: BitArray::get_lowest_on_bit +// Access: Published +// Description: Returns the index of the lowest 1 bit in the array. +// Returns -1 if there are no 1 bits. +//////////////////////////////////////////////////////////////////// +int BitArray:: +get_lowest_on_bit() const { + int num_words = get_num_words(); + for (int w = 0; w < num_words; ++w) { + int b = _array[w].get_lowest_on_bit(); + if (b != -1) { + return w * num_bits_per_word + b; + } + } + if (_highest_bits) { + return num_words * num_bits_per_word; + } else { + return -1; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::get_lowest_off_bit +// Access: Published +// Description: Returns the index of the lowest 0 bit in the array. +// Returns -1 if there are no 0 bits. +//////////////////////////////////////////////////////////////////// +int BitArray:: +get_lowest_off_bit() const { + int num_words = get_num_words(); + for (int w = 0; w < num_words; ++w) { + int b = _array[w].get_lowest_off_bit(); + if (b != -1) { + return w * num_bits_per_word + b; + } + } + if (!_highest_bits) { + return num_words * num_bits_per_word; + } else { + return -1; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::get_highest_on_bit +// Access: Published +// Description: Returns the index of the highest 1 bit in the array. +// Returns -1 if there are no 1 bits or if there an +// infinite number of 1 bits. +//////////////////////////////////////////////////////////////////// +int BitArray:: +get_highest_on_bit() const { + if (_highest_bits) { + return -1; + } + int num_words = get_num_words(); + for (int w = num_words - 1; w >= 0; --w) { + int b = _array[w].get_highest_on_bit(); + if (b != -1) { + return w * num_bits_per_word + b; + } + } + return -1; +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::get_highest_off_bit +// Access: Published +// Description: Returns the index of the highest 0 bit in the array. +// Returns -1 if there are no 0 bits or if there an +// infinite number of 1 bits. +//////////////////////////////////////////////////////////////////// +int BitArray:: +get_highest_off_bit() const { + if (!_highest_bits) { + return -1; + } + int num_words = get_num_words(); + for (int w = num_words - 1; w >= 0; --w) { + int b = _array[w].get_highest_off_bit(); + if (b != -1) { + return w * num_bits_per_word + b; + } + } + return -1; +} + //////////////////////////////////////////////////////////////////// // Function: BitArray::get_next_higher_different_bit // Access: Published @@ -429,8 +517,8 @@ has_bits_in_common(const BitArray &other) const { // 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(); + for (ai = _array.begin() + other._array.size(); + ai != _array.end(); ++ai) { if (!(*ai).is_zero()) { return true; @@ -442,8 +530,8 @@ has_bits_in_common(const BitArray &other) const { // 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(); + for (ai = other._array.begin() + _array.size(); + ai != other._array.end(); ++ai) { if (!(*ai).is_zero()) { return true; @@ -584,8 +672,8 @@ operator &= (const BitArray &other) { // 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(); + for (ai = other._array.begin() + _array.size(); + ai != other._array.end(); ++ai) { _array.push_back(*ai); } @@ -623,8 +711,8 @@ operator |= (const BitArray &other) { // 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(); + for (ai = other._array.begin() + _array.size(); + ai != other._array.end(); ++ai) { _array.push_back(*ai); } @@ -656,8 +744,8 @@ operator ^= (const BitArray &other) { // 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(); + for (ai = _array.begin() + other._array.size(); + ai != _array.end(); ++ai) { (*ai).invert_in_place(); } @@ -668,8 +756,8 @@ operator ^= (const BitArray &other) { // 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(); + for (ai = other._array.begin() + _array.size(); + ai != other._array.end(); ++ai) { _array.push_back(*ai); } @@ -678,8 +766,8 @@ operator ^= (const BitArray &other) { // 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(); + for (ai = other._array.begin() + _array.size(); + ai != other._array.end(); ++ai) { _array.push_back(~(*ai)); } diff --git a/panda/src/putil/bitArray.h b/panda/src/putil/bitArray.h index 76b410a239..5eff24e79e 100755 --- a/panda/src/putil/bitArray.h +++ b/panda/src/putil/bitArray.h @@ -87,6 +87,10 @@ PUBLISHED: int get_num_on_bits() const; int get_num_off_bits() const; + int get_lowest_on_bit() const; + int get_lowest_off_bit() const; + int get_highest_on_bit() const; + int get_highest_off_bit() const; int get_next_higher_different_bit(int low_bit) const; INLINE int get_num_words() const; diff --git a/panda/src/putil/bitMask.I b/panda/src/putil/bitMask.I index 97943af5b5..ecbbd4892a 100644 --- a/panda/src/putil/bitMask.I +++ b/panda/src/putil/bitMask.I @@ -464,6 +464,64 @@ get_num_off_bits() const { return count_bits_in_word(~_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 { + if (_word == 0) { + return -1; + } + + WordType w = (_word & -_word); + return count_bits_in_word(w - 1); +} + +//////////////////////////////////////////////////////////////////// +// 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 { + if (_word == 0) { + return -1; + } + + WordType w = flood_bits_down(_word); + return count_bits_in_word(w) - 1; +} + +//////////////////////////////////////////////////////////////////// +// 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 @@ -820,3 +878,33 @@ count_bits_in_word(PN_uint64 x) { return count_bits_in_word((PN_uint32)x) + count_bits_in_word((PN_uint32)(x >> 32)); } +//////////////////////////////////////////////////////////////////// +// Function: flood_bits_down +// Description: Returns a value such that every bit at or below the +// highest bit in x is 1. +//////////////////////////////////////////////////////////////////// +INLINE PN_uint32 +flood_bits_down(PN_uint32 x) { + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return x; +} + +//////////////////////////////////////////////////////////////////// +// Function: flood_bits_down +// Description: Returns a value such that every bit at or below the +// highest bit in x is 1. +//////////////////////////////////////////////////////////////////// +INLINE PN_uint64 +flood_bits_down(PN_uint64 x) { + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + x |= (x >> 32); + return x; +} diff --git a/panda/src/putil/bitMask.h b/panda/src/putil/bitMask.h index e1a500e341..6a95e6db20 100644 --- a/panda/src/putil/bitMask.h +++ b/panda/src/putil/bitMask.h @@ -78,6 +78,10 @@ PUBLISHED: INLINE int get_num_on_bits() const; INLINE int get_num_off_bits() const; + INLINE int get_lowest_on_bit() const; + INLINE int get_lowest_off_bit() const; + INLINE int get_highest_on_bit() const; + INLINE int get_highest_off_bit() const; INLINE int get_next_higher_different_bit(int low_bit) const; INLINE void invert_in_place(); @@ -138,6 +142,8 @@ private: INLINE int count_bits_in_word(PN_uint32 x); INLINE int count_bits_in_word(PN_uint64 x); +INLINE PN_uint32 flood_bits_down(PN_uint32 x); +INLINE PN_uint64 flood_bits_down(PN_uint64 x); // This table precomputes the number of on bits in each 16-bit word. extern EXPCL_PANDA unsigned char num_bits_on[65536]; diff --git a/panda/src/putil/sparseArray.cxx b/panda/src/putil/sparseArray.cxx index 31fb7611e2..71d6bcce1f 100644 --- a/panda/src/putil/sparseArray.cxx +++ b/panda/src/putil/sparseArray.cxx @@ -98,6 +98,86 @@ get_num_off_bits() const { return result; } +//////////////////////////////////////////////////////////////////// +// Function: SparseArray::get_lowest_on_bit +// Access: Published +// Description: Returns the index of the lowest 1 bit in the array. +// Returns -1 if there are no 1 bits or if there are an +// infinite number of 1 bits. +//////////////////////////////////////////////////////////////////// +int SparseArray:: +get_lowest_on_bit() const { + if (_inverse) { + return -1; + } + + if (_subranges.empty()) { + return -1; + } + + return _subranges[0]._begin; +} + +//////////////////////////////////////////////////////////////////// +// Function: SparseArray::get_lowest_off_bit +// Access: Published +// Description: Returns the index of the lowest 0 bit in the array. +// Returns -1 if there are no 0 bits or if there are an +// infinite number of 1 bits. +//////////////////////////////////////////////////////////////////// +int SparseArray:: +get_lowest_off_bit() const { + if (!_inverse) { + return -1; + } + + if (_subranges.empty()) { + return -1; + } + + return _subranges[0]._begin; +} + +//////////////////////////////////////////////////////////////////// +// Function: SparseArray::get_highest_on_bit +// Access: Published +// Description: Returns the index of the highest 1 bit in the array. +// Returns -1 if there are no 1 bits or if there an +// infinite number of 1 bits. +//////////////////////////////////////////////////////////////////// +int SparseArray:: +get_highest_on_bit() const { + if (_inverse) { + return -1; + } + + if (_subranges.empty()) { + return -1; + } + + return _subranges[_subranges.size() - 1]._end - 1; +} + +//////////////////////////////////////////////////////////////////// +// Function: SparseArray::get_highest_off_bit +// Access: Published +// Description: Returns the index of the highest 0 bit in the array. +// Returns -1 if there are no 0 bits or if there an +// infinite number of 1 bits. +//////////////////////////////////////////////////////////////////// +int SparseArray:: +get_highest_off_bit() const { + if (!_inverse) { + return -1; + } + + if (_subranges.empty()) { + return -1; + } + + return _subranges[_subranges.size() - 1]._end - 1; +} + //////////////////////////////////////////////////////////////////// // Function: SparseArray::get_next_higher_different_bit // Access: Published diff --git a/panda/src/putil/sparseArray.h b/panda/src/putil/sparseArray.h index 9de63f753f..9603d18113 100644 --- a/panda/src/putil/sparseArray.h +++ b/panda/src/putil/sparseArray.h @@ -85,6 +85,10 @@ PUBLISHED: int get_num_on_bits() const; int get_num_off_bits() const; + int get_lowest_on_bit() const; + int get_lowest_off_bit() const; + int get_highest_on_bit() const; + int get_highest_off_bit() const; int get_next_higher_different_bit(int low_bit) const; INLINE void invert_in_place();