2929
3030#include < __algorithm/for_each.h>
3131#include < __algorithm/move.h>
32+ #include < __bit/bit_cast.h>
3233#include < __bit/bit_log2.h>
3334#include < __bit/countl.h>
3435#include < __config>
36+ #include < __cstddef/size_t.h>
3537#include < __functional/identity.h>
3638#include < __iterator/access.h>
3739#include < __iterator/distance.h>
4446#include < __type_traits/enable_if.h>
4547#include < __type_traits/invoke.h>
4648#include < __type_traits/is_assignable.h>
49+ #include < __type_traits/is_enum.h>
50+ #include < __type_traits/is_floating_point.h>
4751#include < __type_traits/is_integral.h>
4852#include < __type_traits/is_unsigned.h>
4953#include < __type_traits/make_unsigned.h>
54+ #include < __type_traits/underlying_type.h>
5055#include < __utility/forward.h>
5156#include < __utility/integer_sequence.h>
5257#include < __utility/move.h>
@@ -298,6 +303,94 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __shift_to_unsigned(_Ip __n) {
298303 return static_cast <make_unsigned_t <_Ip> >(__n ^ __min_value);
299304}
300305
306+ template <size_t _Size>
307+ struct __unsigned_integer_of_size {};
308+
309+ template <>
310+ struct __unsigned_integer_of_size <1 > {
311+ using type = uint8_t ;
312+ };
313+
314+ template <>
315+ struct __unsigned_integer_of_size <2 > {
316+ using type = uint16_t ;
317+ };
318+
319+ template <>
320+ struct __unsigned_integer_of_size <4 > {
321+ using type = uint32_t ;
322+ };
323+
324+ template <>
325+ struct __unsigned_integer_of_size <8 > {
326+ using type = uint64_t ;
327+ };
328+
329+ template <>
330+ struct __unsigned_integer_of_size <16 > {
331+ # if _LIBCPP_HAS_INT128
332+ using type = __int128;
333+ # endif
334+ };
335+
336+ template <size_t _Size>
337+ using __unsigned_integer_of_size_t _LIBCPP_NODEBUG = typename __unsigned_integer_of_size<_Size>::type;
338+
339+ template <class _Sc >
340+ using __unsigned_representation_for_t _LIBCPP_NODEBUG = __unsigned_integer_of_size_t <sizeof (_Sc)>;
341+
342+ // Represent a scalar type as an ordered integer
343+
344+ // The function is defined for ordered scalar types: integers, floating-point numbers, pointers, and enums.
345+ // Returns an integer representation such that for any `x` and `y` such that `x < y`, the expression
346+ // `__to_ordered_integral(x) < __to_ordered_integral(y)` is true, where `x`, `y` are values of the `Scalar` type.
347+ // __unsigned_representation_for_t<_Scalar> __to_ordered_integral(_Scalar);
348+
349+ template <class _Integral , enable_if_t < is_integral<_Integral>::value, int > = 0 >
350+ _LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral (_Integral __n) {
351+ return __n;
352+ }
353+
354+ // An overload for floating-point numbers
355+
356+ // From the IEEE 754 standard, we know that:
357+ // 1. The bit representation of positive floats directly reflects their order:
358+ // When comparing floats by magnitude, the number with the larger exponent is greater, and if the exponents are
359+ // equal, the one with the larger mantissa is greater.
360+ // 2. The bit representation of negative floats reflects their reverse order (for the same reasons).
361+ // 3. The most significant bit (sign bit) is zero for positive floats and one for negative floats. Therefore, in the raw
362+ // bit representation, any negative number will be greater than any positive number.
363+
364+ // The only exception from this rule is `NaN`, which is unordered by definition.
365+
366+ // Based on the above, to obtain correctly ordered integral representation of floating-point numbers, we need to:
367+ // 1. Invert the bit representation (including the sign bit) of negative floats to switch from reverse order to direct
368+ // order;
369+ // 2. Invert the sign bit for positive floats.
370+
371+ // Thus, in final integral representation, we have reversed the order for negative floats and made all negative floats
372+ // smaller than all positive numbers (by inverting the sign bit).
373+ template <class _Floating , enable_if_t < is_floating_point<_Floating>::value, int > = 0 >
374+ _LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral (_Floating __f) {
375+ using __integral_type = __unsigned_representation_for_t <_Floating>;
376+ constexpr auto __bit_count = std::numeric_limits<__integral_type>::digits;
377+ constexpr auto __sign_bit_mask = static_cast <__integral_type>(__integral_type{1 } << (__bit_count - 1 ));
378+
379+ const auto __u = std::__bit_cast<__integral_type>(__f);
380+
381+ return static_cast <__integral_type>(__u & __sign_bit_mask ? ~__u : __u ^ __sign_bit_mask);
382+ }
383+
384+ template <class _Enum , enable_if_t < is_enum<_Enum>::value, int > = 0 >
385+ _LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral (_Enum __e) {
386+ return static_cast <std::underlying_type_t <_Enum>>(__e);
387+ }
388+
389+ template <class _Pointer >
390+ _LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral (_Pointer* __ptr) {
391+ return std::__bit_cast<__unsigned_representation_for_t <_Pointer*>>(__ptr);
392+ }
393+
301394struct __low_byte_fn {
302395 template <class _Ip >
303396 _LIBCPP_HIDE_FROM_ABI constexpr uint8_t operator ()(_Ip __integer) const {
@@ -314,7 +407,9 @@ __radix_sort(_RandomAccessIterator1 __first,
314407 _RandomAccessIterator2 __buffer,
315408 _Map __map,
316409 _Radix __radix) {
317- auto __map_to_unsigned = [__map = std::move (__map)](const auto & __x) { return std::__shift_to_unsigned (__map (__x)); };
410+ auto __map_to_unsigned = [__map = std::move (__map)](const auto & __x) {
411+ return std::__shift_to_unsigned (__map (std::__to_ordered_integral (__x)));
412+ };
318413 std::__radix_sort_impl (__first, __last, __buffer, __map_to_unsigned, __radix);
319414}
320415
0 commit comments