-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[libc++] Support sorting consteval-only ranges #134623
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
d4f2563
9625fe9
421e46e
3aa6f3e
2ce3060
5d68c59
90d2ac2
c189d67
6cd3e63
f06b9cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,10 +17,13 @@ | |
#include <__algorithm/partial_sort.h> | ||
#include <__algorithm/unwrap_iter.h> | ||
#include <__assert> | ||
#include <__bit/bit_log2.h> | ||
#include <__bit/blsr.h> | ||
#include <__bit/countl.h> | ||
#include <__bit/countr.h> | ||
#include <__config> | ||
#include <__cstddef/ptrdiff_t.h> | ||
#include <__cstddef/size_t.h> | ||
#include <__debug_utils/randomize_range.h> | ||
#include <__debug_utils/strict_weak_ordering_check.h> | ||
#include <__functional/operations.h> | ||
|
@@ -34,6 +37,7 @@ | |
#include <__type_traits/is_constant_evaluated.h> | ||
#include <__type_traits/is_same.h> | ||
#include <__type_traits/is_trivially_copyable.h> | ||
#include <__type_traits/make_unsigned.h> | ||
#include <__utility/move.h> | ||
#include <__utility/pair.h> | ||
#include <climits> | ||
|
@@ -138,7 +142,7 @@ template <class, | |
class _Compare, | ||
class _RandomAccessIterator, | ||
__enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>, int> = 0> | ||
inline _LIBCPP_HIDE_FROM_ABI void | ||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void | ||
__sort4(_RandomAccessIterator __x1, | ||
_RandomAccessIterator __x2, | ||
_RandomAccessIterator __x3, | ||
|
@@ -155,7 +159,7 @@ template <class _AlgPolicy, | |
class _Compare, | ||
class _RandomAccessIterator, | ||
__enable_if_t<!__use_branchless_sort<_Compare, _RandomAccessIterator>, int> = 0> | ||
inline _LIBCPP_HIDE_FROM_ABI void | ||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void | ||
__sort4(_RandomAccessIterator __x1, | ||
_RandomAccessIterator __x2, | ||
_RandomAccessIterator __x3, | ||
|
@@ -180,7 +184,7 @@ template <class _AlgPolicy, | |
class _Compare, | ||
class _RandomAccessIterator, | ||
__enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>, int> = 0> | ||
inline _LIBCPP_HIDE_FROM_ABI void | ||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void | ||
__sort5(_RandomAccessIterator __x1, | ||
_RandomAccessIterator __x2, | ||
_RandomAccessIterator __x3, | ||
|
@@ -199,7 +203,7 @@ template <class _AlgPolicy, | |
class _Compare, | ||
class _RandomAccessIterator, | ||
__enable_if_t<!__use_branchless_sort<_Compare, _RandomAccessIterator>, int> = 0> | ||
inline _LIBCPP_HIDE_FROM_ABI void | ||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void | ||
__sort5(_RandomAccessIterator __x1, | ||
_RandomAccessIterator __x2, | ||
_RandomAccessIterator __x3, | ||
|
@@ -238,7 +242,7 @@ __selection_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, | |
// Sort the iterator range [__first, __last) using the comparator __comp using | ||
// the insertion sort algorithm. | ||
template <class _AlgPolicy, class _Compare, class _BidirectionalIterator> | ||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void | ||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void | ||
__insertion_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) { | ||
using _Ops = _IterOps<_AlgPolicy>; | ||
|
||
|
@@ -268,7 +272,7 @@ __insertion_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, | |
// Assumes that there is an element in the position (__first - 1) and that each | ||
// element in the input range is greater or equal to the element at __first - 1. | ||
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> | ||
_LIBCPP_HIDE_FROM_ABI void | ||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void | ||
__insertion_sort_unguarded(_RandomAccessIterator const __first, _RandomAccessIterator __last, _Compare __comp) { | ||
using _Ops = _IterOps<_AlgPolicy>; | ||
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | ||
|
@@ -296,7 +300,7 @@ __insertion_sort_unguarded(_RandomAccessIterator const __first, _RandomAccessIte | |
} | ||
|
||
template <class _AlgPolicy, class _Comp, class _RandomAccessIterator> | ||
_LIBCPP_HIDE_FROM_ABI bool | ||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool | ||
__insertion_sort_incomplete(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) { | ||
using _Ops = _IterOps<_AlgPolicy>; | ||
|
||
|
@@ -350,7 +354,7 @@ __insertion_sort_incomplete(_RandomAccessIterator __first, _RandomAccessIterator | |
} | ||
|
||
template <class _AlgPolicy, class _RandomAccessIterator> | ||
inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos( | ||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __swap_bitmap_pos( | ||
_RandomAccessIterator __first, _RandomAccessIterator __last, uint64_t& __left_bitset, uint64_t& __right_bitset) { | ||
using _Ops = _IterOps<_AlgPolicy>; | ||
typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type; | ||
|
@@ -368,7 +372,7 @@ inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos( | |
template <class _Compare, | ||
class _RandomAccessIterator, | ||
class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type> | ||
inline _LIBCPP_HIDE_FROM_ABI void | ||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void | ||
__populate_left_bitset(_RandomAccessIterator __first, _Compare __comp, _ValueType& __pivot, uint64_t& __left_bitset) { | ||
// Possible vectorization. With a proper "-march" flag, the following loop | ||
// will be compiled into a set of SIMD instructions. | ||
|
@@ -384,7 +388,7 @@ __populate_left_bitset(_RandomAccessIterator __first, _Compare __comp, _ValueTyp | |
template <class _Compare, | ||
class _RandomAccessIterator, | ||
class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type> | ||
inline _LIBCPP_HIDE_FROM_ABI void | ||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void | ||
__populate_right_bitset(_RandomAccessIterator __lm1, _Compare __comp, _ValueType& __pivot, uint64_t& __right_bitset) { | ||
// Possible vectorization. With a proper "-march" flag, the following loop | ||
// will be compiled into a set of SIMD instructions. | ||
|
@@ -401,7 +405,7 @@ template <class _AlgPolicy, | |
class _Compare, | ||
class _RandomAccessIterator, | ||
class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type> | ||
inline _LIBCPP_HIDE_FROM_ABI void __bitset_partition_partial_blocks( | ||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __bitset_partition_partial_blocks( | ||
_RandomAccessIterator& __first, | ||
_RandomAccessIterator& __lm1, | ||
_Compare __comp, | ||
|
@@ -448,7 +452,7 @@ inline _LIBCPP_HIDE_FROM_ABI void __bitset_partition_partial_blocks( | |
} | ||
|
||
template <class _AlgPolicy, class _RandomAccessIterator> | ||
inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos_within( | ||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __swap_bitmap_pos_within( | ||
_RandomAccessIterator& __first, _RandomAccessIterator& __lm1, uint64_t& __left_bitset, uint64_t& __right_bitset) { | ||
using _Ops = _IterOps<_AlgPolicy>; | ||
typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type; | ||
|
@@ -489,7 +493,7 @@ inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos_within( | |
// __bitset_partition uses bitsets for storing outcomes of the comparisons | ||
// between the pivot and other elements. | ||
template <class _AlgPolicy, class _RandomAccessIterator, class _Compare> | ||
_LIBCPP_HIDE_FROM_ABI std::pair<_RandomAccessIterator, bool> | ||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 std::pair<_RandomAccessIterator, bool> | ||
__bitset_partition(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { | ||
using _Ops = _IterOps<_AlgPolicy>; | ||
typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type; | ||
|
@@ -581,7 +585,7 @@ __bitset_partition(_RandomAccessIterator __first, _RandomAccessIterator __last, | |
// the provided range is already sorted, false otherwise. We assume that the | ||
// length of the range is at least three elements. | ||
template <class _AlgPolicy, class _RandomAccessIterator, class _Compare> | ||
_LIBCPP_HIDE_FROM_ABI std::pair<_RandomAccessIterator, bool> | ||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 std::pair<_RandomAccessIterator, bool> | ||
__partition_with_equals_on_right(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { | ||
using _Ops = _IterOps<_AlgPolicy>; | ||
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | ||
|
@@ -649,7 +653,7 @@ __partition_with_equals_on_right(_RandomAccessIterator __first, _RandomAccessIte | |
// Similar to the above function. Elements equivalent to the pivot are put to | ||
// the left of the pivot. Returns the iterator to the pivot element. | ||
template <class _AlgPolicy, class _RandomAccessIterator, class _Compare> | ||
_LIBCPP_HIDE_FROM_ABI _RandomAccessIterator | ||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator | ||
__partition_with_equals_on_left(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { | ||
using _Ops = _IterOps<_AlgPolicy>; | ||
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | ||
|
@@ -712,11 +716,12 @@ __partition_with_equals_on_left(_RandomAccessIterator __first, _RandomAccessIter | |
// The implementation is partly based on Orson Peters' pattern-defeating | ||
// quicksort, published at: <https://github.com/orlp/pdqsort>. | ||
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, bool _UseBitSetPartition> | ||
void __introsort(_RandomAccessIterator __first, | ||
_RandomAccessIterator __last, | ||
_Compare __comp, | ||
typename iterator_traits<_RandomAccessIterator>::difference_type __depth, | ||
bool __leftmost = true) { | ||
_LIBCPP_CONSTEXPR_SINCE_CXX20 void | ||
__introsort(_RandomAccessIterator __first, | ||
_RandomAccessIterator __last, | ||
_Compare __comp, | ||
typename iterator_traits<_RandomAccessIterator>::difference_type __depth, | ||
bool __leftmost = true) { | ||
using _Ops = _IterOps<_AlgPolicy>; | ||
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | ||
using _Comp_ref = __comp_ref_type<_Compare>; | ||
|
@@ -826,25 +831,6 @@ void __introsort(_RandomAccessIterator __first, | |
} | ||
} | ||
|
||
template <typename _Number> | ||
inline _LIBCPP_HIDE_FROM_ABI _Number __log2i(_Number __n) { | ||
if (__n == 0) | ||
return 0; | ||
if (sizeof(__n) <= sizeof(unsigned)) | ||
return sizeof(unsigned) * CHAR_BIT - 1 - __libcpp_clz(static_cast<unsigned>(__n)); | ||
if (sizeof(__n) <= sizeof(unsigned long)) | ||
return sizeof(unsigned long) * CHAR_BIT - 1 - __libcpp_clz(static_cast<unsigned long>(__n)); | ||
if (sizeof(__n) <= sizeof(unsigned long long)) | ||
return sizeof(unsigned long long) * CHAR_BIT - 1 - __libcpp_clz(static_cast<unsigned long long>(__n)); | ||
|
||
_Number __log2 = 0; | ||
while (__n > 1) { | ||
__log2++; | ||
__n >>= 1; | ||
} | ||
return __log2; | ||
} | ||
|
||
template <class _Comp, class _RandomAccessIterator> | ||
void __sort(_RandomAccessIterator, _RandomAccessIterator, _Comp); | ||
|
||
|
@@ -877,8 +863,10 @@ __sort<__less<long double>&, long double*>(long double*, long double*, __less<lo | |
template <class _AlgPolicy, class _RandomAccessIterator, class _Comp> | ||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void | ||
__sort_dispatch(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) { | ||
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | ||
difference_type __depth_limit = 2 * std::__log2i(__last - __first); | ||
using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; | ||
using __size_type = __make_unsigned_t<difference_type>; | ||
difference_type __depth_limit = | ||
static_cast<difference_type>(2 * std::__bit_log2(static_cast<__size_type>(__last - __first))); | ||
|
||
// Only use bitset partitioning for arithmetic types. We should also check | ||
// that the default comparator is in use so that we are sure that there are no | ||
|
@@ -912,30 +900,63 @@ using __sort_is_specialized_in_library _LIBCPP_NODEBUG = __is_any_of< | |
long double>; | ||
|
||
template <class _AlgPolicy, class _Type, __enable_if_t<__sort_is_specialized_in_library<_Type>::value, int> = 0> | ||
_LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, __less<>&) { | ||
__less<_Type> __comp; | ||
std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp); | ||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __sort_dispatch(_Type* __first, _Type* __last, __less<>&) { | ||
#if _LIBCPP_STD_VER >= 20 | ||
if (std::is_constant_evaluated()) { | ||
auto __depth_limit = static_cast<ptrdiff_t>(2 * std::__bit_log2(static_cast<size_t>(__last - __first))); | ||
std::__introsort<_ClassicAlgPolicy, ranges::less, _Type*, __use_branchless_sort<ranges::less, _Type*>>( | ||
__first, __last, ranges::less{}, __depth_limit); | ||
} else | ||
#endif | ||
|
||
{ | ||
__less<_Type> __comp; | ||
std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp); | ||
} | ||
} | ||
|
||
template <class _AlgPolicy, class _Type, __enable_if_t<__sort_is_specialized_in_library<_Type>::value, int> = 0> | ||
_LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, less<_Type>&) { | ||
__less<_Type> __comp; | ||
std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp); | ||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __sort_dispatch(_Type* __first, _Type* __last, less<_Type>&) { | ||
#if _LIBCPP_STD_VER >= 20 | ||
if (std::is_constant_evaluated()) { | ||
auto __depth_limit = static_cast<ptrdiff_t>(2 * std::__bit_log2(static_cast<size_t>(__last - __first))); | ||
std::__introsort<_ClassicAlgPolicy, ranges::less, _Type*, __use_branchless_sort<ranges::less, _Type*>>( | ||
__first, __last, ranges::less{}, __depth_limit); | ||
} else | ||
#endif | ||
{ | ||
__less<_Type> __comp; | ||
std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp); | ||
} | ||
} | ||
|
||
#if _LIBCPP_STD_VER >= 14 | ||
template <class _AlgPolicy, class _Type, __enable_if_t<__sort_is_specialized_in_library<_Type>::value, int> = 0> | ||
_LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, less<>&) { | ||
__less<_Type> __comp; | ||
std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp); | ||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __sort_dispatch(_Type* __first, _Type* __last, less<>&) { | ||
# if _LIBCPP_STD_VER >= 20 | ||
if (std::is_constant_evaluated()) { | ||
auto __depth_limit = static_cast<ptrdiff_t>(2 * std::__bit_log2(static_cast<size_t>(__last - __first))); | ||
std::__introsort<_ClassicAlgPolicy, ranges::less, _Type*, __use_branchless_sort<ranges::less, _Type*>>( | ||
__first, __last, ranges::less{}, __depth_limit); | ||
} else | ||
# endif | ||
{ | ||
__less<_Type> __comp; | ||
std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp); | ||
} | ||
} | ||
#endif | ||
|
||
#if _LIBCPP_STD_VER >= 20 | ||
template <class _AlgPolicy, class _Type, __enable_if_t<__sort_is_specialized_in_library<_Type>::value, int> = 0> | ||
_LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, ranges::less&) { | ||
__less<_Type> __comp; | ||
std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp); | ||
_LIBCPP_HIDE_FROM_ABI constexpr void __sort_dispatch(_Type* __first, _Type* __last, ranges::less&) { | ||
if (std::is_constant_evaluated()) { | ||
auto __depth_limit = static_cast<ptrdiff_t>(2 * std::__bit_log2(static_cast<size_t>(__last - __first))); | ||
std::__introsort<_ClassicAlgPolicy, ranges::less, _Type*, __use_branchless_sort<ranges::less, _Type*>>( | ||
__first, __last, ranges::less{}, __depth_limit); | ||
} else { | ||
__less<_Type> __comp; | ||
std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp); | ||
} | ||
} | ||
#endif | ||
|
||
|
@@ -944,12 +965,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void | |
__sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) { | ||
std::__debug_randomize_range<_AlgPolicy>(__first, __last); | ||
|
||
if (__libcpp_is_constant_evaluated()) { | ||
std::__partial_sort<_AlgPolicy>( | ||
std::__unwrap_iter(__first), std::__unwrap_iter(__last), std::__unwrap_iter(__last), __comp); | ||
} else { | ||
std::__sort_dispatch<_AlgPolicy>(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __comp); | ||
} | ||
std::__sort_dispatch<_AlgPolicy>(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __comp); | ||
std::__check_strict_weak_ordering_sorted(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __comp); | ||
} | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.