[libcxx-commits] [libcxx] [libc++] Fix numeric_limits::digits and digits10 for _BitInt(N) (PR #193002)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Mon Apr 20 12:58:01 PDT 2026


================
@@ -184,9 +185,17 @@ protected:
 
   static _LIBCPP_CONSTEXPR const bool is_specialized = true;
 
-  static _LIBCPP_CONSTEXPR const bool is_signed   = type(-1) < type(0);
-  static _LIBCPP_CONSTEXPR const int digits       = static_cast<int>(sizeof(type) * __CHAR_BIT__ - is_signed);
-  static _LIBCPP_CONSTEXPR const int digits10     = digits * 3 / 10;
+  static _LIBCPP_CONSTEXPR const bool is_signed = type(-1) < type(0);
+  // For _BitInt(N), sizeof(type) * CHAR_BIT may exceed N due to padding
+  // bits. Count the actual value bits: ~make_unsigned_t<type>(0) leaves
+  // padding zero, so popcount yields the value-bit width. Standard
+  // integer types have no padding, so the result matches sizeof * CHAR_BIT.
+  static _LIBCPP_CONSTEXPR const int digits =
+      __builtin_popcountg(static_cast<__make_unsigned_t<type> >(~__make_unsigned_t<type>(0))) - is_signed;
+  // digits10 = floor(digits * log10(2)). 1936274/6432163 is a continued-fraction
+  // convergent of log10(2) and matches floor(d * log10(2)) exactly for every d
----------------
philnik777 wrote:

Can we replace `d` with `digits` so we don't have different names for the same variable? Also, could we have a TODO to use `__builtin_log` once that's constexpr? That should be more readable than the divisions.

https://github.com/llvm/llvm-project/pull/193002


More information about the libcxx-commits mailing list