1717#include < __algorithm/partial_sort.h>
1818#include < __algorithm/unwrap_iter.h>
1919#include < __assert>
20+ #include < __bit/bit_log2.h>
2021#include < __bit/blsr.h>
2122#include < __bit/countl.h>
2223#include < __bit/countr.h>
2324#include < __config>
25+ #include < __cstddef/ptrdiff_t.h>
26+ #include < __cstddef/size_t.h>
2427#include < __debug_utils/randomize_range.h>
2528#include < __debug_utils/strict_weak_ordering_check.h>
2629#include < __functional/operations.h>
3437#include < __type_traits/is_constant_evaluated.h>
3538#include < __type_traits/is_same.h>
3639#include < __type_traits/is_trivially_copyable.h>
40+ #include < __type_traits/make_unsigned.h>
3741#include < __utility/move.h>
3842#include < __utility/pair.h>
3943#include < climits>
@@ -138,7 +142,7 @@ template <class,
138142 class _Compare ,
139143 class _RandomAccessIterator ,
140144 __enable_if_t <__use_branchless_sort<_Compare, _RandomAccessIterator>, int > = 0 >
141- inline _LIBCPP_HIDE_FROM_ABI void
145+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
142146__sort4 (_RandomAccessIterator __x1,
143147 _RandomAccessIterator __x2,
144148 _RandomAccessIterator __x3,
@@ -155,7 +159,7 @@ template <class _AlgPolicy,
155159 class _Compare ,
156160 class _RandomAccessIterator ,
157161 __enable_if_t <!__use_branchless_sort<_Compare, _RandomAccessIterator>, int > = 0 >
158- inline _LIBCPP_HIDE_FROM_ABI void
162+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
159163__sort4 (_RandomAccessIterator __x1,
160164 _RandomAccessIterator __x2,
161165 _RandomAccessIterator __x3,
@@ -180,7 +184,7 @@ template <class _AlgPolicy,
180184 class _Compare ,
181185 class _RandomAccessIterator ,
182186 __enable_if_t <__use_branchless_sort<_Compare, _RandomAccessIterator>, int > = 0 >
183- inline _LIBCPP_HIDE_FROM_ABI void
187+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
184188__sort5 (_RandomAccessIterator __x1,
185189 _RandomAccessIterator __x2,
186190 _RandomAccessIterator __x3,
@@ -199,7 +203,7 @@ template <class _AlgPolicy,
199203 class _Compare ,
200204 class _RandomAccessIterator ,
201205 __enable_if_t <!__use_branchless_sort<_Compare, _RandomAccessIterator>, int > = 0 >
202- inline _LIBCPP_HIDE_FROM_ABI void
206+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
203207__sort5 (_RandomAccessIterator __x1,
204208 _RandomAccessIterator __x2,
205209 _RandomAccessIterator __x3,
@@ -238,7 +242,7 @@ __selection_sort(_BidirectionalIterator __first, _BidirectionalIterator __last,
238242// Sort the iterator range [__first, __last) using the comparator __comp using
239243// the insertion sort algorithm.
240244template <class _AlgPolicy , class _Compare , class _BidirectionalIterator >
241- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
245+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
242246__insertion_sort (_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) {
243247 using _Ops = _IterOps<_AlgPolicy>;
244248
@@ -268,7 +272,7 @@ __insertion_sort(_BidirectionalIterator __first, _BidirectionalIterator __last,
268272// Assumes that there is an element in the position (__first - 1) and that each
269273// element in the input range is greater or equal to the element at __first - 1.
270274template <class _AlgPolicy , class _Compare , class _RandomAccessIterator >
271- _LIBCPP_HIDE_FROM_ABI void
275+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
272276__insertion_sort_unguarded (_RandomAccessIterator const __first, _RandomAccessIterator __last, _Compare __comp) {
273277 using _Ops = _IterOps<_AlgPolicy>;
274278 typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
@@ -296,7 +300,7 @@ __insertion_sort_unguarded(_RandomAccessIterator const __first, _RandomAccessIte
296300}
297301
298302template <class _AlgPolicy , class _Comp , class _RandomAccessIterator >
299- _LIBCPP_HIDE_FROM_ABI bool
303+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
300304__insertion_sort_incomplete (_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) {
301305 using _Ops = _IterOps<_AlgPolicy>;
302306
@@ -350,7 +354,7 @@ __insertion_sort_incomplete(_RandomAccessIterator __first, _RandomAccessIterator
350354}
351355
352356template <class _AlgPolicy , class _RandomAccessIterator >
353- inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos (
357+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __swap_bitmap_pos (
354358 _RandomAccessIterator __first, _RandomAccessIterator __last, uint64_t & __left_bitset, uint64_t & __right_bitset) {
355359 using _Ops = _IterOps<_AlgPolicy>;
356360 typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type;
@@ -368,7 +372,7 @@ inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos(
368372template <class _Compare ,
369373 class _RandomAccessIterator ,
370374 class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type>
371- inline _LIBCPP_HIDE_FROM_ABI void
375+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
372376__populate_left_bitset (_RandomAccessIterator __first, _Compare __comp, _ValueType& __pivot, uint64_t & __left_bitset) {
373377 // Possible vectorization. With a proper "-march" flag, the following loop
374378 // will be compiled into a set of SIMD instructions.
@@ -384,7 +388,7 @@ __populate_left_bitset(_RandomAccessIterator __first, _Compare __comp, _ValueTyp
384388template <class _Compare ,
385389 class _RandomAccessIterator ,
386390 class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type>
387- inline _LIBCPP_HIDE_FROM_ABI void
391+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
388392__populate_right_bitset (_RandomAccessIterator __lm1, _Compare __comp, _ValueType& __pivot, uint64_t & __right_bitset) {
389393 // Possible vectorization. With a proper "-march" flag, the following loop
390394 // will be compiled into a set of SIMD instructions.
@@ -401,7 +405,7 @@ template <class _AlgPolicy,
401405 class _Compare ,
402406 class _RandomAccessIterator ,
403407 class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type>
404- inline _LIBCPP_HIDE_FROM_ABI void __bitset_partition_partial_blocks (
408+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __bitset_partition_partial_blocks (
405409 _RandomAccessIterator& __first,
406410 _RandomAccessIterator& __lm1,
407411 _Compare __comp,
@@ -448,7 +452,7 @@ inline _LIBCPP_HIDE_FROM_ABI void __bitset_partition_partial_blocks(
448452}
449453
450454template <class _AlgPolicy , class _RandomAccessIterator >
451- inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos_within (
455+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __swap_bitmap_pos_within (
452456 _RandomAccessIterator& __first, _RandomAccessIterator& __lm1, uint64_t & __left_bitset, uint64_t & __right_bitset) {
453457 using _Ops = _IterOps<_AlgPolicy>;
454458 typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type;
@@ -489,7 +493,7 @@ inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos_within(
489493// __bitset_partition uses bitsets for storing outcomes of the comparisons
490494// between the pivot and other elements.
491495template <class _AlgPolicy , class _RandomAccessIterator , class _Compare >
492- _LIBCPP_HIDE_FROM_ABI std::pair<_RandomAccessIterator, bool >
496+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 std::pair<_RandomAccessIterator, bool >
493497__bitset_partition (_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
494498 using _Ops = _IterOps<_AlgPolicy>;
495499 typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type;
@@ -581,7 +585,7 @@ __bitset_partition(_RandomAccessIterator __first, _RandomAccessIterator __last,
581585// the provided range is already sorted, false otherwise. We assume that the
582586// length of the range is at least three elements.
583587template <class _AlgPolicy , class _RandomAccessIterator , class _Compare >
584- _LIBCPP_HIDE_FROM_ABI std::pair<_RandomAccessIterator, bool >
588+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 std::pair<_RandomAccessIterator, bool >
585589__partition_with_equals_on_right (_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
586590 using _Ops = _IterOps<_AlgPolicy>;
587591 typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
@@ -649,7 +653,7 @@ __partition_with_equals_on_right(_RandomAccessIterator __first, _RandomAccessIte
649653// Similar to the above function. Elements equivalent to the pivot are put to
650654// the left of the pivot. Returns the iterator to the pivot element.
651655template <class _AlgPolicy , class _RandomAccessIterator , class _Compare >
652- _LIBCPP_HIDE_FROM_ABI _RandomAccessIterator
656+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator
653657__partition_with_equals_on_left (_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
654658 using _Ops = _IterOps<_AlgPolicy>;
655659 typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
@@ -712,11 +716,12 @@ __partition_with_equals_on_left(_RandomAccessIterator __first, _RandomAccessIter
712716// The implementation is partly based on Orson Peters' pattern-defeating
713717// quicksort, published at: <https://github.com/orlp/pdqsort>.
714718template <class _AlgPolicy , class _Compare , class _RandomAccessIterator , bool _UseBitSetPartition>
715- void __introsort (_RandomAccessIterator __first,
716- _RandomAccessIterator __last,
717- _Compare __comp,
718- typename iterator_traits<_RandomAccessIterator>::difference_type __depth,
719- bool __leftmost = true ) {
719+ _LIBCPP_CONSTEXPR_SINCE_CXX20 void
720+ __introsort (_RandomAccessIterator __first,
721+ _RandomAccessIterator __last,
722+ _Compare __comp,
723+ typename iterator_traits<_RandomAccessIterator>::difference_type __depth,
724+ bool __leftmost = true ) {
720725 using _Ops = _IterOps<_AlgPolicy>;
721726 typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
722727 using _Comp_ref = __comp_ref_type<_Compare>;
@@ -826,25 +831,6 @@ void __introsort(_RandomAccessIterator __first,
826831 }
827832}
828833
829- template <typename _Number>
830- inline _LIBCPP_HIDE_FROM_ABI _Number __log2i (_Number __n) {
831- if (__n == 0 )
832- return 0 ;
833- if (sizeof (__n) <= sizeof (unsigned ))
834- return sizeof (unsigned ) * CHAR_BIT - 1 - __libcpp_clz (static_cast <unsigned >(__n));
835- if (sizeof (__n) <= sizeof (unsigned long ))
836- return sizeof (unsigned long ) * CHAR_BIT - 1 - __libcpp_clz (static_cast <unsigned long >(__n));
837- if (sizeof (__n) <= sizeof (unsigned long long ))
838- return sizeof (unsigned long long ) * CHAR_BIT - 1 - __libcpp_clz (static_cast <unsigned long long >(__n));
839-
840- _Number __log2 = 0 ;
841- while (__n > 1 ) {
842- __log2++;
843- __n >>= 1 ;
844- }
845- return __log2;
846- }
847-
848834template <class _Comp , class _RandomAccessIterator >
849835void __sort (_RandomAccessIterator, _RandomAccessIterator, _Comp);
850836
@@ -877,8 +863,10 @@ __sort<__less<long double>&, long double*>(long double*, long double*, __less<lo
877863template <class _AlgPolicy , class _RandomAccessIterator , class _Comp >
878864_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
879865__sort_dispatch (_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) {
880- typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
881- difference_type __depth_limit = 2 * std::__log2i (__last - __first);
866+ using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
867+ using __size_type = __make_unsigned_t <difference_type>;
868+ difference_type __depth_limit =
869+ static_cast <difference_type>(2 * std::__bit_log2 (static_cast <__size_type>(__last - __first)));
882870
883871 // Only use bitset partitioning for arithmetic types. We should also check
884872 // that the default comparator is in use so that we are sure that there are no
@@ -912,30 +900,63 @@ using __sort_is_specialized_in_library _LIBCPP_NODEBUG = __is_any_of<
912900 long double >;
913901
914902template <class _AlgPolicy , class _Type , __enable_if_t <__sort_is_specialized_in_library<_Type>::value, int > = 0 >
915- _LIBCPP_HIDE_FROM_ABI void __sort_dispatch (_Type* __first, _Type* __last, __less<>&) {
916- __less<_Type> __comp;
917- std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
903+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __sort_dispatch (_Type* __first, _Type* __last, __less<>&) {
904+ #if _LIBCPP_STD_VER >= 20
905+ if (std::is_constant_evaluated ()) {
906+ auto __depth_limit = static_cast <ptrdiff_t >(2 * std::__bit_log2 (static_cast <size_t >(__last - __first)));
907+ std::__introsort<_ClassicAlgPolicy, ranges::less, _Type*, __use_branchless_sort<ranges::less, _Type*>>(
908+ __first, __last, ranges::less{}, __depth_limit);
909+ } else
910+ #endif
911+ {
912+ __less<_Type> __comp;
913+ std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
914+ }
918915}
919916
920917template <class _AlgPolicy , class _Type , __enable_if_t <__sort_is_specialized_in_library<_Type>::value, int > = 0 >
921- _LIBCPP_HIDE_FROM_ABI void __sort_dispatch (_Type* __first, _Type* __last, less<_Type>&) {
922- __less<_Type> __comp;
923- std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
918+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __sort_dispatch (_Type* __first, _Type* __last, less<_Type>&) {
919+ #if _LIBCPP_STD_VER >= 20
920+ if (std::is_constant_evaluated ()) {
921+ auto __depth_limit = static_cast <ptrdiff_t >(2 * std::__bit_log2 (static_cast <size_t >(__last - __first)));
922+ std::__introsort<_ClassicAlgPolicy, ranges::less, _Type*, __use_branchless_sort<ranges::less, _Type*>>(
923+ __first, __last, ranges::less{}, __depth_limit);
924+ } else
925+ #endif
926+ {
927+ __less<_Type> __comp;
928+ std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
929+ }
924930}
925931
926932#if _LIBCPP_STD_VER >= 14
927933template <class _AlgPolicy , class _Type , __enable_if_t <__sort_is_specialized_in_library<_Type>::value, int > = 0 >
928- _LIBCPP_HIDE_FROM_ABI void __sort_dispatch (_Type* __first, _Type* __last, less<>&) {
929- __less<_Type> __comp;
930- std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
934+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __sort_dispatch (_Type* __first, _Type* __last, less<>&) {
935+ # if _LIBCPP_STD_VER >= 20
936+ if (std::is_constant_evaluated ()) {
937+ auto __depth_limit = static_cast <ptrdiff_t >(2 * std::__bit_log2 (static_cast <size_t >(__last - __first)));
938+ std::__introsort<_ClassicAlgPolicy, ranges::less, _Type*, __use_branchless_sort<ranges::less, _Type*>>(
939+ __first, __last, ranges::less{}, __depth_limit);
940+ } else
941+ # endif
942+ {
943+ __less<_Type> __comp;
944+ std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
945+ }
931946}
932947#endif
933948
934949#if _LIBCPP_STD_VER >= 20
935950template <class _AlgPolicy , class _Type , __enable_if_t <__sort_is_specialized_in_library<_Type>::value, int > = 0 >
936- _LIBCPP_HIDE_FROM_ABI void __sort_dispatch (_Type* __first, _Type* __last, ranges::less&) {
937- __less<_Type> __comp;
938- std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
951+ _LIBCPP_HIDE_FROM_ABI constexpr void __sort_dispatch (_Type* __first, _Type* __last, ranges::less&) {
952+ if (std::is_constant_evaluated ()) {
953+ auto __depth_limit = static_cast <ptrdiff_t >(2 * std::__bit_log2 (static_cast <size_t >(__last - __first)));
954+ std::__introsort<_ClassicAlgPolicy, ranges::less, _Type*, __use_branchless_sort<ranges::less, _Type*>>(
955+ __first, __last, ranges::less{}, __depth_limit);
956+ } else {
957+ __less<_Type> __comp;
958+ std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
959+ }
939960}
940961#endif
941962
@@ -944,12 +965,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
944965__sort_impl (_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) {
945966 std::__debug_randomize_range<_AlgPolicy>(__first, __last);
946967
947- if (__libcpp_is_constant_evaluated ()) {
948- std::__partial_sort<_AlgPolicy>(
949- std::__unwrap_iter (__first), std::__unwrap_iter (__last), std::__unwrap_iter (__last), __comp);
950- } else {
951- std::__sort_dispatch<_AlgPolicy>(std::__unwrap_iter (__first), std::__unwrap_iter (__last), __comp);
952- }
968+ std::__sort_dispatch<_AlgPolicy>(std::__unwrap_iter (__first), std::__unwrap_iter (__last), __comp);
953969 std::__check_strict_weak_ordering_sorted (std::__unwrap_iter (__first), std::__unwrap_iter (__last), __comp);
954970}
955971
0 commit comments