Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:22

0001 //===----------------------------------------------------------------------===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef _LIBCPP___CXX03___ALGORITHM_SORT_H
0010 #define _LIBCPP___CXX03___ALGORITHM_SORT_H
0011 
0012 #include <__cxx03/__algorithm/comp.h>
0013 #include <__cxx03/__algorithm/comp_ref_type.h>
0014 #include <__cxx03/__algorithm/iter_swap.h>
0015 #include <__cxx03/__algorithm/iterator_operations.h>
0016 #include <__cxx03/__algorithm/min_element.h>
0017 #include <__cxx03/__algorithm/partial_sort.h>
0018 #include <__cxx03/__algorithm/unwrap_iter.h>
0019 #include <__cxx03/__assert>
0020 #include <__cxx03/__bit/blsr.h>
0021 #include <__cxx03/__bit/countl.h>
0022 #include <__cxx03/__bit/countr.h>
0023 #include <__cxx03/__config>
0024 #include <__cxx03/__debug_utils/randomize_range.h>
0025 #include <__cxx03/__debug_utils/strict_weak_ordering_check.h>
0026 #include <__cxx03/__functional/operations.h>
0027 #include <__cxx03/__functional/ranges_operations.h>
0028 #include <__cxx03/__iterator/iterator_traits.h>
0029 #include <__cxx03/__type_traits/conditional.h>
0030 #include <__cxx03/__type_traits/disjunction.h>
0031 #include <__cxx03/__type_traits/is_arithmetic.h>
0032 #include <__cxx03/__type_traits/is_constant_evaluated.h>
0033 #include <__cxx03/__utility/move.h>
0034 #include <__cxx03/__utility/pair.h>
0035 #include <__cxx03/climits>
0036 #include <__cxx03/cstdint>
0037 
0038 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0039 #  pragma GCC system_header
0040 #endif
0041 
0042 _LIBCPP_PUSH_MACROS
0043 #include <__cxx03/__undef_macros>
0044 
0045 _LIBCPP_BEGIN_NAMESPACE_STD
0046 
0047 // stable, 2-3 compares, 0-2 swaps
0048 
0049 template <class _AlgPolicy, class _Compare, class _ForwardIterator>
0050 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 unsigned
0051 __sort3(_ForwardIterator __x, _ForwardIterator __y, _ForwardIterator __z, _Compare __c) {
0052   using _Ops = _IterOps<_AlgPolicy>;
0053 
0054   unsigned __r = 0;
0055   if (!__c(*__y, *__x)) // if x <= y
0056   {
0057     if (!__c(*__z, *__y))      // if y <= z
0058       return __r;              // x <= y && y <= z
0059                                // x <= y && y > z
0060     _Ops::iter_swap(__y, __z); // x <= z && y < z
0061     __r = 1;
0062     if (__c(*__y, *__x)) // if x > y
0063     {
0064       _Ops::iter_swap(__x, __y); // x < y && y <= z
0065       __r = 2;
0066     }
0067     return __r; // x <= y && y < z
0068   }
0069   if (__c(*__z, *__y)) // x > y, if y > z
0070   {
0071     _Ops::iter_swap(__x, __z); // x < y && y < z
0072     __r = 1;
0073     return __r;
0074   }
0075   _Ops::iter_swap(__x, __y); // x > y && y <= z
0076   __r = 1;                   // x < y && x <= z
0077   if (__c(*__z, *__y))       // if y > z
0078   {
0079     _Ops::iter_swap(__y, __z); // x <= y && y < z
0080     __r = 2;
0081   }
0082   return __r;
0083 } // x <= y && y <= z
0084 
0085 // stable, 3-6 compares, 0-5 swaps
0086 
0087 template <class _AlgPolicy, class _Compare, class _ForwardIterator>
0088 _LIBCPP_HIDE_FROM_ABI void
0089 __sort4(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, _ForwardIterator __x4, _Compare __c) {
0090   using _Ops = _IterOps<_AlgPolicy>;
0091   std::__sort3<_AlgPolicy, _Compare>(__x1, __x2, __x3, __c);
0092   if (__c(*__x4, *__x3)) {
0093     _Ops::iter_swap(__x3, __x4);
0094     if (__c(*__x3, *__x2)) {
0095       _Ops::iter_swap(__x2, __x3);
0096       if (__c(*__x2, *__x1)) {
0097         _Ops::iter_swap(__x1, __x2);
0098       }
0099     }
0100   }
0101 }
0102 
0103 // stable, 4-10 compares, 0-9 swaps
0104 
0105 template <class _AlgPolicy, class _Comp, class _ForwardIterator>
0106 _LIBCPP_HIDE_FROM_ABI void
0107 __sort5(_ForwardIterator __x1,
0108         _ForwardIterator __x2,
0109         _ForwardIterator __x3,
0110         _ForwardIterator __x4,
0111         _ForwardIterator __x5,
0112         _Comp __comp) {
0113   using _Ops = _IterOps<_AlgPolicy>;
0114 
0115   std::__sort4<_AlgPolicy, _Comp>(__x1, __x2, __x3, __x4, __comp);
0116   if (__comp(*__x5, *__x4)) {
0117     _Ops::iter_swap(__x4, __x5);
0118     if (__comp(*__x4, *__x3)) {
0119       _Ops::iter_swap(__x3, __x4);
0120       if (__comp(*__x3, *__x2)) {
0121         _Ops::iter_swap(__x2, __x3);
0122         if (__comp(*__x2, *__x1)) {
0123           _Ops::iter_swap(__x1, __x2);
0124         }
0125       }
0126     }
0127   }
0128 }
0129 
0130 // The comparator being simple is a prerequisite for using the branchless optimization.
0131 template <class _Tp>
0132 struct __is_simple_comparator : false_type {};
0133 template <>
0134 struct __is_simple_comparator<__less<>&> : true_type {};
0135 template <class _Tp>
0136 struct __is_simple_comparator<less<_Tp>&> : true_type {};
0137 template <class _Tp>
0138 struct __is_simple_comparator<greater<_Tp>&> : true_type {};
0139 #if _LIBCPP_STD_VER >= 20
0140 template <>
0141 struct __is_simple_comparator<ranges::less&> : true_type {};
0142 template <>
0143 struct __is_simple_comparator<ranges::greater&> : true_type {};
0144 #endif
0145 
0146 template <class _Compare, class _Iter, class _Tp = typename iterator_traits<_Iter>::value_type>
0147 using __use_branchless_sort =
0148     integral_constant<bool,
0149                       __libcpp_is_contiguous_iterator<_Iter>::value && sizeof(_Tp) <= sizeof(void*) &&
0150                           is_arithmetic<_Tp>::value && __is_simple_comparator<_Compare>::value>;
0151 
0152 namespace __detail {
0153 
0154 // Size in bits for the bitset in use.
0155 enum { __block_size = sizeof(uint64_t) * 8 };
0156 
0157 } // namespace __detail
0158 
0159 // Ensures that __c(*__x, *__y) is true by swapping *__x and *__y if necessary.
0160 template <class _Compare, class _RandomAccessIterator>
0161 inline _LIBCPP_HIDE_FROM_ABI void __cond_swap(_RandomAccessIterator __x, _RandomAccessIterator __y, _Compare __c) {
0162   // Note: this function behaves correctly even with proxy iterators (because it relies on `value_type`).
0163   using value_type = typename iterator_traits<_RandomAccessIterator>::value_type;
0164   bool __r         = __c(*__x, *__y);
0165   value_type __tmp = __r ? *__x : *__y;
0166   *__y             = __r ? *__y : *__x;
0167   *__x             = __tmp;
0168 }
0169 
0170 // Ensures that *__x, *__y and *__z are ordered according to the comparator __c,
0171 // under the assumption that *__y and *__z are already ordered.
0172 template <class _Compare, class _RandomAccessIterator>
0173 inline _LIBCPP_HIDE_FROM_ABI void
0174 __partially_sorted_swap(_RandomAccessIterator __x, _RandomAccessIterator __y, _RandomAccessIterator __z, _Compare __c) {
0175   // Note: this function behaves correctly even with proxy iterators (because it relies on `value_type`).
0176   using value_type = typename iterator_traits<_RandomAccessIterator>::value_type;
0177   bool __r         = __c(*__z, *__x);
0178   value_type __tmp = __r ? *__z : *__x;
0179   *__z             = __r ? *__x : *__z;
0180   __r              = __c(__tmp, *__y);
0181   *__x             = __r ? *__x : *__y;
0182   *__y             = __r ? *__y : __tmp;
0183 }
0184 
0185 template <class,
0186           class _Compare,
0187           class _RandomAccessIterator,
0188           __enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>::value, int> = 0>
0189 inline _LIBCPP_HIDE_FROM_ABI void __sort3_maybe_branchless(
0190     _RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, _Compare __c) {
0191   std::__cond_swap<_Compare>(__x2, __x3, __c);
0192   std::__partially_sorted_swap<_Compare>(__x1, __x2, __x3, __c);
0193 }
0194 
0195 template <class _AlgPolicy,
0196           class _Compare,
0197           class _RandomAccessIterator,
0198           __enable_if_t<!__use_branchless_sort<_Compare, _RandomAccessIterator>::value, int> = 0>
0199 inline _LIBCPP_HIDE_FROM_ABI void __sort3_maybe_branchless(
0200     _RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, _Compare __c) {
0201   std::__sort3<_AlgPolicy, _Compare>(__x1, __x2, __x3, __c);
0202 }
0203 
0204 template <class,
0205           class _Compare,
0206           class _RandomAccessIterator,
0207           __enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>::value, int> = 0>
0208 inline _LIBCPP_HIDE_FROM_ABI void __sort4_maybe_branchless(
0209     _RandomAccessIterator __x1,
0210     _RandomAccessIterator __x2,
0211     _RandomAccessIterator __x3,
0212     _RandomAccessIterator __x4,
0213     _Compare __c) {
0214   std::__cond_swap<_Compare>(__x1, __x3, __c);
0215   std::__cond_swap<_Compare>(__x2, __x4, __c);
0216   std::__cond_swap<_Compare>(__x1, __x2, __c);
0217   std::__cond_swap<_Compare>(__x3, __x4, __c);
0218   std::__cond_swap<_Compare>(__x2, __x3, __c);
0219 }
0220 
0221 template <class _AlgPolicy,
0222           class _Compare,
0223           class _RandomAccessIterator,
0224           __enable_if_t<!__use_branchless_sort<_Compare, _RandomAccessIterator>::value, int> = 0>
0225 inline _LIBCPP_HIDE_FROM_ABI void __sort4_maybe_branchless(
0226     _RandomAccessIterator __x1,
0227     _RandomAccessIterator __x2,
0228     _RandomAccessIterator __x3,
0229     _RandomAccessIterator __x4,
0230     _Compare __c) {
0231   std::__sort4<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __c);
0232 }
0233 
0234 template <class _AlgPolicy,
0235           class _Compare,
0236           class _RandomAccessIterator,
0237           __enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>::value, int> = 0>
0238 inline _LIBCPP_HIDE_FROM_ABI void __sort5_maybe_branchless(
0239     _RandomAccessIterator __x1,
0240     _RandomAccessIterator __x2,
0241     _RandomAccessIterator __x3,
0242     _RandomAccessIterator __x4,
0243     _RandomAccessIterator __x5,
0244     _Compare __c) {
0245   std::__cond_swap<_Compare>(__x1, __x2, __c);
0246   std::__cond_swap<_Compare>(__x4, __x5, __c);
0247   std::__partially_sorted_swap<_Compare>(__x3, __x4, __x5, __c);
0248   std::__cond_swap<_Compare>(__x2, __x5, __c);
0249   std::__partially_sorted_swap<_Compare>(__x1, __x3, __x4, __c);
0250   std::__partially_sorted_swap<_Compare>(__x2, __x3, __x4, __c);
0251 }
0252 
0253 template <class _AlgPolicy,
0254           class _Compare,
0255           class _RandomAccessIterator,
0256           __enable_if_t<!__use_branchless_sort<_Compare, _RandomAccessIterator>::value, int> = 0>
0257 inline _LIBCPP_HIDE_FROM_ABI void __sort5_maybe_branchless(
0258     _RandomAccessIterator __x1,
0259     _RandomAccessIterator __x2,
0260     _RandomAccessIterator __x3,
0261     _RandomAccessIterator __x4,
0262     _RandomAccessIterator __x5,
0263     _Compare __c) {
0264   std::__sort5<_AlgPolicy, _Compare, _RandomAccessIterator>(
0265       std::move(__x1), std::move(__x2), std::move(__x3), std::move(__x4), std::move(__x5), __c);
0266 }
0267 
0268 // Assumes size > 0
0269 template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
0270 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
0271 __selection_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) {
0272   _BidirectionalIterator __lm1 = __last;
0273   for (--__lm1; __first != __lm1; ++__first) {
0274     _BidirectionalIterator __i = std::__min_element<_Compare>(__first, __last, __comp);
0275     if (__i != __first)
0276       _IterOps<_AlgPolicy>::iter_swap(__first, __i);
0277   }
0278 }
0279 
0280 // Sort the iterator range [__first, __last) using the comparator __comp using
0281 // the insertion sort algorithm.
0282 template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
0283 _LIBCPP_HIDE_FROM_ABI void
0284 __insertion_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) {
0285   using _Ops = _IterOps<_AlgPolicy>;
0286 
0287   typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
0288   if (__first == __last)
0289     return;
0290   _BidirectionalIterator __i = __first;
0291   for (++__i; __i != __last; ++__i) {
0292     _BidirectionalIterator __j = __i;
0293     --__j;
0294     if (__comp(*__i, *__j)) {
0295       value_type __t(_Ops::__iter_move(__i));
0296       _BidirectionalIterator __k = __j;
0297       __j                        = __i;
0298       do {
0299         *__j = _Ops::__iter_move(__k);
0300         __j  = __k;
0301       } while (__j != __first && __comp(__t, *--__k));
0302       *__j = std::move(__t);
0303     }
0304   }
0305 }
0306 
0307 // Sort the iterator range [__first, __last) using the comparator __comp using
0308 // the insertion sort algorithm.  Insertion sort has two loops, outer and inner.
0309 // The implementation below has no bounds check (unguarded) for the inner loop.
0310 // Assumes that there is an element in the position (__first - 1) and that each
0311 // element in the input range is greater or equal to the element at __first - 1.
0312 template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
0313 _LIBCPP_HIDE_FROM_ABI void
0314 __insertion_sort_unguarded(_RandomAccessIterator const __first, _RandomAccessIterator __last, _Compare __comp) {
0315   using _Ops = _IterOps<_AlgPolicy>;
0316   typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
0317   typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
0318   if (__first == __last)
0319     return;
0320   const _RandomAccessIterator __leftmost = __first - difference_type(1);
0321   (void)__leftmost; // can be unused when assertions are disabled
0322   for (_RandomAccessIterator __i = __first + difference_type(1); __i != __last; ++__i) {
0323     _RandomAccessIterator __j = __i - difference_type(1);
0324     if (__comp(*__i, *__j)) {
0325       value_type __t(_Ops::__iter_move(__i));
0326       _RandomAccessIterator __k = __j;
0327       __j                       = __i;
0328       do {
0329         *__j = _Ops::__iter_move(__k);
0330         __j  = __k;
0331         _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0332             __k != __leftmost,
0333             "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
0334       } while (__comp(__t, *--__k)); // No need for bounds check due to the assumption stated above.
0335       *__j = std::move(__t);
0336     }
0337   }
0338 }
0339 
0340 template <class _AlgPolicy, class _Comp, class _RandomAccessIterator>
0341 _LIBCPP_HIDE_FROM_ABI bool
0342 __insertion_sort_incomplete(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) {
0343   using _Ops = _IterOps<_AlgPolicy>;
0344 
0345   typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
0346   switch (__last - __first) {
0347   case 0:
0348   case 1:
0349     return true;
0350   case 2:
0351     if (__comp(*--__last, *__first))
0352       _Ops::iter_swap(__first, __last);
0353     return true;
0354   case 3:
0355     std::__sort3_maybe_branchless<_AlgPolicy, _Comp>(__first, __first + difference_type(1), --__last, __comp);
0356     return true;
0357   case 4:
0358     std::__sort4_maybe_branchless<_AlgPolicy, _Comp>(
0359         __first, __first + difference_type(1), __first + difference_type(2), --__last, __comp);
0360     return true;
0361   case 5:
0362     std::__sort5_maybe_branchless<_AlgPolicy, _Comp>(
0363         __first,
0364         __first + difference_type(1),
0365         __first + difference_type(2),
0366         __first + difference_type(3),
0367         --__last,
0368         __comp);
0369     return true;
0370   }
0371   typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
0372   _RandomAccessIterator __j = __first + difference_type(2);
0373   std::__sort3_maybe_branchless<_AlgPolicy, _Comp>(__first, __first + difference_type(1), __j, __comp);
0374   const unsigned __limit = 8;
0375   unsigned __count       = 0;
0376   for (_RandomAccessIterator __i = __j + difference_type(1); __i != __last; ++__i) {
0377     if (__comp(*__i, *__j)) {
0378       value_type __t(_Ops::__iter_move(__i));
0379       _RandomAccessIterator __k = __j;
0380       __j                       = __i;
0381       do {
0382         *__j = _Ops::__iter_move(__k);
0383         __j  = __k;
0384       } while (__j != __first && __comp(__t, *--__k));
0385       *__j = std::move(__t);
0386       if (++__count == __limit)
0387         return ++__i == __last;
0388     }
0389     __j = __i;
0390   }
0391   return true;
0392 }
0393 
0394 template <class _AlgPolicy, class _RandomAccessIterator>
0395 inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos(
0396     _RandomAccessIterator __first, _RandomAccessIterator __last, uint64_t& __left_bitset, uint64_t& __right_bitset) {
0397   using _Ops = _IterOps<_AlgPolicy>;
0398   typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type;
0399   // Swap one pair on each iteration as long as both bitsets have at least one
0400   // element for swapping.
0401   while (__left_bitset != 0 && __right_bitset != 0) {
0402     difference_type __tz_left  = __libcpp_ctz(__left_bitset);
0403     __left_bitset              = __libcpp_blsr(__left_bitset);
0404     difference_type __tz_right = __libcpp_ctz(__right_bitset);
0405     __right_bitset             = __libcpp_blsr(__right_bitset);
0406     _Ops::iter_swap(__first + __tz_left, __last - __tz_right);
0407   }
0408 }
0409 
0410 template <class _Compare,
0411           class _RandomAccessIterator,
0412           class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type>
0413 inline _LIBCPP_HIDE_FROM_ABI void
0414 __populate_left_bitset(_RandomAccessIterator __first, _Compare __comp, _ValueType& __pivot, uint64_t& __left_bitset) {
0415   // Possible vectorization. With a proper "-march" flag, the following loop
0416   // will be compiled into a set of SIMD instructions.
0417   _RandomAccessIterator __iter = __first;
0418   for (int __j = 0; __j < __detail::__block_size;) {
0419     bool __comp_result = !__comp(*__iter, __pivot);
0420     __left_bitset |= (static_cast<uint64_t>(__comp_result) << __j);
0421     __j++;
0422     ++__iter;
0423   }
0424 }
0425 
0426 template <class _Compare,
0427           class _RandomAccessIterator,
0428           class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type>
0429 inline _LIBCPP_HIDE_FROM_ABI void
0430 __populate_right_bitset(_RandomAccessIterator __lm1, _Compare __comp, _ValueType& __pivot, uint64_t& __right_bitset) {
0431   // Possible vectorization. With a proper "-march" flag, the following loop
0432   // will be compiled into a set of SIMD instructions.
0433   _RandomAccessIterator __iter = __lm1;
0434   for (int __j = 0; __j < __detail::__block_size;) {
0435     bool __comp_result = __comp(*__iter, __pivot);
0436     __right_bitset |= (static_cast<uint64_t>(__comp_result) << __j);
0437     __j++;
0438     --__iter;
0439   }
0440 }
0441 
0442 template <class _AlgPolicy,
0443           class _Compare,
0444           class _RandomAccessIterator,
0445           class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type>
0446 inline _LIBCPP_HIDE_FROM_ABI void __bitset_partition_partial_blocks(
0447     _RandomAccessIterator& __first,
0448     _RandomAccessIterator& __lm1,
0449     _Compare __comp,
0450     _ValueType& __pivot,
0451     uint64_t& __left_bitset,
0452     uint64_t& __right_bitset) {
0453   typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type;
0454   difference_type __remaining_len = __lm1 - __first + 1;
0455   difference_type __l_size;
0456   difference_type __r_size;
0457   if (__left_bitset == 0 && __right_bitset == 0) {
0458     __l_size = __remaining_len / 2;
0459     __r_size = __remaining_len - __l_size;
0460   } else if (__left_bitset == 0) {
0461     // We know at least one side is a full block.
0462     __l_size = __remaining_len - __detail::__block_size;
0463     __r_size = __detail::__block_size;
0464   } else { // if (__right_bitset == 0)
0465     __l_size = __detail::__block_size;
0466     __r_size = __remaining_len - __detail::__block_size;
0467   }
0468   // Record the comparison outcomes for the elements currently on the left side.
0469   if (__left_bitset == 0) {
0470     _RandomAccessIterator __iter = __first;
0471     for (int __j = 0; __j < __l_size; __j++) {
0472       bool __comp_result = !__comp(*__iter, __pivot);
0473       __left_bitset |= (static_cast<uint64_t>(__comp_result) << __j);
0474       ++__iter;
0475     }
0476   }
0477   // Record the comparison outcomes for the elements currently on the right
0478   // side.
0479   if (__right_bitset == 0) {
0480     _RandomAccessIterator __iter = __lm1;
0481     for (int __j = 0; __j < __r_size; __j++) {
0482       bool __comp_result = __comp(*__iter, __pivot);
0483       __right_bitset |= (static_cast<uint64_t>(__comp_result) << __j);
0484       --__iter;
0485     }
0486   }
0487   std::__swap_bitmap_pos<_AlgPolicy, _RandomAccessIterator>(__first, __lm1, __left_bitset, __right_bitset);
0488   __first += (__left_bitset == 0) ? __l_size : 0;
0489   __lm1 -= (__right_bitset == 0) ? __r_size : 0;
0490 }
0491 
0492 template <class _AlgPolicy, class _RandomAccessIterator>
0493 inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos_within(
0494     _RandomAccessIterator& __first, _RandomAccessIterator& __lm1, uint64_t& __left_bitset, uint64_t& __right_bitset) {
0495   using _Ops = _IterOps<_AlgPolicy>;
0496   typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type;
0497   if (__left_bitset) {
0498     // Swap within the left side.  Need to find set positions in the reverse
0499     // order.
0500     while (__left_bitset != 0) {
0501       difference_type __tz_left = __detail::__block_size - 1 - __libcpp_clz(__left_bitset);
0502       __left_bitset &= (static_cast<uint64_t>(1) << __tz_left) - 1;
0503       _RandomAccessIterator __it = __first + __tz_left;
0504       if (__it != __lm1) {
0505         _Ops::iter_swap(__it, __lm1);
0506       }
0507       --__lm1;
0508     }
0509     __first = __lm1 + difference_type(1);
0510   } else if (__right_bitset) {
0511     // Swap within the right side.  Need to find set positions in the reverse
0512     // order.
0513     while (__right_bitset != 0) {
0514       difference_type __tz_right = __detail::__block_size - 1 - __libcpp_clz(__right_bitset);
0515       __right_bitset &= (static_cast<uint64_t>(1) << __tz_right) - 1;
0516       _RandomAccessIterator __it = __lm1 - __tz_right;
0517       if (__it != __first) {
0518         _Ops::iter_swap(__it, __first);
0519       }
0520       ++__first;
0521     }
0522   }
0523 }
0524 
0525 // Partition [__first, __last) using the comparator __comp.  *__first has the
0526 // chosen pivot.  Elements that are equivalent are kept to the left of the
0527 // pivot.  Returns the iterator for the pivot and a bool value which is true if
0528 // the provided range is already sorted, false otherwise.  We assume that the
0529 // length of the range is at least three elements.
0530 //
0531 // __bitset_partition uses bitsets for storing outcomes of the comparisons
0532 // between the pivot and other elements.
0533 template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
0534 _LIBCPP_HIDE_FROM_ABI std::pair<_RandomAccessIterator, bool>
0535 __bitset_partition(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
0536   using _Ops = _IterOps<_AlgPolicy>;
0537   typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type;
0538   typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type;
0539   _LIBCPP_ASSERT_INTERNAL(__last - __first >= difference_type(3), "");
0540   const _RandomAccessIterator __begin = __first; // used for bounds checking, those are not moved around
0541   const _RandomAccessIterator __end   = __last;
0542   (void)__end; //
0543 
0544   value_type __pivot(_Ops::__iter_move(__first));
0545   // Find the first element greater than the pivot.
0546   if (__comp(__pivot, *(__last - difference_type(1)))) {
0547     // Not guarded since we know the last element is greater than the pivot.
0548     do {
0549       ++__first;
0550       _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0551           __first != __end,
0552           "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
0553     } while (!__comp(__pivot, *__first));
0554   } else {
0555     while (++__first < __last && !__comp(__pivot, *__first)) {
0556     }
0557   }
0558   // Find the last element less than or equal to the pivot.
0559   if (__first < __last) {
0560     // It will be always guarded because __introsort will do the median-of-three
0561     // before calling this.
0562     do {
0563       _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0564           __last != __begin,
0565           "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
0566       --__last;
0567     } while (__comp(__pivot, *__last));
0568   }
0569   // If the first element greater than the pivot is at or after the
0570   // last element less than or equal to the pivot, then we have covered the
0571   // entire range without swapping elements.  This implies the range is already
0572   // partitioned.
0573   bool __already_partitioned = __first >= __last;
0574   if (!__already_partitioned) {
0575     _Ops::iter_swap(__first, __last);
0576     ++__first;
0577   }
0578 
0579   // In [__first, __last) __last is not inclusive. From now on, it uses last
0580   // minus one to be inclusive on both sides.
0581   _RandomAccessIterator __lm1 = __last - difference_type(1);
0582   uint64_t __left_bitset      = 0;
0583   uint64_t __right_bitset     = 0;
0584 
0585   // Reminder: length = __lm1 - __first + 1.
0586   while (__lm1 - __first >= 2 * __detail::__block_size - 1) {
0587     // Record the comparison outcomes for the elements currently on the left
0588     // side.
0589     if (__left_bitset == 0)
0590       std::__populate_left_bitset<_Compare>(__first, __comp, __pivot, __left_bitset);
0591     // Record the comparison outcomes for the elements currently on the right
0592     // side.
0593     if (__right_bitset == 0)
0594       std::__populate_right_bitset<_Compare>(__lm1, __comp, __pivot, __right_bitset);
0595     // Swap the elements recorded to be the candidates for swapping in the
0596     // bitsets.
0597     std::__swap_bitmap_pos<_AlgPolicy, _RandomAccessIterator>(__first, __lm1, __left_bitset, __right_bitset);
0598     // Only advance the iterator if all the elements that need to be moved to
0599     // other side were moved.
0600     __first += (__left_bitset == 0) ? difference_type(__detail::__block_size) : difference_type(0);
0601     __lm1 -= (__right_bitset == 0) ? difference_type(__detail::__block_size) : difference_type(0);
0602   }
0603   // Now, we have a less-than a block worth of elements on at least one of the
0604   // sides.
0605   std::__bitset_partition_partial_blocks<_AlgPolicy, _Compare>(
0606       __first, __lm1, __comp, __pivot, __left_bitset, __right_bitset);
0607   // At least one the bitsets would be empty.  For the non-empty one, we need to
0608   // properly partition the elements that appear within that bitset.
0609   std::__swap_bitmap_pos_within<_AlgPolicy>(__first, __lm1, __left_bitset, __right_bitset);
0610 
0611   // Move the pivot to its correct position.
0612   _RandomAccessIterator __pivot_pos = __first - difference_type(1);
0613   if (__begin != __pivot_pos) {
0614     *__begin = _Ops::__iter_move(__pivot_pos);
0615   }
0616   *__pivot_pos = std::move(__pivot);
0617   return std::make_pair(__pivot_pos, __already_partitioned);
0618 }
0619 
0620 // Partition [__first, __last) using the comparator __comp.  *__first has the
0621 // chosen pivot.  Elements that are equivalent are kept to the right of the
0622 // pivot.  Returns the iterator for the pivot and a bool value which is true if
0623 // the provided range is already sorted, false otherwise.  We assume that the
0624 // length of the range is at least three elements.
0625 template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
0626 _LIBCPP_HIDE_FROM_ABI std::pair<_RandomAccessIterator, bool>
0627 __partition_with_equals_on_right(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
0628   using _Ops = _IterOps<_AlgPolicy>;
0629   typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
0630   typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type;
0631   _LIBCPP_ASSERT_INTERNAL(__last - __first >= difference_type(3), "");
0632   const _RandomAccessIterator __begin = __first; // used for bounds checking, those are not moved around
0633   const _RandomAccessIterator __end   = __last;
0634   (void)__end; //
0635   value_type __pivot(_Ops::__iter_move(__first));
0636   // Find the first element greater or equal to the pivot.  It will be always
0637   // guarded because __introsort will do the median-of-three before calling
0638   // this.
0639   do {
0640     ++__first;
0641     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0642         __first != __end,
0643         "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
0644   } while (__comp(*__first, __pivot));
0645 
0646   // Find the last element less than the pivot.
0647   if (__begin == __first - difference_type(1)) {
0648     while (__first < __last && !__comp(*--__last, __pivot))
0649       ;
0650   } else {
0651     // Guarded.
0652     do {
0653       _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0654           __last != __begin,
0655           "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
0656       --__last;
0657     } while (!__comp(*__last, __pivot));
0658   }
0659 
0660   // If the first element greater than or equal to the pivot is at or after the
0661   // last element less than the pivot, then we have covered the entire range
0662   // without swapping elements.  This implies the range is already partitioned.
0663   bool __already_partitioned = __first >= __last;
0664   // Go through the remaining elements.  Swap pairs of elements (one to the
0665   // right of the pivot and the other to left of the pivot) that are not on the
0666   // correct side of the pivot.
0667   while (__first < __last) {
0668     _Ops::iter_swap(__first, __last);
0669     do {
0670       ++__first;
0671       _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0672           __first != __end,
0673           "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
0674     } while (__comp(*__first, __pivot));
0675     do {
0676       _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0677           __last != __begin,
0678           "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
0679       --__last;
0680     } while (!__comp(*__last, __pivot));
0681   }
0682   // Move the pivot to its correct position.
0683   _RandomAccessIterator __pivot_pos = __first - difference_type(1);
0684   if (__begin != __pivot_pos) {
0685     *__begin = _Ops::__iter_move(__pivot_pos);
0686   }
0687   *__pivot_pos = std::move(__pivot);
0688   return std::make_pair(__pivot_pos, __already_partitioned);
0689 }
0690 
0691 // Similar to the above function.  Elements equivalent to the pivot are put to
0692 // the left of the pivot.  Returns the iterator to the pivot element.
0693 template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
0694 _LIBCPP_HIDE_FROM_ABI _RandomAccessIterator
0695 __partition_with_equals_on_left(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
0696   using _Ops = _IterOps<_AlgPolicy>;
0697   typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
0698   typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type;
0699   const _RandomAccessIterator __begin = __first; // used for bounds checking, those are not moved around
0700   const _RandomAccessIterator __end   = __last;
0701   (void)__end; //
0702   value_type __pivot(_Ops::__iter_move(__first));
0703   if (__comp(__pivot, *(__last - difference_type(1)))) {
0704     // Guarded.
0705     do {
0706       ++__first;
0707       _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0708           __first != __end,
0709           "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
0710     } while (!__comp(__pivot, *__first));
0711   } else {
0712     while (++__first < __last && !__comp(__pivot, *__first)) {
0713     }
0714   }
0715 
0716   if (__first < __last) {
0717     // It will be always guarded because __introsort will do the
0718     // median-of-three before calling this.
0719     do {
0720       _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0721           __last != __begin,
0722           "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
0723       --__last;
0724     } while (__comp(__pivot, *__last));
0725   }
0726   while (__first < __last) {
0727     _Ops::iter_swap(__first, __last);
0728     do {
0729       ++__first;
0730       _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0731           __first != __end,
0732           "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
0733     } while (!__comp(__pivot, *__first));
0734     do {
0735       _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0736           __last != __begin,
0737           "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
0738       --__last;
0739     } while (__comp(__pivot, *__last));
0740   }
0741   _RandomAccessIterator __pivot_pos = __first - difference_type(1);
0742   if (__begin != __pivot_pos) {
0743     *__begin = _Ops::__iter_move(__pivot_pos);
0744   }
0745   *__pivot_pos = std::move(__pivot);
0746   return __first;
0747 }
0748 
0749 // The main sorting function.  Implements introsort combined with other ideas:
0750 //  - option of using block quick sort for partitioning,
0751 //  - guarded and unguarded insertion sort for small lengths,
0752 //  - Tuckey's ninther technique for computing the pivot,
0753 //  - check on whether partition was not required.
0754 // The implementation is partly based on Orson Peters' pattern-defeating
0755 // quicksort, published at: <https://github.com/orlp/pdqsort>.
0756 template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, bool _UseBitSetPartition>
0757 void __introsort(_RandomAccessIterator __first,
0758                  _RandomAccessIterator __last,
0759                  _Compare __comp,
0760                  typename iterator_traits<_RandomAccessIterator>::difference_type __depth,
0761                  bool __leftmost = true) {
0762   using _Ops = _IterOps<_AlgPolicy>;
0763   typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
0764   using _Comp_ref = __comp_ref_type<_Compare>;
0765   // Upper bound for using insertion sort for sorting.
0766   _LIBCPP_CONSTEXPR difference_type __limit = 24;
0767   // Lower bound for using Tuckey's ninther technique for median computation.
0768   _LIBCPP_CONSTEXPR difference_type __ninther_threshold = 128;
0769   while (true) {
0770     difference_type __len = __last - __first;
0771     switch (__len) {
0772     case 0:
0773     case 1:
0774       return;
0775     case 2:
0776       if (__comp(*--__last, *__first))
0777         _Ops::iter_swap(__first, __last);
0778       return;
0779     case 3:
0780       std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), --__last, __comp);
0781       return;
0782     case 4:
0783       std::__sort4_maybe_branchless<_AlgPolicy, _Compare>(
0784           __first, __first + difference_type(1), __first + difference_type(2), --__last, __comp);
0785       return;
0786     case 5:
0787       std::__sort5_maybe_branchless<_AlgPolicy, _Compare>(
0788           __first,
0789           __first + difference_type(1),
0790           __first + difference_type(2),
0791           __first + difference_type(3),
0792           --__last,
0793           __comp);
0794       return;
0795     }
0796     // Use insertion sort if the length of the range is below the specified limit.
0797     if (__len < __limit) {
0798       if (__leftmost) {
0799         std::__insertion_sort<_AlgPolicy, _Compare>(__first, __last, __comp);
0800       } else {
0801         std::__insertion_sort_unguarded<_AlgPolicy, _Compare>(__first, __last, __comp);
0802       }
0803       return;
0804     }
0805     if (__depth == 0) {
0806       // Fallback to heap sort as Introsort suggests.
0807       std::__partial_sort<_AlgPolicy, _Compare>(__first, __last, __last, __comp);
0808       return;
0809     }
0810     --__depth;
0811     {
0812       difference_type __half_len = __len / 2;
0813       // Use Tuckey's ninther technique or median of 3 for pivot selection
0814       // depending on the length of the range being sorted.
0815       if (__len > __ninther_threshold) {
0816         std::__sort3<_AlgPolicy, _Compare>(__first, __first + __half_len, __last - difference_type(1), __comp);
0817         std::__sort3<_AlgPolicy, _Compare>(
0818             __first + difference_type(1), __first + (__half_len - 1), __last - difference_type(2), __comp);
0819         std::__sort3<_AlgPolicy, _Compare>(
0820             __first + difference_type(2), __first + (__half_len + 1), __last - difference_type(3), __comp);
0821         std::__sort3<_AlgPolicy, _Compare>(
0822             __first + (__half_len - 1), __first + __half_len, __first + (__half_len + 1), __comp);
0823         _Ops::iter_swap(__first, __first + __half_len);
0824       } else {
0825         std::__sort3<_AlgPolicy, _Compare>(__first + __half_len, __first, __last - difference_type(1), __comp);
0826       }
0827     }
0828     // The elements to the left of the current iterator range are already
0829     // sorted.  If the current iterator range to be sorted is not the
0830     // leftmost part of the entire iterator range and the pivot is same as
0831     // the highest element in the range to the left, then we know that all
0832     // the elements in the range [first, pivot] would be equal to the pivot,
0833     // assuming the equal elements are put on the left side when
0834     // partitioned.  This also means that we do not need to sort the left
0835     // side of the partition.
0836     if (!__leftmost && !__comp(*(__first - difference_type(1)), *__first)) {
0837       __first = std::__partition_with_equals_on_left<_AlgPolicy, _RandomAccessIterator, _Comp_ref>(
0838           __first, __last, _Comp_ref(__comp));
0839       continue;
0840     }
0841     // Use bitset partition only if asked for.
0842     auto __ret                = _UseBitSetPartition
0843                                   ? std::__bitset_partition<_AlgPolicy, _RandomAccessIterator, _Compare>(__first, __last, __comp)
0844                                   : std::__partition_with_equals_on_right<_AlgPolicy, _RandomAccessIterator, _Compare>(
0845                          __first, __last, __comp);
0846     _RandomAccessIterator __i = __ret.first;
0847     // [__first, __i) < *__i and *__i <= [__i+1, __last)
0848     // If we were given a perfect partition, see if insertion sort is quick...
0849     if (__ret.second) {
0850       bool __fs = std::__insertion_sort_incomplete<_AlgPolicy, _Compare>(__first, __i, __comp);
0851       if (std::__insertion_sort_incomplete<_AlgPolicy, _Compare>(__i + difference_type(1), __last, __comp)) {
0852         if (__fs)
0853           return;
0854         __last = __i;
0855         continue;
0856       } else {
0857         if (__fs) {
0858           __first = ++__i;
0859           continue;
0860         }
0861       }
0862     }
0863     // Sort the left partiton recursively and the right partition with tail recursion elimination.
0864     std::__introsort<_AlgPolicy, _Compare, _RandomAccessIterator, _UseBitSetPartition>(
0865         __first, __i, __comp, __depth, __leftmost);
0866     __leftmost = false;
0867     __first    = ++__i;
0868   }
0869 }
0870 
0871 template <typename _Number>
0872 inline _LIBCPP_HIDE_FROM_ABI _Number __log2i(_Number __n) {
0873   if (__n == 0)
0874     return 0;
0875   if (sizeof(__n) <= sizeof(unsigned))
0876     return sizeof(unsigned) * CHAR_BIT - 1 - __libcpp_clz(static_cast<unsigned>(__n));
0877   if (sizeof(__n) <= sizeof(unsigned long))
0878     return sizeof(unsigned long) * CHAR_BIT - 1 - __libcpp_clz(static_cast<unsigned long>(__n));
0879   if (sizeof(__n) <= sizeof(unsigned long long))
0880     return sizeof(unsigned long long) * CHAR_BIT - 1 - __libcpp_clz(static_cast<unsigned long long>(__n));
0881 
0882   _Number __log2 = 0;
0883   while (__n > 1) {
0884     __log2++;
0885     __n >>= 1;
0886   }
0887   return __log2;
0888 }
0889 
0890 template <class _Comp, class _RandomAccessIterator>
0891 void __sort(_RandomAccessIterator, _RandomAccessIterator, _Comp);
0892 
0893 extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<char>&, char*>(char*, char*, __less<char>&);
0894 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
0895 extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&);
0896 #endif
0897 extern template _LIBCPP_EXPORTED_FROM_ABI void
0898 __sort<__less<signed char>&, signed char*>(signed char*, signed char*, __less<signed char>&);
0899 extern template _LIBCPP_EXPORTED_FROM_ABI void
0900 __sort<__less<unsigned char>&, unsigned char*>(unsigned char*, unsigned char*, __less<unsigned char>&);
0901 extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<short>&, short*>(short*, short*, __less<short>&);
0902 extern template _LIBCPP_EXPORTED_FROM_ABI void
0903 __sort<__less<unsigned short>&, unsigned short*>(unsigned short*, unsigned short*, __less<unsigned short>&);
0904 extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<int>&, int*>(int*, int*, __less<int>&);
0905 extern template _LIBCPP_EXPORTED_FROM_ABI void
0906 __sort<__less<unsigned>&, unsigned*>(unsigned*, unsigned*, __less<unsigned>&);
0907 extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<long>&, long*>(long*, long*, __less<long>&);
0908 extern template _LIBCPP_EXPORTED_FROM_ABI void
0909 __sort<__less<unsigned long>&, unsigned long*>(unsigned long*, unsigned long*, __less<unsigned long>&);
0910 extern template _LIBCPP_EXPORTED_FROM_ABI void
0911 __sort<__less<long long>&, long long*>(long long*, long long*, __less<long long>&);
0912 extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<unsigned long long>&, unsigned long long*>(
0913     unsigned long long*, unsigned long long*, __less<unsigned long long>&);
0914 extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<float>&, float*>(float*, float*, __less<float>&);
0915 extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<double>&, double*>(double*, double*, __less<double>&);
0916 extern template _LIBCPP_EXPORTED_FROM_ABI void
0917 __sort<__less<long double>&, long double*>(long double*, long double*, __less<long double>&);
0918 
0919 template <class _AlgPolicy, class _RandomAccessIterator, class _Comp>
0920 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
0921 __sort_dispatch(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) {
0922   typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
0923   difference_type __depth_limit = 2 * std::__log2i(__last - __first);
0924 
0925   // Only use bitset partitioning for arithmetic types.  We should also check
0926   // that the default comparator is in use so that we are sure that there are no
0927   // branches in the comparator.
0928   std::__introsort<_AlgPolicy,
0929                    _Comp&,
0930                    _RandomAccessIterator,
0931                    __use_branchless_sort<_Comp, _RandomAccessIterator>::value>(__first, __last, __comp, __depth_limit);
0932 }
0933 
0934 template <class _Type, class... _Options>
0935 using __is_any_of = _Or<is_same<_Type, _Options>...>;
0936 
0937 template <class _Type>
0938 using __sort_is_specialized_in_library = __is_any_of<
0939     _Type,
0940     char,
0941 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
0942     wchar_t,
0943 #endif
0944     signed char,
0945     unsigned char,
0946     short,
0947     unsigned short,
0948     int,
0949     unsigned int,
0950     long,
0951     unsigned long,
0952     long long,
0953     unsigned long long,
0954     float,
0955     double,
0956     long double>;
0957 
0958 template <class _AlgPolicy, class _Type, __enable_if_t<__sort_is_specialized_in_library<_Type>::value, int> = 0>
0959 _LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, __less<>&) {
0960   __less<_Type> __comp;
0961   std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
0962 }
0963 
0964 template <class _AlgPolicy, class _Type, __enable_if_t<__sort_is_specialized_in_library<_Type>::value, int> = 0>
0965 _LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, less<_Type>&) {
0966   __less<_Type> __comp;
0967   std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
0968 }
0969 
0970 #if _LIBCPP_STD_VER >= 14
0971 template <class _AlgPolicy, class _Type, __enable_if_t<__sort_is_specialized_in_library<_Type>::value, int> = 0>
0972 _LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, less<>&) {
0973   __less<_Type> __comp;
0974   std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
0975 }
0976 #endif
0977 
0978 #if _LIBCPP_STD_VER >= 20
0979 template <class _AlgPolicy, class _Type, __enable_if_t<__sort_is_specialized_in_library<_Type>::value, int> = 0>
0980 _LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, ranges::less&) {
0981   __less<_Type> __comp;
0982   std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
0983 }
0984 #endif
0985 
0986 template <class _AlgPolicy, class _RandomAccessIterator, class _Comp>
0987 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
0988 __sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) {
0989   std::__debug_randomize_range<_AlgPolicy>(__first, __last);
0990 
0991   if (__libcpp_is_constant_evaluated()) {
0992     std::__partial_sort<_AlgPolicy>(
0993         std::__unwrap_iter(__first), std::__unwrap_iter(__last), std::__unwrap_iter(__last), __comp);
0994   } else {
0995     std::__sort_dispatch<_AlgPolicy>(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __comp);
0996   }
0997   std::__check_strict_weak_ordering_sorted(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __comp);
0998 }
0999 
1000 template <class _RandomAccessIterator, class _Comp>
1001 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
1002 sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) {
1003   std::__sort_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp);
1004 }
1005 
1006 template <class _RandomAccessIterator>
1007 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
1008 sort(_RandomAccessIterator __first, _RandomAccessIterator __last) {
1009   std::sort(__first, __last, __less<>());
1010 }
1011 
1012 _LIBCPP_END_NAMESPACE_STD
1013 
1014 _LIBCPP_POP_MACROS
1015 
1016 #endif // _LIBCPP___CXX03___ALGORITHM_SORT_H