@@ -337,6 +337,22 @@ using __unsigned_integer_of_size_t _LIBCPP_NODEBUG = typename __unsigned_integer
337337template <class _Sc >
338338using __unsigned_representation_for_t _LIBCPP_NODEBUG = __unsigned_integer_of_size_t <sizeof (_Sc)>;
339339
340+ // Returns number of bits that are actually used by a floating-point type.
341+
342+ // Counts the number of leading zero bits after the sign bit, and subtracts it from the total number of bits in the
343+ // integer representation.
344+ // E.g. there are platforms, where `sizeof(long double)` is equal to 16, but only 80 of 128 bits are actually used to
345+ // represent a floating point number, and the remaining bits are zero-padded. In these cases we need to determine the
346+ // actual bit capacity of `long double`.
347+
348+ // Suitable for all IEEE 754 floats, but designed specifically for zero-padded 80-bit `long double`.
349+ template <class _Floating , enable_if_t < numeric_limits<_Floating>::is_iec559, int > = 0 >
350+ _LIBCPP_HIDE_FROM_ABI constexpr size_t __bit_capacity () noexcept {
351+ using __integral_type = __unsigned_representation_for_t <_Floating>;
352+ return numeric_limits<__integral_type>::digits -
353+ std::__countl_zero (std::__bit_cast<__integral_type>(-numeric_limits<_Floating>::infinity ()));
354+ }
355+
340356// The function `__to_ordered_integral` is defined for integers and IEEE 754 floating-point numbers.
341357// Returns an integer representation such that for any `x` and `y` such that `x < y`, the expression
342358// `__to_ordered_integral(x) < __to_ordered_integral(y)` is true, where `x`, `y` are integers or IEEE 754 floats.
@@ -367,12 +383,13 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral(_Integral __n) {
367383template <class _Floating , enable_if_t < numeric_limits<_Floating>::is_iec559, int > = 0 >
368384_LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral (_Floating __f) {
369385 using __integral_type = __unsigned_representation_for_t <_Floating>;
370- constexpr auto __bit_count = std::numeric_limits<__integral_type>::digits ;
386+ constexpr auto __bit_count = std::__bit_capacity<_Floating>() ;
371387 constexpr auto __sign_bit_mask = static_cast <__integral_type>(__integral_type{1 } << (__bit_count - 1 ));
388+ constexpr auto __all_bits_mask = static_cast <__integral_type>((__sign_bit_mask - 1 ) | __sign_bit_mask);
372389
373390 const auto __u = std::__bit_cast<__integral_type>(__f);
374391
375- return static_cast <__integral_type>(__u & __sign_bit_mask ? ~ __u : __u ^ __sign_bit_mask);
392+ return static_cast <__integral_type>(__u & __sign_bit_mask ? __u ^ __all_bits_mask : __u ^ __sign_bit_mask);
376393}
377394
378395// There may exist user-defined comparison for enum, so we cannot compare enums just like integers.
0 commit comments