Skip to content

Commit a816f7b

Browse files
committed
long-double
1 parent 4077d33 commit a816f7b

File tree

2 files changed

+20
-2
lines changed

2 files changed

+20
-2
lines changed

libcxx/include/__algorithm/radix_sort.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,22 @@ using __unsigned_integer_of_size_t _LIBCPP_NODEBUG = typename __unsigned_integer
337337
template <class _Sc>
338338
using __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) {
367383
template <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.

libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ int main(int, char**) {
250250
test<int>();
251251
test_floating<float>();
252252
test_floating<double>();
253+
test_floating<long double>();
253254
test_enum();
254255
#if TEST_STD_VER >= 26
255256
static_assert(test<int>());

0 commit comments

Comments
 (0)