1134723edSLouis Dionne //===----------------------------------------------------------------------===// 2134723edSLouis Dionne // 3134723edSLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4134723edSLouis Dionne // See https://llvm.org/LICENSE.txt for license information. 5134723edSLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6134723edSLouis Dionne // 7134723edSLouis Dionne //===----------------------------------------------------------------------===// 8134723edSLouis Dionne 9134723edSLouis Dionne #ifndef _LIBCPP___ALGORITHM_SORT_H 10134723edSLouis Dionne #define _LIBCPP___ALGORITHM_SORT_H 11134723edSLouis Dionne 12134723edSLouis Dionne #include <__algorithm/comp.h> 13134723edSLouis Dionne #include <__algorithm/comp_ref_type.h> 14a7c3379cSKonstantin Varlamov #include <__algorithm/iterator_operations.h> 15134723edSLouis Dionne #include <__algorithm/min_element.h> 16134723edSLouis Dionne #include <__algorithm/partial_sort.h> 17134723edSLouis Dionne #include <__algorithm/unwrap_iter.h> 18865ad6bdSHans Wennborg #include <__bits> 194d81a46fSArthur O'Dwyer #include <__config> 20f3966eafSLouis Dionne #include <__debug> 212aea8af2SNikolas Klauser #include <__debug_utils/randomize_range.h> 2234f73804SNikolas Klauser #include <__functional/operations.h> 23ff3989e6SKonstantin Varlamov #include <__functional/ranges_operations.h> 243cd4531bSNikolas Klauser #include <__iterator/iterator_traits.h> 25865ad6bdSHans Wennborg #include <climits> 26134723edSLouis Dionne #include <memory> 27134723edSLouis Dionne 28134723edSLouis Dionne #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 29134723edSLouis Dionne # pragma GCC system_header 30134723edSLouis Dionne #endif 31134723edSLouis Dionne 32134723edSLouis Dionne _LIBCPP_BEGIN_NAMESPACE_STD 33134723edSLouis Dionne 34a7c3379cSKonstantin Varlamov // Wraps an algorithm policy tag and a comparator in a single struct, used to pass the policy tag around without 35a7c3379cSKonstantin Varlamov // changing the number of template arguments (to keep the ABI stable). This is only used for the "range" policy tag. 36a7c3379cSKonstantin Varlamov // 37a7c3379cSKonstantin Varlamov // To create an object of this type, use `_WrapAlgPolicy<T, C>::type` -- see the specialization below for the rationale. 38a7c3379cSKonstantin Varlamov template <class _PolicyT, class _CompT, class = void> 39a7c3379cSKonstantin Varlamov struct _WrapAlgPolicy { 40a7c3379cSKonstantin Varlamov using type = _WrapAlgPolicy; 41a7c3379cSKonstantin Varlamov 42a7c3379cSKonstantin Varlamov using _AlgPolicy = _PolicyT; 43a7c3379cSKonstantin Varlamov using _Comp = _CompT; 44a7c3379cSKonstantin Varlamov _Comp& __comp; 45a7c3379cSKonstantin Varlamov 46a7c3379cSKonstantin Varlamov _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _WrapAlgPolicy_WrapAlgPolicy47a7c3379cSKonstantin Varlamov _WrapAlgPolicy(_Comp& __c) : __comp(__c) {} 48a7c3379cSKonstantin Varlamov }; 49a7c3379cSKonstantin Varlamov 50a7c3379cSKonstantin Varlamov // Specialization for the "classic" policy tag that avoids creating a struct and simply defines an alias for the 51a7c3379cSKonstantin Varlamov // comparator. When unwrapping, a pristine comparator is always considered to have the "classic" tag attached. Passing 52a7c3379cSKonstantin Varlamov // the pristine comparator where possible allows using template instantiations from the dylib. 53a7c3379cSKonstantin Varlamov template <class _PolicyT, class _CompT> 54a7c3379cSKonstantin Varlamov struct _WrapAlgPolicy<_PolicyT, _CompT, __enable_if_t<std::is_same<_PolicyT, _ClassicAlgPolicy>::value> > { 55a7c3379cSKonstantin Varlamov using type = _CompT; 56a7c3379cSKonstantin Varlamov }; 57a7c3379cSKonstantin Varlamov 58a7c3379cSKonstantin Varlamov // Unwraps a pristine functor (e.g. `std::less`) as if it were wrapped using `_WrapAlgPolicy`. The policy tag is always 59a7c3379cSKonstantin Varlamov // set to "classic". 60a7c3379cSKonstantin Varlamov template <class _CompT> 61a7c3379cSKonstantin Varlamov struct _UnwrapAlgPolicy { 62a7c3379cSKonstantin Varlamov using _AlgPolicy = _ClassicAlgPolicy; 63a7c3379cSKonstantin Varlamov using _Comp = _CompT; 64a7c3379cSKonstantin Varlamov 65a7c3379cSKonstantin Varlamov _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 static 66a7c3379cSKonstantin Varlamov _Comp __get_comp(_Comp __comp) { return __comp; } 67a7c3379cSKonstantin Varlamov }; 68a7c3379cSKonstantin Varlamov 69a7c3379cSKonstantin Varlamov // Unwraps a `_WrapAlgPolicy` struct. 70a7c3379cSKonstantin Varlamov template <class... _Ts> 71a7c3379cSKonstantin Varlamov struct _UnwrapAlgPolicy<_WrapAlgPolicy<_Ts...> > { 72a7c3379cSKonstantin Varlamov using _Wrapped = _WrapAlgPolicy<_Ts...>; 73a7c3379cSKonstantin Varlamov using _AlgPolicy = typename _Wrapped::_AlgPolicy; 74a7c3379cSKonstantin Varlamov using _Comp = typename _Wrapped::_Comp; 75a7c3379cSKonstantin Varlamov 76a7c3379cSKonstantin Varlamov _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 static 77a7c3379cSKonstantin Varlamov _Comp __get_comp(_Wrapped& __w) { return __w.__comp; } 78a7c3379cSKonstantin Varlamov }; 79a7c3379cSKonstantin Varlamov 80134723edSLouis Dionne // stable, 2-3 compares, 0-2 swaps 81134723edSLouis Dionne 82a7c3379cSKonstantin Varlamov template <class _AlgPolicy, class _Compare, class _ForwardIterator> 83f950ba00SNilay Vaish _LIBCPP_CONSTEXPR_AFTER_CXX11 unsigned __sort3(_ForwardIterator __x, _ForwardIterator __y, _ForwardIterator __z, 84f950ba00SNilay Vaish _Compare __c) { 85a7c3379cSKonstantin Varlamov using _Ops = _IterOps<_AlgPolicy>; 86a7c3379cSKonstantin Varlamov 87134723edSLouis Dionne unsigned __r = 0; 88134723edSLouis Dionne if (!__c(*__y, *__x)) // if x <= y 89134723edSLouis Dionne { 90134723edSLouis Dionne if (!__c(*__z, *__y)) // if y <= z 91134723edSLouis Dionne return __r; // x <= y && y <= z 92134723edSLouis Dionne // x <= y && y > z 93a7c3379cSKonstantin Varlamov _Ops::iter_swap(__y, __z); // x <= z && y < z 94134723edSLouis Dionne __r = 1; 95134723edSLouis Dionne if (__c(*__y, *__x)) // if x > y 96134723edSLouis Dionne { 97a7c3379cSKonstantin Varlamov _Ops::iter_swap(__x, __y); // x < y && y <= z 98134723edSLouis Dionne __r = 2; 99134723edSLouis Dionne } 100134723edSLouis Dionne return __r; // x <= y && y < z 101134723edSLouis Dionne } 102134723edSLouis Dionne if (__c(*__z, *__y)) // x > y, if y > z 103134723edSLouis Dionne { 104a7c3379cSKonstantin Varlamov _Ops::iter_swap(__x, __z); // x < y && y < z 105134723edSLouis Dionne __r = 1; 106134723edSLouis Dionne return __r; 107134723edSLouis Dionne } 108a7c3379cSKonstantin Varlamov _Ops::iter_swap(__x, __y); // x > y && y <= z 109134723edSLouis Dionne __r = 1; // x < y && x <= z 110134723edSLouis Dionne if (__c(*__z, *__y)) // if y > z 111134723edSLouis Dionne { 112a7c3379cSKonstantin Varlamov _Ops::iter_swap(__y, __z); // x <= y && y < z 113134723edSLouis Dionne __r = 2; 114134723edSLouis Dionne } 115134723edSLouis Dionne return __r; 116134723edSLouis Dionne } // x <= y && y <= z 117134723edSLouis Dionne 118134723edSLouis Dionne // stable, 3-6 compares, 0-5 swaps 119134723edSLouis Dionne 120a7c3379cSKonstantin Varlamov template <class _AlgPolicy, class _Compare, class _ForwardIterator> 121f950ba00SNilay Vaish unsigned __sort4(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, _ForwardIterator __x4, 122f950ba00SNilay Vaish _Compare __c) { 123a7c3379cSKonstantin Varlamov using _Ops = _IterOps<_AlgPolicy>; 124a7c3379cSKonstantin Varlamov 125a7c3379cSKonstantin Varlamov unsigned __r = std::__sort3<_AlgPolicy, _Compare>(__x1, __x2, __x3, __c); 126f950ba00SNilay Vaish if (__c(*__x4, *__x3)) { 127a7c3379cSKonstantin Varlamov _Ops::iter_swap(__x3, __x4); 128134723edSLouis Dionne ++__r; 129f950ba00SNilay Vaish if (__c(*__x3, *__x2)) { 130a7c3379cSKonstantin Varlamov _Ops::iter_swap(__x2, __x3); 131134723edSLouis Dionne ++__r; 132f950ba00SNilay Vaish if (__c(*__x2, *__x1)) { 133a7c3379cSKonstantin Varlamov _Ops::iter_swap(__x1, __x2); 134134723edSLouis Dionne ++__r; 135134723edSLouis Dionne } 136134723edSLouis Dionne } 137134723edSLouis Dionne } 138134723edSLouis Dionne return __r; 139134723edSLouis Dionne } 140134723edSLouis Dionne 141134723edSLouis Dionne // stable, 4-10 compares, 0-9 swaps 142134723edSLouis Dionne 143a7c3379cSKonstantin Varlamov template <class _WrappedComp, class _ForwardIterator> 144f950ba00SNilay Vaish _LIBCPP_HIDDEN unsigned __sort5(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, 145a7c3379cSKonstantin Varlamov _ForwardIterator __x4, _ForwardIterator __x5, _WrappedComp __wrapped_comp) { 146a7c3379cSKonstantin Varlamov using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>; 147a7c3379cSKonstantin Varlamov using _AlgPolicy = typename _Unwrap::_AlgPolicy; 148a7c3379cSKonstantin Varlamov using _Ops = _IterOps<_AlgPolicy>; 149a7c3379cSKonstantin Varlamov 150a7c3379cSKonstantin Varlamov using _Compare = typename _Unwrap::_Comp; 151a7c3379cSKonstantin Varlamov _Compare __c = _Unwrap::__get_comp(__wrapped_comp); 152a7c3379cSKonstantin Varlamov 153a7c3379cSKonstantin Varlamov unsigned __r = std::__sort4<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __c); 154f950ba00SNilay Vaish if (__c(*__x5, *__x4)) { 155a7c3379cSKonstantin Varlamov _Ops::iter_swap(__x4, __x5); 156134723edSLouis Dionne ++__r; 157f950ba00SNilay Vaish if (__c(*__x4, *__x3)) { 158a7c3379cSKonstantin Varlamov _Ops::iter_swap(__x3, __x4); 159134723edSLouis Dionne ++__r; 160f950ba00SNilay Vaish if (__c(*__x3, *__x2)) { 161a7c3379cSKonstantin Varlamov _Ops::iter_swap(__x2, __x3); 162134723edSLouis Dionne ++__r; 163f950ba00SNilay Vaish if (__c(*__x2, *__x1)) { 164a7c3379cSKonstantin Varlamov _Ops::iter_swap(__x1, __x2); 165134723edSLouis Dionne ++__r; 166134723edSLouis Dionne } 167134723edSLouis Dionne } 168134723edSLouis Dionne } 169134723edSLouis Dionne } 170134723edSLouis Dionne return __r; 171134723edSLouis Dionne } 172134723edSLouis Dionne 173a7c3379cSKonstantin Varlamov template <class _AlgPolicy, class _Compare, class _ForwardIterator> 174a7c3379cSKonstantin Varlamov _LIBCPP_HIDDEN unsigned __sort5_wrap_policy( 175a7c3379cSKonstantin Varlamov _ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, _ForwardIterator __x4, _ForwardIterator __x5, 176a7c3379cSKonstantin Varlamov _Compare __c) { 177a7c3379cSKonstantin Varlamov using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Compare>::type; 178a7c3379cSKonstantin Varlamov _WrappedComp __wrapped_comp(__c); 179a7c3379cSKonstantin Varlamov return std::__sort5<_WrappedComp>( 180a7c3379cSKonstantin Varlamov std::move(__x1), std::move(__x2), std::move(__x3), std::move(__x4), std::move(__x5), __wrapped_comp); 181a7c3379cSKonstantin Varlamov } 182a7c3379cSKonstantin Varlamov 183ff3989e6SKonstantin Varlamov // The comparator being simple is a prerequisite for using the branchless optimization. 184194d1965SMarco Gelmi template <class _Tp> 185194d1965SMarco Gelmi struct __is_simple_comparator : false_type {}; 186194d1965SMarco Gelmi template <class _Tp> 187194d1965SMarco Gelmi struct __is_simple_comparator<__less<_Tp>&> : true_type {}; 188194d1965SMarco Gelmi template <class _Tp> 189194d1965SMarco Gelmi struct __is_simple_comparator<less<_Tp>&> : true_type {}; 190194d1965SMarco Gelmi template <class _Tp> 191194d1965SMarco Gelmi struct __is_simple_comparator<greater<_Tp>&> : true_type {}; 192ff3989e6SKonstantin Varlamov #if _LIBCPP_STD_VER > 17 193ff3989e6SKonstantin Varlamov template <> 194ff3989e6SKonstantin Varlamov struct __is_simple_comparator<ranges::less&> : true_type {}; 195ff3989e6SKonstantin Varlamov template <> 196ff3989e6SKonstantin Varlamov struct __is_simple_comparator<ranges::greater&> : true_type {}; 197ff3989e6SKonstantin Varlamov #endif 198194d1965SMarco Gelmi 199194d1965SMarco Gelmi template <class _Compare, class _Iter, class _Tp = typename iterator_traits<_Iter>::value_type> 200194d1965SMarco Gelmi using __use_branchless_sort = 201194d1965SMarco Gelmi integral_constant<bool, __is_cpp17_contiguous_iterator<_Iter>::value && sizeof(_Tp) <= sizeof(void*) && 202194d1965SMarco Gelmi is_arithmetic<_Tp>::value && __is_simple_comparator<_Compare>::value>; 203194d1965SMarco Gelmi 204194d1965SMarco Gelmi // Ensures that __c(*__x, *__y) is true by swapping *__x and *__y if necessary. 205194d1965SMarco Gelmi template <class _Compare, class _RandomAccessIterator> 206194d1965SMarco Gelmi inline _LIBCPP_HIDE_FROM_ABI void __cond_swap(_RandomAccessIterator __x, _RandomAccessIterator __y, _Compare __c) { 207a7c3379cSKonstantin Varlamov // Note: this function behaves correctly even with proxy iterators (because it relies on `value_type`). 208194d1965SMarco Gelmi using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; 209194d1965SMarco Gelmi bool __r = __c(*__x, *__y); 210194d1965SMarco Gelmi value_type __tmp = __r ? *__x : *__y; 211194d1965SMarco Gelmi *__y = __r ? *__y : *__x; 212194d1965SMarco Gelmi *__x = __tmp; 213194d1965SMarco Gelmi } 214194d1965SMarco Gelmi 215194d1965SMarco Gelmi // Ensures that *__x, *__y and *__z are ordered according to the comparator __c, 216194d1965SMarco Gelmi // under the assumption that *__y and *__z are already ordered. 217194d1965SMarco Gelmi template <class _Compare, class _RandomAccessIterator> 218194d1965SMarco Gelmi inline _LIBCPP_HIDE_FROM_ABI void __partially_sorted_swap(_RandomAccessIterator __x, _RandomAccessIterator __y, 219194d1965SMarco Gelmi _RandomAccessIterator __z, _Compare __c) { 220a7c3379cSKonstantin Varlamov // Note: this function behaves correctly even with proxy iterators (because it relies on `value_type`). 221194d1965SMarco Gelmi using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; 222194d1965SMarco Gelmi bool __r = __c(*__z, *__x); 223194d1965SMarco Gelmi value_type __tmp = __r ? *__z : *__x; 224194d1965SMarco Gelmi *__z = __r ? *__x : *__z; 225194d1965SMarco Gelmi __r = __c(__tmp, *__y); 226194d1965SMarco Gelmi *__x = __r ? *__x : *__y; 227194d1965SMarco Gelmi *__y = __r ? *__y : __tmp; 228194d1965SMarco Gelmi } 229194d1965SMarco Gelmi 230a7c3379cSKonstantin Varlamov template <class, class _Compare, class _RandomAccessIterator> 231194d1965SMarco Gelmi inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void> 232194d1965SMarco Gelmi __sort3_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, 233194d1965SMarco Gelmi _Compare __c) { 234194d1965SMarco Gelmi _VSTD::__cond_swap<_Compare>(__x2, __x3, __c); 235194d1965SMarco Gelmi _VSTD::__partially_sorted_swap<_Compare>(__x1, __x2, __x3, __c); 236194d1965SMarco Gelmi } 237194d1965SMarco Gelmi 238a7c3379cSKonstantin Varlamov template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> 239194d1965SMarco Gelmi inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<!__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void> 240194d1965SMarco Gelmi __sort3_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, 241194d1965SMarco Gelmi _Compare __c) { 242a7c3379cSKonstantin Varlamov std::__sort3<_AlgPolicy, _Compare>(__x1, __x2, __x3, __c); 243194d1965SMarco Gelmi } 244194d1965SMarco Gelmi 245a7c3379cSKonstantin Varlamov template <class, class _Compare, class _RandomAccessIterator> 246194d1965SMarco Gelmi inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void> 247194d1965SMarco Gelmi __sort4_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, 248194d1965SMarco Gelmi _RandomAccessIterator __x4, _Compare __c) { 249194d1965SMarco Gelmi _VSTD::__cond_swap<_Compare>(__x1, __x3, __c); 250194d1965SMarco Gelmi _VSTD::__cond_swap<_Compare>(__x2, __x4, __c); 251194d1965SMarco Gelmi _VSTD::__cond_swap<_Compare>(__x1, __x2, __c); 252194d1965SMarco Gelmi _VSTD::__cond_swap<_Compare>(__x3, __x4, __c); 253194d1965SMarco Gelmi _VSTD::__cond_swap<_Compare>(__x2, __x3, __c); 254194d1965SMarco Gelmi } 255194d1965SMarco Gelmi 256a7c3379cSKonstantin Varlamov template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> 257194d1965SMarco Gelmi inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<!__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void> 258194d1965SMarco Gelmi __sort4_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, 259194d1965SMarco Gelmi _RandomAccessIterator __x4, _Compare __c) { 260a7c3379cSKonstantin Varlamov std::__sort4<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __c); 261194d1965SMarco Gelmi } 262194d1965SMarco Gelmi 263a7c3379cSKonstantin Varlamov template <class, class _Compare, class _RandomAccessIterator> 264194d1965SMarco Gelmi inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void> 265194d1965SMarco Gelmi __sort5_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, 266194d1965SMarco Gelmi _RandomAccessIterator __x4, _RandomAccessIterator __x5, _Compare __c) { 267194d1965SMarco Gelmi _VSTD::__cond_swap<_Compare>(__x1, __x2, __c); 268194d1965SMarco Gelmi _VSTD::__cond_swap<_Compare>(__x4, __x5, __c); 269194d1965SMarco Gelmi _VSTD::__partially_sorted_swap<_Compare>(__x3, __x4, __x5, __c); 270194d1965SMarco Gelmi _VSTD::__cond_swap<_Compare>(__x2, __x5, __c); 271194d1965SMarco Gelmi _VSTD::__partially_sorted_swap<_Compare>(__x1, __x3, __x4, __c); 272194d1965SMarco Gelmi _VSTD::__partially_sorted_swap<_Compare>(__x2, __x3, __x4, __c); 273194d1965SMarco Gelmi } 274194d1965SMarco Gelmi 275a7c3379cSKonstantin Varlamov template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> 276194d1965SMarco Gelmi inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<!__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void> 277194d1965SMarco Gelmi __sort5_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, 278194d1965SMarco Gelmi _RandomAccessIterator __x4, _RandomAccessIterator __x5, _Compare __c) { 279a7c3379cSKonstantin Varlamov std::__sort5_wrap_policy<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __x5, __c); 280194d1965SMarco Gelmi } 281194d1965SMarco Gelmi 282134723edSLouis Dionne // Assumes size > 0 283a7c3379cSKonstantin Varlamov template <class _AlgPolicy, class _Compare, class _BidirectionalIterator> 284f950ba00SNilay Vaish _LIBCPP_CONSTEXPR_AFTER_CXX11 void __selection_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, 285f950ba00SNilay Vaish _Compare __comp) { 286134723edSLouis Dionne _BidirectionalIterator __lm1 = __last; 287f950ba00SNilay Vaish for (--__lm1; __first != __lm1; ++__first) { 288a7c3379cSKonstantin Varlamov _BidirectionalIterator __i = std::__min_element<_Compare>(__first, __last, __comp); 289134723edSLouis Dionne if (__i != __first) 290a7c3379cSKonstantin Varlamov _IterOps<_AlgPolicy>::iter_swap(__first, __i); 291134723edSLouis Dionne } 292134723edSLouis Dionne } 293134723edSLouis Dionne 294a7c3379cSKonstantin Varlamov template <class _AlgPolicy, class _Compare, class _BidirectionalIterator> 295f950ba00SNilay Vaish void __insertion_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) { 296a7c3379cSKonstantin Varlamov using _Ops = _IterOps<_AlgPolicy>; 297a7c3379cSKonstantin Varlamov 298134723edSLouis Dionne typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; 299f950ba00SNilay Vaish if (__first != __last) { 300134723edSLouis Dionne _BidirectionalIterator __i = __first; 301f950ba00SNilay Vaish for (++__i; __i != __last; ++__i) { 302134723edSLouis Dionne _BidirectionalIterator __j = __i; 303a7c3379cSKonstantin Varlamov value_type __t(_Ops::__iter_move(__j)); 304134723edSLouis Dionne for (_BidirectionalIterator __k = __i; __k != __first && __comp(__t, *--__k); --__j) 305a7c3379cSKonstantin Varlamov *__j = _Ops::__iter_move(__k); 306134723edSLouis Dionne *__j = _VSTD::move(__t); 307134723edSLouis Dionne } 308134723edSLouis Dionne } 309134723edSLouis Dionne } 310134723edSLouis Dionne 311a7c3379cSKonstantin Varlamov template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> 312f950ba00SNilay Vaish void __insertion_sort_3(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { 313a7c3379cSKonstantin Varlamov using _Ops = _IterOps<_AlgPolicy>; 314a7c3379cSKonstantin Varlamov 315dc1c2714SFabian Wolff typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 316134723edSLouis Dionne typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; 317dc1c2714SFabian Wolff _RandomAccessIterator __j = __first + difference_type(2); 318a7c3379cSKonstantin Varlamov std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), __j, __comp); 319f950ba00SNilay Vaish for (_RandomAccessIterator __i = __j + difference_type(1); __i != __last; ++__i) { 320f950ba00SNilay Vaish if (__comp(*__i, *__j)) { 321a7c3379cSKonstantin Varlamov value_type __t(_Ops::__iter_move(__i)); 322134723edSLouis Dionne _RandomAccessIterator __k = __j; 323134723edSLouis Dionne __j = __i; 324f950ba00SNilay Vaish do { 325a7c3379cSKonstantin Varlamov *__j = _Ops::__iter_move(__k); 326134723edSLouis Dionne __j = __k; 327134723edSLouis Dionne } while (__j != __first && __comp(__t, *--__k)); 328134723edSLouis Dionne *__j = _VSTD::move(__t); 329134723edSLouis Dionne } 330134723edSLouis Dionne __j = __i; 331134723edSLouis Dionne } 332134723edSLouis Dionne } 333134723edSLouis Dionne 334a7c3379cSKonstantin Varlamov template <class _WrappedComp, class _RandomAccessIterator> 335a7c3379cSKonstantin Varlamov bool __insertion_sort_incomplete( 336a7c3379cSKonstantin Varlamov _RandomAccessIterator __first, _RandomAccessIterator __last, _WrappedComp __wrapped_comp) { 337a7c3379cSKonstantin Varlamov using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>; 338a7c3379cSKonstantin Varlamov using _AlgPolicy = typename _Unwrap::_AlgPolicy; 339a7c3379cSKonstantin Varlamov using _Ops = _IterOps<_AlgPolicy>; 340a7c3379cSKonstantin Varlamov 341a7c3379cSKonstantin Varlamov using _Compare = typename _Unwrap::_Comp; 342a7c3379cSKonstantin Varlamov _Compare __comp = _Unwrap::__get_comp(__wrapped_comp); 343a7c3379cSKonstantin Varlamov 344dc1c2714SFabian Wolff typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 345f950ba00SNilay Vaish switch (__last - __first) { 346134723edSLouis Dionne case 0: 347134723edSLouis Dionne case 1: 348134723edSLouis Dionne return true; 349134723edSLouis Dionne case 2: 350134723edSLouis Dionne if (__comp(*--__last, *__first)) 351a7c3379cSKonstantin Varlamov _IterOps<_AlgPolicy>::iter_swap(__first, __last); 352134723edSLouis Dionne return true; 353134723edSLouis Dionne case 3: 354a7c3379cSKonstantin Varlamov std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), --__last, __comp); 355134723edSLouis Dionne return true; 356134723edSLouis Dionne case 4: 357a7c3379cSKonstantin Varlamov std::__sort4_maybe_branchless<_AlgPolicy, _Compare>( 358a7c3379cSKonstantin Varlamov __first, __first + difference_type(1), __first + difference_type(2), --__last, __comp); 359134723edSLouis Dionne return true; 360134723edSLouis Dionne case 5: 361a7c3379cSKonstantin Varlamov std::__sort5_maybe_branchless<_AlgPolicy, _Compare>( 362a7c3379cSKonstantin Varlamov __first, __first + difference_type(1), __first + difference_type(2), __first + difference_type(3), 363a7c3379cSKonstantin Varlamov --__last, __comp); 364134723edSLouis Dionne return true; 365134723edSLouis Dionne } 366134723edSLouis Dionne typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; 367dc1c2714SFabian Wolff _RandomAccessIterator __j = __first + difference_type(2); 368a7c3379cSKonstantin Varlamov std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), __j, __comp); 369134723edSLouis Dionne const unsigned __limit = 8; 370134723edSLouis Dionne unsigned __count = 0; 371f950ba00SNilay Vaish for (_RandomAccessIterator __i = __j + difference_type(1); __i != __last; ++__i) { 372f950ba00SNilay Vaish if (__comp(*__i, *__j)) { 373a7c3379cSKonstantin Varlamov value_type __t(_Ops::__iter_move(__i)); 374134723edSLouis Dionne _RandomAccessIterator __k = __j; 375134723edSLouis Dionne __j = __i; 376f950ba00SNilay Vaish do { 377a7c3379cSKonstantin Varlamov *__j = _Ops::__iter_move(__k); 378134723edSLouis Dionne __j = __k; 379134723edSLouis Dionne } while (__j != __first && __comp(__t, *--__k)); 380134723edSLouis Dionne *__j = _VSTD::move(__t); 381134723edSLouis Dionne if (++__count == __limit) 382134723edSLouis Dionne return ++__i == __last; 383134723edSLouis Dionne } 384134723edSLouis Dionne __j = __i; 385134723edSLouis Dionne } 386134723edSLouis Dionne return true; 387134723edSLouis Dionne } 388134723edSLouis Dionne 389a7c3379cSKonstantin Varlamov template <class _AlgPolicy, class _Compare, class _BidirectionalIterator> 390f950ba00SNilay Vaish void __insertion_sort_move(_BidirectionalIterator __first1, _BidirectionalIterator __last1, 391f950ba00SNilay Vaish typename iterator_traits<_BidirectionalIterator>::value_type* __first2, _Compare __comp) { 392a7c3379cSKonstantin Varlamov using _Ops = _IterOps<_AlgPolicy>; 393a7c3379cSKonstantin Varlamov 394134723edSLouis Dionne typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; 395f950ba00SNilay Vaish if (__first1 != __last1) { 396134723edSLouis Dionne __destruct_n __d(0); 397134723edSLouis Dionne unique_ptr<value_type, __destruct_n&> __h(__first2, __d); 398134723edSLouis Dionne value_type* __last2 = __first2; 399a7c3379cSKonstantin Varlamov ::new ((void*)__last2) value_type(_Ops::__iter_move(__first1)); 400134723edSLouis Dionne __d.template __incr<value_type>(); 401f950ba00SNilay Vaish for (++__last2; ++__first1 != __last1; ++__last2) { 402134723edSLouis Dionne value_type* __j2 = __last2; 403134723edSLouis Dionne value_type* __i2 = __j2; 404f950ba00SNilay Vaish if (__comp(*__first1, *--__i2)) { 405a7c3379cSKonstantin Varlamov ::new ((void*)__j2) value_type(std::move(*__i2)); 406134723edSLouis Dionne __d.template __incr<value_type>(); 407134723edSLouis Dionne for (--__j2; __i2 != __first2 && __comp(*__first1, *--__i2); --__j2) 408a7c3379cSKonstantin Varlamov *__j2 = std::move(*__i2); 409a7c3379cSKonstantin Varlamov *__j2 = _Ops::__iter_move(__first1); 410f950ba00SNilay Vaish } else { 411a7c3379cSKonstantin Varlamov ::new ((void*)__j2) value_type(_Ops::__iter_move(__first1)); 412134723edSLouis Dionne __d.template __incr<value_type>(); 413134723edSLouis Dionne } 414134723edSLouis Dionne } 415134723edSLouis Dionne __h.release(); 416134723edSLouis Dionne } 417134723edSLouis Dionne } 418134723edSLouis Dionne 419a7c3379cSKonstantin Varlamov template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> 420f950ba00SNilay Vaish void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, 421f950ba00SNilay Vaish typename iterator_traits<_RandomAccessIterator>::difference_type __depth) { 422a7c3379cSKonstantin Varlamov using _Ops = _IterOps<_AlgPolicy>; 423a7c3379cSKonstantin Varlamov 424134723edSLouis Dionne typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 425134723edSLouis Dionne typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; 426f950ba00SNilay Vaish const difference_type __limit = 427f950ba00SNilay Vaish is_trivially_copy_constructible<value_type>::value && is_trivially_copy_assignable<value_type>::value ? 30 : 6; 428f950ba00SNilay Vaish while (true) { 429134723edSLouis Dionne __restart: 430134723edSLouis Dionne difference_type __len = __last - __first; 431f950ba00SNilay Vaish switch (__len) { 432134723edSLouis Dionne case 0: 433134723edSLouis Dionne case 1: 434134723edSLouis Dionne return; 435134723edSLouis Dionne case 2: 436134723edSLouis Dionne if (__comp(*--__last, *__first)) 437a7c3379cSKonstantin Varlamov _IterOps<_AlgPolicy>::iter_swap(__first, __last); 438134723edSLouis Dionne return; 439134723edSLouis Dionne case 3: 440a7c3379cSKonstantin Varlamov std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), --__last, __comp); 441134723edSLouis Dionne return; 442134723edSLouis Dionne case 4: 443a7c3379cSKonstantin Varlamov std::__sort4_maybe_branchless<_AlgPolicy, _Compare>( 444a7c3379cSKonstantin Varlamov __first, __first + difference_type(1), __first + difference_type(2), --__last, __comp); 445134723edSLouis Dionne return; 446134723edSLouis Dionne case 5: 447a7c3379cSKonstantin Varlamov std::__sort5_maybe_branchless<_AlgPolicy, _Compare>( 448a7c3379cSKonstantin Varlamov __first, __first + difference_type(1), __first + difference_type(2), __first + difference_type(3), 449a7c3379cSKonstantin Varlamov --__last, __comp); 450134723edSLouis Dionne return; 451134723edSLouis Dionne } 452f950ba00SNilay Vaish if (__len <= __limit) { 453a7c3379cSKonstantin Varlamov std::__insertion_sort_3<_AlgPolicy, _Compare>(__first, __last, __comp); 454134723edSLouis Dionne return; 455134723edSLouis Dionne } 456134723edSLouis Dionne // __len > 5 457f950ba00SNilay Vaish if (__depth == 0) { 4587f287390SNilay Vaish // Fallback to heap sort as Introsort suggests. 459a7c3379cSKonstantin Varlamov std::__partial_sort<_AlgPolicy, _Compare>(__first, __last, __last, __comp); 4607f287390SNilay Vaish return; 4617f287390SNilay Vaish } 4627f287390SNilay Vaish --__depth; 463134723edSLouis Dionne _RandomAccessIterator __m = __first; 464134723edSLouis Dionne _RandomAccessIterator __lm1 = __last; 465134723edSLouis Dionne --__lm1; 466134723edSLouis Dionne unsigned __n_swaps; 467134723edSLouis Dionne { 468134723edSLouis Dionne difference_type __delta; 469f950ba00SNilay Vaish if (__len >= 1000) { 470134723edSLouis Dionne __delta = __len / 2; 471134723edSLouis Dionne __m += __delta; 472134723edSLouis Dionne __delta /= 2; 473a7c3379cSKonstantin Varlamov __n_swaps = std::__sort5_wrap_policy<_AlgPolicy, _Compare>( 474a7c3379cSKonstantin Varlamov __first, __first + __delta, __m, __m + __delta, __lm1, __comp); 475f950ba00SNilay Vaish } else { 476134723edSLouis Dionne __delta = __len / 2; 477134723edSLouis Dionne __m += __delta; 478a7c3379cSKonstantin Varlamov __n_swaps = std::__sort3<_AlgPolicy, _Compare>(__first, __m, __lm1, __comp); 479134723edSLouis Dionne } 480134723edSLouis Dionne } 481134723edSLouis Dionne // *__m is median 482134723edSLouis Dionne // partition [__first, __m) < *__m and *__m <= [__m, __last) 483134723edSLouis Dionne // (this inhibits tossing elements equivalent to __m around unnecessarily) 484134723edSLouis Dionne _RandomAccessIterator __i = __first; 485134723edSLouis Dionne _RandomAccessIterator __j = __lm1; 486134723edSLouis Dionne // j points beyond range to be tested, *__m is known to be <= *__lm1 487134723edSLouis Dionne // The search going up is known to be guarded but the search coming down isn't. 488134723edSLouis Dionne // Prime the downward search with a guard. 489134723edSLouis Dionne if (!__comp(*__i, *__m)) // if *__first == *__m 490134723edSLouis Dionne { 491134723edSLouis Dionne // *__first == *__m, *__first doesn't go in first part 492134723edSLouis Dionne // manually guard downward moving __j against __i 493f950ba00SNilay Vaish while (true) { 494f950ba00SNilay Vaish if (__i == --__j) { 495134723edSLouis Dionne // *__first == *__m, *__m <= all other elements 496134723edSLouis Dionne // Parition instead into [__first, __i) == *__first and *__first < [__i, __last) 497134723edSLouis Dionne ++__i; // __first + 1 498134723edSLouis Dionne __j = __last; 499134723edSLouis Dionne if (!__comp(*__first, *--__j)) // we need a guard if *__first == *(__last-1) 500134723edSLouis Dionne { 501f950ba00SNilay Vaish while (true) { 502134723edSLouis Dionne if (__i == __j) 503134723edSLouis Dionne return; // [__first, __last) all equivalent elements 504f950ba00SNilay Vaish if (__comp(*__first, *__i)) { 505a7c3379cSKonstantin Varlamov _Ops::iter_swap(__i, __j); 506134723edSLouis Dionne ++__n_swaps; 507134723edSLouis Dionne ++__i; 508134723edSLouis Dionne break; 509134723edSLouis Dionne } 510134723edSLouis Dionne ++__i; 511134723edSLouis Dionne } 512134723edSLouis Dionne } 513134723edSLouis Dionne // [__first, __i) == *__first and *__first < [__j, __last) and __j == __last - 1 514134723edSLouis Dionne if (__i == __j) 515134723edSLouis Dionne return; 516f950ba00SNilay Vaish while (true) { 517134723edSLouis Dionne while (!__comp(*__first, *__i)) 518134723edSLouis Dionne ++__i; 519134723edSLouis Dionne while (__comp(*__first, *--__j)) 520134723edSLouis Dionne ; 521134723edSLouis Dionne if (__i >= __j) 522134723edSLouis Dionne break; 523a7c3379cSKonstantin Varlamov _Ops::iter_swap(__i, __j); 524134723edSLouis Dionne ++__n_swaps; 525134723edSLouis Dionne ++__i; 526134723edSLouis Dionne } 527134723edSLouis Dionne // [__first, __i) == *__first and *__first < [__i, __last) 528134723edSLouis Dionne // The first part is sorted, sort the second part 529134723edSLouis Dionne // _VSTD::__sort<_Compare>(__i, __last, __comp); 530134723edSLouis Dionne __first = __i; 531134723edSLouis Dionne goto __restart; 532134723edSLouis Dionne } 533f950ba00SNilay Vaish if (__comp(*__j, *__m)) { 534a7c3379cSKonstantin Varlamov _Ops::iter_swap(__i, __j); 535134723edSLouis Dionne ++__n_swaps; 536134723edSLouis Dionne break; // found guard for downward moving __j, now use unguarded partition 537134723edSLouis Dionne } 538134723edSLouis Dionne } 539134723edSLouis Dionne } 540134723edSLouis Dionne // It is known that *__i < *__m 541134723edSLouis Dionne ++__i; 542134723edSLouis Dionne // j points beyond range to be tested, *__m is known to be <= *__lm1 543134723edSLouis Dionne // if not yet partitioned... 544f950ba00SNilay Vaish if (__i < __j) { 545134723edSLouis Dionne // known that *(__i - 1) < *__m 546134723edSLouis Dionne // known that __i <= __m 547f950ba00SNilay Vaish while (true) { 548134723edSLouis Dionne // __m still guards upward moving __i 549134723edSLouis Dionne while (__comp(*__i, *__m)) 550134723edSLouis Dionne ++__i; 551134723edSLouis Dionne // It is now known that a guard exists for downward moving __j 552134723edSLouis Dionne while (!__comp(*--__j, *__m)) 553134723edSLouis Dionne ; 554134723edSLouis Dionne if (__i > __j) 555134723edSLouis Dionne break; 556a7c3379cSKonstantin Varlamov _Ops::iter_swap(__i, __j); 557134723edSLouis Dionne ++__n_swaps; 558134723edSLouis Dionne // It is known that __m != __j 559134723edSLouis Dionne // If __m just moved, follow it 560134723edSLouis Dionne if (__m == __i) 561134723edSLouis Dionne __m = __j; 562134723edSLouis Dionne ++__i; 563134723edSLouis Dionne } 564134723edSLouis Dionne } 565134723edSLouis Dionne // [__first, __i) < *__m and *__m <= [__i, __last) 566f950ba00SNilay Vaish if (__i != __m && __comp(*__m, *__i)) { 567a7c3379cSKonstantin Varlamov _Ops::iter_swap(__i, __m); 568134723edSLouis Dionne ++__n_swaps; 569134723edSLouis Dionne } 570134723edSLouis Dionne // [__first, __i) < *__i and *__i <= [__i+1, __last) 571134723edSLouis Dionne // If we were given a perfect partition, see if insertion sort is quick... 572f950ba00SNilay Vaish if (__n_swaps == 0) { 573a7c3379cSKonstantin Varlamov using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Compare>::type; 574a7c3379cSKonstantin Varlamov _WrappedComp __wrapped_comp(__comp); 575a7c3379cSKonstantin Varlamov bool __fs = std::__insertion_sort_incomplete<_WrappedComp>(__first, __i, __wrapped_comp); 576a7c3379cSKonstantin Varlamov if (std::__insertion_sort_incomplete<_WrappedComp>(__i + difference_type(1), __last, __wrapped_comp)) { 577134723edSLouis Dionne if (__fs) 578134723edSLouis Dionne return; 579134723edSLouis Dionne __last = __i; 580134723edSLouis Dionne continue; 581f950ba00SNilay Vaish } else { 582f950ba00SNilay Vaish if (__fs) { 583134723edSLouis Dionne __first = ++__i; 584134723edSLouis Dionne continue; 585134723edSLouis Dionne } 586134723edSLouis Dionne } 587134723edSLouis Dionne } 588134723edSLouis Dionne // sort smaller range with recursive call and larger with tail recursion elimination 589f950ba00SNilay Vaish if (__i - __first < __last - __i) { 590a7c3379cSKonstantin Varlamov std::__introsort<_AlgPolicy, _Compare>(__first, __i, __comp, __depth); 591134723edSLouis Dionne __first = ++__i; 592f950ba00SNilay Vaish } else { 593a7c3379cSKonstantin Varlamov std::__introsort<_AlgPolicy, _Compare>(__i + difference_type(1), __last, __comp, __depth); 594134723edSLouis Dionne __last = __i; 595134723edSLouis Dionne } 596134723edSLouis Dionne } 597134723edSLouis Dionne } 598134723edSLouis Dionne 5997f287390SNilay Vaish template <typename _Number> 6007f287390SNilay Vaish inline _LIBCPP_HIDE_FROM_ABI _Number __log2i(_Number __n) { 601865ad6bdSHans Wennborg if (__n == 0) 602865ad6bdSHans Wennborg return 0; 603865ad6bdSHans Wennborg if (sizeof(__n) <= sizeof(unsigned)) 604865ad6bdSHans Wennborg return sizeof(unsigned) * CHAR_BIT - 1 - __libcpp_clz(static_cast<unsigned>(__n)); 605865ad6bdSHans Wennborg if (sizeof(__n) <= sizeof(unsigned long)) 606865ad6bdSHans Wennborg return sizeof(unsigned long) * CHAR_BIT - 1 - __libcpp_clz(static_cast<unsigned long>(__n)); 607865ad6bdSHans Wennborg if (sizeof(__n) <= sizeof(unsigned long long)) 608865ad6bdSHans Wennborg return sizeof(unsigned long long) * CHAR_BIT - 1 - __libcpp_clz(static_cast<unsigned long long>(__n)); 609865ad6bdSHans Wennborg 6107f287390SNilay Vaish _Number __log2 = 0; 6117f287390SNilay Vaish while (__n > 1) { 6127f287390SNilay Vaish __log2++; 6137f287390SNilay Vaish __n >>= 1; 6147f287390SNilay Vaish } 6157f287390SNilay Vaish return __log2; 6167f287390SNilay Vaish } 6177f287390SNilay Vaish 618a7c3379cSKonstantin Varlamov template <class _WrappedComp, class _RandomAccessIterator> 619a7c3379cSKonstantin Varlamov void __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _WrappedComp __wrapped_comp) { 6207f287390SNilay Vaish typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 6217f287390SNilay Vaish difference_type __depth_limit = 2 * __log2i(__last - __first); 622a7c3379cSKonstantin Varlamov 623a7c3379cSKonstantin Varlamov using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>; 624a7c3379cSKonstantin Varlamov using _AlgPolicy = typename _Unwrap::_AlgPolicy; 625a7c3379cSKonstantin Varlamov using _Compare = typename _Unwrap::_Comp; 626a7c3379cSKonstantin Varlamov _Compare __comp = _Unwrap::__get_comp(__wrapped_comp); 627a7c3379cSKonstantin Varlamov std::__introsort<_AlgPolicy, _Compare>(__first, __last, __comp, __depth_limit); 6287f287390SNilay Vaish } 6297f287390SNilay Vaish 630134723edSLouis Dionne template <class _Compare, class _Tp> 631f950ba00SNilay Vaish inline _LIBCPP_INLINE_VISIBILITY void __sort(_Tp** __first, _Tp** __last, __less<_Tp*>&) { 632134723edSLouis Dionne __less<uintptr_t> __comp; 633a7c3379cSKonstantin Varlamov std::__sort<__less<uintptr_t>&, uintptr_t*>((uintptr_t*)__first, (uintptr_t*)__last, __comp); 634134723edSLouis Dionne } 635134723edSLouis Dionne 6362ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS void __sort<__less<char>&, char*>(char*, char*, __less<char>&); 637f4c1258dSLouis Dionne #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 6382ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS void __sort<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&); 639f4c1258dSLouis Dionne #endif 6402ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS void __sort<__less<signed char>&, signed char*>(signed char*, signed char*, __less<signed char>&); 6412ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS void __sort<__less<unsigned char>&, unsigned char*>(unsigned char*, unsigned char*, __less<unsigned char>&); 6422ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS void __sort<__less<short>&, short*>(short*, short*, __less<short>&); 6432ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS void __sort<__less<unsigned short>&, unsigned short*>(unsigned short*, unsigned short*, __less<unsigned short>&); 6442ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS void __sort<__less<int>&, int*>(int*, int*, __less<int>&); 6452ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS void __sort<__less<unsigned>&, unsigned*>(unsigned*, unsigned*, __less<unsigned>&); 6462ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS void __sort<__less<long>&, long*>(long*, long*, __less<long>&); 6472ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS void __sort<__less<unsigned long>&, unsigned long*>(unsigned long*, unsigned long*, __less<unsigned long>&); 6482ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS void __sort<__less<long long>&, long long*>(long long*, long long*, __less<long long>&); 6492ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS void __sort<__less<unsigned long long>&, unsigned long long*>(unsigned long long*, unsigned long long*, __less<unsigned long long>&); 6502ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS void __sort<__less<float>&, float*>(float*, float*, __less<float>&); 6512ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS void __sort<__less<double>&, double*>(double*, double*, __less<double>&); 6522ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS void __sort<__less<long double>&, long double*>(long double*, long double*, __less<long double>&); 653134723edSLouis Dionne 6542ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<char>&, char*>(char*, char*, __less<char>&); 655f4c1258dSLouis Dionne #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 6562ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&); 657f4c1258dSLouis Dionne #endif 6582ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<signed char>&, signed char*>(signed char*, signed char*, __less<signed char>&); 6592ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned char>&, unsigned char*>(unsigned char*, unsigned char*, __less<unsigned char>&); 6602ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<short>&, short*>(short*, short*, __less<short>&); 6612ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned short>&, unsigned short*>(unsigned short*, unsigned short*, __less<unsigned short>&); 6622ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<int>&, int*>(int*, int*, __less<int>&); 6632ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned>&, unsigned*>(unsigned*, unsigned*, __less<unsigned>&); 6642ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<long>&, long*>(long*, long*, __less<long>&); 6652ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned long>&, unsigned long*>(unsigned long*, unsigned long*, __less<unsigned long>&); 6662ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<long long>&, long long*>(long long*, long long*, __less<long long>&); 6672ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned long long>&, unsigned long long*>(unsigned long long*, unsigned long long*, __less<unsigned long long>&); 6682ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<float>&, float*>(float*, float*, __less<float>&); 6692ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<double>&, double*>(double*, double*, __less<double>&); 6702ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<long double>&, long double*>(long double*, long double*, __less<long double>&); 671134723edSLouis Dionne 6722ae52326SLouis Dionne extern template _LIBCPP_FUNC_VIS unsigned __sort5<__less<long double>&, long double*>(long double*, long double*, long double*, long double*, long double*, __less<long double>&); 673134723edSLouis Dionne 674a7c3379cSKonstantin Varlamov template <class _AlgPolicy, class _RandomAccessIterator, class _Comp> 675ff3989e6SKonstantin Varlamov inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 676ff3989e6SKonstantin Varlamov void __sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) { 677a7c3379cSKonstantin Varlamov std::__debug_randomize_range<_AlgPolicy>(__first, __last); 678a7c3379cSKonstantin Varlamov 679ff3989e6SKonstantin Varlamov using _Comp_ref = typename __comp_ref_type<_Comp>::type; 680134723edSLouis Dionne if (__libcpp_is_constant_evaluated()) { 681*5dd19adaSvarconst std::__partial_sort<_AlgPolicy>(__first, __last, __last, __comp); 682a7c3379cSKonstantin Varlamov 683134723edSLouis Dionne } else { 684a7c3379cSKonstantin Varlamov using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Comp_ref>::type; 685a7c3379cSKonstantin Varlamov _Comp_ref __comp_ref(__comp); 686a7c3379cSKonstantin Varlamov _WrappedComp __wrapped_comp(__comp_ref); 687a7c3379cSKonstantin Varlamov std::__sort<_WrappedComp>(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __wrapped_comp); 688134723edSLouis Dionne } 689134723edSLouis Dionne } 690134723edSLouis Dionne 691ff3989e6SKonstantin Varlamov template <class _RandomAccessIterator, class _Comp> 692ff3989e6SKonstantin Varlamov inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 693ff3989e6SKonstantin Varlamov void sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) { 694a7c3379cSKonstantin Varlamov std::__sort_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp); 695ff3989e6SKonstantin Varlamov } 696ff3989e6SKonstantin Varlamov 697134723edSLouis Dionne template <class _RandomAccessIterator> 698ff3989e6SKonstantin Varlamov inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 699ff3989e6SKonstantin Varlamov void sort(_RandomAccessIterator __first, _RandomAccessIterator __last) { 700ff3989e6SKonstantin Varlamov std::sort(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); 701134723edSLouis Dionne } 702134723edSLouis Dionne 703134723edSLouis Dionne _LIBCPP_END_NAMESPACE_STD 704134723edSLouis Dionne 705134723edSLouis Dionne #endif // _LIBCPP___ALGORITHM_SORT_H 706