2929
3030#include < __algorithm/for_each.h>
3131#include < __algorithm/move.h>
32+ #include < __bit/bit_cast.h>
3233#include < __bit/bit_log2.h>
33- #include < __bit/countl.h>
3434#include < __config>
35+ #include < __cstddef/size_t.h>
3536#include < __functional/identity.h>
3637#include < __iterator/access.h>
3738#include < __iterator/distance.h>
4445#include < __type_traits/enable_if.h>
4546#include < __type_traits/invoke.h>
4647#include < __type_traits/is_assignable.h>
48+ #include < __type_traits/is_enum.h>
4749#include < __type_traits/is_integral.h>
4850#include < __type_traits/is_unsigned.h>
4951#include < __type_traits/make_unsigned.h>
52+ #include < __type_traits/void_t.h>
53+ #include < __utility/declval.h>
5054#include < __utility/forward.h>
5155#include < __utility/integer_sequence.h>
5256#include < __utility/move.h>
@@ -298,6 +302,96 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __shift_to_unsigned(_Ip __n) {
298302 return static_cast <make_unsigned_t <_Ip> >(__n ^ __min_value);
299303}
300304
305+ template <size_t _Size>
306+ struct __unsigned_integer_of_size ;
307+
308+ template <>
309+ struct __unsigned_integer_of_size <1 > {
310+ using type _LIBCPP_NODEBUG = uint8_t ;
311+ };
312+
313+ template <>
314+ struct __unsigned_integer_of_size <2 > {
315+ using type _LIBCPP_NODEBUG = uint16_t ;
316+ };
317+
318+ template <>
319+ struct __unsigned_integer_of_size <4 > {
320+ using type _LIBCPP_NODEBUG = uint32_t ;
321+ };
322+
323+ template <>
324+ struct __unsigned_integer_of_size <8 > {
325+ using type _LIBCPP_NODEBUG = uint64_t ;
326+ };
327+
328+ # if _LIBCPP_HAS_INT128
329+ template <>
330+ struct __unsigned_integer_of_size <16 > {
331+ using type _LIBCPP_NODEBUG = unsigned __int128;
332+ };
333+ # endif
334+
335+ template <size_t _Size>
336+ using __unsigned_integer_of_size_t _LIBCPP_NODEBUG = typename __unsigned_integer_of_size<_Size>::type;
337+
338+ template <class _Sc >
339+ using __unsigned_representation_for_t _LIBCPP_NODEBUG = __unsigned_integer_of_size_t <sizeof (_Sc)>;
340+
341+ // The function `__to_ordered_integral` is defined for integers and IEEE 754 floating-point numbers.
342+ // Returns an integer representation such that for any `x` and `y` such that `x < y`, the expression
343+ // `__to_ordered_integral(x) < __to_ordered_integral(y)` is true, where `x`, `y` are integers or IEEE 754 floats.
344+ template <class _Integral , enable_if_t < is_integral<_Integral>::value, int > = 0 >
345+ _LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral (_Integral __n) {
346+ return __n;
347+ }
348+
349+ // An overload for IEEE 754 floating-point numbers
350+
351+ // For the floats conforming to IEEE 754 (IEC 559) standard, we know that:
352+ // 1. The bit representation of positive floats directly reflects their order:
353+ // When comparing floats by magnitude, the number with the larger exponent is greater, and if the exponents are
354+ // equal, the one with the larger mantissa is greater.
355+ // 2. The bit representation of negative floats reflects their reverse order (for the same reasons).
356+ // 3. The most significant bit (sign bit) is zero for positive floats and one for negative floats. Therefore, in the raw
357+ // bit representation, any negative number will be greater than any positive number.
358+
359+ // The only exception from this rule is `NaN`, which is unordered by definition.
360+
361+ // Based on the above, to obtain correctly ordered integral representation of floating-point numbers, we need to:
362+ // 1. Invert the bit representation (including the sign bit) of negative floats to switch from reverse order to direct
363+ // order;
364+ // 2. Invert the sign bit for positive floats.
365+
366+ // Thus, in final integral representation, we have reversed the order for negative floats and made all negative floats
367+ // smaller than all positive numbers (by inverting the sign bit).
368+ template <class _Floating , enable_if_t < numeric_limits<_Floating>::is_iec559, int > = 0 >
369+ _LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral (_Floating __f) {
370+ using __integral_type = __unsigned_representation_for_t <_Floating>;
371+ constexpr auto __bit_count = std::numeric_limits<__integral_type>::digits;
372+ constexpr auto __sign_bit_mask = static_cast <__integral_type>(__integral_type{1 } << (__bit_count - 1 ));
373+
374+ const auto __u = std::__bit_cast<__integral_type>(__f);
375+
376+ return static_cast <__integral_type>(__u & __sign_bit_mask ? ~__u : __u ^ __sign_bit_mask);
377+ }
378+
379+ // There may exist user-defined comparison for enum, so we cannot compare enums just like integers.
380+ template <class _Enum , enable_if_t < is_enum<_Enum>::value, int > = 0 >
381+ _LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral (_Enum __e) = delete;
382+
383+ // `long double` varies significantly across platforms and compilers, making it practically
384+ // impossible to determine its actual bit width for conversion to an ordered integer.
385+ inline _LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral (long double ) = delete;
386+
387+ template <class _Tp , class = void >
388+ inline const bool __is_ordered_integer_representable_v = false ;
389+
390+ template <class _Tp >
391+ inline const bool
392+ __is_ordered_integer_representable_v<_Tp, __void_t <decltype (std::__to_ordered_integral(std::declval<_Tp>()))>> =
393+ true ;
394+
301395struct __low_byte_fn {
302396 template <class _Ip >
303397 _LIBCPP_HIDE_FROM_ABI constexpr uint8_t operator ()(_Ip __integer) const {
@@ -314,7 +408,9 @@ __radix_sort(_RandomAccessIterator1 __first,
314408 _RandomAccessIterator2 __buffer,
315409 _Map __map,
316410 _Radix __radix) {
317- auto __map_to_unsigned = [__map = std::move (__map)](const auto & __x) { return std::__shift_to_unsigned (__map (__x)); };
411+ auto __map_to_unsigned = [__map = std::move (__map)](const auto & __x) {
412+ return std::__shift_to_unsigned (__map (std::__to_ordered_integral (__x)));
413+ };
318414 std::__radix_sort_impl (__first, __last, __buffer, __map_to_unsigned, __radix);
319415}
320416
0 commit comments