| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- /*
- Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Neither the name of LibCat nor the names of its contributors may be used
- to endorse or promote products derived from this software without
- specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- */
- #ifndef CAT_BITMATH_HPP
- #define CAT_BITMATH_HPP
- #include <cat/Platform.hpp>
- #if defined(CAT_OS_WINDOWS)
- # include <cat/port/WindowsInclude.hpp>
- #endif
- namespace cat {
- // Next highest power of two (e.g. 13 -> 16)
- CAT_INLINE u32 NextHighestPow2(u32 n)
- {
- n |= n >> 1;
- n |= n >> 2;
- n |= n >> 4;
- n |= n >> 8;
- n |= n >> 16;
- return n + 1;
- }
- CAT_INLINE u64 NextHighestPow2(u64 n)
- {
- n |= n >> 1;
- n |= n >> 2;
- n |= n >> 4;
- n |= n >> 8;
- n |= n >> 16;
- n |= n >> 32;
- return n + 1;
- }
- // Bit Scan Forward (BSF)
- // Scans from bit 0 to MSB
- // Undefined when input is zero
- CAT_INLINE u32 BSF32(u32 x);
- CAT_INLINE u32 BSF64(u64 x);
- // Bit Scan Reverse (BSR)
- // Scans from MSB to bit 0
- // Undefined when input is zero
- CAT_INLINE u32 BSR32(u32 x);
- CAT_INLINE u32 BSR64(u64 x);
- // Returns the count of bits set in the input for types up to 128 bits
- template<typename T> CAT_INLINE T BitCount(T v)
- {
- // From Stanford Bit Twiddling Hacks collection
- // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
- v = v - ((v >> 1) & (T)~(T)0/3);
- v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3);
- v = (v + (v >> 4)) & (T)~(T)0/255*15;
- return (T)(v * ((T)~(T)0/255)) >> ((sizeof(v) - 1) * 8);
- }
- // Reconstruct a 32-bit or 64-bit counter that increments by one each time,
- // given a truncated sample of its low bits, and the last accepted value of the counter.
- template<int BITS, typename T> CAT_INLINE T ReconstructCounter(T last_accepted_count, u32 partial_low_bits)
- {
- const u32 IV_MSB = (1 << BITS); // BITS < 32
- const u32 IV_MASK = (IV_MSB - 1);
- s32 diff = partial_low_bits - (u32)(last_accepted_count & IV_MASK);
- return ((last_accepted_count & ~(T)IV_MASK) | partial_low_bits)
- - (((IV_MSB >> 1) - (diff & IV_MASK)) & IV_MSB)
- + (diff & IV_MSB);
- }
- u32 BSF32(u32 x)
- {
- #if defined(CAT_COMPILER_MSVC) && defined(CAT_WORD_64) && !defined(CAT_DEBUG)
- u32 index;
- _BitScanForward((unsigned long*)&index, x);
- return index;
- #elif defined(CAT_ASM_INTEL) && defined(CAT_ISA_X86)
- CAT_ASM_BEGIN
- BSF eax, [x]
- CAT_ASM_END
- #elif defined(CAT_ASM_ATT) && defined(CAT_ISA_X86)
- u32 retval;
- CAT_ASM_BEGIN
- "BSFl %1, %%eax"
- : "=a" (retval)
- : "r" (x)
- : "cc"
- CAT_ASM_END
- return retval;
- #else
- return BSR32(x ^ (x - 1));
- #endif
- }
- u32 BSR32(u32 x)
- {
- #if defined(CAT_COMPILER_MSVC) && defined(CAT_WORD_64) && !defined(CAT_DEBUG)
- u32 index;
- _BitScanReverse((unsigned long*)&index, x);
- return index;
- #elif defined(CAT_ASM_INTEL) && defined(CAT_ISA_X86)
- CAT_ASM_BEGIN
- BSR eax, [x]
- CAT_ASM_END
- #elif defined(CAT_ASM_ATT) && defined(CAT_ISA_X86)
- u32 retval;
- CAT_ASM_BEGIN
- "BSRl %1, %%eax"
- : "=a" (retval)
- : "r" (x)
- : "cc"
- CAT_ASM_END
- return retval;
- #else
- // Adapted from the Stanford Bit Twiddling Hacks collection
- register u32 shift, r;
- r = (x > 0xFFFF) << 4; x >>= r;
- shift = (x > 0xFF) << 3; x >>= shift; r |= shift;
- shift = (x > 0xF) << 2; x >>= shift; r |= shift;
- shift = (x > 0x3) << 1; x >>= shift; r |= shift;
- r |= (x >> 1);
- return r;
- #endif
- }
- u32 BSF64(u64 x)
- {
- #if defined(CAT_COMPILER_MSVC) && !defined(CAT_DEBUG) && defined(CAT_WORD_64)
- u32 index;
- _BitScanForward64((unsigned long*)&index, x);
- return index;
- #elif defined(CAT_ASM_ATT) && defined(CAT_WORD_64) && defined(CAT_ISA_X86)
- u32 retval;
- CAT_ASM_BEGIN
- "BSFq %1, %%rax"
- : "=a" (retval)
- : "r" (x)
- : "cc"
- CAT_ASM_END
- return retval;
- #else
- return BSR64(x ^ (x - 1));
- #endif
- }
- u32 BSR64(u64 x)
- {
- #if defined(CAT_COMPILER_MSVC) && !defined(CAT_DEBUG) && defined(CAT_WORD_64)
- u32 index;
- _BitScanReverse64((unsigned long*)&index, x);
- return index;
- #elif defined(CAT_ASM_ATT) && defined(CAT_WORD_64) && defined(CAT_ISA_X86)
- u32 retval;
- CAT_ASM_BEGIN
- "BSRq %1, %%rax"
- : "=a" (retval)
- : "r" (x)
- : "cc"
- CAT_ASM_END
- return retval;
- #else
- // Adapted from the Stanford Bit Twiddling Hacks collection
- register u32 shift, r;
- r = (x > 0xFFFFFFFF) << 5; x >>= r;
- shift = (x > 0xFFFF) << 4; x >>= shift; r |= shift;
- shift = (x > 0xFF) << 3; x >>= shift; r |= shift;
- shift = (x > 0xF) << 2; x >>= shift; r |= shift;
- shift = (x > 0x3) << 1; x >>= shift; r |= shift;
- r |= (u32)(x >> 1);
- return r;
- #endif
- }
- } // namespace cat
- #endif // CAT_BITMATH_HPP
|