From a4b51594b8a6ccd79dc2ab97d92f9affb2b8e440 Mon Sep 17 00:00:00 2001 From: Josh Wilson Date: Tue, 29 Jan 2008 22:02:47 +0000 Subject: [PATCH] adding getNextHighestBit() and getNextLowestBit() functions --- panda/src/putil/bitMask.I | 206 +++++++++++++++++++++++++++++++++++++- panda/src/putil/bitMask.h | 13 +++ 2 files changed, 218 insertions(+), 1 deletion(-) diff --git a/panda/src/putil/bitMask.I b/panda/src/putil/bitMask.I index 74198d3f38..e552813a56 100644 --- a/panda/src/putil/bitMask.I +++ b/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 +INLINE void BitMask:: +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 +INLINE void BitMask:: +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 +INLINE BitMask BitMask:: +flood_bits_up() const { + BitMask result(::flood_bits_up(_word)); + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: BitMask::flood_bits_down +// Access: Published +// Description: Returns a BitMask with the bits flooded down. +//////////////////////////////////////////////////////////////////// +template +INLINE BitMask BitMask:: +flood_bits_down() const { + BitMask 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 +INLINE BitMask BitMask:: +keep_next_highest_bit() const { + int low_bit = get_lowest_on_bit(); + if (low_bit >= 0) { + return BitMask::bit(low_bit); + } else { + return BitMask::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 +INLINE BitMask BitMask:: +keep_next_lowest_bit() const { + int high_bit = get_highest_on_bit(); + if (high_bit >= 0) { + return BitMask::bit(high_bit); + } else { + return BitMask::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 +INLINE BitMask BitMask:: +keep_next_highest_bit(int index) const { + BitMask 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 +INLINE BitMask BitMask:: +keep_next_lowest_bit(int index) const { + BitMask 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 +INLINE BitMask BitMask:: +keep_next_highest_bit(const BitMask &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 +INLINE BitMask BitMask:: +keep_next_lowest_bit(const BitMask &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(); + } +} diff --git a/panda/src/putil/bitMask.h b/panda/src/putil/bitMask.h index 303fc210e6..be1b3475ce 100644 --- a/panda/src/putil/bitMask.h +++ b/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 flood_bits_down() const; + INLINE BitMask flood_bits_up() const; + INLINE BitMask keep_next_highest_bit() const; + INLINE BitMask keep_next_lowest_bit() const; + INLINE BitMask keep_next_highest_bit(int index) const; + INLINE BitMask keep_next_lowest_bit(int index) const; + INLINE BitMask keep_next_highest_bit(const BitMask &other) const; + INLINE BitMask keep_next_lowest_bit(const BitMask &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];