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

Xavier Roche via libcxx-commits libcxx-commits at lists.llvm.org
Tue Apr 21 00:23:26 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
----------------
xroche wrote:

Done! [ I'm skeptical on the constexpr floating point functions though - wouldn't it imply a very strict implementation that returns the exact same value whatever the architecture ? ]

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


More information about the libcxx-commits mailing list