summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorMerry <git@mary.rs>2022-07-07 22:57:21 +0100
committerMerry <git@mary.rs>2022-07-10 22:17:09 +0100
commit20ccc38f0fad309d4e830af7334d5478a224155a (patch)
tree983b6a4f307a039ae54f88f47b4ab93d9982d930 /Source/Core
parent4d99506b4c3c87fc4d34932cfeaa59e09d54bf12 (diff)
BitUtils: Implement CountTrailingZeros
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Common/BitUtils.h50
1 files changed, 50 insertions, 0 deletions
diff --git a/Source/Core/Common/BitUtils.h b/Source/Core/Common/BitUtils.h
index 1934809e21..bd0801491d 100644
--- a/Source/Core/Common/BitUtils.h
+++ b/Source/Core/Common/BitUtils.h
@@ -411,6 +411,56 @@ constexpr int CountLeadingZeros(uint32_t value)
#endif
}
+template <typename T>
+constexpr int CountTrailingZerosConst(T value)
+{
+ int result = sizeof(T) * 8;
+ while (value)
+ {
+ result--;
+ value <<= 1;
+ }
+ return result;
+}
+
+constexpr int CountTrailingZeros(uint64_t value)
+{
+#if defined(__GNUC__)
+ return value ? __builtin_ctzll(value) : 64;
+#elif defined(_MSC_VER)
+ if (std::is_constant_evaluated())
+ {
+ return CountTrailingZerosConst(value);
+ }
+ else
+ {
+ unsigned long index = 0;
+ return _BitScanForward64(&index, value) ? index : 64;
+ }
+#else
+ return CountTrailingZerosConst(value);
+#endif
+}
+
+constexpr int CountTrailingZeros(uint32_t value)
+{
+#if defined(__GNUC__)
+ return value ? __builtin_ctz(value) : 32;
+#elif defined(_MSC_VER)
+ if (std::is_constant_evaluated())
+ {
+ return CountTrailingZerosConst(value);
+ }
+ else
+ {
+ unsigned long index = 0;
+ return _BitScanForward(&index, value) ? index : 32;
+ }
+#else
+ return CountLeadingZerosConst(value);
+#endif
+}
+
#undef CONSTEXPR_FROM_INTRINSIC
template <typename T>