Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:23

0001 //===----------------------------------------------------------------------===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 // TODO: __builtin_clzg is available since Clang 19 and GCC 14. When support for older versions is dropped, we can
0010 //  refactor this code to exclusively use __builtin_clzg.
0011 
0012 #ifndef _LIBCPP___CXX03___BIT_COUNTL_H
0013 #define _LIBCPP___CXX03___BIT_COUNTL_H
0014 
0015 #include <__cxx03/__bit/rotate.h>
0016 #include <__cxx03/__concepts/arithmetic.h>
0017 #include <__cxx03/__config>
0018 #include <__cxx03/__type_traits/is_unsigned_integer.h>
0019 #include <__cxx03/limits>
0020 
0021 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0022 #  pragma GCC system_header
0023 #endif
0024 
0025 _LIBCPP_PUSH_MACROS
0026 #include <__cxx03/__undef_macros>
0027 
0028 _LIBCPP_BEGIN_NAMESPACE_STD
0029 
0030 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned __x) _NOEXCEPT {
0031   return __builtin_clz(__x);
0032 }
0033 
0034 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned long __x) _NOEXCEPT {
0035   return __builtin_clzl(__x);
0036 }
0037 
0038 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned long long __x) _NOEXCEPT {
0039   return __builtin_clzll(__x);
0040 }
0041 
0042 #ifndef _LIBCPP_HAS_NO_INT128
0043 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(__uint128_t __x) _NOEXCEPT {
0044 #  if __has_builtin(__builtin_clzg)
0045   return __builtin_clzg(__x);
0046 #  else
0047   // The function is written in this form due to C++ constexpr limitations.
0048   // The algorithm:
0049   // - Test whether any bit in the high 64-bits is set
0050   // - No bits set:
0051   //   - The high 64-bits contain 64 leading zeros,
0052   //   - Add the result of the low 64-bits.
0053   // - Any bits set:
0054   //   - The number of leading zeros of the input is the number of leading
0055   //     zeros in the high 64-bits.
0056   return ((__x >> 64) == 0) ? (64 + __builtin_clzll(static_cast<unsigned long long>(__x)))
0057                             : __builtin_clzll(static_cast<unsigned long long>(__x >> 64));
0058 #  endif
0059 }
0060 #endif // _LIBCPP_HAS_NO_INT128
0061 
0062 template <class _Tp>
0063 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __countl_zero(_Tp __t) _NOEXCEPT {
0064   static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__countl_zero requires an unsigned integer type");
0065 #if __has_builtin(__builtin_clzg)
0066   return __builtin_clzg(__t, numeric_limits<_Tp>::digits);
0067 #else  // __has_builtin(__builtin_clzg)
0068   if (__t == 0)
0069     return numeric_limits<_Tp>::digits;
0070 
0071   if (sizeof(_Tp) <= sizeof(unsigned int))
0072     return std::__libcpp_clz(static_cast<unsigned int>(__t)) -
0073            (numeric_limits<unsigned int>::digits - numeric_limits<_Tp>::digits);
0074   else if (sizeof(_Tp) <= sizeof(unsigned long))
0075     return std::__libcpp_clz(static_cast<unsigned long>(__t)) -
0076            (numeric_limits<unsigned long>::digits - numeric_limits<_Tp>::digits);
0077   else if (sizeof(_Tp) <= sizeof(unsigned long long))
0078     return std::__libcpp_clz(static_cast<unsigned long long>(__t)) -
0079            (numeric_limits<unsigned long long>::digits - numeric_limits<_Tp>::digits);
0080   else {
0081     int __ret                      = 0;
0082     int __iter                     = 0;
0083     const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits;
0084     while (true) {
0085       __t = std::__rotl(__t, __ulldigits);
0086       if ((__iter = std::__countl_zero(static_cast<unsigned long long>(__t))) != __ulldigits)
0087         break;
0088       __ret += __iter;
0089     }
0090     return __ret + __iter;
0091   }
0092 #endif // __has_builtin(__builtin_clzg)
0093 }
0094 
0095 #if _LIBCPP_STD_VER >= 20
0096 
0097 template <__libcpp_unsigned_integer _Tp>
0098 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept {
0099   return std::__countl_zero(__t);
0100 }
0101 
0102 template <__libcpp_unsigned_integer _Tp>
0103 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept {
0104   return __t != numeric_limits<_Tp>::max() ? std::countl_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits;
0105 }
0106 
0107 #endif // _LIBCPP_STD_VER >= 20
0108 
0109 _LIBCPP_END_NAMESPACE_STD
0110 
0111 _LIBCPP_POP_MACROS
0112 
0113 #endif // _LIBCPP___CXX03___BIT_COUNTL_H