29
29
30
30
#include < __algorithm/for_each.h>
31
31
#include < __algorithm/move.h>
32
+ #include < __bit/bit_cast.h>
32
33
#include < __bit/bit_log2.h>
33
34
#include < __bit/countl.h>
34
35
#include < __config>
36
+ #include < __cstddef/size_t.h>
35
37
#include < __functional/identity.h>
36
38
#include < __iterator/access.h>
37
39
#include < __iterator/distance.h>
44
46
#include < __type_traits/enable_if.h>
45
47
#include < __type_traits/invoke.h>
46
48
#include < __type_traits/is_assignable.h>
49
+ #include < __type_traits/is_enum.h>
50
+ #include < __type_traits/is_floating_point.h>
47
51
#include < __type_traits/is_integral.h>
48
52
#include < __type_traits/is_unsigned.h>
49
53
#include < __type_traits/make_unsigned.h>
54
+ #include < __type_traits/underlying_type.h>
50
55
#include < __utility/forward.h>
51
56
#include < __utility/integer_sequence.h>
52
57
#include < __utility/move.h>
@@ -298,6 +303,94 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __shift_to_unsigned(_Ip __n) {
298
303
return static_cast <make_unsigned_t <_Ip> >(__n ^ __min_value);
299
304
}
300
305
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_v<_Integral>, 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_v<_Floating>, 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_v<_Enum>, 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
+
301
394
struct __low_byte_fn {
302
395
template <class _Ip >
303
396
_LIBCPP_HIDE_FROM_ABI constexpr uint8_t operator ()(_Ip __integer) const {
@@ -314,7 +407,9 @@ __radix_sort(_RandomAccessIterator1 __first,
314
407
_RandomAccessIterator2 __buffer,
315
408
_Map __map,
316
409
_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
+ };
318
413
std::__radix_sort_impl (__first, __last, __buffer, __map_to_unsigned, __radix);
319
414
}
320
415
0 commit comments