[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