瀏覽代碼

add get_lowest_on_bit(), etc

David Rose 18 年之前
父節點
當前提交
8cfcf69cbe

+ 102 - 14
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));
       }

+ 4 - 0
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;

+ 88 - 0
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<class WType, int nbits>
+INLINE int BitMask<WType, nbits>::
+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<class WType, int nbits>
+INLINE int BitMask<WType, nbits>::
+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<class WType, int nbits>
+INLINE int BitMask<WType, nbits>::
+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<class WType, int nbits>
+INLINE int BitMask<WType, nbits>::
+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;
+}

+ 6 - 0
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];

+ 80 - 0
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

+ 4 - 0
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();