summaryrefslogtreecommitdiffstats
path: root/libc/src/__support/math_extras.h
diff options
context:
space:
mode:
Diffstat (limited to 'libc/src/__support/math_extras.h')
-rw-r--r--libc/src/__support/math_extras.h37
1 files changed, 36 insertions, 1 deletions
diff --git a/libc/src/__support/math_extras.h b/libc/src/__support/math_extras.h
index c6b458ddecda..28ee1be8b999 100644
--- a/libc/src/__support/math_extras.h
+++ b/libc/src/__support/math_extras.h
@@ -10,7 +10,8 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_EXTRAS_H
#define LLVM_LIBC_SRC___SUPPORT_MATH_EXTRAS_H
-#include "src/__support/CPP/limits.h" // CHAR_BIT
+#include "src/__support/CPP/bit.h" // countl_one, countr_zero
+#include "src/__support/CPP/limits.h" // CHAR_BIT, numeric_limits
#include "src/__support/CPP/type_traits.h" // is_unsigned_v
#include "src/__support/macros/attributes.h" // LIBC_INLINE
#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN
@@ -226,6 +227,40 @@ sub_with_borrow<unsigned long long>(unsigned long long a, unsigned long long b,
#endif // LIBC_HAS_BUILTIN(__builtin_subc)
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+first_leading_zero(T value) {
+ return value == cpp::numeric_limits<T>::max() ? 0
+ : cpp::countl_one(value) + 1;
+}
+
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+first_leading_one(T value) {
+ return first_leading_zero(static_cast<T>(~value));
+}
+
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+first_trailing_zero(T value) {
+ return value == cpp::numeric_limits<T>::max()
+ ? 0
+ : cpp::countr_zero(static_cast<T>(~value)) + 1;
+}
+
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+first_trailing_one(T value) {
+ return value == cpp::numeric_limits<T>::max() ? 0
+ : cpp::countr_zero(value) + 1;
+}
+
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+count_zeros(T value) {
+ return cpp::popcount<T>(static_cast<T>(~value));
+}
+
} // namespace LIBC_NAMESPACE
#endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXTRAS_H