[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