Browse Source

adding getNextHighestBit() and getNextLowestBit() functions

Josh Wilson 18 years ago
parent
commit
a4b51594b8
2 changed files with 218 additions and 1 deletions
  1. 205 1
      panda/src/putil/bitMask.I
  2. 13 0
      panda/src/putil/bitMask.h

+ 205 - 1
panda/src/putil/bitMask.I

@@ -466,7 +466,7 @@ get_highest_on_bit() const {
     return -1;
   }
 
-  WordType w = flood_bits_down(_word);
+  WordType w = ::flood_bits_down(_word);
   return count_bits_in_word(w) - 1;
 }
 
@@ -919,3 +919,207 @@ flood_bits_down(PN_uint64 x) {
   x |= (x >> 32);
   return x;
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: flood_bits_up
+//  Description: Returns a value such that every bit at or above the
+//               highest bit in x is 1.
+////////////////////////////////////////////////////////////////////
+INLINE PN_uint32
+flood_bits_up(PN_uint32 x) {
+  x |= (x << 1);
+  x |= (x << 2);
+  x |= (x << 4);
+  x |= (x << 8);
+  x |= (x << 16);
+  return x;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: flood_bits_up
+//  Description: Returns a value such that every bit at or above the
+//               highest bit in x is 1.
+////////////////////////////////////////////////////////////////////
+INLINE PN_uint64
+flood_bits_up(PN_uint64 x) {
+  x |= (x << 1);
+  x |= (x << 2);
+  x |= (x << 4);
+  x |= (x << 8);
+  x |= (x << 16);
+  x |= (x << 32);
+  return x;
+}
+
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: BitMask::flood_up_in_place
+//       Access: Published
+//  Description: Floods this bitmask's bits upwards.
+////////////////////////////////////////////////////////////////////
+template<class WType, int nbits>
+INLINE void BitMask<WType, nbits>::
+flood_up_in_place() {
+  _word = ::flood_bits_up(_word);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BitMask::flood_down_in_place
+//       Access: Published
+//  Description: Floods this bitmask's bits downwards.
+////////////////////////////////////////////////////////////////////
+template<class WType, int nbits>
+INLINE void BitMask<WType, nbits>::
+flood_down_in_place() {
+  _word = ::flood_bits_down(_word);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BitMask::flood_bits_up
+//       Access: Published
+//  Description: Returns a BitMask with the bits flooded upwards.
+////////////////////////////////////////////////////////////////////
+template<class WType, int nbits>
+INLINE BitMask<WType, nbits> BitMask<WType, nbits>::
+flood_bits_up() const {
+  BitMask<WType, nbits> result(::flood_bits_up(_word));
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BitMask::flood_bits_down
+//       Access: Published
+//  Description: Returns a BitMask with the bits flooded down.
+////////////////////////////////////////////////////////////////////
+template<class WType, int nbits>
+INLINE BitMask<WType, nbits> BitMask<WType, nbits>::
+flood_bits_down() const {
+  BitMask<WType, nbits> result(::flood_bits_down(_word));
+  return result;
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: BitMask::keep_next_highest_bit
+//       Access: Published
+//  Description: Returns a BitMask with only the next highest
+//               bit above the indicated bit on, or all_off.
+////////////////////////////////////////////////////////////////////
+template<class WType, int nbits>
+INLINE BitMask<WType, nbits> BitMask<WType, nbits>::
+keep_next_highest_bit() const {
+  int low_bit = get_lowest_on_bit();
+  if (low_bit >= 0) {
+    return BitMask<WType, nbits>::bit(low_bit);
+  } else {
+    return BitMask<WType, nbits>::all_off();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BitMask::keep_next_lowest_bit
+//       Access: Published
+//  Description: Returns a BitMask with only the next lower
+//               bit below the indicated bit on, or all_off.
+////////////////////////////////////////////////////////////////////
+template<class WType, int nbits>
+INLINE BitMask<WType, nbits> BitMask<WType, nbits>::
+keep_next_lowest_bit() const {
+  int high_bit = get_highest_on_bit();
+  if (high_bit >= 0) {
+    return BitMask<WType, nbits>::bit(high_bit);
+  } else {
+    return BitMask<WType, nbits>::all_off();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BitMask::keep_next_highest_bit
+//       Access: Published
+//  Description: Returns a BitMask with only the next highest
+//               bit above the indicated bit on, or all.
+////////////////////////////////////////////////////////////////////
+template<class WType, int nbits>
+INLINE BitMask<WType, nbits> BitMask<WType, nbits>::
+keep_next_highest_bit(int index) const {
+  BitMask<WType, nbits> mask,temp;
+  nassertr(index >= 0 && index < num_bits, mask);
+  
+  mask.set_bit(index); 
+  mask.flood_down_in_place();
+  mask.invert_in_place();
+  mask &= *this;
+  temp = mask;
+
+  mask <<= 1;
+  mask.flood_up_in_place();
+  mask.invert_in_place();
+  mask &= temp;
+  
+  return mask;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BitMask::keep_next_lowest_bit
+//       Access: Published
+//  Description: Returns a BitMask with only the next lower
+//               bit below the indicated bit on, or all_off.
+////////////////////////////////////////////////////////////////////
+template<class WType, int nbits>
+INLINE BitMask<WType, nbits> BitMask<WType, nbits>::
+keep_next_lowest_bit(int index) const {
+  BitMask<WType, nbits> mask, temp;
+  nassertr(index >= 0 && index < num_bits, mask);
+  
+  mask.set_bit(index); 
+  mask.flood_up_in_place();
+  mask.invert_in_place();
+  mask &= *this;
+  temp = mask;
+
+  mask >>= 1;
+  mask.flood_down_in_place();
+  mask.invert_in_place();
+  mask &= temp;
+  
+  return mask;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BitMask::keep_next_highest_bit
+//       Access: Published
+//  Description: Returns a BitMask with only the next highest "on"
+//               bit above all "on" bits in the passed in bitmask, or 
+//               all_off. If there are no "on" bits in the passed in 
+//               bitmask, it will return keep_next_highest_bit().
+////////////////////////////////////////////////////////////////////
+template<class WType, int nbits>
+INLINE BitMask<WType, nbits> BitMask<WType, nbits>::
+keep_next_highest_bit(const BitMask<WType, nbits> &other) const {
+  int high_bit = other.get_highest_on_bit();
+  if (high_bit >= 0) {
+    return keep_next_highest_bit(high_bit);
+  } else {
+    return keep_next_highest_bit();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BitMask::keep_next_lowest_bit
+//       Access: Published
+//  Description: Returns a BitMask with only the next lowest "on"
+//               bit below all "on" bits in the passed in bitmask, or 
+//               all_off. If there are no "on" bits in the passed in 
+//               bitmask, it will return keep_next_lowest_bit().
+////////////////////////////////////////////////////////////////////
+template<class WType, int nbits>
+INLINE BitMask<WType, nbits> BitMask<WType, nbits>::
+keep_next_lowest_bit(const BitMask<WType, nbits> &other) const {
+  int low_bit = other.get_lowest_on_bit();
+  if (low_bit >= 0) {
+    return keep_next_lowest_bit(low_bit);
+  } else {
+    return keep_next_lowest_bit();
+  }
+}

+ 13 - 0
panda/src/putil/bitMask.h

@@ -122,6 +122,17 @@ PUBLISHED:
   INLINE void operator <<= (int shift);
   INLINE void operator >>= (int shift);
 
+  INLINE void flood_down_in_place();
+  INLINE void flood_up_in_place();
+  INLINE BitMask<WType, nbits> flood_bits_down() const;
+  INLINE BitMask<WType, nbits> flood_bits_up() const;
+  INLINE BitMask<WType, nbits> keep_next_highest_bit() const;
+  INLINE BitMask<WType, nbits> keep_next_lowest_bit() const;
+  INLINE BitMask<WType, nbits> keep_next_highest_bit(int index) const;
+  INLINE BitMask<WType, nbits> keep_next_lowest_bit(int index) const;
+  INLINE BitMask<WType, nbits> keep_next_highest_bit(const BitMask<WType, nbits> &other) const;
+  INLINE BitMask<WType, nbits> keep_next_lowest_bit(const BitMask<WType, nbits> &other) const;
+
   INLINE int get_key() const;
 
 public:
@@ -144,6 +155,8 @@ 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);
+INLINE PN_uint32 flood_bits_up(PN_uint32 x);
+INLINE PN_uint64 flood_bits_up(PN_uint64 x);
 
 // This table precomputes the number of on bits in each 16-bit word.
 extern EXPCL_PANDA_PUTIL unsigned char num_bits_on[65536];