Back to home page

EIC code displayed by LXR

 
 

    


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

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