aboutsummaryrefslogtreecommitdiffstats
path: root/common/alnumeric.h
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2020-10-13 01:21:44 -0700
committerChris Robinson <[email protected]>2020-10-13 01:21:44 -0700
commit303ca3af72aa7aecc25d94690f3886085c5c6e5b (patch)
tree05c0a6626b7884a76d181c8972d04f69800c2ece /common/alnumeric.h
parent45ff10fb4d847662ec7d1048f7e740c0ca55cf27 (diff)
Use inline functions for popcnt and ctz instead of macros
Diffstat (limited to 'common/alnumeric.h')
-rw-r--r--common/alnumeric.h95
1 files changed, 47 insertions, 48 deletions
diff --git a/common/alnumeric.h b/common/alnumeric.h
index af8e7b2e..d3d0edfd 100644
--- a/common/alnumeric.h
+++ b/common/alnumeric.h
@@ -90,34 +90,33 @@ inline size_t RoundUp(size_t value, size_t r) noexcept
}
-/* Define CTZ macros (count trailing zeros), and POPCNT macros (population
- * count/count 1 bits), for 32- and 64-bit integers. The CTZ macros' results
- * are *UNDEFINED* if the value is 0.
+/* Define CountTrailingZeros (count trailing zero bits, starting from the lsb)
+ * and PopCount (population count/count 1 bits) methods, for 32- and 64-bit
+ * integers. The CountTrailingZeros results are *UNDEFINED* if the value is 0.
*/
-#ifdef __GNUC__
+template<typename T>
+inline int PopCount(T val) = delete;
+template<typename T>
+inline int CountTrailingZeros(T val) = delete;
-namespace detail_ {
+#ifdef __GNUC__
-template<typename T>
-constexpr inline auto popcnt64(T val) = delete;
+/* Define variations for unsigned (long (long)) int, since we don't know what
+ * uint32/64_t are typedef'd to.
+ */
+template<>
+inline int PopCount(unsigned long long val) { return __builtin_popcountll(val); }
template<>
-constexpr inline auto popcnt64(unsigned long long val) { return __builtin_popcountll(val); }
+inline int PopCount(unsigned long val) { return __builtin_popcountl(val); }
template<>
-constexpr inline auto popcnt64(unsigned long val) { return __builtin_popcountl(val); }
+inline int PopCount(unsigned int val) { return __builtin_popcount(val); }
-template<typename T>
-constexpr inline auto ctz64(T val) = delete;
template<>
-constexpr inline auto ctz64(unsigned long long val) { return __builtin_ctzll(val); }
+inline int CountTrailingZeros(unsigned long long val) { return __builtin_ctzll(val); }
template<>
-constexpr inline auto ctz64(unsigned long val) { return __builtin_ctzl(val); }
-
-} // namespace detail_
-
-#define POPCNT32 __builtin_popcount
-#define CTZ32 __builtin_ctz
-#define POPCNT64 detail_::popcnt64<uint64_t>
-#define CTZ64 detail_::ctz64<uint64_t>
+inline int CountTrailingZeros(unsigned long val) { return __builtin_ctzl(val); }
+template<>
+inline int CountTrailingZeros(unsigned int val) { return __builtin_ctz(val); }
#else
@@ -128,69 +127,69 @@ constexpr inline auto ctz64(unsigned long val) { return __builtin_ctzl(val); }
* as the ntz2 variant. These likely aren't the most efficient methods, but
* they're good enough if the GCC built-ins aren't available.
*/
-inline int fallback_popcnt32(uint32_t v)
+template<>
+inline int PopCount(uint32_t v)
{
v = v - ((v >> 1) & 0x55555555u);
v = (v & 0x33333333u) + ((v >> 2) & 0x33333333u);
v = (v + (v >> 4)) & 0x0f0f0f0fu;
- return (int)((v * 0x01010101u) >> 24);
+ return static_cast<int>((v * 0x01010101u) >> 24);
}
-#define POPCNT32 fallback_popcnt32
-inline int fallback_popcnt64(uint64_t v)
+template<>
+inline int PopCount(uint64_t v)
{
v = v - ((v >> 1) & 0x5555555555555555_u64);
v = (v & 0x3333333333333333_u64) + ((v >> 2) & 0x3333333333333333_u64);
v = (v + (v >> 4)) & 0x0f0f0f0f0f0f0f0f_u64;
- return (int)((v * 0x0101010101010101_u64) >> 56);
+ return static_cast<int>((v * 0x0101010101010101_u64) >> 56);
}
-#define POPCNT64 fallback_popcnt64
#if defined(_WIN64)
-inline int msvc64_ctz32(uint32_t v)
+template<>
+inline int CountTrailingZeros(uint32_t v)
{
unsigned long idx = 32;
_BitScanForward(&idx, v);
- return (int)idx;
+ return static_cast<int>(idx);
}
-#define CTZ32 msvc64_ctz32
-inline int msvc64_ctz64(uint64_t v)
+template<>
+inline int CountTrailingZeros(uint64_t v)
{
unsigned long idx = 64;
_BitScanForward64(&idx, v);
- return (int)idx;
+ return static_cast<int>(idx);
}
-#define CTZ64 msvc64_ctz64
#elif defined(_WIN32)
-inline int msvc_ctz32(uint32_t v)
+template<>
+inline int CountTrailingZeros(uint32_t v)
{
unsigned long idx = 32;
_BitScanForward(&idx, v);
- return (int)idx;
+ return static_cast<int>(idx);
}
-#define CTZ32 msvc_ctz32
-inline int msvc_ctz64(uint64_t v)
+template<>
+inline int CountTrailingZeros(uint64_t v)
{
unsigned long idx = 64;
- if(!_BitScanForward(&idx, (uint32_t)(v&0xffffffff)))
+ if(!_BitScanForward(&idx, static_cast<uint32_t>(v&0xffffffff)))
{
- if(_BitScanForward(&idx, (uint32_t)(v>>32)))
+ if(_BitScanForward(&idx, static_cast<uint32_t>(v>>32)))
idx += 32;
}
- return (int)idx;
+ return static_cast<int>(idx);
}
-#define CTZ64 msvc_ctz64
#else
-inline int fallback_ctz32(uint32_t value)
-{ return POPCNT32(~value & (value - 1)); }
-#define CTZ32 fallback_ctz32
-inline int fallback_ctz64(uint64_t value)
-{ return POPCNT64(~value & (value - 1)); }
-#define CTZ64 fallback_ctz64
+template<>
+inline int CountTrailingZeros(uint32_t value)
+{ return PopCount(~value & (value - 1)); }
+template<>
+inline int CountTrailingZeros(uint64_t value)
+{ return PopCount(~value & (value - 1)); }
#endif
#endif
@@ -240,7 +239,7 @@ inline int float2int(float f) noexcept
#elif (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP == 0) \
|| ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) \
- && !defined(__SSE_MATH__))
+ && !defined(__SSE_MATH__))
int sign, shift, mant;
union {
float f;
@@ -276,7 +275,7 @@ inline int double2int(double d) noexcept
#elif (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP < 2) \
|| ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) \
- && !defined(__SSE2_MATH__))
+ && !defined(__SSE2_MATH__))
int sign, shift;
int64_t mant;
union {