libcxx: update to LLVM 18

release/18.x branch, commit 78b99c73ee4b96fe9ce0e294d4632326afb2db42

This adds the flag `-D_LIBCPP_HARDENING_MODE` which is determined based
on the Zig optimization mode.

This commit also fixes libunwind, libcxx, and libcxxabi to properly
report sub compilation errors.
This commit is contained in:
Andrew Kelley 2024-04-26 15:33:29 -07:00
parent bc6ebc6f25
commit 06ee65af9e
902 changed files with 80977 additions and 107576 deletions

View File

@ -19,7 +19,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Predicate> template <class _InputIterator, class _Predicate>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
for (; __first != __last; ++__first) for (; __first != __last; ++__first)
if (__pred(*__first)) if (__pred(*__first))

View File

@ -22,22 +22,16 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator, class _Tp, class _Compare> template <class _ForwardIterator, class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) {
bool __first = std::lower_bound<_ForwardIterator, _Tp, __comp_ref_type<_Compare> >(__first, __last, __value, __comp);
binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) return __first != __last && !__comp(__value, *__first);
{
__first = std::lower_bound<_ForwardIterator, _Tp, __comp_ref_type<_Compare> >(__first, __last, __value, __comp);
return __first != __last && !__comp(__value, *__first);
} }
template <class _ForwardIterator, class _Tp> template <class _ForwardIterator, class _Tp>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
bool return std::binary_search(__first, __last, __value, __less<>());
binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value)
{
return std::binary_search(__first, __last, __value, __less<>());
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -20,24 +20,22 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 17 #if _LIBCPP_STD_VER >= 17
template<class _Tp, class _Compare> template <class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&
_LIBCPP_INLINE_VISIBILITY constexpr clamp(_LIBCPP_LIFETIMEBOUND const _Tp& __v,
const _Tp& _LIBCPP_LIFETIMEBOUND const _Tp& __lo,
clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp) _LIBCPP_LIFETIMEBOUND const _Tp& __hi,
{ _Compare __comp) {
_LIBCPP_ASSERT_UNCATEGORIZED(!__comp(__hi, __lo), "Bad bounds passed to std::clamp"); _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(!__comp(__hi, __lo), "Bad bounds passed to std::clamp");
return __comp(__v, __lo) ? __lo : __comp(__hi, __v) ? __hi : __v; return __comp(__v, __lo) ? __lo : __comp(__hi, __v) ? __hi : __v;
} }
template<class _Tp> template <class _Tp>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&
_LIBCPP_INLINE_VISIBILITY constexpr clamp(_LIBCPP_LIFETIMEBOUND const _Tp& __v,
const _Tp& _LIBCPP_LIFETIMEBOUND const _Tp& __lo,
clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi) _LIBCPP_LIFETIMEBOUND const _Tp& __hi) {
{ return std::clamp(__v, __lo, __hi, __less<>());
return _VSTD::clamp(__v, __lo, __hi, __less<>());
} }
#endif #endif

View File

@ -11,7 +11,7 @@
#include <__config> #include <__config>
#include <__type_traits/integral_constant.h> #include <__type_traits/integral_constant.h>
#include <__type_traits/predicate_traits.h> #include <__type_traits/operation_traits.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@ -26,8 +26,8 @@ struct __equal_to {
} }
}; };
template <class _Lhs, class _Rhs> template <class _Tp, class _Up>
struct __is_trivial_equality_predicate<__equal_to, _Lhs, _Rhs> : true_type {}; struct __desugars_to<__equal_tag, __equal_to, _Tp, _Up> : true_type {};
// The definition is required because __less is part of the ABI, but it's empty // The definition is required because __less is part of the ABI, but it's empty
// because all comparisons should be transparent. // because all comparisons should be transparent.

View File

@ -20,52 +20,41 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Compare> template <class _Compare>
struct __debug_less struct __debug_less {
{ _Compare& __comp_;
_Compare &__comp_; _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI __debug_less(_Compare& __c) : __comp_(__c) {}
_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI __debug_less(_Compare& __c) : __comp_(__c) {}
template <class _Tp, class _Up> template <class _Tp, class _Up>
_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x, const _Up& __y) {
bool operator()(const _Tp& __x, const _Up& __y) bool __r = __comp_(__x, __y);
{ if (__r)
bool __r = __comp_(__x, __y); __do_compare_assert(0, __y, __x);
if (__r) return __r;
__do_compare_assert(0, __y, __x); }
return __r;
}
template <class _Tp, class _Up> template <class _Tp, class _Up>
_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool operator()(_Tp& __x, _Up& __y) {
bool operator()(_Tp& __x, _Up& __y) bool __r = __comp_(__x, __y);
{ if (__r)
bool __r = __comp_(__x, __y); __do_compare_assert(0, __y, __x);
if (__r) return __r;
__do_compare_assert(0, __y, __x); }
return __r;
}
template <class _LHS, class _RHS> template <class _LHS, class _RHS>
_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_CONSTEXPR_SINCE_CXX14 inline _LIBCPP_HIDE_FROM_ABI decltype((void)std::declval<_Compare&>()(
inline _LIBCPP_INLINE_VISIBILITY std::declval<_LHS&>(), std::declval<_RHS&>()))
decltype((void)std::declval<_Compare&>()( __do_compare_assert(int, _LHS& __l, _RHS& __r) {
std::declval<_LHS &>(), std::declval<_RHS &>())) _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(!__comp_(__l, __r), "Comparator does not induce a strict weak ordering");
__do_compare_assert(int, _LHS & __l, _RHS & __r) { (void)__l;
_LIBCPP_ASSERT_UNCATEGORIZED(!__comp_(__l, __r), (void)__r;
"Comparator does not induce a strict weak ordering"); }
(void)__l;
(void)__r;
}
template <class _LHS, class _RHS> template <class _LHS, class _RHS>
_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_CONSTEXPR_SINCE_CXX14 inline _LIBCPP_HIDE_FROM_ABI void __do_compare_assert(long, _LHS&, _RHS&) {}
inline _LIBCPP_INLINE_VISIBILITY
void __do_compare_assert(long, _LHS &, _RHS &) {}
}; };
// Pass the comparator by lvalue reference. Or in debug mode, using a // Pass the comparator by lvalue reference. Or in the debug mode, using a debugging wrapper that stores a reference.
// debugging wrapper that stores a reference. #if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
#if _LIBCPP_ENABLE_DEBUG_MODE
template <class _Comp> template <class _Comp>
using __comp_ref_type = __debug_less<_Comp>; using __comp_ref_type = __debug_less<_Comp>;
#else #else

View File

@ -51,9 +51,10 @@ struct __copy_loop {
_OutIter& __result_; _OutIter& __result_;
_LIBCPP_HIDE_FROM_ABI _CopySegment(_OutIter& __result) : __result_(__result) {} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit _CopySegment(_OutIter& __result)
: __result_(__result) {}
_LIBCPP_HIDE_FROM_ABI void _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
operator()(typename _Traits::__local_iterator __lfirst, typename _Traits::__local_iterator __llast) { operator()(typename _Traits::__local_iterator __lfirst, typename _Traits::__local_iterator __llast) {
__result_ = std::__copy<_AlgPolicy>(__lfirst, __llast, std::move(__result_)).second; __result_ = std::__copy<_AlgPolicy>(__lfirst, __llast, std::move(__result_)).second;
} }
@ -112,7 +113,7 @@ __copy(_InIter __first, _Sent __last, _OutIter __result) {
} }
template <class _InputIterator, class _OutputIterator> template <class _InputIterator, class _OutputIterator>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
return std::__copy<_ClassicAlgPolicy>(__first, __last, __result).second; return std::__copy<_ClassicAlgPolicy>(__first, __last, __result).second;
} }

View File

@ -108,8 +108,7 @@ struct __copy_backward_loop {
struct __copy_backward_trivial { struct __copy_backward_trivial {
// At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
template <class _In, class _Out, template <class _In, class _Out, __enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0>
__enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
operator()(_In* __first, _In* __last, _Out* __result) const { operator()(_In* __first, _In* __last, _Out* __result) const {
return std::__copy_backward_trivial_impl(__first, __last, __result); return std::__copy_backward_trivial_impl(__first, __last, __result);
@ -124,16 +123,13 @@ __copy_backward(_BidirectionalIterator1 __first, _Sentinel __last, _Bidirectiona
} }
template <class _BidirectionalIterator1, class _BidirectionalIterator2> template <class _BidirectionalIterator1, class _BidirectionalIterator2>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _BidirectionalIterator2
_BidirectionalIterator2 copy_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _BidirectionalIterator2 __result) {
copy_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last,
_BidirectionalIterator2 __result)
{
static_assert(std::is_copy_constructible<_BidirectionalIterator1>::value && static_assert(std::is_copy_constructible<_BidirectionalIterator1>::value &&
std::is_copy_constructible<_BidirectionalIterator1>::value, "Iterators must be copy constructible."); std::is_copy_constructible<_BidirectionalIterator1>::value,
"Iterators must be copy constructible.");
return std::__copy_backward<_ClassicAlgPolicy>( return std::__copy_backward<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)).second;
std::move(__first), std::move(__last), std::move(__result)).second;
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -17,21 +17,16 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template<class _InputIterator, class _OutputIterator, class _Predicate> template <class _InputIterator, class _OutputIterator, class _Predicate>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
_OutputIterator copy_if(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _Predicate __pred) {
copy_if(_InputIterator __first, _InputIterator __last, for (; __first != __last; ++__first) {
_OutputIterator __result, _Predicate __pred) if (__pred(*__first)) {
{ *__result = *__first;
for (; __first != __last; ++__first) ++__result;
{
if (__pred(*__first))
{
*__result = *__first;
++__result;
}
} }
return __result; }
return __result;
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -31,6 +31,9 @@
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
// Type traits. // Type traits.
@ -38,22 +41,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _From, class _To> template <class _From, class _To>
struct __can_lower_copy_assignment_to_memmove { struct __can_lower_copy_assignment_to_memmove {
static const bool value = static const bool value =
// If the types are always bitcastable, it's valid to do a bitwise copy between them. // If the types are always bitcastable, it's valid to do a bitwise copy between them.
__is_always_bitcastable<_From, _To>::value && __is_always_bitcastable<_From, _To>::value &&
// Reject conversions that wouldn't be performed by the regular built-in assignment (e.g. between arrays). // Reject conversions that wouldn't be performed by the regular built-in assignment (e.g. between arrays).
is_trivially_assignable<_To&, const _From&>::value && is_trivially_assignable<_To&, const _From&>::value &&
// `memmove` doesn't accept `volatile` pointers, make sure the optimization SFINAEs away in that case. // `memmove` doesn't accept `volatile` pointers, make sure the optimization SFINAEs away in that case.
!is_volatile<_From>::value && !is_volatile<_From>::value && !is_volatile<_To>::value;
!is_volatile<_To>::value;
}; };
template <class _From, class _To> template <class _From, class _To>
struct __can_lower_move_assignment_to_memmove { struct __can_lower_move_assignment_to_memmove {
static const bool value = static const bool value =
__is_always_bitcastable<_From, _To>::value && __is_always_bitcastable<_From, _To>::value && is_trivially_assignable<_To&, _From&&>::value &&
is_trivially_assignable<_To&, _From&&>::value && !is_volatile<_From>::value && !is_volatile<_To>::value;
!is_volatile<_From>::value &&
!is_volatile<_To>::value;
}; };
// `memmove` algorithms implementation. // `memmove` algorithms implementation.
@ -95,8 +95,8 @@ struct __can_rewrap<_InIter,
_Sent, _Sent,
_OutIter, _OutIter,
// Note that sentinels are always copy-constructible. // Note that sentinels are always copy-constructible.
__enable_if_t< is_copy_constructible<_InIter>::value && __enable_if_t< is_copy_constructible<_InIter>::value && is_copy_constructible<_OutIter>::value > >
is_copy_constructible<_OutIter>::value > > : true_type {}; : true_type {};
template <class _Algorithm, template <class _Algorithm,
class _InIter, class _InIter,
@ -108,7 +108,7 @@ __unwrap_and_dispatch(_InIter __first, _Sent __last, _OutIter __out_first) {
auto __range = std::__unwrap_range(__first, std::move(__last)); auto __range = std::__unwrap_range(__first, std::move(__last));
auto __result = _Algorithm()(std::move(__range.first), std::move(__range.second), std::__unwrap_iter(__out_first)); auto __result = _Algorithm()(std::move(__range.first), std::move(__range.second), std::__unwrap_iter(__out_first));
return std::make_pair(std::__rewrap_range<_Sent>(std::move(__first), std::move(__result.first)), return std::make_pair(std::__rewrap_range<_Sent>(std::move(__first), std::move(__result.first)),
std::__rewrap_iter(std::move(__out_first), std::move(__result.second))); std::__rewrap_iter(std::move(__out_first), std::move(__result.second)));
} }
template <class _Algorithm, template <class _Algorithm,
@ -135,4 +135,6 @@ __dispatch_copy_or_move(_InIter __first, _Sent __last, _OutIter __out_first) {
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_COPY_MOVE_COMMON_H #endif // _LIBCPP___ALGORITHM_COPY_MOVE_COMMON_H

View File

@ -21,45 +21,38 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template<class _InputIterator, class _Size, class _OutputIterator> template <class _InputIterator,
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 class _Size,
typename enable_if class _OutputIterator,
< __enable_if_t<__has_input_iterator_category<_InputIterator>::value &&
__has_input_iterator_category<_InputIterator>::value && !__has_random_access_iterator_category<_InputIterator>::value,
!__has_random_access_iterator_category<_InputIterator>::value, int> = 0>
_OutputIterator inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
>::type copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) {
copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize;
{ _IntegralSize __n = __orig_n;
typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; if (__n > 0) {
_IntegralSize __n = __orig_n; *__result = *__first;
if (__n > 0) ++__result;
{ for (--__n; __n > 0; --__n) {
*__result = *__first; ++__first;
++__result; *__result = *__first;
for (--__n; __n > 0; --__n) ++__result;
{
++__first;
*__result = *__first;
++__result;
}
} }
return __result; }
return __result;
} }
template<class _InputIterator, class _Size, class _OutputIterator> template <class _InputIterator,
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 class _Size,
typename enable_if class _OutputIterator,
< __enable_if_t<__has_random_access_iterator_category<_InputIterator>::value, int> = 0>
__has_random_access_iterator_category<_InputIterator>::value, inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
_OutputIterator copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) {
>::type typedef typename iterator_traits<_InputIterator>::difference_type difference_type;
copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize;
{ _IntegralSize __n = __orig_n;
typedef typename iterator_traits<_InputIterator>::difference_type difference_type; return std::copy(__first, __first + difference_type(__n), __result);
typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize;
_IntegralSize __n = __orig_n;
return _VSTD::copy(__first, __first + difference_type(__n), __result);
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -10,26 +10,83 @@
#ifndef _LIBCPP___ALGORITHM_COUNT_H #ifndef _LIBCPP___ALGORITHM_COUNT_H
#define _LIBCPP___ALGORITHM_COUNT_H #define _LIBCPP___ALGORITHM_COUNT_H
#include <__algorithm/iterator_operations.h>
#include <__algorithm/min.h>
#include <__bit/invert_if.h>
#include <__bit/popcount.h>
#include <__config> #include <__config>
#include <__functional/identity.h>
#include <__functional/invoke.h>
#include <__fwd/bit_reference.h>
#include <__iterator/iterator_traits.h> #include <__iterator/iterator_traits.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Tp> // generic implementation
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 template <class _AlgPolicy, class _Iter, class _Sent, class _Tp, class _Proj>
typename iterator_traits<_InputIterator>::difference_type _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename _IterOps<_AlgPolicy>::template __difference_type<_Iter>
count(_InputIterator __first, _InputIterator __last, const _Tp& __value) { __count(_Iter __first, _Sent __last, const _Tp& __value, _Proj& __proj) {
typename iterator_traits<_InputIterator>::difference_type __r(0); typename _IterOps<_AlgPolicy>::template __difference_type<_Iter> __r(0);
for (; __first != __last; ++__first) for (; __first != __last; ++__first)
if (*__first == __value) if (std::__invoke(__proj, *__first) == __value)
++__r; ++__r;
return __r; return __r;
} }
// __bit_iterator implementation
template <bool _ToCount, class _Cp, bool _IsConst>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __bit_iterator<_Cp, _IsConst>::difference_type
__count_bool(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n) {
using _It = __bit_iterator<_Cp, _IsConst>;
using __storage_type = typename _It::__storage_type;
using difference_type = typename _It::difference_type;
const int __bits_per_word = _It::__bits_per_word;
difference_type __r = 0;
// do first partial word
if (__first.__ctz_ != 0) {
__storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
__storage_type __dn = std::min(__clz_f, __n);
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
__r = std::__libcpp_popcount(std::__invert_if<!_ToCount>(*__first.__seg_) & __m);
__n -= __dn;
++__first.__seg_;
}
// do middle whole words
for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word)
__r += std::__libcpp_popcount(std::__invert_if<!_ToCount>(*__first.__seg_));
// do last partial word
if (__n > 0) {
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
__r += std::__libcpp_popcount(std::__invert_if<!_ToCount>(*__first.__seg_) & __m);
}
return __r;
}
template <class, class _Cp, bool _IsConst, class _Tp, class _Proj, __enable_if_t<__is_identity<_Proj>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __iter_diff_t<__bit_iterator<_Cp, _IsConst> >
__count(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, const _Tp& __value, _Proj&) {
if (__value)
return std::__count_bool<true>(__first, static_cast<typename _Cp::size_type>(__last - __first));
return std::__count_bool<false>(__first, static_cast<typename _Cp::size_type>(__last - __first));
}
template <class _InputIterator, class _Tp>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __iter_diff_t<_InputIterator>
count(_InputIterator __first, _InputIterator __last, const _Tp& __value) {
__identity __proj;
return std::__count<_ClassicAlgPolicy>(__first, __last, __value, __proj);
}
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_COUNT_H #endif // _LIBCPP___ALGORITHM_COUNT_H

View File

@ -20,7 +20,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Predicate> template <class _InputIterator, class _Predicate>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
typename iterator_traits<_InputIterator>::difference_type typename iterator_traits<_InputIterator>::difference_type
count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) { count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
typename iterator_traits<_InputIterator>::difference_type __r(0); typename iterator_traits<_InputIterator>::difference_type __r(0);

View File

@ -23,13 +23,16 @@
#include <__type_traits/is_constant_evaluated.h> #include <__type_traits/is_constant_evaluated.h>
#include <__type_traits/is_equality_comparable.h> #include <__type_traits/is_equality_comparable.h>
#include <__type_traits/is_volatile.h> #include <__type_traits/is_volatile.h>
#include <__type_traits/predicate_traits.h> #include <__type_traits/operation_traits.h>
#include <__utility/move.h> #include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate>
@ -41,13 +44,12 @@ _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 boo
return true; return true;
} }
template < template <class _Tp,
class _Tp, class _Up,
class _Up, class _BinaryPredicate,
class _BinaryPredicate, __enable_if_t<__desugars_to<__equal_tag, _BinaryPredicate, _Tp, _Up>::value && !is_volatile<_Tp>::value &&
__enable_if_t<__is_trivial_equality_predicate<_BinaryPredicate, _Tp, _Up>::value && !is_volatile<_Tp>::value && !is_volatile<_Up>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
!is_volatile<_Up>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value, int> = 0>
int> = 0>
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
__equal_iter_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _BinaryPredicate&) { __equal_iter_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _BinaryPredicate&) {
return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1)); return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1));
@ -69,8 +71,13 @@ equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first
#if _LIBCPP_STD_VER >= 14 #if _LIBCPP_STD_VER >= 14
template <class _BinaryPredicate, class _InputIterator1, class _InputIterator2> template <class _BinaryPredicate, class _InputIterator1, class _InputIterator2>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
__equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, __equal(_InputIterator1 __first1,
_BinaryPredicate __pred, input_iterator_tag, input_iterator_tag) { _InputIterator1 __last1,
_InputIterator2 __first2,
_InputIterator2 __last2,
_BinaryPredicate __pred,
input_iterator_tag,
input_iterator_tag) {
for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2) for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2)
if (!__pred(*__first1, *__first2)) if (!__pred(*__first1, *__first2))
return false; return false;
@ -94,21 +101,25 @@ template <class _Tp,
class _Pred, class _Pred,
class _Proj1, class _Proj1,
class _Proj2, class _Proj2,
__enable_if_t<__is_trivial_equality_predicate<_Pred, _Tp, _Up>::value && __is_identity<_Proj1>::value && __enable_if_t<__desugars_to<__equal_tag, _Pred, _Tp, _Up>::value && __is_identity<_Proj1>::value &&
__is_identity<_Proj2>::value && !is_volatile<_Tp>::value && !is_volatile<_Up>::value && __is_identity<_Proj2>::value && !is_volatile<_Tp>::value && !is_volatile<_Up>::value &&
__libcpp_is_trivially_equality_comparable<_Tp, _Up>::value, __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
int> = 0> int> = 0>
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl( _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, _Proj2&) { __equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, _Proj2&) {
return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1)); return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1));
} }
template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2> template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
__equal(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, __equal(_RandomAccessIterator1 __first1,
_RandomAccessIterator2 __last2, _BinaryPredicate __pred, random_access_iterator_tag, _RandomAccessIterator1 __last1,
_RandomAccessIterator2 __first2,
_RandomAccessIterator2 __last2,
_BinaryPredicate __pred,
random_access_iterator_tag,
random_access_iterator_tag) { random_access_iterator_tag) {
if (_VSTD::distance(__first1, __last1) != _VSTD::distance(__first2, __last2)) if (std::distance(__first1, __last1) != std::distance(__first2, __last2))
return false; return false;
__identity __proj; __identity __proj;
return std::__equal_impl( return std::__equal_impl(
@ -123,10 +134,18 @@ __equal(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _Random
template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, equal(_InputIterator1 __first1,
_InputIterator1 __last1,
_InputIterator2 __first2,
_InputIterator2 __last2,
_BinaryPredicate __pred) { _BinaryPredicate __pred) {
return _VSTD::__equal<_BinaryPredicate&>( return std::__equal<_BinaryPredicate&>(
__first1, __last1, __first2, __last2, __pred, typename iterator_traits<_InputIterator1>::iterator_category(), __first1,
__last1,
__first2,
__last2,
__pred,
typename iterator_traits<_InputIterator1>::iterator_category(),
typename iterator_traits<_InputIterator2>::iterator_category()); typename iterator_traits<_InputIterator2>::iterator_category());
} }
@ -146,4 +165,6 @@ equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_EQUAL_H #endif // _LIBCPP___ALGORITHM_EQUAL_H

View File

@ -31,6 +31,9 @@
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _Iter, class _Sent, class _Tp, class _Proj> template <class _AlgPolicy, class _Compare, class _Iter, class _Sent, class _Tp, class _Proj>
@ -49,9 +52,8 @@ __equal_range(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp
__len = __half_len; __len = __half_len;
} else { } else {
_Iter __mp1 = __mid; _Iter __mp1 = __mid;
return pair<_Iter, _Iter>( return pair<_Iter, _Iter>(std::__lower_bound<_AlgPolicy>(__first, __mid, __value, __comp, __proj),
std::__lower_bound<_AlgPolicy>(__first, __mid, __value, __comp, __proj), std::__upper_bound<_AlgPolicy>(++__mp1, __end, __value, __comp, __proj));
std::__upper_bound<_AlgPolicy>(++__mp1, __end, __value, __comp, __proj));
} }
} }
return pair<_Iter, _Iter>(__first, __first); return pair<_Iter, _Iter>(__first, __first);
@ -60,10 +62,8 @@ __equal_range(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp
template <class _ForwardIterator, class _Tp, class _Compare> template <class _ForwardIterator, class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator>
equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) {
static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
"The comparator has to be callable"); static_assert(is_copy_constructible<_ForwardIterator>::value, "Iterator has to be copy constructible");
static_assert(is_copy_constructible<_ForwardIterator>::value,
"Iterator has to be copy constructible");
return std::__equal_range<_ClassicAlgPolicy>( return std::__equal_range<_ClassicAlgPolicy>(
std::move(__first), std::move(__first),
std::move(__last), std::move(__last),
@ -80,4 +80,6 @@ equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_EQUAL_RANGE_H #endif // _LIBCPP___ALGORITHM_EQUAL_RANGE_H

View File

@ -22,28 +22,22 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// fill isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset. // fill isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset.
template <class _ForwardIterator, class _Tp> template <class _ForwardIterator, class _Tp>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
void __fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, forward_iterator_tag) {
__fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, forward_iterator_tag) for (; __first != __last; ++__first)
{ *__first = __value;
for (; __first != __last; ++__first)
*__first = __value;
} }
template <class _RandomAccessIterator, class _Tp> template <class _RandomAccessIterator, class _Tp>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
void __fill(_RandomAccessIterator __first, _RandomAccessIterator __last, const _Tp& __value, random_access_iterator_tag) {
__fill(_RandomAccessIterator __first, _RandomAccessIterator __last, const _Tp& __value, random_access_iterator_tag) std::fill_n(__first, __last - __first, __value);
{
_VSTD::fill_n(__first, __last - __first, __value);
} }
template <class _ForwardIterator, class _Tp> template <class _ForwardIterator, class _Tp>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
void fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) std::__fill(__first, __last, __value, typename iterator_traits<_ForwardIterator>::iterator_category());
{
_VSTD::__fill(__first, __last, __value, typename iterator_traits<_ForwardIterator>::iterator_category());
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -22,21 +22,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// fill_n isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset. // fill_n isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset.
template <class _OutputIterator, class _Size, class _Tp> template <class _OutputIterator, class _Size, class _Tp>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
_OutputIterator __fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) {
__fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) for (; __n > 0; ++__first, (void)--__n)
{ *__first = __value;
for (; __n > 0; ++__first, (void) --__n) return __first;
*__first = __value;
return __first;
} }
template <class _OutputIterator, class _Size, class _Tp> template <class _OutputIterator, class _Size, class _Tp>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
_OutputIterator fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) {
fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) return std::__fill_n(__first, std::__convert_to_integral(__n), __value);
{
return _VSTD::__fill_n(__first, _VSTD::__convert_to_integral(__n), __value);
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -10,12 +10,22 @@
#ifndef _LIBCPP___ALGORITHM_FIND_H #ifndef _LIBCPP___ALGORITHM_FIND_H
#define _LIBCPP___ALGORITHM_FIND_H #define _LIBCPP___ALGORITHM_FIND_H
#include <__algorithm/find_segment_if.h>
#include <__algorithm/min.h>
#include <__algorithm/unwrap_iter.h> #include <__algorithm/unwrap_iter.h>
#include <__bit/countr.h>
#include <__bit/invert_if.h>
#include <__config> #include <__config>
#include <__functional/identity.h> #include <__functional/identity.h>
#include <__functional/invoke.h> #include <__functional/invoke.h>
#include <__fwd/bit_reference.h>
#include <__iterator/segmented_iterator.h>
#include <__string/constexpr_c_functions.h> #include <__string/constexpr_c_functions.h>
#include <__type_traits/is_integral.h>
#include <__type_traits/is_same.h> #include <__type_traits/is_same.h>
#include <__type_traits/is_signed.h>
#include <__utility/move.h>
#include <limits>
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
# include <cwchar> # include <cwchar>
@ -25,8 +35,12 @@
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
// generic implementation
template <class _Iter, class _Sent, class _Tp, class _Proj> template <class _Iter, class _Sent, class _Tp, class _Proj>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter
__find_impl(_Iter __first, _Sent __last, const _Tp& __value, _Proj& __proj) { __find_impl(_Iter __first, _Sent __last, const _Tp& __value, _Proj& __proj) {
@ -36,6 +50,7 @@ __find_impl(_Iter __first, _Sent __last, const _Tp& __value, _Proj& __proj) {
return __first; return __first;
} }
// trivially equality comparable implementations
template <class _Tp, template <class _Tp,
class _Up, class _Up,
class _Proj, class _Proj,
@ -64,8 +79,97 @@ __find_impl(_Tp* __first, _Tp* __last, const _Up& __value, _Proj&) {
} }
#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
// TODO: This should also be possible to get right with different signedness
// cast integral types to allow vectorization
template <class _Tp,
class _Up,
class _Proj,
__enable_if_t<__is_identity<_Proj>::value && !__libcpp_is_trivially_equality_comparable<_Tp, _Up>::value &&
is_integral<_Tp>::value && is_integral<_Up>::value &&
is_signed<_Tp>::value == is_signed<_Up>::value,
int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp*
__find_impl(_Tp* __first, _Tp* __last, const _Up& __value, _Proj& __proj) {
if (__value < numeric_limits<_Tp>::min() || __value > numeric_limits<_Tp>::max())
return __last;
return std::__find_impl(__first, __last, _Tp(__value), __proj);
}
// __bit_iterator implementation
template <bool _ToFind, class _Cp, bool _IsConst>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, _IsConst>
__find_bool(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n) {
using _It = __bit_iterator<_Cp, _IsConst>;
using __storage_type = typename _It::__storage_type;
const int __bits_per_word = _It::__bits_per_word;
// do first partial word
if (__first.__ctz_ != 0) {
__storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
__storage_type __dn = std::min(__clz_f, __n);
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
__storage_type __b = std::__invert_if<!_ToFind>(*__first.__seg_) & __m;
if (__b)
return _It(__first.__seg_, static_cast<unsigned>(std::__libcpp_ctz(__b)));
if (__n == __dn)
return __first + __n;
__n -= __dn;
++__first.__seg_;
}
// do middle whole words
for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word) {
__storage_type __b = std::__invert_if<!_ToFind>(*__first.__seg_);
if (__b)
return _It(__first.__seg_, static_cast<unsigned>(std::__libcpp_ctz(__b)));
}
// do last partial word
if (__n > 0) {
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
__storage_type __b = std::__invert_if<!_ToFind>(*__first.__seg_) & __m;
if (__b)
return _It(__first.__seg_, static_cast<unsigned>(std::__libcpp_ctz(__b)));
}
return _It(__first.__seg_, static_cast<unsigned>(__n));
}
template <class _Cp, bool _IsConst, class _Tp, class _Proj, __enable_if_t<__is_identity<_Proj>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, _IsConst>
__find_impl(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, const _Tp& __value, _Proj&) {
if (static_cast<bool>(__value))
return std::__find_bool<true>(__first, static_cast<typename _Cp::size_type>(__last - __first));
return std::__find_bool<false>(__first, static_cast<typename _Cp::size_type>(__last - __first));
}
// segmented iterator implementation
template <class>
struct __find_segment;
template <class _SegmentedIterator,
class _Tp,
class _Proj,
__enable_if_t<__is_segmented_iterator<_SegmentedIterator>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _SegmentedIterator
__find_impl(_SegmentedIterator __first, _SegmentedIterator __last, const _Tp& __value, _Proj& __proj) {
return std::__find_segment_if(std::move(__first), std::move(__last), __find_segment<_Tp>(__value), __proj);
}
template <class _Tp>
struct __find_segment {
const _Tp& __value_;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __find_segment(const _Tp& __value) : __value_(__value) {}
template <class _InputIterator, class _Proj>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _InputIterator
operator()(_InputIterator __first, _InputIterator __last, _Proj& __proj) const {
return std::__find_impl(__first, __last, __value_, __proj);
}
};
// public API
template <class _InputIterator, class _Tp> template <class _InputIterator, class _Tp>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
find(_InputIterator __first, _InputIterator __last, const _Tp& __value) { find(_InputIterator __first, _InputIterator __last, const _Tp& __value) {
__identity __proj; __identity __proj;
return std::__rewrap_iter( return std::__rewrap_iter(
@ -74,4 +178,6 @@ find(_InputIterator __first, _InputIterator __last, const _Tp& __value) {
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_FIND_H #endif // _LIBCPP___ALGORITHM_FIND_H

View File

@ -28,15 +28,14 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template < template < class _AlgPolicy,
class _AlgPolicy, class _Iter1,
class _Iter1, class _Sent1,
class _Sent1, class _Iter2,
class _Iter2, class _Sent2,
class _Sent2, class _Pred,
class _Pred, class _Proj1,
class _Proj1, class _Proj2>
class _Proj2>
_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1> __find_end_impl( _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1> __find_end_impl(
_Iter1 __first1, _Iter1 __first1,
_Sent1 __last1, _Sent1 __last1,
@ -49,7 +48,7 @@ _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1>
forward_iterator_tag) { forward_iterator_tag) {
// modeled after search algorithm // modeled after search algorithm
_Iter1 __match_first = _IterOps<_AlgPolicy>::next(__first1, __last1); // __last1 is the "default" answer _Iter1 __match_first = _IterOps<_AlgPolicy>::next(__first1, __last1); // __last1 is the "default" answer
_Iter1 __match_last = __match_first; _Iter1 __match_last = __match_first;
if (__first2 == __last2) if (__first2 == __last2)
return pair<_Iter1, _Iter1>(__match_last, __match_last); return pair<_Iter1, _Iter1>(__match_last, __match_last);
while (true) { while (true) {
@ -66,15 +65,14 @@ _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1>
while (true) { while (true) {
if (++__m2 == __last2) { // Pattern exhaused, record answer and search for another one if (++__m2 == __last2) { // Pattern exhaused, record answer and search for another one
__match_first = __first1; __match_first = __first1;
__match_last = ++__m1; __match_last = ++__m1;
++__first1; ++__first1;
break; break;
} }
if (++__m1 == __last1) // Source exhausted, return last answer if (++__m1 == __last1) // Source exhausted, return last answer
return pair<_Iter1, _Iter1>(__match_first, __match_last); return pair<_Iter1, _Iter1>(__match_first, __match_last);
// mismatch, restart with a new __first // mismatch, restart with a new __first
if (!std::__invoke(__pred, std::__invoke(__proj1, *__m1), std::__invoke(__proj2, *__m2))) if (!std::__invoke(__pred, std::__invoke(__proj1, *__m1), std::__invoke(__proj2, *__m2))) {
{
++__first1; ++__first1;
break; break;
} // else there is a match, check next elements } // else there is a match, check next elements
@ -82,15 +80,14 @@ _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1>
} }
} }
template < template < class _IterOps,
class _IterOps, class _Pred,
class _Pred, class _Iter1,
class _Iter1, class _Sent1,
class _Sent1, class _Iter2,
class _Iter2, class _Sent2,
class _Sent2, class _Proj1,
class _Proj1, class _Proj2>
class _Proj2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter1 __find_end( _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter1 __find_end(
_Iter1 __first1, _Iter1 __first1,
_Sent1 __sent1, _Sent1 __sent1,
@ -127,23 +124,21 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter1 __find_end(
return __last1; return __last1;
// if there is a mismatch, restart with a new __l1 // if there is a mismatch, restart with a new __l1
if (!std::__invoke(__pred, std::__invoke(__proj1, *--__m1), std::__invoke(__proj2, *--__m2))) if (!std::__invoke(__pred, std::__invoke(__proj1, *--__m1), std::__invoke(__proj2, *--__m2))) {
{
break; break;
} // else there is a match, check next elements } // else there is a match, check next elements
} }
} }
} }
template < template < class _AlgPolicy,
class _AlgPolicy, class _Pred,
class _Pred, class _Iter1,
class _Iter1, class _Sent1,
class _Sent1, class _Iter2,
class _Iter2, class _Sent2,
class _Sent2, class _Proj1,
class _Proj1, class _Proj2>
class _Proj2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter1 __find_end( _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter1 __find_end(
_Iter1 __first1, _Iter1 __first1,
_Sent1 __sent1, _Sent1 __sent1,
@ -165,8 +160,8 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter1 __find_end(
if (__len1 < __len2) if (__len1 < __len2)
return __last1; return __last1;
const _Iter1 __s = __first1 + _D1(__len2 - 1); // End of pattern match can't go before here const _Iter1 __s = __first1 + _D1(__len2 - 1); // End of pattern match can't go before here
_Iter1 __l1 = __last1; _Iter1 __l1 = __last1;
_Iter2 __l2 = __last2; _Iter2 __l2 = __last2;
--__l2; --__l2;
while (true) { while (true) {
while (true) { while (true) {
@ -189,10 +184,12 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter1 __find_end(
} }
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator1 __find_end_classic(
_ForwardIterator1 __find_end_classic(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator1 __first1,
_ForwardIterator2 __first2, _ForwardIterator2 __last2, _ForwardIterator1 __last1,
_BinaryPredicate& __pred) { _ForwardIterator2 __first2,
_ForwardIterator2 __last2,
_BinaryPredicate& __pred) {
auto __proj = __identity(); auto __proj = __identity();
return std::__find_end_impl<_ClassicAlgPolicy>( return std::__find_end_impl<_ClassicAlgPolicy>(
__first1, __first1,
@ -208,17 +205,18 @@ _ForwardIterator1 __find_end_classic(_ForwardIterator1 __first1, _ForwardIterato
} }
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_end(
_ForwardIterator1 find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator1 __first1,
_ForwardIterator2 __first2, _ForwardIterator2 __last2, _ForwardIterator1 __last1,
_BinaryPredicate __pred) { _ForwardIterator2 __first2,
_ForwardIterator2 __last2,
_BinaryPredicate __pred) {
return std::__find_end_classic(__first1, __last1, __first2, __last2, __pred); return std::__find_end_classic(__first1, __last1, __first2, __last2, __pred);
} }
template <class _ForwardIterator1, class _ForwardIterator2> template <class _ForwardIterator1, class _ForwardIterator2>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1
_ForwardIterator1 find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) {
_ForwardIterator2 __first2, _ForwardIterator2 __last2) {
return std::find_end(__first1, __last1, __first2, __last2, __equal_to()); return std::find_end(__first1, __last1, __first2, __last2, __equal_to());
} }

View File

@ -21,12 +21,12 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator1 __find_first_of_ce(
_LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator1 __find_first_of_ce(_ForwardIterator1 __first1, _ForwardIterator1 __first1,
_ForwardIterator1 __last1, _ForwardIterator1 __last1,
_ForwardIterator2 __first2, _ForwardIterator2 __first2,
_ForwardIterator2 __last2, _ForwardIterator2 __last2,
_BinaryPredicate&& __pred) { _BinaryPredicate&& __pred) {
for (; __first1 != __last1; ++__first1) for (; __first1 != __last1; ++__first1)
for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j) for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j)
if (__pred(*__first1, *__j)) if (__pred(*__first1, *__j))
@ -35,14 +35,17 @@ _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator1 __find_first_of_ce(_ForwardItera
} }
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of(
find_first_of(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator1 __first1,
_ForwardIterator2 __last2, _BinaryPredicate __pred) { _ForwardIterator1 __last1,
return _VSTD::__find_first_of_ce(__first1, __last1, __first2, __last2, __pred); _ForwardIterator2 __first2,
_ForwardIterator2 __last2,
_BinaryPredicate __pred) {
return std::__find_first_of_ce(__first1, __last1, __first2, __last2, __pred);
} }
template <class _ForwardIterator1, class _ForwardIterator2> template <class _ForwardIterator1, class _ForwardIterator2>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of( _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of(
_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) {
return std::__find_first_of_ce(__first1, __last1, __first2, __last2, __equal_to()); return std::__find_first_of_ce(__first1, __last1, __first2, __last2, __equal_to());
} }

View File

@ -19,7 +19,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Predicate> template <class _InputIterator, class _Predicate>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
find_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) { find_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
for (; __first != __last; ++__first) for (; __first != __last; ++__first)
if (__pred(*__first)) if (__pred(*__first))

View File

@ -19,7 +19,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Predicate> template <class _InputIterator, class _Predicate>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred) { find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
for (; __first != __last; ++__first) for (; __first != __last; ++__first)
if (!__pred(*__first)) if (!__pred(*__first))

View File

@ -0,0 +1,62 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___ALGORITHM_FIND_SEGMENT_IF_H
#define _LIBCPP___ALGORITHM_FIND_SEGMENT_IF_H
#include <__config>
#include <__iterator/segmented_iterator.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
// __find_segment_if is a utility function for optimizing iteration over segmented iterators linearly.
// [__first, __last) has to be a segmented range. __pred is expected to take a range of local iterators and the __proj.
// It returns an iterator to the first element that satisfies the predicate, or a one-past-the-end iterator if there was
// no match. __proj may be anything that should be passed to __pred, but is expected to be a projection to support
// ranges algorithms, or __identity for classic algorithms.
template <class _SegmentedIterator, class _Pred, class _Proj>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _SegmentedIterator
__find_segment_if(_SegmentedIterator __first, _SegmentedIterator __last, _Pred __pred, _Proj& __proj) {
using _Traits = __segmented_iterator_traits<_SegmentedIterator>;
auto __sfirst = _Traits::__segment(__first);
auto __slast = _Traits::__segment(__last);
// We are in a single segment, so we might not be at the beginning or end
if (__sfirst == __slast)
return _Traits::__compose(__sfirst, __pred(_Traits::__local(__first), _Traits::__local(__last), __proj));
{ // We have more than one segment. Iterate over the first segment, since we might not start at the beginning
auto __llast = _Traits::__end(__sfirst);
auto __liter = __pred(_Traits::__local(__first), __llast, __proj);
if (__liter != __llast)
return _Traits::__compose(__sfirst, __liter);
}
++__sfirst;
// Iterate over the segments which are guaranteed to be completely in the range
while (__sfirst != __slast) {
auto __llast = _Traits::__end(__sfirst);
auto __liter = __pred(_Traits::__begin(__sfirst), _Traits::__end(__sfirst), __proj);
if (__liter != __llast)
return _Traits::__compose(__sfirst, __liter);
++__sfirst;
}
// Iterate over the last segment
return _Traits::__compose(__sfirst, __pred(_Traits::__begin(__sfirst), _Traits::__local(__last), __proj));
}
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___ALGORITHM_FIND_SEGMENT_IF_H

130
lib/libcxx/include/__algorithm/fold.h vendored Normal file
View File

@ -0,0 +1,130 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___ALGORITHM_FOLD_H
#define _LIBCPP___ALGORITHM_FOLD_H
#include <__concepts/assignable.h>
#include <__concepts/convertible_to.h>
#include <__concepts/invocable.h>
#include <__concepts/movable.h>
#include <__config>
#include <__functional/invoke.h>
#include <__functional/reference_wrapper.h>
#include <__iterator/concepts.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/next.h>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <__ranges/dangling.h>
#include <__type_traits/decay.h>
#include <__type_traits/invoke.h>
#include <__utility/forward.h>
#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 23
namespace ranges {
template <class _Ip, class _Tp>
struct in_value_result {
_LIBCPP_NO_UNIQUE_ADDRESS _Ip in;
_LIBCPP_NO_UNIQUE_ADDRESS _Tp value;
template <class _I2, class _T2>
requires convertible_to<const _Ip&, _I2> && convertible_to<const _Tp&, _T2>
_LIBCPP_HIDE_FROM_ABI constexpr operator in_value_result<_I2, _T2>() const& {
return {in, value};
}
template <class _I2, class _T2>
requires convertible_to<_Ip, _I2> && convertible_to<_Tp, _T2>
_LIBCPP_HIDE_FROM_ABI constexpr operator in_value_result<_I2, _T2>() && {
return {std::move(in), std::move(value)};
}
};
template <class _Ip, class _Tp>
using fold_left_with_iter_result = in_value_result<_Ip, _Tp>;
template <class _Fp, class _Tp, class _Ip, class _Rp, class _Up = decay_t<_Rp>>
concept __indirectly_binary_left_foldable_impl =
convertible_to<_Rp, _Up> && //
movable<_Tp> && //
movable<_Up> && //
convertible_to<_Tp, _Up> && //
invocable<_Fp&, _Up, iter_reference_t<_Ip>> && //
assignable_from<_Up&, invoke_result_t<_Fp&, _Up, iter_reference_t<_Ip>>>;
template <class _Fp, class _Tp, class _Ip>
concept __indirectly_binary_left_foldable =
copy_constructible<_Fp> && //
invocable<_Fp&, _Tp, iter_reference_t<_Ip>> && //
__indirectly_binary_left_foldable_impl<_Fp, _Tp, _Ip, invoke_result_t<_Fp&, _Tp, iter_reference_t<_Ip>>>;
struct __fold_left_with_iter {
template <input_iterator _Ip, sentinel_for<_Ip> _Sp, class _Tp, __indirectly_binary_left_foldable<_Tp, _Ip> _Fp>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto
operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) {
using _Up = decay_t<invoke_result_t<_Fp&, _Tp, iter_reference_t<_Ip>>>;
if (__first == __last) {
return fold_left_with_iter_result<_Ip, _Up>{std::move(__first), _Up(std::move(__init))};
}
_Up __result = std::invoke(__f, std::move(__init), *__first);
for (++__first; __first != __last; ++__first) {
__result = std::invoke(__f, std::move(__result), *__first);
}
return fold_left_with_iter_result<_Ip, _Up>{std::move(__first), std::move(__result)};
}
template <input_range _Rp, class _Tp, __indirectly_binary_left_foldable<_Tp, iterator_t<_Rp>> _Fp>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Rp&& __r, _Tp __init, _Fp __f) {
auto __result = operator()(ranges::begin(__r), ranges::end(__r), std::move(__init), std::ref(__f));
using _Up = decay_t<invoke_result_t<_Fp&, _Tp, range_reference_t<_Rp>>>;
return fold_left_with_iter_result<borrowed_iterator_t<_Rp>, _Up>{std::move(__result.in), std::move(__result.value)};
}
};
inline constexpr auto fold_left_with_iter = __fold_left_with_iter();
struct __fold_left {
template <input_iterator _Ip, sentinel_for<_Ip> _Sp, class _Tp, __indirectly_binary_left_foldable<_Tp, _Ip> _Fp>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto
operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) {
return fold_left_with_iter(std::move(__first), std::move(__last), std::move(__init), std::ref(__f)).value;
}
template <input_range _Rp, class _Tp, __indirectly_binary_left_foldable<_Tp, iterator_t<_Rp>> _Fp>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Rp&& __r, _Tp __init, _Fp __f) {
return fold_left_with_iter(ranges::begin(__r), ranges::end(__r), std::move(__init), std::ref(__f)).value;
}
};
inline constexpr auto fold_left = __fold_left();
} // namespace ranges
#endif // _LIBCPP_STD_VER >= 23
_LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_FOLD_H

View File

@ -10,23 +10,48 @@
#ifndef _LIBCPP___ALGORITHM_FOR_EACH_H #ifndef _LIBCPP___ALGORITHM_FOR_EACH_H
#define _LIBCPP___ALGORITHM_FOR_EACH_H #define _LIBCPP___ALGORITHM_FOR_EACH_H
#include <__algorithm/for_each_segment.h>
#include <__config> #include <__config>
#include <__iterator/segmented_iterator.h>
#include <__ranges/movable_box.h>
#include <__type_traits/enable_if.h>
#include <__utility/in_place.h>
#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Function> template <class _InputIterator, class _Function>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _Function for_each(_InputIterator __first, _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Function
_InputIterator __last, for_each(_InputIterator __first, _InputIterator __last, _Function __f) {
_Function __f) {
for (; __first != __last; ++__first) for (; __first != __last; ++__first)
__f(*__first); __f(*__first);
return __f; return __f;
} }
// __movable_box is available in C++20, but is actually a copyable-box, so optimization is only correct in C++23
#if _LIBCPP_STD_VER >= 23
template <class _SegmentedIterator, class _Function>
requires __is_segmented_iterator<_SegmentedIterator>::value
_LIBCPP_HIDE_FROM_ABI constexpr _Function
for_each(_SegmentedIterator __first, _SegmentedIterator __last, _Function __func) {
ranges::__movable_box<_Function> __wrapped_func(in_place, std::move(__func));
std::__for_each_segment(__first, __last, [&](auto __lfirst, auto __llast) {
__wrapped_func =
ranges::__movable_box<_Function>(in_place, std::for_each(__lfirst, __llast, std::move(*__wrapped_func)));
});
return std::move(*__wrapped_func);
}
#endif // _LIBCPP_STD_VER >= 23
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_FOR_EACH_H #endif // _LIBCPP___ALGORITHM_FOR_EACH_H

View File

@ -22,10 +22,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 17 #if _LIBCPP_STD_VER >= 17
template <class _InputIterator, class _Size, class _Function> template <class _InputIterator, class _Size, class _Function>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator for_each_n(_InputIterator __first, inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
_Size __orig_n, for_each_n(_InputIterator __first, _Size __orig_n, _Function __f) {
_Function __f) { typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize;
typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize;
_IntegralSize __n = __orig_n; _IntegralSize __n = __orig_n;
while (__n > 0) { while (__n > 0) {
__f(*__first); __f(*__first);

View File

@ -18,12 +18,10 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator, class _Generator> template <class _ForwardIterator, class _Generator>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
void generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen) {
generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen) for (; __first != __last; ++__first)
{ *__first = __gen();
for (; __first != __last; ++__first)
*__first = __gen();
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -19,15 +19,13 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _OutputIterator, class _Size, class _Generator> template <class _OutputIterator, class _Size, class _Generator>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
_OutputIterator generate_n(_OutputIterator __first, _Size __orig_n, _Generator __gen) {
generate_n(_OutputIterator __first, _Size __orig_n, _Generator __gen) typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize;
{ _IntegralSize __n = __orig_n;
typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; for (; __n > 0; ++__first, (void)--__n)
_IntegralSize __n = __orig_n; *__first = __gen();
for (; __n > 0; ++__first, (void) --__n) return __first;
*__first = __gen();
return __first;
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -22,28 +22,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// Perform division by two quickly for positive integers (llvm.org/PR39129) // Perform division by two quickly for positive integers (llvm.org/PR39129)
template <typename _Integral> template <typename _Integral, __enable_if_t<is_integral<_Integral>::value, int> = 0>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Integral __half_positive(_Integral __value) {
typename enable_if return static_cast<_Integral>(static_cast<__make_unsigned_t<_Integral> >(__value) / 2);
<
is_integral<_Integral>::value,
_Integral
>::type
__half_positive(_Integral __value)
{
return static_cast<_Integral>(static_cast<__make_unsigned_t<_Integral> >(__value) / 2);
} }
template <typename _Tp> template <typename _Tp, __enable_if_t<!is_integral<_Tp>::value, int> = 0>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp __half_positive(_Tp __value) {
typename enable_if return __value / 2;
<
!is_integral<_Tp>::value,
_Tp
>::type
__half_positive(_Tp __value)
{
return __value / 2;
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -18,6 +18,9 @@
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if _LIBCPP_STD_VER >= 20 #if _LIBCPP_STD_VER >= 20
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
@ -30,7 +33,7 @@ struct in_found_result {
template <class _InIter2> template <class _InIter2>
requires convertible_to<const _InIter1&, _InIter2> requires convertible_to<const _InIter1&, _InIter2>
_LIBCPP_HIDE_FROM_ABI constexpr operator in_found_result<_InIter2>() const & { _LIBCPP_HIDE_FROM_ABI constexpr operator in_found_result<_InIter2>() const& {
return {in, found}; return {in, found};
} }
@ -46,4 +49,6 @@ _LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP_STD_VER >= 20
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_IN_FOUND_RESULT_H #endif // _LIBCPP___ALGORITHM_IN_FOUND_RESULT_H

View File

@ -18,6 +18,9 @@
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 20 #if _LIBCPP_STD_VER >= 20
@ -30,7 +33,7 @@ struct in_fun_result {
template <class _InIter2, class _Func2> template <class _InIter2, class _Func2>
requires convertible_to<const _InIter1&, _InIter2> && convertible_to<const _Func1&, _Func2> requires convertible_to<const _InIter1&, _InIter2> && convertible_to<const _Func1&, _Func2>
_LIBCPP_HIDE_FROM_ABI constexpr operator in_fun_result<_InIter2, _Func2>() const & { _LIBCPP_HIDE_FROM_ABI constexpr operator in_fun_result<_InIter2, _Func2>() const& {
return {in, fun}; return {in, fun};
} }
@ -46,4 +49,6 @@ struct in_fun_result {
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_IN_FUN_RESULT_H #endif // _LIBCPP___ALGORITHM_IN_FUN_RESULT_H

View File

@ -18,6 +18,9 @@
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 20 #if _LIBCPP_STD_VER >= 20
@ -31,18 +34,16 @@ struct in_in_out_result {
_LIBCPP_NO_UNIQUE_ADDRESS _OutIter1 out; _LIBCPP_NO_UNIQUE_ADDRESS _OutIter1 out;
template <class _InIter3, class _InIter4, class _OutIter2> template <class _InIter3, class _InIter4, class _OutIter2>
requires convertible_to<const _InIter1&, _InIter3> requires convertible_to<const _InIter1&, _InIter3> && convertible_to<const _InIter2&, _InIter4> &&
&& convertible_to<const _InIter2&, _InIter4> && convertible_to<const _OutIter1&, _OutIter2> convertible_to<const _OutIter1&, _OutIter2>
_LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_HIDE_FROM_ABI constexpr operator in_in_out_result<_InIter3, _InIter4, _OutIter2>() const& {
operator in_in_out_result<_InIter3, _InIter4, _OutIter2>() const& {
return {in1, in2, out}; return {in1, in2, out};
} }
template <class _InIter3, class _InIter4, class _OutIter2> template <class _InIter3, class _InIter4, class _OutIter2>
requires convertible_to<_InIter1, _InIter3> requires convertible_to<_InIter1, _InIter3> && convertible_to<_InIter2, _InIter4> &&
&& convertible_to<_InIter2, _InIter4> && convertible_to<_OutIter1, _OutIter2> convertible_to<_OutIter1, _OutIter2>
_LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_HIDE_FROM_ABI constexpr operator in_in_out_result<_InIter3, _InIter4, _OutIter2>() && {
operator in_in_out_result<_InIter3, _InIter4, _OutIter2>() && {
return {std::move(in1), std::move(in2), std::move(out)}; return {std::move(in1), std::move(in2), std::move(out)};
} }
}; };
@ -53,4 +54,6 @@ struct in_in_out_result {
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_IN_IN_OUT_RESULT_H #endif // _LIBCPP___ALGORITHM_IN_IN_OUT_RESULT_H

View File

@ -18,6 +18,9 @@
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 20 #if _LIBCPP_STD_VER >= 20
@ -31,15 +34,13 @@ struct in_in_result {
template <class _InIter3, class _InIter4> template <class _InIter3, class _InIter4>
requires convertible_to<const _InIter1&, _InIter3> && convertible_to<const _InIter2&, _InIter4> requires convertible_to<const _InIter1&, _InIter3> && convertible_to<const _InIter2&, _InIter4>
_LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_HIDE_FROM_ABI constexpr operator in_in_result<_InIter3, _InIter4>() const& {
operator in_in_result<_InIter3, _InIter4>() const & {
return {in1, in2}; return {in1, in2};
} }
template <class _InIter3, class _InIter4> template <class _InIter3, class _InIter4>
requires convertible_to<_InIter1, _InIter3> && convertible_to<_InIter2, _InIter4> requires convertible_to<_InIter1, _InIter3> && convertible_to<_InIter2, _InIter4>
_LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_HIDE_FROM_ABI constexpr operator in_in_result<_InIter3, _InIter4>() && {
operator in_in_result<_InIter3, _InIter4>() && {
return {std::move(in1), std::move(in2)}; return {std::move(in1), std::move(in2)};
} }
}; };
@ -50,4 +51,6 @@ struct in_in_result {
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_IN_IN_RESULT_H #endif // _LIBCPP___ALGORITHM_IN_IN_RESULT_H

View File

@ -18,6 +18,9 @@
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 20 #if _LIBCPP_STD_VER >= 20
@ -30,18 +33,16 @@ struct in_out_out_result {
_LIBCPP_NO_UNIQUE_ADDRESS _OutIter2 out2; _LIBCPP_NO_UNIQUE_ADDRESS _OutIter2 out2;
template <class _InIter2, class _OutIter3, class _OutIter4> template <class _InIter2, class _OutIter3, class _OutIter4>
requires convertible_to<const _InIter1&, _InIter2> requires convertible_to<const _InIter1&, _InIter2> && convertible_to<const _OutIter1&, _OutIter3> &&
&& convertible_to<const _OutIter1&, _OutIter3> && convertible_to<const _OutIter2&, _OutIter4> convertible_to<const _OutIter2&, _OutIter4>
_LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_HIDE_FROM_ABI constexpr operator in_out_out_result<_InIter2, _OutIter3, _OutIter4>() const& {
operator in_out_out_result<_InIter2, _OutIter3, _OutIter4>() const& {
return {in, out1, out2}; return {in, out1, out2};
} }
template <class _InIter2, class _OutIter3, class _OutIter4> template <class _InIter2, class _OutIter3, class _OutIter4>
requires convertible_to<_InIter1, _InIter2> requires convertible_to<_InIter1, _InIter2> && convertible_to<_OutIter1, _OutIter3> &&
&& convertible_to<_OutIter1, _OutIter3> && convertible_to<_OutIter2, _OutIter4> convertible_to<_OutIter2, _OutIter4>
_LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_HIDE_FROM_ABI constexpr operator in_out_out_result<_InIter2, _OutIter3, _OutIter4>() && {
operator in_out_out_result<_InIter2, _OutIter3, _OutIter4>() && {
return {std::move(in), std::move(out1), std::move(out2)}; return {std::move(in), std::move(out1), std::move(out2)};
} }
}; };
@ -51,4 +52,6 @@ struct in_out_out_result {
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_IN_OUT_OUT_RESULT_H #endif // _LIBCPP___ALGORITHM_IN_OUT_OUT_RESULT_H

View File

@ -27,22 +27,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace ranges { namespace ranges {
template<class _InIter1, class _OutIter1> template <class _InIter1, class _OutIter1>
struct in_out_result { struct in_out_result {
_LIBCPP_NO_UNIQUE_ADDRESS _InIter1 in; _LIBCPP_NO_UNIQUE_ADDRESS _InIter1 in;
_LIBCPP_NO_UNIQUE_ADDRESS _OutIter1 out; _LIBCPP_NO_UNIQUE_ADDRESS _OutIter1 out;
template <class _InIter2, class _OutIter2> template <class _InIter2, class _OutIter2>
requires convertible_to<const _InIter1&, _InIter2> && convertible_to<const _OutIter1&, _OutIter2> requires convertible_to<const _InIter1&, _InIter2> && convertible_to<const _OutIter1&, _OutIter2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDE_FROM_ABI constexpr operator in_out_result<_InIter2, _OutIter2>() const& {
constexpr operator in_out_result<_InIter2, _OutIter2>() const & {
return {in, out}; return {in, out};
} }
template <class _InIter2, class _OutIter2> template <class _InIter2, class _OutIter2>
requires convertible_to<_InIter1, _InIter2> && convertible_to<_OutIter1, _OutIter2> requires convertible_to<_InIter1, _InIter2> && convertible_to<_OutIter1, _OutIter2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDE_FROM_ABI constexpr operator in_out_result<_InIter2, _OutIter2>() && {
constexpr operator in_out_result<_InIter2, _OutIter2>() && {
return {std::move(in), std::move(out)}; return {std::move(in), std::move(out)};
} }
}; };

View File

@ -22,15 +22,23 @@
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Comp, class _Proj1, class _Proj2> template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Comp, class _Proj1, class _Proj2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __includes(
__includes(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Iter1 __first1,
_Comp&& __comp, _Proj1&& __proj1, _Proj2&& __proj2) { _Sent1 __last1,
_Iter2 __first2,
_Sent2 __last2,
_Comp&& __comp,
_Proj1&& __proj1,
_Proj2&& __proj2) {
for (; __first2 != __last2; ++__first1) { for (; __first2 != __last2; ++__first1) {
if (__first1 == __last1 || std::__invoke( if (__first1 == __last1 ||
__comp, std::__invoke(__proj2, *__first2), std::__invoke(__proj1, *__first1))) std::__invoke(__comp, std::__invoke(__proj2, *__first2), std::__invoke(__proj1, *__first1)))
return false; return false;
if (!std::__invoke(__comp, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) if (!std::__invoke(__comp, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2)))
++__first2; ++__first2;
@ -39,14 +47,14 @@ __includes(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
} }
template <class _InputIterator1, class _InputIterator2, class _Compare> template <class _InputIterator1, class _InputIterator2, class _Compare>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool includes( _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
_InputIterator1 __first1, includes(_InputIterator1 __first1,
_InputIterator1 __last1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __first2,
_InputIterator2 __last2, _InputIterator2 __last2,
_Compare __comp) { _Compare __comp) {
static_assert(__is_callable<_Compare, decltype(*__first1), decltype(*__first2)>::value, static_assert(
"Comparator has to be callable"); __is_callable<_Compare, decltype(*__first1), decltype(*__first2)>::value, "Comparator has to be callable");
return std::__includes( return std::__includes(
std::move(__first1), std::move(__first1),
@ -66,4 +74,6 @@ includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __fi
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_INCLUDES_H #endif // _LIBCPP___ALGORITHM_INCLUDES_H

View File

@ -42,54 +42,57 @@ template <class _Predicate>
class __invert // invert the sense of a comparison class __invert // invert the sense of a comparison
{ {
private: private:
_Predicate __p_; _Predicate __p_;
public: public:
_LIBCPP_INLINE_VISIBILITY __invert() {} _LIBCPP_HIDE_FROM_ABI __invert() {}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_HIDE_FROM_ABI explicit __invert(_Predicate __p) : __p_(__p) {}
explicit __invert(_Predicate __p) : __p_(__p) {}
template <class _T1> template <class _T1>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_HIDE_FROM_ABI bool operator()(const _T1& __x) {
bool operator()(const _T1& __x) {return !__p_(__x);} return !__p_(__x);
}
template <class _T1, class _T2> template <class _T1, class _T2>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_HIDE_FROM_ABI bool operator()(const _T1& __x, const _T2& __y) {
bool operator()(const _T1& __x, const _T2& __y) {return __p_(__y, __x);} return __p_(__y, __x);
}
}; };
template <class _AlgPolicy, class _Compare, class _InputIterator1, class _Sent1, template <class _AlgPolicy,
class _InputIterator2, class _Sent2, class _OutputIterator> class _Compare,
_LIBCPP_HIDE_FROM_ABI class _InputIterator1,
void __half_inplace_merge(_InputIterator1 __first1, _Sent1 __last1, class _Sent1,
_InputIterator2 __first2, _Sent2 __last2, class _InputIterator2,
_OutputIterator __result, _Compare&& __comp) class _Sent2,
{ class _OutputIterator>
for (; __first1 != __last1; ++__result) _LIBCPP_HIDE_FROM_ABI void __half_inplace_merge(
{ _InputIterator1 __first1,
if (__first2 == __last2) _Sent1 __last1,
{ _InputIterator2 __first2,
std::__move<_AlgPolicy>(__first1, __last1, __result); _Sent2 __last2,
return; _OutputIterator __result,
} _Compare&& __comp) {
for (; __first1 != __last1; ++__result) {
if (__comp(*__first2, *__first1)) if (__first2 == __last2) {
{ std::__move<_AlgPolicy>(__first1, __last1, __result);
*__result = _IterOps<_AlgPolicy>::__iter_move(__first2); return;
++__first2;
}
else
{
*__result = _IterOps<_AlgPolicy>::__iter_move(__first1);
++__first1;
}
} }
// __first2 through __last2 are already in the right spot.
if (__comp(*__first2, *__first1)) {
*__result = _IterOps<_AlgPolicy>::__iter_move(__first2);
++__first2;
} else {
*__result = _IterOps<_AlgPolicy>::__iter_move(__first1);
++__first1;
}
}
// __first2 through __last2 are already in the right spot.
} }
template <class _AlgPolicy, class _Compare, class _BidirectionalIterator> template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDE_FROM_ABI void __buffered_inplace_merge(
void __buffered_inplace_merge(
_BidirectionalIterator __first, _BidirectionalIterator __first,
_BidirectionalIterator __middle, _BidirectionalIterator __middle,
_BidirectionalIterator __last, _BidirectionalIterator __last,
@ -98,27 +101,25 @@ void __buffered_inplace_merge(
typename iterator_traits<_BidirectionalIterator>::difference_type __len2, typename iterator_traits<_BidirectionalIterator>::difference_type __len2,
typename iterator_traits<_BidirectionalIterator>::value_type* __buff) { typename iterator_traits<_BidirectionalIterator>::value_type* __buff) {
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
__destruct_n __d(0); __destruct_n __d(0);
unique_ptr<value_type, __destruct_n&> __h2(__buff, __d); unique_ptr<value_type, __destruct_n&> __h2(__buff, __d);
if (__len1 <= __len2) if (__len1 <= __len2) {
{ value_type* __p = __buff;
value_type* __p = __buff; for (_BidirectionalIterator __i = __first; __i != __middle;
for (_BidirectionalIterator __i = __first; __i != __middle; __d.template __incr<value_type>(), (void) ++__i, (void) ++__p) __d.template __incr<value_type>(), (void)++__i, (void)++__p)
::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i)); ::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i));
std::__half_inplace_merge<_AlgPolicy>(__buff, __p, __middle, __last, __first, __comp); std::__half_inplace_merge<_AlgPolicy>(__buff, __p, __middle, __last, __first, __comp);
} } else {
else value_type* __p = __buff;
{ for (_BidirectionalIterator __i = __middle; __i != __last;
value_type* __p = __buff; __d.template __incr<value_type>(), (void)++__i, (void)++__p)
for (_BidirectionalIterator __i = __middle; __i != __last; __d.template __incr<value_type>(), (void) ++__i, (void) ++__p) ::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i));
::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i)); typedef __unconstrained_reverse_iterator<_BidirectionalIterator> _RBi;
typedef __unconstrained_reverse_iterator<_BidirectionalIterator> _RBi; typedef __unconstrained_reverse_iterator<value_type*> _Rv;
typedef __unconstrained_reverse_iterator<value_type*> _Rv; typedef __invert<_Compare> _Inverted;
typedef __invert<_Compare> _Inverted; std::__half_inplace_merge<_AlgPolicy>(
std::__half_inplace_merge<_AlgPolicy>(_Rv(__p), _Rv(__buff), _Rv(__p), _Rv(__buff), _RBi(__middle), _RBi(__first), _RBi(__last), _Inverted(__comp));
_RBi(__middle), _RBi(__first), }
_RBi(__last), _Inverted(__comp));
}
} }
template <class _AlgPolicy, class _Compare, class _BidirectionalIterator> template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
@ -131,107 +132,92 @@ void __inplace_merge(
typename iterator_traits<_BidirectionalIterator>::difference_type __len2, typename iterator_traits<_BidirectionalIterator>::difference_type __len2,
typename iterator_traits<_BidirectionalIterator>::value_type* __buff, typename iterator_traits<_BidirectionalIterator>::value_type* __buff,
ptrdiff_t __buff_size) { ptrdiff_t __buff_size) {
using _Ops = _IterOps<_AlgPolicy>; using _Ops = _IterOps<_AlgPolicy>;
typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type;
while (true) while (true) {
{ // if __middle == __last, we're done
// if __middle == __last, we're done if (__len2 == 0)
if (__len2 == 0) return;
return; if (__len1 <= __buff_size || __len2 <= __buff_size)
if (__len1 <= __buff_size || __len2 <= __buff_size) return std::__buffered_inplace_merge<_AlgPolicy>(__first, __middle, __last, __comp, __len1, __len2, __buff);
return std::__buffered_inplace_merge<_AlgPolicy> // shrink [__first, __middle) as much as possible (with no moves), returning if it shrinks to 0
(__first, __middle, __last, __comp, __len1, __len2, __buff); for (; true; ++__first, (void)--__len1) {
// shrink [__first, __middle) as much as possible (with no moves), returning if it shrinks to 0 if (__len1 == 0)
for (; true; ++__first, (void) --__len1) return;
{ if (__comp(*__middle, *__first))
if (__len1 == 0) break;
return;
if (__comp(*__middle, *__first))
break;
}
// __first < __middle < __last
// *__first > *__middle
// partition [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last) such that
// all elements in:
// [__first, __m1) <= [__middle, __m2)
// [__middle, __m2) < [__m1, __middle)
// [__m1, __middle) <= [__m2, __last)
// and __m1 or __m2 is in the middle of its range
_BidirectionalIterator __m1; // "median" of [__first, __middle)
_BidirectionalIterator __m2; // "median" of [__middle, __last)
difference_type __len11; // distance(__first, __m1)
difference_type __len21; // distance(__middle, __m2)
// binary search smaller range
if (__len1 < __len2)
{ // __len >= 1, __len2 >= 2
__len21 = __len2 / 2;
__m2 = __middle;
_Ops::advance(__m2, __len21);
__m1 = std::__upper_bound<_AlgPolicy>(__first, __middle, *__m2, __comp, std::__identity());
__len11 = _Ops::distance(__first, __m1);
}
else
{
if (__len1 == 1)
{ // __len1 >= __len2 && __len2 > 0, therefore __len2 == 1
// It is known *__first > *__middle
_Ops::iter_swap(__first, __middle);
return;
}
// __len1 >= 2, __len2 >= 1
__len11 = __len1 / 2;
__m1 = __first;
_Ops::advance(__m1, __len11);
__m2 = std::lower_bound(__middle, __last, *__m1, __comp);
__len21 = _Ops::distance(__middle, __m2);
}
difference_type __len12 = __len1 - __len11; // distance(__m1, __middle)
difference_type __len22 = __len2 - __len21; // distance(__m2, __last)
// [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last)
// swap middle two partitions
__middle = std::__rotate<_AlgPolicy>(__m1, __middle, __m2).first;
// __len12 and __len21 now have swapped meanings
// merge smaller range with recursive call and larger with tail recursion elimination
if (__len11 + __len21 < __len12 + __len22)
{
std::__inplace_merge<_AlgPolicy>(
__first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size);
__first = __middle;
__middle = __m2;
__len1 = __len12;
__len2 = __len22;
}
else
{
std::__inplace_merge<_AlgPolicy>(
__middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size);
__last = __middle;
__middle = __m1;
__len1 = __len11;
__len2 = __len21;
}
} }
// __first < __middle < __last
// *__first > *__middle
// partition [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last) such that
// all elements in:
// [__first, __m1) <= [__middle, __m2)
// [__middle, __m2) < [__m1, __middle)
// [__m1, __middle) <= [__m2, __last)
// and __m1 or __m2 is in the middle of its range
_BidirectionalIterator __m1; // "median" of [__first, __middle)
_BidirectionalIterator __m2; // "median" of [__middle, __last)
difference_type __len11; // distance(__first, __m1)
difference_type __len21; // distance(__middle, __m2)
// binary search smaller range
if (__len1 < __len2) { // __len >= 1, __len2 >= 2
__len21 = __len2 / 2;
__m2 = __middle;
_Ops::advance(__m2, __len21);
__m1 = std::__upper_bound<_AlgPolicy>(__first, __middle, *__m2, __comp, std::__identity());
__len11 = _Ops::distance(__first, __m1);
} else {
if (__len1 == 1) { // __len1 >= __len2 && __len2 > 0, therefore __len2 == 1
// It is known *__first > *__middle
_Ops::iter_swap(__first, __middle);
return;
}
// __len1 >= 2, __len2 >= 1
__len11 = __len1 / 2;
__m1 = __first;
_Ops::advance(__m1, __len11);
__m2 = std::lower_bound(__middle, __last, *__m1, __comp);
__len21 = _Ops::distance(__middle, __m2);
}
difference_type __len12 = __len1 - __len11; // distance(__m1, __middle)
difference_type __len22 = __len2 - __len21; // distance(__m2, __last)
// [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last)
// swap middle two partitions
__middle = std::__rotate<_AlgPolicy>(__m1, __middle, __m2).first;
// __len12 and __len21 now have swapped meanings
// merge smaller range with recursive call and larger with tail recursion elimination
if (__len11 + __len21 < __len12 + __len22) {
std::__inplace_merge<_AlgPolicy>(__first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size);
__first = __middle;
__middle = __m2;
__len1 = __len12;
__len2 = __len22;
} else {
std::__inplace_merge<_AlgPolicy>(__middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size);
__last = __middle;
__middle = __m1;
__len1 = __len11;
__len2 = __len21;
}
}
} }
template <class _AlgPolicy, class _BidirectionalIterator, class _Compare> template <class _AlgPolicy, class _BidirectionalIterator, class _Compare>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDE_FROM_ABI void __inplace_merge(
void _BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare&& __comp) {
__inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
_Compare&& __comp) typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type;
{ difference_type __len1 = _IterOps<_AlgPolicy>::distance(__first, __middle);
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; difference_type __len2 = _IterOps<_AlgPolicy>::distance(__middle, __last);
typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; difference_type __buf_size = std::min(__len1, __len2);
difference_type __len1 = _IterOps<_AlgPolicy>::distance(__first, __middle); // TODO: Remove the use of std::get_temporary_buffer
difference_type __len2 = _IterOps<_AlgPolicy>::distance(__middle, __last); _LIBCPP_SUPPRESS_DEPRECATED_PUSH
difference_type __buf_size = _VSTD::min(__len1, __len2); pair<value_type*, ptrdiff_t> __buf = std::get_temporary_buffer<value_type>(__buf_size);
// TODO: Remove the use of std::get_temporary_buffer _LIBCPP_SUPPRESS_DEPRECATED_POP
_LIBCPP_SUPPRESS_DEPRECATED_PUSH unique_ptr<value_type, __return_temporary_buffer> __h(__buf.first);
pair<value_type*, ptrdiff_t> __buf = _VSTD::get_temporary_buffer<value_type>(__buf_size); return std::__inplace_merge<_AlgPolicy>(
_LIBCPP_SUPPRESS_DEPRECATED_POP std::move(__first), std::move(__middle), std::move(__last), __comp, __len1, __len2, __buf.first, __buf.second);
unique_ptr<value_type, __return_temporary_buffer> __h(__buf.first);
return std::__inplace_merge<_AlgPolicy>(
std::move(__first), std::move(__middle), std::move(__last), __comp, __len1, __len2, __buf.first, __buf.second);
} }
template <class _BidirectionalIterator, class _Compare> template <class _BidirectionalIterator, class _Compare>
@ -242,11 +228,9 @@ inline _LIBCPP_HIDE_FROM_ABI void inplace_merge(
} }
template <class _BidirectionalIterator> template <class _BidirectionalIterator>
inline _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_HIDE_FROM_ABI void
void inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last) {
inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last) std::inplace_merge(std::move(__first), std::move(__middle), std::move(__last), __less<>());
{
std::inplace_merge(std::move(__first), std::move(__middle), std::move(__last), __less<>());
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -22,21 +22,15 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _RandomAccessIterator, class _Compare> template <class _RandomAccessIterator, class _Compare>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
bool return std::__is_heap_until(__first, __last, static_cast<__comp_ref_type<_Compare> >(__comp)) == __last;
is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp)
{
return std::__is_heap_until(__first, __last, static_cast<__comp_ref_type<_Compare> >(__comp)) == __last;
} }
template<class _RandomAccessIterator> template <class _RandomAccessIterator>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) {
bool return std::is_heap(__first, __last, __less<>());
is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
return _VSTD::is_heap(__first, __last, __less<>());
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -22,43 +22,39 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Compare, class _RandomAccessIterator> template <class _Compare, class _RandomAccessIterator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator
__is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) __is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) {
{ typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; difference_type __len = __last - __first;
difference_type __len = __last - __first; difference_type __p = 0;
difference_type __p = 0; difference_type __c = 1;
difference_type __c = 1; _RandomAccessIterator __pp = __first;
_RandomAccessIterator __pp = __first; while (__c < __len) {
while (__c < __len) _RandomAccessIterator __cp = __first + __c;
{ if (__comp(*__pp, *__cp))
_RandomAccessIterator __cp = __first + __c; return __cp;
if (__comp(*__pp, *__cp)) ++__c;
return __cp; ++__cp;
++__c; if (__c == __len)
++__cp; return __last;
if (__c == __len) if (__comp(*__pp, *__cp))
return __last; return __cp;
if (__comp(*__pp, *__cp)) ++__p;
return __cp; ++__pp;
++__p; __c = 2 * __p + 1;
++__pp; }
__c = 2 * __p + 1; return __last;
}
return __last;
} }
template <class _RandomAccessIterator, class _Compare> template <class _RandomAccessIterator, class _Compare>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator
is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
{ return std::__is_heap_until(__first, __last, static_cast<__comp_ref_type<_Compare> >(__comp));
return std::__is_heap_until(__first, __last, static_cast<__comp_ref_type<_Compare> >(__comp));
} }
template<class _RandomAccessIterator> template <class _RandomAccessIterator>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator
is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last) is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last) {
{ return std::__is_heap_until(__first, __last, __less<>());
return _VSTD::__is_heap_until(__first, __last, __less<>());
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -19,18 +19,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Predicate> template <class _InputIterator, class _Predicate>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
is_partitioned(_InputIterator __first, _InputIterator __last, _Predicate __pred) is_partitioned(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
{ for (; __first != __last; ++__first)
for (; __first != __last; ++__first) if (!__pred(*__first))
if (!__pred(*__first)) break;
break; if (__first == __last)
if ( __first == __last )
return true;
++__first;
for (; __first != __last; ++__first)
if (__pred(*__first))
return false;
return true; return true;
++__first;
for (; __first != __last; ++__first)
if (__pred(*__first))
return false;
return true;
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -37,18 +37,24 @@ struct _ConstTimeDistance : false_type {};
#if _LIBCPP_STD_VER >= 20 #if _LIBCPP_STD_VER >= 20
template <class _Iter1, class _Sent1, class _Iter2, class _Sent2> template <class _Iter1, class _Sent1, class _Iter2, class _Sent2>
struct _ConstTimeDistance<_Iter1, _Sent1, _Iter2, _Sent2, __enable_if_t< struct _ConstTimeDistance<_Iter1,
sized_sentinel_for<_Sent1, _Iter1> && _Sent1,
sized_sentinel_for<_Sent2, _Iter2> _Iter2,
>> : true_type {}; _Sent2,
__enable_if_t< sized_sentinel_for<_Sent1, _Iter1> && sized_sentinel_for<_Sent2, _Iter2> >>
: true_type {};
#else #else
template <class _Iter1, class _Iter2> template <class _Iter1, class _Iter2>
struct _ConstTimeDistance<_Iter1, _Iter1, _Iter2, _Iter2, __enable_if_t< struct _ConstTimeDistance<
is_same<typename iterator_traits<_Iter1>::iterator_category, random_access_iterator_tag>::value && _Iter1,
is_same<typename iterator_traits<_Iter2>::iterator_category, random_access_iterator_tag>::value _Iter1,
> > : true_type {}; _Iter2,
_Iter2,
__enable_if_t< is_same<typename iterator_traits<_Iter1>::iterator_category, random_access_iterator_tag>::value &&
is_same<typename iterator_traits<_Iter2>::iterator_category, random_access_iterator_tag>::value > >
: true_type {};
#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP_STD_VER >= 20
@ -56,11 +62,21 @@ struct _ConstTimeDistance<_Iter1, _Iter1, _Iter2, _Iter2, __enable_if_t<
// For each element in [f1, l1) see if there are the same number of equal elements in [f2, l2) // For each element in [f1, l1) see if there are the same number of equal elements in [f2, l2)
template <class _AlgPolicy, template <class _AlgPolicy,
class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Iter1,
class _Proj1, class _Proj2, class _Pred> class _Sent1,
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool class _Iter2,
__is_permutation_impl(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, class _Sent2,
_Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2) { class _Proj1,
class _Proj2,
class _Pred>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation_impl(
_Iter1 __first1,
_Sent1 __last1,
_Iter2 __first2,
_Sent2 __last2,
_Pred&& __pred,
_Proj1&& __proj1,
_Proj2&& __proj2) {
using _D1 = __iter_diff_t<_Iter1>; using _D1 = __iter_diff_t<_Iter1>;
for (auto __i = __first1; __i != __last1; ++__i) { for (auto __i = __first1; __i != __last1; ++__i) {
@ -97,9 +113,8 @@ __is_permutation_impl(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 _
// 2+1 iterators, predicate. Not used by range algorithms. // 2+1 iterators, predicate. Not used by range algorithms.
template <class _AlgPolicy, class _ForwardIterator1, class _Sentinel1, class _ForwardIterator2, class _BinaryPredicate> template <class _AlgPolicy, class _ForwardIterator1, class _Sentinel1, class _ForwardIterator2, class _BinaryPredicate>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation(
__is_permutation(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2, _ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2, _BinaryPredicate&& __pred) {
_BinaryPredicate&& __pred) {
// Shorten sequences as much as possible by lopping of any equal prefix. // Shorten sequences as much as possible by lopping of any equal prefix.
for (; __first1 != __last1; ++__first1, (void)++__first2) { for (; __first1 != __last1; ++__first1, (void)++__first2) {
if (!__pred(*__first1, *__first2)) if (!__pred(*__first1, *__first2))
@ -111,24 +126,39 @@ __is_permutation(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterato
// __first1 != __last1 && *__first1 != *__first2 // __first1 != __last1 && *__first1 != *__first2
using _D1 = __iter_diff_t<_ForwardIterator1>; using _D1 = __iter_diff_t<_ForwardIterator1>;
_D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1); _D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1);
if (__l1 == _D1(1)) if (__l1 == _D1(1))
return false; return false;
auto __last2 = _IterOps<_AlgPolicy>::next(__first2, __l1); auto __last2 = _IterOps<_AlgPolicy>::next(__first2, __l1);
return std::__is_permutation_impl<_AlgPolicy>( return std::__is_permutation_impl<_AlgPolicy>(
std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::move(__first1),
__pred, __identity(), __identity()); std::move(__last1),
std::move(__first2),
std::move(__last2),
__pred,
__identity(),
__identity());
} }
// 2+2 iterators, predicate, non-constant time `distance`. // 2+2 iterators, predicate, non-constant time `distance`.
template <class _AlgPolicy, template <class _AlgPolicy,
class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Iter1,
class _Proj1, class _Proj2, class _Pred> class _Sent1,
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool class _Iter2,
__is_permutation(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, class _Sent2,
_Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2, class _Proj1,
/*_ConstTimeDistance=*/false_type) { class _Proj2,
class _Pred>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation(
_Iter1 __first1,
_Sent1 __last1,
_Iter2 __first2,
_Sent2 __last2,
_Pred&& __pred,
_Proj1&& __proj1,
_Proj2&& __proj2,
/*_ConstTimeDistance=*/false_type) {
// Shorten sequences as much as possible by lopping of any equal prefix. // Shorten sequences as much as possible by lopping of any equal prefix.
while (__first1 != __last1 && __first2 != __last2) { while (__first1 != __last1 && __first2 != __last2) {
if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2)))
@ -143,44 +173,73 @@ __is_permutation(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last
return false; return false;
using _D1 = __iter_diff_t<_Iter1>; using _D1 = __iter_diff_t<_Iter1>;
_D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1); _D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1);
using _D2 = __iter_diff_t<_Iter2>; using _D2 = __iter_diff_t<_Iter2>;
_D2 __l2 = _IterOps<_AlgPolicy>::distance(__first2, __last2); _D2 __l2 = _IterOps<_AlgPolicy>::distance(__first2, __last2);
if (__l1 != __l2) if (__l1 != __l2)
return false; return false;
return std::__is_permutation_impl<_AlgPolicy>( return std::__is_permutation_impl<_AlgPolicy>(
std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2);
__pred, __proj1, __proj2);
} }
// 2+2 iterators, predicate, specialization for constant-time `distance` call. // 2+2 iterators, predicate, specialization for constant-time `distance` call.
template <class _AlgPolicy, template <class _AlgPolicy,
class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Iter1,
class _Proj1, class _Proj2, class _Pred> class _Sent1,
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool class _Iter2,
__is_permutation(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, class _Sent2,
_Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2, class _Proj1,
/*_ConstTimeDistance=*/true_type) { class _Proj2,
class _Pred>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation(
_Iter1 __first1,
_Sent1 __last1,
_Iter2 __first2,
_Sent2 __last2,
_Pred&& __pred,
_Proj1&& __proj1,
_Proj2&& __proj2,
/*_ConstTimeDistance=*/true_type) {
if (std::distance(__first1, __last1) != std::distance(__first2, __last2)) if (std::distance(__first1, __last1) != std::distance(__first2, __last2))
return false; return false;
return std::__is_permutation<_AlgPolicy>( return std::__is_permutation<_AlgPolicy>(
std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::move(__first1),
__pred, __proj1, __proj2, std::move(__last1),
std::move(__first2),
std::move(__last2),
__pred,
__proj1,
__proj2,
/*_ConstTimeDistance=*/false_type()); /*_ConstTimeDistance=*/false_type());
} }
// 2+2 iterators, predicate // 2+2 iterators, predicate
template <class _AlgPolicy, template <class _AlgPolicy,
class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Iter1,
class _Proj1, class _Proj2, class _Pred> class _Sent1,
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool class _Iter2,
__is_permutation(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, class _Sent2,
_Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2) { class _Proj1,
class _Proj2,
class _Pred>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation(
_Iter1 __first1,
_Sent1 __last1,
_Iter2 __first2,
_Sent2 __last2,
_Pred&& __pred,
_Proj1&& __proj1,
_Proj2&& __proj2) {
return std::__is_permutation<_AlgPolicy>( return std::__is_permutation<_AlgPolicy>(
std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::move(__first1),
__pred, __proj1, __proj2, std::move(__last1),
std::move(__first2),
std::move(__last2),
__pred,
__proj1,
__proj2,
_ConstTimeDistance<_Iter1, _Sent1, _Iter2, _Sent2>()); _ConstTimeDistance<_Iter1, _Sent1, _Iter2, _Sent2>());
} }
@ -188,14 +247,12 @@ __is_permutation(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last
// 2+1 iterators, predicate // 2+1 iterators, predicate
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation(
is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _BinaryPredicate __pred) {
_BinaryPredicate __pred) {
static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value, static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value,
"The predicate has to be callable"); "The predicate has to be callable");
return std::__is_permutation<_ClassicAlgPolicy>( return std::__is_permutation<_ClassicAlgPolicy>(std::move(__first1), std::move(__last1), std::move(__first2), __pred);
std::move(__first1), std::move(__last1), std::move(__first2), __pred);
} }
// 2+1 iterators // 2+1 iterators
@ -223,15 +280,23 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
// 2+2 iterators, predicate // 2+2 iterators, predicate
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation(
is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator1 __first1,
_ForwardIterator2 __last2, _BinaryPredicate __pred) { _ForwardIterator1 __last1,
_ForwardIterator2 __first2,
_ForwardIterator2 __last2,
_BinaryPredicate __pred) {
static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value, static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value,
"The predicate has to be callable"); "The predicate has to be callable");
return std::__is_permutation<_ClassicAlgPolicy>( return std::__is_permutation<_ClassicAlgPolicy>(
std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::move(__first1),
__pred, __identity(), __identity()); std::move(__last1),
std::move(__first2),
std::move(__last2),
__pred,
__identity(),
__identity());
} }
#endif // _LIBCPP_STD_VER >= 14 #endif // _LIBCPP_STD_VER >= 14

View File

@ -22,21 +22,15 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator, class _Compare> template <class _ForwardIterator, class _Compare>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 is_sorted(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) {
bool return std::__is_sorted_until<__comp_ref_type<_Compare> >(__first, __last, __comp) == __last;
is_sorted(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
{
return _VSTD::__is_sorted_until<__comp_ref_type<_Compare> >(__first, __last, __comp) == __last;
} }
template<class _ForwardIterator> template <class _ForwardIterator>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 is_sorted(_ForwardIterator __first, _ForwardIterator __last) {
bool return std::is_sorted(__first, __last, __less<>());
is_sorted(_ForwardIterator __first, _ForwardIterator __last)
{
return _VSTD::is_sorted(__first, __last, __less<>());
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -22,33 +22,28 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Compare, class _ForwardIterator> template <class _Compare, class _ForwardIterator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
__is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) __is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) {
{ if (__first != __last) {
if (__first != __last) _ForwardIterator __i = __first;
{ while (++__i != __last) {
_ForwardIterator __i = __first; if (__comp(*__i, *__first))
while (++__i != __last) return __i;
{ __first = __i;
if (__comp(*__i, *__first))
return __i;
__first = __i;
}
} }
return __last; }
return __last;
} }
template <class _ForwardIterator, class _Compare> template <class _ForwardIterator, class _Compare>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) {
{ return std::__is_sorted_until<__comp_ref_type<_Compare> >(__first, __last, __comp);
return _VSTD::__is_sorted_until<__comp_ref_type<_Compare> >(__first, __last, __comp);
} }
template<class _ForwardIterator> template <class _ForwardIterator>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) {
{ return std::is_sorted_until(__first, __last, __less<>());
return _VSTD::is_sorted_until(__first, __last, __less<>());
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -20,8 +20,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator1, class _ForwardIterator2> template <class _ForwardIterator1, class _ForwardIterator2>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void iter_swap(_ForwardIterator1 __a, inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b)
_ForwardIterator2 __b)
// _NOEXCEPT_(_NOEXCEPT_(swap(*__a, *__b))) // _NOEXCEPT_(_NOEXCEPT_(swap(*__a, *__b)))
_NOEXCEPT_(_NOEXCEPT_(swap(*std::declval<_ForwardIterator1>(), *std::declval<_ForwardIterator2>()))) { _NOEXCEPT_(_NOEXCEPT_(swap(*std::declval<_ForwardIterator1>(), *std::declval<_ForwardIterator2>()))) {
swap(*__a, *__b); swap(*__a, *__b);

View File

@ -38,14 +38,14 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy> struct _IterOps; template <class _AlgPolicy>
struct _IterOps;
#if _LIBCPP_STD_VER >= 20 #if _LIBCPP_STD_VER >= 20
struct _RangeAlgPolicy {}; struct _RangeAlgPolicy {};
template <> template <>
struct _IterOps<_RangeAlgPolicy> { struct _IterOps<_RangeAlgPolicy> {
template <class _Iter> template <class _Iter>
using __value_type = iter_value_t<_Iter>; using __value_type = iter_value_t<_Iter>;
@ -55,12 +55,12 @@ struct _IterOps<_RangeAlgPolicy> {
template <class _Iter> template <class _Iter>
using __difference_type = iter_difference_t<_Iter>; using __difference_type = iter_difference_t<_Iter>;
static constexpr auto advance = ranges::advance; static constexpr auto advance = ranges::advance;
static constexpr auto distance = ranges::distance; static constexpr auto distance = ranges::distance;
static constexpr auto __iter_move = ranges::iter_move; static constexpr auto __iter_move = ranges::iter_move;
static constexpr auto iter_swap = ranges::iter_swap; static constexpr auto iter_swap = ranges::iter_swap;
static constexpr auto next = ranges::next; static constexpr auto next = ranges::next;
static constexpr auto prev = ranges::prev; static constexpr auto prev = ranges::prev;
static constexpr auto __advance_to = ranges::advance; static constexpr auto __advance_to = ranges::advance;
}; };
@ -70,7 +70,6 @@ struct _ClassicAlgPolicy {};
template <> template <>
struct _IterOps<_ClassicAlgPolicy> { struct _IterOps<_ClassicAlgPolicy> {
template <class _Iter> template <class _Iter>
using __value_type = typename iterator_traits<_Iter>::value_type; using __value_type = typename iterator_traits<_Iter>::value_type;
@ -82,15 +81,14 @@ struct _IterOps<_ClassicAlgPolicy> {
// advance // advance
template <class _Iter, class _Distance> template <class _Iter, class _Distance>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static void advance(_Iter& __iter, _Distance __count) {
static void advance(_Iter& __iter, _Distance __count) {
std::advance(__iter, __count); std::advance(__iter, __count);
} }
// distance // distance
template <class _Iter> template <class _Iter>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static typename iterator_traits<_Iter>::difference_type
static typename iterator_traits<_Iter>::difference_type distance(_Iter __first, _Iter __last) { distance(_Iter __first, _Iter __last) {
return std::distance(__first, __last); return std::distance(__first, __last);
} }
@ -101,37 +99,33 @@ struct _IterOps<_ClassicAlgPolicy> {
using __move_t = decltype(std::move(*std::declval<_Iter&>())); using __move_t = decltype(std::move(*std::declval<_Iter&>()));
template <class _Iter> template <class _Iter>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static void __validate_iter_reference() {
static void __validate_iter_reference() { static_assert(
static_assert(is_same<__deref_t<_Iter>, typename iterator_traits<__remove_cvref_t<_Iter> >::reference>::value, is_same<__deref_t<_Iter>, typename iterator_traits<__remove_cvref_t<_Iter> >::reference>::value,
"It looks like your iterator's `iterator_traits<It>::reference` does not match the return type of " "It looks like your iterator's `iterator_traits<It>::reference` does not match the return type of "
"dereferencing the iterator, i.e., calling `*it`. This is undefined behavior according to [input.iterators] " "dereferencing the iterator, i.e., calling `*it`. This is undefined behavior according to [input.iterators] "
"and can lead to dangling reference issues at runtime, so we are flagging this."); "and can lead to dangling reference issues at runtime, so we are flagging this.");
} }
// iter_move // iter_move
template <class _Iter> template <class _Iter, __enable_if_t<is_reference<__deref_t<_Iter> >::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static
// If the result of dereferencing `_Iter` is a reference type, deduce the result of calling `std::move` on it. Note // If the result of dereferencing `_Iter` is a reference type, deduce the result of calling `std::move` on it.
// that the C++03 mode doesn't support `decltype(auto)` as the return type. // Note that the C++03 mode doesn't support `decltype(auto)` as the return type.
__enable_if_t< __move_t<_Iter>
is_reference<__deref_t<_Iter> >::value, __iter_move(_Iter&& __i) {
__move_t<_Iter> >
__iter_move(_Iter&& __i) {
__validate_iter_reference<_Iter>(); __validate_iter_reference<_Iter>();
return std::move(*std::forward<_Iter>(__i)); return std::move(*std::forward<_Iter>(__i));
} }
template <class _Iter> template <class _Iter, __enable_if_t<!is_reference<__deref_t<_Iter> >::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static
// If the result of dereferencing `_Iter` is a value type, deduce the return value of this function to also be a // If the result of dereferencing `_Iter` is a value type, deduce the return value of this function to also be a
// value -- otherwise, after `operator*` returns a temporary, this function would return a dangling reference to that // value -- otherwise, after `operator*` returns a temporary, this function would return a dangling reference to
// temporary. Note that the C++03 mode doesn't support `auto` as the return type. // that temporary. Note that the C++03 mode doesn't support `auto` as the return type.
__enable_if_t< __deref_t<_Iter>
!is_reference<__deref_t<_Iter> >::value, __iter_move(_Iter&& __i) {
__deref_t<_Iter> >
__iter_move(_Iter&& __i) {
__validate_iter_reference<_Iter>(); __validate_iter_reference<_Iter>();
return *std::forward<_Iter>(__i); return *std::forward<_Iter>(__i);
@ -139,36 +133,31 @@ struct _IterOps<_ClassicAlgPolicy> {
// iter_swap // iter_swap
template <class _Iter1, class _Iter2> template <class _Iter1, class _Iter2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static void iter_swap(_Iter1&& __a, _Iter2&& __b) {
static void iter_swap(_Iter1&& __a, _Iter2&& __b) {
std::iter_swap(std::forward<_Iter1>(__a), std::forward<_Iter2>(__b)); std::iter_swap(std::forward<_Iter1>(__a), std::forward<_Iter2>(__b));
} }
// next // next
template <class _Iterator> template <class _Iterator>
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iterator next(_Iterator, _Iterator __last) {
_Iterator next(_Iterator, _Iterator __last) {
return __last; return __last;
} }
template <class _Iter> template <class _Iter>
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 __remove_cvref_t<_Iter>
__remove_cvref_t<_Iter> next(_Iter&& __it, next(_Iter&& __it, typename iterator_traits<__remove_cvref_t<_Iter> >::difference_type __n = 1) {
typename iterator_traits<__remove_cvref_t<_Iter> >::difference_type __n = 1) {
return std::next(std::forward<_Iter>(__it), __n); return std::next(std::forward<_Iter>(__it), __n);
} }
// prev // prev
template <class _Iter> template <class _Iter>
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 __remove_cvref_t<_Iter>
__remove_cvref_t<_Iter> prev(_Iter&& __iter, prev(_Iter&& __iter, typename iterator_traits<__remove_cvref_t<_Iter> >::difference_type __n = 1) {
typename iterator_traits<__remove_cvref_t<_Iter> >::difference_type __n = 1) {
return std::prev(std::forward<_Iter>(__iter), __n); return std::prev(std::forward<_Iter>(__iter), __n);
} }
template <class _Iter> template <class _Iter>
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 void __advance_to(_Iter& __first, _Iter __last) {
void __advance_to(_Iter& __first, _Iter __last) {
__first = __last; __first = __last;
} }
}; };

View File

@ -21,38 +21,35 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Compare, class _InputIterator1, class _InputIterator2> template <class _Compare, class _InputIterator1, class _InputIterator2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __lexicographical_compare(
__lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator1 __first1,
_InputIterator2 __first2, _InputIterator2 __last2, _Compare __comp) _InputIterator1 __last1,
{ _InputIterator2 __first2,
for (; __first2 != __last2; ++__first1, (void) ++__first2) _InputIterator2 __last2,
{ _Compare __comp) {
if (__first1 == __last1 || __comp(*__first1, *__first2)) for (; __first2 != __last2; ++__first1, (void)++__first2) {
return true; if (__first1 == __last1 || __comp(*__first1, *__first2))
if (__comp(*__first2, *__first1)) return true;
return false; if (__comp(*__first2, *__first1))
} return false;
return false; }
return false;
} }
template <class _InputIterator1, class _InputIterator2, class _Compare> template <class _InputIterator1, class _InputIterator2, class _Compare>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool lexicographical_compare(
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator1 __first1,
bool _InputIterator1 __last1,
lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2,
_InputIterator2 __first2, _InputIterator2 __last2, _Compare __comp) _InputIterator2 __last2,
{ _Compare __comp) {
return _VSTD::__lexicographical_compare<__comp_ref_type<_Compare> >(__first1, __last1, __first2, __last2, __comp); return std::__lexicographical_compare<__comp_ref_type<_Compare> >(__first1, __last1, __first2, __last2, __comp);
} }
template <class _InputIterator1, class _InputIterator2> template <class _InputIterator1, class _InputIterator2>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool lexicographical_compare(
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) {
bool return std::lexicographical_compare(__first1, __last1, __first2, __last2, __less<>());
lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2)
{
return _VSTD::lexicographical_compare(__first1, __last1, __first2, __last2, __less<>());
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -28,8 +28,8 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Iter, class _Sent, class _Type, class _Proj, class _Comp> template <class _AlgPolicy, class _Iter, class _Sent, class _Type, class _Proj, class _Comp>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter
_Iter __lower_bound(_Iter __first, _Sent __last, const _Type& __value, _Comp& __comp, _Proj& __proj) { __lower_bound(_Iter __first, _Sent __last, const _Type& __value, _Comp& __comp, _Proj& __proj) {
auto __len = _IterOps<_AlgPolicy>::distance(__first, __last); auto __len = _IterOps<_AlgPolicy>::distance(__first, __last);
while (__len != 0) { while (__len != 0) {
@ -47,17 +47,16 @@ _Iter __lower_bound(_Iter __first, _Sent __last, const _Type& __value, _Comp& __
} }
template <class _ForwardIterator, class _Tp, class _Compare> template <class _ForwardIterator, class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
_ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) {
static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
"The comparator has to be callable");
auto __proj = std::__identity(); auto __proj = std::__identity();
return std::__lower_bound<_ClassicAlgPolicy>(__first, __last, __value, __comp, __proj); return std::__lower_bound<_ClassicAlgPolicy>(__first, __last, __value, __comp, __proj);
} }
template <class _ForwardIterator, class _Tp> template <class _ForwardIterator, class _Tp>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
_ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
return std::lower_bound(__first, __last, __value, __less<>()); return std::lower_bound(__first, __last, __value, __less<>());
} }

View File

@ -27,29 +27,29 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
void __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) { __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) {
__comp_ref_type<_Compare> __comp_ref = __comp; __comp_ref_type<_Compare> __comp_ref = __comp;
using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
difference_type __n = __last - __first; difference_type __n = __last - __first;
if (__n > 1) { if (__n > 1) {
// start from the first parent, there is no need to consider children // start from the first parent, there is no need to consider children
for (difference_type __start = (__n - 2) / 2; __start >= 0; --__start) { for (difference_type __start = (__n - 2) / 2; __start >= 0; --__start) {
std::__sift_down<_AlgPolicy>(__first, __comp_ref, __n, __first + __start); std::__sift_down<_AlgPolicy>(__first, __comp_ref, __n, __first + __start);
} }
} }
} }
template <class _RandomAccessIterator, class _Compare> template <class _RandomAccessIterator, class _Compare>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
void make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
std::__make_heap<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp); std::__make_heap<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp);
} }
template <class _RandomAccessIterator> template <class _RandomAccessIterator>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
void make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) {
std::make_heap(std::move(__first), std::move(__last), __less<>()); std::make_heap(std::move(__first), std::move(__last), __less<>());
} }

View File

@ -36,44 +36,38 @@ struct _ProjectedPred {
: __pred(__pred_arg), __proj(__proj_arg) {} : __pred(__pred_arg), __proj(__proj_arg) {}
template <class _Tp> template <class _Tp>
typename __invoke_of<_Pred&, typename __invoke_of<_Pred&, decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_Tp>())) >::
decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_Tp>())) type _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI
>::type operator()(_Tp&& __v) const {
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI operator()(_Tp&& __v) const {
return std::__invoke(__pred, std::__invoke(__proj, std::forward<_Tp>(__v))); return std::__invoke(__pred, std::__invoke(__proj, std::forward<_Tp>(__v)));
} }
template <class _T1, class _T2> template <class _T1, class _T2>
typename __invoke_of<_Pred&, typename __invoke_of<_Pred&,
decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T1>())), decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T1>())),
decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T2>())) decltype(std::__invoke(std::declval<_Proj&>(),
>::type std::declval<_T2>())) >::type _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI operator()(_T1&& __lhs, _T2&& __rhs) const { operator()(_T1&& __lhs, _T2&& __rhs) const {
return std::__invoke(__pred, return std::__invoke(
std::__invoke(__proj, std::forward<_T1>(__lhs)), __pred, std::__invoke(__proj, std::forward<_T1>(__lhs)), std::__invoke(__proj, std::forward<_T2>(__rhs)));
std::__invoke(__proj, std::forward<_T2>(__rhs)));
} }
}; };
template <class _Pred, template <
class _Proj, class _Pred,
__enable_if_t<!(!is_member_pointer<__decay_t<_Pred> >::value && class _Proj,
__is_identity<__decay_t<_Proj> >::value), __enable_if_t<!(!is_member_pointer<__decay_t<_Pred> >::value && __is_identity<__decay_t<_Proj> >::value), int> = 0>
int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ProjectedPred<_Pred, _Proj> __make_projected(_Pred& __pred, _Proj& __proj) {
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ProjectedPred<_Pred, _Proj>
__make_projected(_Pred& __pred, _Proj& __proj) {
return _ProjectedPred<_Pred, _Proj>(__pred, __proj); return _ProjectedPred<_Pred, _Proj>(__pred, __proj);
} }
// Avoid creating the functor and just use the pristine comparator -- for certain algorithms, this would enable // Avoid creating the functor and just use the pristine comparator -- for certain algorithms, this would enable
// optimizations that rely on the type of the comparator. Additionally, this results in less layers of indirection in // optimizations that rely on the type of the comparator. Additionally, this results in less layers of indirection in
// the call stack when the comparator is invoked, even in an unoptimized build. // the call stack when the comparator is invoked, even in an unoptimized build.
template <class _Pred, template <
class _Proj, class _Pred,
__enable_if_t<!is_member_pointer<__decay_t<_Pred> >::value && class _Proj,
__is_identity<__decay_t<_Proj> >::value, __enable_if_t<!is_member_pointer<__decay_t<_Pred> >::value && __is_identity<__decay_t<_Proj> >::value, int> = 0>
int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Pred& __make_projected(_Pred& __pred, _Proj&) { _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Pred& __make_projected(_Pred& __pred, _Proj&) {
return __pred; return __pred;
} }
@ -87,8 +81,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace ranges { namespace ranges {
template <class _Comp, class _Proj1, class _Proj2> template <class _Comp, class _Proj1, class _Proj2>
_LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __proj2) {
decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __proj2) {
if constexpr (__is_identity<decay_t<_Proj1>>::value && __is_identity<decay_t<_Proj2>>::value && if constexpr (__is_identity<decay_t<_Proj1>>::value && __is_identity<decay_t<_Proj2>>::value &&
!is_member_pointer_v<decay_t<_Comp>>) { !is_member_pointer_v<decay_t<_Comp>>) {
// Avoid creating the lambda and just use the pristine comparator -- for certain algorithms, this would enable // Avoid creating the lambda and just use the pristine comparator -- for certain algorithms, this would enable
@ -96,10 +89,10 @@ decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __p
return __comp; return __comp;
} else { } else {
return [&](auto&& __lhs, auto&& __rhs) { return [&](auto&& __lhs, auto&& __rhs) -> bool {
return std::invoke(__comp, return std::invoke(__comp,
std::invoke(__proj1, std::forward<decltype(__lhs)>(__lhs)), std::invoke(__proj1, std::forward<decltype(__lhs)>(__lhs)),
std::invoke(__proj2, std::forward<decltype(__rhs)>(__rhs))); std::invoke(__proj2, std::forward<decltype(__rhs)>(__rhs)));
}; };
} }
} }

View File

@ -25,41 +25,28 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp, class _Compare> template <class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp&
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) {
const _Tp& return __comp(__a, __b) ? __b : __a;
max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp)
{
return __comp(__a, __b) ? __b : __a;
} }
template <class _Tp> template <class _Tp>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp&
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) {
const _Tp& return std::max(__a, __b, __less<>());
max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b)
{
return _VSTD::max(__a, __b, __less<>());
} }
#ifndef _LIBCPP_CXX03_LANG #ifndef _LIBCPP_CXX03_LANG
template<class _Tp, class _Compare> template <class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 max(initializer_list<_Tp> __t, _Compare __comp) {
_Tp return *std::__max_element<__comp_ref_type<_Compare> >(__t.begin(), __t.end(), __comp);
max(initializer_list<_Tp> __t, _Compare __comp)
{
return *_VSTD::__max_element<__comp_ref_type<_Compare> >(__t.begin(), __t.end(), __comp);
} }
template<class _Tp> template <class _Tp>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp max(initializer_list<_Tp> __t) {
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 return *std::max_element(__t.begin(), __t.end(), __less<>());
_Tp
max(initializer_list<_Tp> __t)
{
return *_VSTD::max_element(__t.begin(), __t.end(), __less<>());
} }
#endif // _LIBCPP_CXX03_LANG #endif // _LIBCPP_CXX03_LANG

View File

@ -22,33 +22,28 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Compare, class _ForwardIterator> template <class _Compare, class _ForwardIterator>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
__max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) __max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) {
{ static_assert(
static_assert(__has_forward_iterator_category<_ForwardIterator>::value, __has_forward_iterator_category<_ForwardIterator>::value, "std::max_element requires a ForwardIterator");
"std::max_element requires a ForwardIterator"); if (__first != __last) {
if (__first != __last) _ForwardIterator __i = __first;
{ while (++__i != __last)
_ForwardIterator __i = __first; if (__comp(*__first, *__i))
while (++__i != __last) __first = __i;
if (__comp(*__first, *__i)) }
__first = __i; return __first;
}
return __first;
} }
template <class _ForwardIterator, class _Compare> template <class _ForwardIterator, class _Compare>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) {
{ return std::__max_element<__comp_ref_type<_Compare> >(__first, __last, __comp);
return _VSTD::__max_element<__comp_ref_type<_Compare> >(__first, __last, __comp);
} }
template <class _ForwardIterator> template <class _ForwardIterator>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
max_element(_ForwardIterator __first, _ForwardIterator __last) max_element(_ForwardIterator __first, _ForwardIterator __last) {
{ return std::max_element(__first, __last, __less<>());
return _VSTD::max_element(__first, __last, __less<>());
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -22,45 +22,46 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator __merge(
_OutputIterator _InputIterator1 __first1,
__merge(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) _InputIterator2 __first2,
{ _InputIterator2 __last2,
for (; __first1 != __last1; ++__result) _OutputIterator __result,
{ _Compare __comp) {
if (__first2 == __last2) for (; __first1 != __last1; ++__result) {
return _VSTD::copy(__first1, __last1, __result); if (__first2 == __last2)
if (__comp(*__first2, *__first1)) return std::copy(__first1, __last1, __result);
{ if (__comp(*__first2, *__first1)) {
*__result = *__first2; *__result = *__first2;
++__first2; ++__first2;
} } else {
else *__result = *__first1;
{ ++__first1;
*__result = *__first1;
++__first1;
}
} }
return _VSTD::copy(__first2, __last2, __result); }
return std::copy(__first2, __last2, __result);
} }
template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare> template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
_OutputIterator merge(_InputIterator1 __first1,
merge(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) _InputIterator2 __first2,
{ _InputIterator2 __last2,
return _VSTD::__merge<__comp_ref_type<_Compare> >(__first1, __last1, __first2, __last2, __result, __comp); _OutputIterator __result,
_Compare __comp) {
return std::__merge<__comp_ref_type<_Compare> >(__first1, __last1, __first2, __last2, __result, __comp);
} }
template <class _InputIterator1, class _InputIterator2, class _OutputIterator> template <class _InputIterator1, class _InputIterator2, class _OutputIterator>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
_OutputIterator merge(_InputIterator1 __first1,
merge(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) _InputIterator2 __first2,
{ _InputIterator2 __last2,
return _VSTD::merge(__first1, __last1, __first2, __last2, __result, __less<>()); _OutputIterator __result) {
return std::merge(__first1, __last1, __first2, __last2, __result, __less<>());
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -25,41 +25,28 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp, class _Compare> template <class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp&
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) {
const _Tp& return __comp(__b, __a) ? __b : __a;
min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp)
{
return __comp(__b, __a) ? __b : __a;
} }
template <class _Tp> template <class _Tp>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp&
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) {
const _Tp& return std::min(__a, __b, __less<>());
min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b)
{
return _VSTD::min(__a, __b, __less<>());
} }
#ifndef _LIBCPP_CXX03_LANG #ifndef _LIBCPP_CXX03_LANG
template<class _Tp, class _Compare> template <class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 min(initializer_list<_Tp> __t, _Compare __comp) {
_Tp return *std::__min_element<__comp_ref_type<_Compare> >(__t.begin(), __t.end(), __comp);
min(initializer_list<_Tp> __t, _Compare __comp)
{
return *_VSTD::__min_element<__comp_ref_type<_Compare> >(__t.begin(), __t.end(), __comp);
} }
template<class _Tp> template <class _Tp>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp min(initializer_list<_Tp> __t) {
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 return *std::min_element(__t.begin(), __t.end(), __less<>());
_Tp
min(initializer_list<_Tp> __t)
{
return *_VSTD::min_element(__t.begin(), __t.end(), __less<>());
} }
#endif // _LIBCPP_CXX03_LANG #endif // _LIBCPP_CXX03_LANG

View File

@ -28,8 +28,8 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Comp, class _Iter, class _Sent, class _Proj> template <class _Comp, class _Iter, class _Sent, class _Proj>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter
_Iter __min_element(_Iter __first, _Sent __last, _Comp __comp, _Proj& __proj) { __min_element(_Iter __first, _Sent __last, _Comp __comp, _Proj& __proj) {
if (__first == __last) if (__first == __last)
return __first; return __first;
@ -42,29 +42,26 @@ _Iter __min_element(_Iter __first, _Sent __last, _Comp __comp, _Proj& __proj) {
} }
template <class _Comp, class _Iter, class _Sent> template <class _Comp, class _Iter, class _Sent>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter __min_element(_Iter __first, _Sent __last, _Comp __comp) {
_Iter __min_element(_Iter __first, _Sent __last, _Comp __comp) {
auto __proj = __identity(); auto __proj = __identity();
return std::__min_element<_Comp>(std::move(__first), std::move(__last), __comp, __proj); return std::__min_element<_Comp>(std::move(__first), std::move(__last), __comp, __proj);
} }
template <class _ForwardIterator, class _Compare> template <class _ForwardIterator, class _Compare>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) {
{ static_assert(
static_assert(__has_forward_iterator_category<_ForwardIterator>::value, __has_forward_iterator_category<_ForwardIterator>::value, "std::min_element requires a ForwardIterator");
"std::min_element requires a ForwardIterator"); static_assert(
static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, __is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable");
"The comparator has to be callable");
return std::__min_element<__comp_ref_type<_Compare> >(std::move(__first), std::move(__last), __comp); return std::__min_element<__comp_ref_type<_Compare> >(std::move(__first), std::move(__last), __comp);
} }
template <class _ForwardIterator> template <class _ForwardIterator>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
min_element(_ForwardIterator __first, _ForwardIterator __last) min_element(_ForwardIterator __first, _ForwardIterator __last) {
{ return std::min_element(__first, __last, __less<>());
return _VSTD::min_element(__first, __last, __less<>());
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -34,7 +34,7 @@ struct min_max_result {
template <class _T2> template <class _T2>
requires convertible_to<const _T1&, _T2> requires convertible_to<const _T1&, _T2>
_LIBCPP_HIDE_FROM_ABI constexpr operator min_max_result<_T2>() const & { _LIBCPP_HIDE_FROM_ABI constexpr operator min_max_result<_T2>() const& {
return {min, max}; return {min, max};
} }

View File

@ -23,43 +23,33 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template<class _Tp, class _Compare> template <class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<const _Tp&, const _Tp&>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) {
pair<const _Tp&, const _Tp&> return __comp(__b, __a) ? pair<const _Tp&, const _Tp&>(__b, __a) : pair<const _Tp&, const _Tp&>(__a, __b);
minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp)
{
return __comp(__b, __a) ? pair<const _Tp&, const _Tp&>(__b, __a) :
pair<const _Tp&, const _Tp&>(__a, __b);
} }
template<class _Tp> template <class _Tp>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<const _Tp&, const _Tp&>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) {
pair<const _Tp&, const _Tp&> return std::minmax(__a, __b, __less<>());
minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b)
{
return std::minmax(__a, __b, __less<>());
} }
#ifndef _LIBCPP_CXX03_LANG #ifndef _LIBCPP_CXX03_LANG
template<class _Tp, class _Compare> template <class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp>
pair<_Tp, _Tp> minmax(initializer_list<_Tp> __t, _Compare __comp) { minmax(initializer_list<_Tp> __t, _Compare __comp) {
static_assert(__is_callable<_Compare, _Tp, _Tp>::value, "The comparator has to be callable"); static_assert(__is_callable<_Compare, _Tp, _Tp>::value, "The comparator has to be callable");
__identity __proj; __identity __proj;
auto __ret = std::__minmax_element_impl(__t.begin(), __t.end(), __comp, __proj); auto __ret = std::__minmax_element_impl(__t.begin(), __t.end(), __comp, __proj);
return pair<_Tp, _Tp>(*__ret.first, *__ret.second); return pair<_Tp, _Tp>(*__ret.first, *__ret.second);
} }
template<class _Tp> template <class _Tp>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 minmax(initializer_list<_Tp> __t) {
pair<_Tp, _Tp> return std::minmax(__t, __less<>());
minmax(initializer_list<_Tp> __t)
{
return std::minmax(__t, __less<>());
} }
#endif // _LIBCPP_CXX03_LANG #endif // _LIBCPP_CXX03_LANG

View File

@ -29,19 +29,18 @@ class _MinmaxElementLessFunc {
_Proj& __proj_; _Proj& __proj_;
public: public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _MinmaxElementLessFunc(_Comp& __comp, _Proj& __proj)
_MinmaxElementLessFunc(_Comp& __comp, _Proj& __proj) : __comp_(__comp), __proj_(__proj) {} : __comp_(__comp), __proj_(__proj) {}
template <class _Iter> template <class _Iter>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator()(_Iter& __it1, _Iter& __it2) {
bool operator()(_Iter& __it1, _Iter& __it2) {
return std::__invoke(__comp_, std::__invoke(__proj_, *__it1), std::__invoke(__proj_, *__it2)); return std::__invoke(__comp_, std::__invoke(__proj_, *__it1), std::__invoke(__proj_, *__it2));
} }
}; };
template <class _Iter, class _Sent, class _Proj, class _Comp> template <class _Iter, class _Sent, class _Proj, class _Comp>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter, _Iter>
pair<_Iter, _Iter> __minmax_element_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { __minmax_element_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __less = _MinmaxElementLessFunc<_Comp, _Proj>(__comp, __proj); auto __less = _MinmaxElementLessFunc<_Comp, _Proj>(__comp, __proj);
pair<_Iter, _Iter> __result(__first, __first); pair<_Iter, _Iter> __result(__first, __first);
@ -66,8 +65,8 @@ pair<_Iter, _Iter> __minmax_element_impl(_Iter __first, _Sent __last, _Comp& __c
if (__less(__first, __i)) { if (__less(__first, __i)) {
if (__less(__first, __result.first)) if (__less(__first, __result.first))
__result.first = __first; __result.first = __first;
if (!__less(__i, __result.second)) if (!__less(__i, __result.second))
__result.second = __i; __result.second = __i;
} else { } else {
if (__less(__i, __result.first)) if (__less(__i, __result.first))
__result.first = __i; __result.first = __i;
@ -80,21 +79,21 @@ pair<_Iter, _Iter> __minmax_element_impl(_Iter __first, _Sent __last, _Comp& __c
} }
template <class _ForwardIterator, class _Compare> template <class _ForwardIterator, class _Compare>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_ForwardIterator, _ForwardIterator>
pair<_ForwardIterator, _ForwardIterator>
minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) {
static_assert(__has_forward_iterator_category<_ForwardIterator>::value, static_assert(
"std::minmax_element requires a ForwardIterator"); __has_forward_iterator_category<_ForwardIterator>::value, "std::minmax_element requires a ForwardIterator");
static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, static_assert(
"The comparator has to be callable"); __is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable");
auto __proj = __identity(); auto __proj = __identity();
return std::__minmax_element_impl(__first, __last, __comp, __proj); return std::__minmax_element_impl(__first, __last, __comp, __proj);
} }
template <class _ForwardIterator> template <class _ForwardIterator>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
pair<_ForwardIterator, _ForwardIterator> minmax_element(_ForwardIterator __first, _ForwardIterator __last) { pair<_ForwardIterator, _ForwardIterator>
return std::minmax_element(__first, __last, __less<>()); minmax_element(_ForwardIterator __first, _ForwardIterator __last) {
return std::minmax_element(__first, __last, __less<>());
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -22,9 +22,8 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2>
_LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) {
mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) {
for (; __first1 != __last1; ++__first1, (void)++__first2) for (; __first1 != __last1; ++__first1, (void)++__first2)
if (!__pred(*__first1, *__first2)) if (!__pred(*__first1, *__first2))
break; break;
@ -32,18 +31,19 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY
} }
template <class _InputIterator1, class _InputIterator2> template <class _InputIterator1, class _InputIterator2>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2>
_LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) {
mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) {
return std::mismatch(__first1, __last1, __first2, __equal_to()); return std::mismatch(__first1, __last1, __first2, __equal_to());
} }
#if _LIBCPP_STD_VER >= 14 #if _LIBCPP_STD_VER >= 14
template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2>
_LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1,
mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _InputIterator1 __last1,
_BinaryPredicate __pred) { _InputIterator2 __first2,
_InputIterator2 __last2,
_BinaryPredicate __pred) {
for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2) for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2)
if (!__pred(*__first1, *__first2)) if (!__pred(*__first1, *__first2))
break; break;
@ -51,9 +51,8 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY
} }
template <class _InputIterator1, class _InputIterator2> template <class _InputIterator1, class _InputIterator2>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2>
_LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) {
mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) {
return std::mismatch(__first1, __last1, __first2, __last2, __equal_to()); return std::mismatch(__first1, __last1, __first2, __last2, __equal_to());
} }
#endif #endif

View File

@ -52,9 +52,10 @@ struct __move_loop {
_OutIter& __result_; _OutIter& __result_;
_LIBCPP_HIDE_FROM_ABI _MoveSegment(_OutIter& __result) : __result_(__result) {} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit _MoveSegment(_OutIter& __result)
: __result_(__result) {}
_LIBCPP_HIDE_FROM_ABI void _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
operator()(typename _Traits::__local_iterator __lfirst, typename _Traits::__local_iterator __llast) { operator()(typename _Traits::__local_iterator __lfirst, typename _Traits::__local_iterator __llast) {
__result_ = std::__move<_AlgPolicy>(__lfirst, __llast, std::move(__result_)).second; __result_ = std::__move<_AlgPolicy>(__lfirst, __llast, std::move(__result_)).second;
} }
@ -98,8 +99,7 @@ struct __move_loop {
struct __move_trivial { struct __move_trivial {
// At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
template <class _In, class _Out, template <class _In, class _Out, __enable_if_t<__can_lower_move_assignment_to_memmove<_In, _Out>::value, int> = 0>
__enable_if_t<__can_lower_move_assignment_to_memmove<_In, _Out>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
operator()(_In* __first, _In* __last, _Out* __result) const { operator()(_In* __first, _In* __last, _Out* __result) const {
return std::__copy_trivial_impl(__first, __last, __result); return std::__copy_trivial_impl(__first, __last, __result);

View File

@ -108,8 +108,7 @@ struct __move_backward_loop {
struct __move_backward_trivial { struct __move_backward_trivial {
// At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
template <class _In, class _Out, template <class _In, class _Out, __enable_if_t<__can_lower_move_assignment_to_memmove<_In, _Out>::value, int> = 0>
__enable_if_t<__can_lower_move_assignment_to_memmove<_In, _Out>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
operator()(_In* __first, _In* __last, _Out* __result) const { operator()(_In* __first, _In* __last, _Out* __result) const {
return std::__copy_backward_trivial_impl(__first, __last, __result); return std::__copy_backward_trivial_impl(__first, __last, __result);
@ -120,14 +119,15 @@ template <class _AlgPolicy, class _BidirectionalIterator1, class _Sentinel, clas
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1, _BidirectionalIterator2> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1, _BidirectionalIterator2>
__move_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result) { __move_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result) {
static_assert(std::is_copy_constructible<_BidirectionalIterator1>::value && static_assert(std::is_copy_constructible<_BidirectionalIterator1>::value &&
std::is_copy_constructible<_BidirectionalIterator1>::value, "Iterators must be copy constructible."); std::is_copy_constructible<_BidirectionalIterator1>::value,
"Iterators must be copy constructible.");
return std::__dispatch_copy_or_move<_AlgPolicy, __move_backward_loop<_AlgPolicy>, __move_backward_trivial>( return std::__dispatch_copy_or_move<_AlgPolicy, __move_backward_loop<_AlgPolicy>, __move_backward_trivial>(
std::move(__first), std::move(__last), std::move(__result)); std::move(__first), std::move(__last), std::move(__result));
} }
template <class _BidirectionalIterator1, class _BidirectionalIterator2> template <class _BidirectionalIterator1, class _BidirectionalIterator2>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _BidirectionalIterator2 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _BidirectionalIterator2
move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _BidirectionalIterator2 __result) { move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _BidirectionalIterator2 __result) {
return std::__move_backward<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)).second; return std::__move_backward<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)).second;
} }

View File

@ -22,56 +22,54 @@
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _BidirectionalIterator, class _Sentinel> template <class _AlgPolicy, class _Compare, class _BidirectionalIterator, class _Sentinel>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator, bool> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator, bool>
__next_permutation(_BidirectionalIterator __first, _Sentinel __last, _Compare&& __comp) __next_permutation(_BidirectionalIterator __first, _Sentinel __last, _Compare&& __comp) {
{ using _Result = pair<_BidirectionalIterator, bool>;
using _Result = pair<_BidirectionalIterator, bool>;
_BidirectionalIterator __last_iter = _IterOps<_AlgPolicy>::next(__first, __last); _BidirectionalIterator __last_iter = _IterOps<_AlgPolicy>::next(__first, __last);
_BidirectionalIterator __i = __last_iter; _BidirectionalIterator __i = __last_iter;
if (__first == __last || __first == --__i) if (__first == __last || __first == --__i)
return _Result(std::move(__last_iter), false); return _Result(std::move(__last_iter), false);
while (true) while (true) {
{ _BidirectionalIterator __ip1 = __i;
_BidirectionalIterator __ip1 = __i; if (__comp(*--__i, *__ip1)) {
if (__comp(*--__i, *__ip1)) _BidirectionalIterator __j = __last_iter;
{ while (!__comp(*__i, *--__j))
_BidirectionalIterator __j = __last_iter; ;
while (!__comp(*__i, *--__j)) _IterOps<_AlgPolicy>::iter_swap(__i, __j);
; std::__reverse<_AlgPolicy>(__ip1, __last_iter);
_IterOps<_AlgPolicy>::iter_swap(__i, __j); return _Result(std::move(__last_iter), true);
std::__reverse<_AlgPolicy>(__ip1, __last_iter);
return _Result(std::move(__last_iter), true);
}
if (__i == __first)
{
std::__reverse<_AlgPolicy>(__first, __last_iter);
return _Result(std::move(__last_iter), false);
}
} }
if (__i == __first) {
std::__reverse<_AlgPolicy>(__first, __last_iter);
return _Result(std::move(__last_iter), false);
}
}
} }
template <class _BidirectionalIterator, class _Compare> template <class _BidirectionalIterator, class _Compare>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
bool next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) {
next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp)
{
return std::__next_permutation<_ClassicAlgPolicy>( return std::__next_permutation<_ClassicAlgPolicy>(
std::move(__first), std::move(__last), static_cast<__comp_ref_type<_Compare> >(__comp)).second; std::move(__first), std::move(__last), static_cast<__comp_ref_type<_Compare> >(__comp))
.second;
} }
template <class _BidirectionalIterator> template <class _BidirectionalIterator>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
bool next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last) {
next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last) return std::next_permutation(__first, __last, __less<>());
{
return _VSTD::next_permutation(__first, __last, __less<>());
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_NEXT_PERMUTATION_H #endif // _LIBCPP___ALGORITHM_NEXT_PERMUTATION_H

View File

@ -19,7 +19,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Predicate> template <class _InputIterator, class _Predicate>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
for (; __first != __last; ++__first) for (; __first != __last; ++__first)
if (__pred(*__first)) if (__pred(*__first))

View File

@ -13,6 +13,7 @@
#include <__algorithm/comp_ref_type.h> #include <__algorithm/comp_ref_type.h>
#include <__algorithm/iterator_operations.h> #include <__algorithm/iterator_operations.h>
#include <__algorithm/sort.h> #include <__algorithm/sort.h>
#include <__assert>
#include <__config> #include <__config>
#include <__debug_utils/randomize_range.h> #include <__debug_utils/randomize_range.h>
#include <__iterator/iterator_traits.h> #include <__iterator/iterator_traits.h>
@ -22,209 +23,212 @@
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template<class _Compare, class _RandomAccessIterator> template <class _Compare, class _RandomAccessIterator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool __nth_element_find_guard(
__nth_element_find_guard(_RandomAccessIterator& __i, _RandomAccessIterator& __j, _RandomAccessIterator& __i, _RandomAccessIterator& __j, _RandomAccessIterator __m, _Compare __comp) {
_RandomAccessIterator __m, _Compare __comp) // manually guard downward moving __j against __i
{ while (true) {
// manually guard downward moving __j against __i if (__i == --__j) {
while (true) { return false;
if (__i == --__j) {
return false;
}
if (__comp(*__j, *__m)) {
return true; // found guard for downward moving __j, now use unguarded partition
}
} }
if (__comp(*__j, *__m)) {
return true; // found guard for downward moving __j, now use unguarded partition
}
}
} }
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
__nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp) // NOLINTNEXTLINE(readability-function-cognitive-complexity)
{ __nth_element(
using _Ops = _IterOps<_AlgPolicy>; _RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp) {
using _Ops = _IterOps<_AlgPolicy>;
// _Compare is known to be a reference type // _Compare is known to be a reference type
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
const difference_type __limit = 7; const difference_type __limit = 7;
while (true) while (true) {
{ if (__nth == __last)
if (__nth == __last) return;
return; difference_type __len = __last - __first;
difference_type __len = __last - __first; switch (__len) {
switch (__len) case 0:
{ case 1:
case 0: return;
case 1: case 2:
return; if (__comp(*--__last, *__first))
case 2: _Ops::iter_swap(__first, __last);
if (__comp(*--__last, *__first)) return;
_Ops::iter_swap(__first, __last); case 3: {
return; _RandomAccessIterator __m = __first;
case 3: std::__sort3<_AlgPolicy, _Compare>(__first, ++__m, --__last, __comp);
{ return;
_RandomAccessIterator __m = __first;
std::__sort3<_AlgPolicy, _Compare>(__first, ++__m, --__last, __comp);
return;
}
}
if (__len <= __limit)
{
std::__selection_sort<_AlgPolicy, _Compare>(__first, __last, __comp);
return;
}
// __len > __limit >= 3
_RandomAccessIterator __m = __first + __len/2;
_RandomAccessIterator __lm1 = __last;
unsigned __n_swaps = std::__sort3<_AlgPolicy, _Compare>(__first, __m, --__lm1, __comp);
// *__m is median
// partition [__first, __m) < *__m and *__m <= [__m, __last)
// (this inhibits tossing elements equivalent to __m around unnecessarily)
_RandomAccessIterator __i = __first;
_RandomAccessIterator __j = __lm1;
// j points beyond range to be tested, *__lm1 is known to be <= *__m
// The search going up is known to be guarded but the search coming down isn't.
// Prime the downward search with a guard.
if (!__comp(*__i, *__m)) // if *__first == *__m
{
// *__first == *__m, *__first doesn't go in first part
if (_VSTD::__nth_element_find_guard<_Compare>(__i, __j, __m, __comp)) {
_Ops::iter_swap(__i, __j);
++__n_swaps;
} else {
// *__first == *__m, *__m <= all other elements
// Partition instead into [__first, __i) == *__first and *__first < [__i, __last)
++__i; // __first + 1
__j = __last;
if (!__comp(*__first, *--__j)) { // we need a guard if *__first == *(__last-1)
while (true) {
if (__i == __j) {
return; // [__first, __last) all equivalent elements
} else if (__comp(*__first, *__i)) {
_Ops::iter_swap(__i, __j);
++__n_swaps;
++__i;
break;
}
++__i;
}
}
// [__first, __i) == *__first and *__first < [__j, __last) and __j == __last - 1
if (__i == __j) {
return;
}
while (true) {
while (!__comp(*__first, *__i))
++__i;
while (__comp(*__first, *--__j))
;
if (__i >= __j)
break;
_Ops::iter_swap(__i, __j);
++__n_swaps;
++__i;
}
// [__first, __i) == *__first and *__first < [__i, __last)
// The first part is sorted,
if (__nth < __i) {
return;
}
// __nth_element the second part
// _VSTD::__nth_element<_Compare>(__i, __nth, __last, __comp);
__first = __i;
continue;
}
}
++__i;
// j points beyond range to be tested, *__lm1 is known to be <= *__m
// if not yet partitioned...
if (__i < __j)
{
// known that *(__i - 1) < *__m
while (true)
{
// __m still guards upward moving __i
while (__comp(*__i, *__m))
++__i;
// It is now known that a guard exists for downward moving __j
while (!__comp(*--__j, *__m))
;
if (__i >= __j)
break;
_Ops::iter_swap(__i, __j);
++__n_swaps;
// It is known that __m != __j
// If __m just moved, follow it
if (__m == __i)
__m = __j;
++__i;
}
}
// [__first, __i) < *__m and *__m <= [__i, __last)
if (__i != __m && __comp(*__m, *__i))
{
_Ops::iter_swap(__i, __m);
++__n_swaps;
}
// [__first, __i) < *__i and *__i <= [__i+1, __last)
if (__nth == __i)
return;
if (__n_swaps == 0)
{
// We were given a perfectly partitioned sequence. Coincidence?
if (__nth < __i)
{
// Check for [__first, __i) already sorted
__j = __m = __first;
while (true) {
if (++__j == __i) {
// [__first, __i) sorted
return;
}
if (__comp(*__j, *__m)) {
// not yet sorted, so sort
break;
}
__m = __j;
}
}
else
{
// Check for [__i, __last) already sorted
__j = __m = __i;
while (true) {
if (++__j == __last) {
// [__i, __last) sorted
return;
}
if (__comp(*__j, *__m)) {
// not yet sorted, so sort
break;
}
__m = __j;
}
}
}
// __nth_element on range containing __nth
if (__nth < __i)
{
// _VSTD::__nth_element<_Compare>(__first, __nth, __i, __comp);
__last = __i;
}
else
{
// _VSTD::__nth_element<_Compare>(__i+1, __nth, __last, __comp);
__first = ++__i;
}
} }
}
if (__len <= __limit) {
std::__selection_sort<_AlgPolicy, _Compare>(__first, __last, __comp);
return;
}
// __len > __limit >= 3
_RandomAccessIterator __m = __first + __len / 2;
_RandomAccessIterator __lm1 = __last;
unsigned __n_swaps = std::__sort3<_AlgPolicy, _Compare>(__first, __m, --__lm1, __comp);
// *__m is median
// partition [__first, __m) < *__m and *__m <= [__m, __last)
// (this inhibits tossing elements equivalent to __m around unnecessarily)
_RandomAccessIterator __i = __first;
_RandomAccessIterator __j = __lm1;
// j points beyond range to be tested, *__lm1 is known to be <= *__m
// The search going up is known to be guarded but the search coming down isn't.
// Prime the downward search with a guard.
if (!__comp(*__i, *__m)) // if *__first == *__m
{
// *__first == *__m, *__first doesn't go in first part
if (std::__nth_element_find_guard<_Compare>(__i, __j, __m, __comp)) {
_Ops::iter_swap(__i, __j);
++__n_swaps;
} else {
// *__first == *__m, *__m <= all other elements
// Partition instead into [__first, __i) == *__first and *__first < [__i, __last)
++__i; // __first + 1
__j = __last;
if (!__comp(*__first, *--__j)) { // we need a guard if *__first == *(__last-1)
while (true) {
if (__i == __j) {
return; // [__first, __last) all equivalent elements
} else if (__comp(*__first, *__i)) {
_Ops::iter_swap(__i, __j);
++__n_swaps;
++__i;
break;
}
++__i;
}
}
// [__first, __i) == *__first and *__first < [__j, __last) and __j == __last - 1
if (__i == __j) {
return;
}
while (true) {
while (!__comp(*__first, *__i)) {
++__i;
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__i != __last,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
}
do {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__j != __first,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
--__j;
} while (__comp(*__first, *__j));
if (__i >= __j)
break;
_Ops::iter_swap(__i, __j);
++__n_swaps;
++__i;
}
// [__first, __i) == *__first and *__first < [__i, __last)
// The first part is sorted,
if (__nth < __i) {
return;
}
// __nth_element the second part
// std::__nth_element<_Compare>(__i, __nth, __last, __comp);
__first = __i;
continue;
}
}
++__i;
// j points beyond range to be tested, *__lm1 is known to be <= *__m
// if not yet partitioned...
if (__i < __j) {
// known that *(__i - 1) < *__m
while (true) {
// __m still guards upward moving __i
while (__comp(*__i, *__m)) {
++__i;
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__i != __last,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
}
// It is now known that a guard exists for downward moving __j
do {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__j != __first,
"Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?");
--__j;
} while (!__comp(*__j, *__m));
if (__i >= __j)
break;
_Ops::iter_swap(__i, __j);
++__n_swaps;
// It is known that __m != __j
// If __m just moved, follow it
if (__m == __i)
__m = __j;
++__i;
}
}
// [__first, __i) < *__m and *__m <= [__i, __last)
if (__i != __m && __comp(*__m, *__i)) {
_Ops::iter_swap(__i, __m);
++__n_swaps;
}
// [__first, __i) < *__i and *__i <= [__i+1, __last)
if (__nth == __i)
return;
if (__n_swaps == 0) {
// We were given a perfectly partitioned sequence. Coincidence?
if (__nth < __i) {
// Check for [__first, __i) already sorted
__j = __m = __first;
while (true) {
if (++__j == __i) {
// [__first, __i) sorted
return;
}
if (__comp(*__j, *__m)) {
// not yet sorted, so sort
break;
}
__m = __j;
}
} else {
// Check for [__i, __last) already sorted
__j = __m = __i;
while (true) {
if (++__j == __last) {
// [__i, __last) sorted
return;
}
if (__comp(*__j, *__m)) {
// not yet sorted, so sort
break;
}
__m = __j;
}
}
}
// __nth_element on range containing __nth
if (__nth < __i) {
// std::__nth_element<_Compare>(__first, __nth, __i, __comp);
__last = __i;
} else {
// std::__nth_element<_Compare>(__i+1, __nth, __last, __comp);
__first = ++__i;
}
}
} }
template <class _AlgPolicy, class _RandomAccessIterator, class _Compare> template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __nth_element_impl(
void __nth_element_impl(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare& __comp) {
_Compare& __comp) {
if (__nth == __last) if (__nth == __last)
return; return;
@ -239,18 +243,19 @@ void __nth_element_impl(_RandomAccessIterator __first, _RandomAccessIterator __n
} }
template <class _RandomAccessIterator, class _Compare> template <class _RandomAccessIterator, class _Compare>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
void nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp) {
_Compare __comp) {
std::__nth_element_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__nth), std::move(__last), __comp); std::__nth_element_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__nth), std::move(__last), __comp);
} }
template <class _RandomAccessIterator> template <class _RandomAccessIterator>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
void nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last) { nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last) {
std::nth_element(std::move(__first), std::move(__nth), std::move(__last), __less<>()); std::nth_element(std::move(__first), std::move(__nth), std::move(__last), __less<>());
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_NTH_ELEMENT_H #endif // _LIBCPP___ALGORITHM_NTH_ELEMENT_H

View File

@ -26,11 +26,13 @@
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, class _Sentinel> template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, class _Sentinel>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator __partial_sort_impl(
_RandomAccessIterator __partial_sort_impl(
_RandomAccessIterator __first, _RandomAccessIterator __middle, _Sentinel __last, _Compare&& __comp) { _RandomAccessIterator __first, _RandomAccessIterator __middle, _Sentinel __last, _Compare&& __comp) {
if (__first == __middle) { if (__first == __middle) {
return _IterOps<_AlgPolicy>::next(__middle, __last); return _IterOps<_AlgPolicy>::next(__middle, __last);
@ -39,14 +41,12 @@ _RandomAccessIterator __partial_sort_impl(
std::__make_heap<_AlgPolicy>(__first, __middle, __comp); std::__make_heap<_AlgPolicy>(__first, __middle, __comp);
typename iterator_traits<_RandomAccessIterator>::difference_type __len = __middle - __first; typename iterator_traits<_RandomAccessIterator>::difference_type __len = __middle - __first;
_RandomAccessIterator __i = __middle; _RandomAccessIterator __i = __middle;
for (; __i != __last; ++__i) for (; __i != __last; ++__i) {
{ if (__comp(*__i, *__first)) {
if (__comp(*__i, *__first)) _IterOps<_AlgPolicy>::iter_swap(__i, __first);
{ std::__sift_down<_AlgPolicy>(__first, __comp, __len, __first);
_IterOps<_AlgPolicy>::iter_swap(__i, __first); }
std::__sift_down<_AlgPolicy>(__first, __comp, __len, __first);
}
} }
std::__sort_heap<_AlgPolicy>(std::move(__first), std::move(__middle), __comp); std::__sort_heap<_AlgPolicy>(std::move(__first), std::move(__middle), __comp);
@ -54,11 +54,10 @@ _RandomAccessIterator __partial_sort_impl(
} }
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, class _Sentinel> template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, class _Sentinel>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator
_RandomAccessIterator __partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _Sentinel __last, __partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _Sentinel __last, _Compare& __comp) {
_Compare& __comp) {
if (__first == __middle) if (__first == __middle)
return _IterOps<_AlgPolicy>::next(__middle, __last); return _IterOps<_AlgPolicy>::next(__middle, __last);
std::__debug_randomize_range<_AlgPolicy>(__first, __last); std::__debug_randomize_range<_AlgPolicy>(__first, __last);
@ -71,11 +70,8 @@ _RandomAccessIterator __partial_sort(_RandomAccessIterator __first, _RandomAcces
} }
template <class _RandomAccessIterator, class _Compare> template <class _RandomAccessIterator, class _Compare>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void partial_sort(
void _RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, _Compare __comp) {
partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last,
_Compare __comp)
{
static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible."); static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible.");
static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable."); static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable.");
@ -83,13 +79,13 @@ partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _Ran
} }
template <class _RandomAccessIterator> template <class _RandomAccessIterator>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
void partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last) {
partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last) std::partial_sort(__first, __middle, __last, __less<>());
{
_VSTD::partial_sort(__first, __middle, __last, __less<>());
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PARTIAL_SORT_H #endif // _LIBCPP___ALGORITHM_PARTIAL_SORT_H

View File

@ -28,60 +28,79 @@
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, template <class _AlgPolicy,
class _InputIterator, class _Sentinel1, class _RandomAccessIterator, class _Sentinel2, class _Compare,
class _Proj1, class _Proj2> class _InputIterator,
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator, _RandomAccessIterator> class _Sentinel1,
__partial_sort_copy(_InputIterator __first, _Sentinel1 __last, class _RandomAccessIterator,
_RandomAccessIterator __result_first, _Sentinel2 __result_last, class _Sentinel2,
_Compare&& __comp, _Proj1&& __proj1, _Proj2&& __proj2) class _Proj1,
{ class _Proj2>
_RandomAccessIterator __r = __result_first; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator, _RandomAccessIterator> __partial_sort_copy(
auto&& __projected_comp = std::__make_projected(__comp, __proj2); _InputIterator __first,
_Sentinel1 __last,
_RandomAccessIterator __result_first,
_Sentinel2 __result_last,
_Compare&& __comp,
_Proj1&& __proj1,
_Proj2&& __proj2) {
_RandomAccessIterator __r = __result_first;
auto&& __projected_comp = std::__make_projected(__comp, __proj2);
if (__r != __result_last) if (__r != __result_last) {
{ for (; __first != __last && __r != __result_last; ++__first, (void)++__r)
for (; __first != __last && __r != __result_last; ++__first, (void) ++__r) *__r = *__first;
*__r = *__first; std::__make_heap<_AlgPolicy>(__result_first, __r, __projected_comp);
std::__make_heap<_AlgPolicy>(__result_first, __r, __projected_comp); typename iterator_traits<_RandomAccessIterator>::difference_type __len = __r - __result_first;
typename iterator_traits<_RandomAccessIterator>::difference_type __len = __r - __result_first; for (; __first != __last; ++__first)
for (; __first != __last; ++__first) if (std::__invoke(__comp, std::__invoke(__proj1, *__first), std::__invoke(__proj2, *__result_first))) {
if (std::__invoke(__comp, std::__invoke(__proj1, *__first), std::__invoke(__proj2, *__result_first))) { *__result_first = *__first;
*__result_first = *__first; std::__sift_down<_AlgPolicy>(__result_first, __projected_comp, __len, __result_first);
std::__sift_down<_AlgPolicy>(__result_first, __projected_comp, __len, __result_first); }
} std::__sort_heap<_AlgPolicy>(__result_first, __r, __projected_comp);
std::__sort_heap<_AlgPolicy>(__result_first, __r, __projected_comp); }
}
return pair<_InputIterator, _RandomAccessIterator>( return pair<_InputIterator, _RandomAccessIterator>(
_IterOps<_AlgPolicy>::next(std::move(__first), std::move(__last)), std::move(__r)); _IterOps<_AlgPolicy>::next(std::move(__first), std::move(__last)), std::move(__r));
} }
template <class _InputIterator, class _RandomAccessIterator, class _Compare> template <class _InputIterator, class _RandomAccessIterator, class _Compare>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator partial_sort_copy(
_RandomAccessIterator _InputIterator __first,
partial_sort_copy(_InputIterator __first, _InputIterator __last, _InputIterator __last,
_RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp) _RandomAccessIterator __result_first,
{ _RandomAccessIterator __result_last,
static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__result_first)>::value, _Compare __comp) {
"Comparator has to be callable"); static_assert(
__is_callable<_Compare, decltype(*__first), decltype(*__result_first)>::value, "Comparator has to be callable");
auto __result = std::__partial_sort_copy<_ClassicAlgPolicy>(__first, __last, __result_first, __result_last, auto __result = std::__partial_sort_copy<_ClassicAlgPolicy>(
static_cast<__comp_ref_type<_Compare> >(__comp), __identity(), __identity()); __first,
__last,
__result_first,
__result_last,
static_cast<__comp_ref_type<_Compare> >(__comp),
__identity(),
__identity());
return __result.second; return __result.second;
} }
template <class _InputIterator, class _RandomAccessIterator> template <class _InputIterator, class _RandomAccessIterator>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator partial_sort_copy(
_RandomAccessIterator _InputIterator __first,
partial_sort_copy(_InputIterator __first, _InputIterator __last, _InputIterator __last,
_RandomAccessIterator __result_first, _RandomAccessIterator __result_last) _RandomAccessIterator __result_first,
{ _RandomAccessIterator __result_last) {
return _VSTD::partial_sort_copy(__first, __last, __result_first, __result_last, __less<>()); return std::partial_sort_copy(__first, __last, __result_first, __result_last, __less<>());
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PARTIAL_SORT_COPY_H #endif // _LIBCPP___ALGORITHM_PARTIAL_SORT_COPY_H

View File

@ -19,74 +19,65 @@
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Predicate, class _AlgPolicy, class _ForwardIterator, class _Sentinel> template <class _Predicate, class _AlgPolicy, class _ForwardIterator, class _Sentinel>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator>
__partition_impl(_ForwardIterator __first, _Sentinel __last, _Predicate __pred, forward_iterator_tag) __partition_impl(_ForwardIterator __first, _Sentinel __last, _Predicate __pred, forward_iterator_tag) {
{ while (true) {
while (true) if (__first == __last)
{ return std::make_pair(std::move(__first), std::move(__first));
if (__first == __last) if (!__pred(*__first))
return std::make_pair(std::move(__first), std::move(__first)); break;
if (!__pred(*__first)) ++__first;
break; }
++__first;
}
_ForwardIterator __p = __first; _ForwardIterator __p = __first;
while (++__p != __last) while (++__p != __last) {
{ if (__pred(*__p)) {
if (__pred(*__p)) _IterOps<_AlgPolicy>::iter_swap(__first, __p);
{ ++__first;
_IterOps<_AlgPolicy>::iter_swap(__first, __p);
++__first;
}
} }
return std::make_pair(std::move(__first), std::move(__p)); }
return std::make_pair(std::move(__first), std::move(__p));
} }
template <class _Predicate, class _AlgPolicy, class _BidirectionalIterator, class _Sentinel> template <class _Predicate, class _AlgPolicy, class _BidirectionalIterator, class _Sentinel>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator, _BidirectionalIterator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator, _BidirectionalIterator>
__partition_impl(_BidirectionalIterator __first, _Sentinel __sentinel, _Predicate __pred, __partition_impl(_BidirectionalIterator __first, _Sentinel __sentinel, _Predicate __pred, bidirectional_iterator_tag) {
bidirectional_iterator_tag) _BidirectionalIterator __original_last = _IterOps<_AlgPolicy>::next(__first, __sentinel);
{ _BidirectionalIterator __last = __original_last;
_BidirectionalIterator __original_last = _IterOps<_AlgPolicy>::next(__first, __sentinel);
_BidirectionalIterator __last = __original_last;
while (true) while (true) {
{ while (true) {
while (true) if (__first == __last)
{ return std::make_pair(std::move(__first), std::move(__original_last));
if (__first == __last) if (!__pred(*__first))
return std::make_pair(std::move(__first), std::move(__original_last)); break;
if (!__pred(*__first)) ++__first;
break;
++__first;
}
do
{
if (__first == --__last)
return std::make_pair(std::move(__first), std::move(__original_last));
} while (!__pred(*__last));
_IterOps<_AlgPolicy>::iter_swap(__first, __last);
++__first;
} }
do {
if (__first == --__last)
return std::make_pair(std::move(__first), std::move(__original_last));
} while (!__pred(*__last));
_IterOps<_AlgPolicy>::iter_swap(__first, __last);
++__first;
}
} }
template <class _AlgPolicy, class _ForwardIterator, class _Sentinel, class _Predicate, class _IterCategory> template <class _AlgPolicy, class _ForwardIterator, class _Sentinel, class _Predicate, class _IterCategory>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator>
pair<_ForwardIterator, _ForwardIterator> __partition( __partition(_ForwardIterator __first, _Sentinel __last, _Predicate&& __pred, _IterCategory __iter_category) {
_ForwardIterator __first, _Sentinel __last, _Predicate&& __pred, _IterCategory __iter_category) {
return std::__partition_impl<__remove_cvref_t<_Predicate>&, _AlgPolicy>( return std::__partition_impl<__remove_cvref_t<_Predicate>&, _AlgPolicy>(
std::move(__first), std::move(__last), __pred, __iter_category); std::move(__first), std::move(__last), __pred, __iter_category);
} }
template <class _ForwardIterator, class _Predicate> template <class _ForwardIterator, class _Predicate>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
_ForwardIterator partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred)
{
using _IterCategory = typename iterator_traits<_ForwardIterator>::iterator_category; using _IterCategory = typename iterator_traits<_ForwardIterator>::iterator_category;
auto __result = std::__partition<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __pred, _IterCategory()); auto __result = std::__partition<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __pred, _IterCategory());
return __result.first; return __result.first;
@ -94,4 +85,6 @@ partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred)
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PARTITION_H #endif // _LIBCPP___ALGORITHM_PARTITION_H

View File

@ -19,27 +19,23 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _OutputIterator1, template <class _InputIterator, class _OutputIterator1, class _OutputIterator2, class _Predicate>
class _OutputIterator2, class _Predicate> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_OutputIterator1, _OutputIterator2> partition_copy(
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_OutputIterator1, _OutputIterator2> _InputIterator __first,
partition_copy(_InputIterator __first, _InputIterator __last, _InputIterator __last,
_OutputIterator1 __out_true, _OutputIterator2 __out_false, _OutputIterator1 __out_true,
_Predicate __pred) _OutputIterator2 __out_false,
{ _Predicate __pred) {
for (; __first != __last; ++__first) for (; __first != __last; ++__first) {
{ if (__pred(*__first)) {
if (__pred(*__first)) *__out_true = *__first;
{ ++__out_true;
*__out_true = *__first; } else {
++__out_true; *__out_false = *__first;
} ++__out_false;
else
{
*__out_false = *__first;
++__out_false;
}
} }
return pair<_OutputIterator1, _OutputIterator2>(__out_true, __out_false); }
return pair<_OutputIterator1, _OutputIterator2>(__out_true, __out_false);
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -21,26 +21,22 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template<class _ForwardIterator, class _Predicate> template <class _ForwardIterator, class _Predicate>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
partition_point(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) partition_point(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
{ typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type;
typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; difference_type __len = std::distance(__first, __last);
difference_type __len = _VSTD::distance(__first, __last); while (__len != 0) {
while (__len != 0) difference_type __l2 = std::__half_positive(__len);
{ _ForwardIterator __m = __first;
difference_type __l2 = _VSTD::__half_positive(__len); std::advance(__m, __l2);
_ForwardIterator __m = __first; if (__pred(*__m)) {
_VSTD::advance(__m, __l2); __first = ++__m;
if (__pred(*__m)) __len -= __l2 + 1;
{ } else
__first = ++__m; __len = __l2;
__len -= __l2 + 1; }
} return __first;
else
__len = __l2;
}
return __first;
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD

View File

@ -31,16 +31,19 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp, __pop_heap(_RandomAccessIterator __first,
typename iterator_traits<_RandomAccessIterator>::difference_type __len) { _RandomAccessIterator __last,
_LIBCPP_ASSERT_UNCATEGORIZED(__len > 0, "The heap given to pop_heap must be non-empty"); _Compare& __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __len) {
// Calling `pop_heap` on an empty range is undefined behavior, but in practice it will be a no-op.
_LIBCPP_ASSERT_PEDANTIC(__len > 0, "The heap given to pop_heap must be non-empty");
__comp_ref_type<_Compare> __comp_ref = __comp; __comp_ref_type<_Compare> __comp_ref = __comp;
using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; using value_type = typename iterator_traits<_RandomAccessIterator>::value_type;
if (__len > 1) { if (__len > 1) {
value_type __top = _IterOps<_AlgPolicy>::__iter_move(__first); // create a hole at __first value_type __top = _IterOps<_AlgPolicy>::__iter_move(__first); // create a hole at __first
_RandomAccessIterator __hole = std::__floyd_sift_down<_AlgPolicy>(__first, __comp_ref, __len); _RandomAccessIterator __hole = std::__floyd_sift_down<_AlgPolicy>(__first, __comp_ref, __len);
--__last; --__last;
@ -56,8 +59,8 @@ void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Co
} }
template <class _RandomAccessIterator, class _Compare> template <class _RandomAccessIterator, class _Compare>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
void pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible."); static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible.");
static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable."); static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable.");
@ -66,8 +69,8 @@ void pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp
} }
template <class _RandomAccessIterator> template <class _RandomAccessIterator>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
void pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) {
std::pop_heap(std::move(__first), std::move(__last), __less<>()); std::pop_heap(std::move(__first), std::move(__last), __less<>());
} }

View File

@ -22,57 +22,54 @@
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _BidirectionalIterator, class _Sentinel> template <class _AlgPolicy, class _Compare, class _BidirectionalIterator, class _Sentinel>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator, bool>
pair<_BidirectionalIterator, bool> __prev_permutation(_BidirectionalIterator __first, _Sentinel __last, _Compare&& __comp) {
__prev_permutation(_BidirectionalIterator __first, _Sentinel __last, _Compare&& __comp) using _Result = pair<_BidirectionalIterator, bool>;
{
using _Result = pair<_BidirectionalIterator, bool>;
_BidirectionalIterator __last_iter = _IterOps<_AlgPolicy>::next(__first, __last); _BidirectionalIterator __last_iter = _IterOps<_AlgPolicy>::next(__first, __last);
_BidirectionalIterator __i = __last_iter; _BidirectionalIterator __i = __last_iter;
if (__first == __last || __first == --__i) if (__first == __last || __first == --__i)
return _Result(std::move(__last_iter), false); return _Result(std::move(__last_iter), false);
while (true) while (true) {
{ _BidirectionalIterator __ip1 = __i;
_BidirectionalIterator __ip1 = __i; if (__comp(*__ip1, *--__i)) {
if (__comp(*__ip1, *--__i)) _BidirectionalIterator __j = __last_iter;
{ while (!__comp(*--__j, *__i))
_BidirectionalIterator __j = __last_iter; ;
while (!__comp(*--__j, *__i)) _IterOps<_AlgPolicy>::iter_swap(__i, __j);
; std::__reverse<_AlgPolicy>(__ip1, __last_iter);
_IterOps<_AlgPolicy>::iter_swap(__i, __j); return _Result(std::move(__last_iter), true);
std::__reverse<_AlgPolicy>(__ip1, __last_iter);
return _Result(std::move(__last_iter), true);
}
if (__i == __first)
{
std::__reverse<_AlgPolicy>(__first, __last_iter);
return _Result(std::move(__last_iter), false);
}
} }
if (__i == __first) {
std::__reverse<_AlgPolicy>(__first, __last_iter);
return _Result(std::move(__last_iter), false);
}
}
} }
template <class _BidirectionalIterator, class _Compare> template <class _BidirectionalIterator, class _Compare>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
bool prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) {
prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp)
{
return std::__prev_permutation<_ClassicAlgPolicy>( return std::__prev_permutation<_ClassicAlgPolicy>(
std::move(__first), std::move(__last), static_cast<__comp_ref_type<_Compare> >(__comp)).second; std::move(__first), std::move(__last), static_cast<__comp_ref_type<_Compare> >(__comp))
.second;
} }
template <class _BidirectionalIterator> template <class _BidirectionalIterator>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
bool prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last) {
prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last) return std::prev_permutation(__first, __last, __less<>());
{
return _VSTD::prev_permutation(__first, __last, __less<>());
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PREV_PERMUTATION_H #endif // _LIBCPP___ALGORITHM_PREV_PERMUTATION_H

View File

@ -13,17 +13,19 @@
#include <__algorithm/pstl_frontend_dispatch.h> #include <__algorithm/pstl_frontend_dispatch.h>
#include <__config> #include <__config>
#include <__iterator/cpp17_iterator_concepts.h> #include <__iterator/cpp17_iterator_concepts.h>
#include <__iterator/iterator_traits.h>
#include <__type_traits/enable_if.h> #include <__type_traits/enable_if.h>
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__type_traits/remove_cvref.h> #include <__type_traits/remove_cvref.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <__utility/terminate_on_exception.h> #include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
@ -36,19 +38,35 @@ template <class _ExecutionPolicy,
class _Predicate, class _Predicate,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> __any_of(
any_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { _ExecutionPolicy&& __policy, _ForwardIterator&& __first, _ForwardIterator&& __last, _Predicate&& __pred) noexcept {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
return std::__pstl_frontend_dispatch( return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_any_of), _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_any_of, _RawPolicy),
[&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) { [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) -> optional<bool> {
return std::find_if(__policy, __g_first, __g_last, __g_pred) != __g_last; auto __res = std::__find_if(__policy, __g_first, __g_last, __g_pred);
if (!__res)
return nullopt;
return *__res != __g_last;
}, },
std::move(__first), std::move(__first),
std::move(__last), std::move(__last),
std::move(__pred)); std::move(__pred));
} }
template <class _ExecutionPolicy,
class _ForwardIterator,
class _Predicate,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool
any_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
auto __res = std::__any_of(__policy, std::move(__first), std::move(__last), std::move(__pred));
if (!__res)
std::__throw_bad_alloc();
return *std::move(__res);
}
template <class> template <class>
void __pstl_all_of(); // declaration needed for the frontend dispatch below void __pstl_all_of(); // declaration needed for the frontend dispatch below
@ -57,21 +75,37 @@ template <class _ExecutionPolicy,
class _Pred, class _Pred,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool>
all_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) { __all_of(_ExecutionPolicy&& __policy, _ForwardIterator&& __first, _ForwardIterator&& __last, _Pred&& __pred) noexcept {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
return std::__pstl_frontend_dispatch( return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_all_of), _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_all_of, _RawPolicy),
[&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Pred __g_pred) { [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Pred __g_pred) -> optional<bool> {
return !std::any_of(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __value) { auto __res = std::__any_of(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __value) {
return !__g_pred(__value); return !__g_pred(__value);
}); });
if (!__res)
return nullopt;
return !*__res;
}, },
std::move(__first), std::move(__first),
std::move(__last), std::move(__last),
std::move(__pred)); std::move(__pred));
} }
template <class _ExecutionPolicy,
class _ForwardIterator,
class _Pred,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool
all_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
auto __res = std::__all_of(__policy, std::move(__first), std::move(__last), std::move(__pred));
if (!__res)
std::__throw_bad_alloc();
return *std::move(__res);
}
template <class> template <class>
void __pstl_none_of(); // declaration needed for the frontend dispatch below void __pstl_none_of(); // declaration needed for the frontend dispatch below
@ -80,21 +114,39 @@ template <class _ExecutionPolicy,
class _Pred, class _Pred,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool>
none_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) { __none_of(_ExecutionPolicy&& __policy, _ForwardIterator&& __first, _ForwardIterator&& __last, _Pred&& __pred) noexcept {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
return std::__pstl_frontend_dispatch( return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_none_of), _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_none_of, _RawPolicy),
[&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Pred __g_pred) { [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Pred __g_pred) -> optional<bool> {
return !std::any_of(__policy, __g_first, __g_last, __g_pred); auto __res = std::__any_of(__policy, __g_first, __g_last, __g_pred);
if (!__res)
return nullopt;
return !*__res;
}, },
std::move(__first), std::move(__first),
std::move(__last), std::move(__last),
std::move(__pred)); std::move(__pred));
} }
template <class _ExecutionPolicy,
class _ForwardIterator,
class _Pred,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool
none_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
auto __res = std::__none_of(__policy, std::move(__first), std::move(__last), std::move(__pred));
if (!__res)
std::__throw_bad_alloc();
return *std::move(__res);
}
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PSTL_ANY_ALL_NONE_OF_H #endif // _LIBCPP___ALGORITHM_PSTL_ANY_ALL_NONE_OF_H

View File

@ -27,23 +27,38 @@ TODO: Documentation of how backends work
A PSTL parallel backend is a tag type to which the following functions are associated, at minimum: A PSTL parallel backend is a tag type to which the following functions are associated, at minimum:
template <class _ExecutionPolicy, class _Iterator, class _Func> template <class _ExecutionPolicy, class _Iterator, class _Func>
void __pstl_for_each(_Backend, _ExecutionPolicy&&, _Iterator __first, _Iterator __last, _Func __f); optional<__empty> __pstl_for_each(_Backend, _ExecutionPolicy&&, _Iterator __first, _Iterator __last, _Func __f);
template <class _ExecutionPolicy, class _Iterator, class _Predicate> template <class _ExecutionPolicy, class _Iterator, class _Predicate>
_Iterator __pstl_find_if(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred); optional<_Iterator> __pstl_find_if(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred);
template <class _ExecutionPolicy, class _RandomAccessIterator, class _Comp> template <class _ExecutionPolicy, class _RandomAccessIterator, class _Comp>
void __pstl_stable_sort(_Backend, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp); optional<__empty>
__pstl_stable_sort(_Backend, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp);
template <class _ExecutionPolicy,
class _ForwardIterator1,
class _ForwardIterator2,
class _ForwardOutIterator,
class _Comp>
optional<_ForwardOutIterator> __pstl_merge(_Backend,
_ForwardIterator1 __first1,
_ForwardIterator1 __last1,
_ForwardIterator2 __first2,
_ForwardIterator2 __last2,
_ForwardOutIterator __result,
_Comp __comp);
template <class _ExecutionPolicy, class _InIterator, class _OutIterator, class _UnaryOperation> template <class _ExecutionPolicy, class _InIterator, class _OutIterator, class _UnaryOperation>
_OutIterator __pstl_transform(_InIterator __first, _InIterator __last, _OutIterator __result, _UnaryOperation __op); optional<_OutIterator>
__pstl_transform(_Backend, _InIterator __first, _InIterator __last, _OutIterator __result, _UnaryOperation __op);
template <class _ExecutionPolicy, class _InIterator1, class _InIterator2, class _OutIterator, class _BinaryOperation> template <class _ExecutionPolicy, class _InIterator1, class _InIterator2, class _OutIterator, class _BinaryOperation>
_OutIterator __pstl_transform(_InIterator1 __first1, optional<_OutIterator> __pstl_transform(_InIterator1 __first1,
_InIterator1 __last1, _InIterator2 __first2,
_InIterator2 __first2, _InIterator1 __last1,
_OutIterator __result, _OutIterator __result,
_BinaryOperation __op); _BinaryOperation __op);
template <class _ExecutionPolicy, template <class _ExecutionPolicy,
class _Iterator1, class _Iterator1,
@ -51,22 +66,22 @@ A PSTL parallel backend is a tag type to which the following functions are assoc
class _Tp, class _Tp,
class _BinaryOperation1, class _BinaryOperation1,
class _BinaryOperation2> class _BinaryOperation2>
_Tp __pstl_transform_reduce(_Backend, optional<_Tp> __pstl_transform_reduce(_Backend,
_Iterator1 __first1, _Iterator1 __first1,
_Iterator1 __last1, _Iterator1 __last1,
_Iterator2 __first2, _Iterator2 __first2,
_Iterator2 __last2, _Iterator2 __last2,
_Tp __init, _Tp __init,
_BinaryOperation1 __reduce, _BinaryOperation1 __reduce,
_BinaryOperation2 __transform); _BinaryOperation2 __transform);
template <class _ExecutionPolicy, class _Iterator, class _Tp, class _BinaryOperation, class _UnaryOperation> template <class _ExecutionPolicy, class _Iterator, class _Tp, class _BinaryOperation, class _UnaryOperation>
_Tp __pstl_transform_reduce(_Backend, optional<_Tp> __pstl_transform_reduce(_Backend,
_Iterator __first, _Iterator __first,
_Iterator __last, _Iterator __last,
_Tp __init, _Tp __init,
_BinaryOperation __reduce, _BinaryOperation __reduce,
_UnaryOperation __transform); _UnaryOperation __transform);
// TODO: Complete this list // TODO: Complete this list
@ -75,86 +90,105 @@ algorithms, otherwise they are implemented in terms of other algorithms. If none
implemented, all the algorithms will eventually forward to the basis algorithms listed above: implemented, all the algorithms will eventually forward to the basis algorithms listed above:
template <class _ExecutionPolicy, class _Iterator, class _Size, class _Func> template <class _ExecutionPolicy, class _Iterator, class _Size, class _Func>
void __pstl_for_each_n(_Backend, _Iterator __first, _Size __n, _Func __f); optional<__empty> __pstl_for_each_n(_Backend, _Iterator __first, _Size __n, _Func __f);
template <class _ExecutionPolicy, class _Iterator, class _Predicate> template <class _ExecutionPolicy, class _Iterator, class _Predicate>
bool __pstl_any_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred); optional<bool> __pstl_any_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred);
template <class _ExecutionPolicy, class _Iterator, class _Predicate> template <class _ExecutionPolicy, class _Iterator, class _Predicate>
bool __pstl_all_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred); optional<bool> __pstl_all_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred);
template <class _ExecutionPolicy, class _Iterator, class _Predicate> template <class _ExecutionPolicy, class _Iterator, class _Predicate>
bool __pstl_none_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred); optional<bool> __pstl_none_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred);
template <class _ExecutionPolicy, class _Iterator, class _Tp> template <class _ExecutionPolicy, class _Iterator, class _Tp>
_Iterator __pstl_find(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value); optional<_Iterator> __pstl_find(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value);
template <class _ExecutionPolicy, class _Iterator, class _Predicate> template <class _ExecutionPolicy, class _Iterator, class _Predicate>
_Iterator __pstl_find_if_not(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred); optional<_Iterator> __pstl_find_if_not(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred);
template <class _ExecutionPolicy, class _Iterator, class _Tp> template <class _ExecutionPolicy, class _Iterator, class _Tp>
void __pstl_fill(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value); optional<__empty> __pstl_fill(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value);
template <class _ExecutionPolicy, class _Iterator, class _SizeT, class _Tp> template <class _ExecutionPolicy, class _Iterator, class _SizeT, class _Tp>
void __pstl_fill_n(_Backend, _Iterator __first, _SizeT __n, const _Tp& __value); optional<__empty> __pstl_fill_n(_Backend, _Iterator __first, _SizeT __n, const _Tp& __value);
template <class _ExecutionPolicy, class _Iterator, class _Generator> template <class _ExecutionPolicy, class _Iterator, class _Generator>
void __pstl_generate(_Backend, _Iterator __first, _Iterator __last, _Generator __gen); optional<__empty> __pstl_generate(_Backend, _Iterator __first, _Iterator __last, _Generator __gen);
template <class _ExecutionPolicy, class _Iterator, class _Predicate> template <class _ExecutionPolicy, class _Iterator, class _Predicate>
void __pstl_is_partitioned(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred); optional<__empty> __pstl_is_partitioned(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred);
template <class _ExecutionPolicy, class _Iterator, class _Size, class _Generator> template <class _ExecutionPolicy, class _Iterator, class _Size, class _Generator>
void __pstl_generator_n(_Backend, _Iterator __first, _Size __n, _Generator __gen); optional<__empty> __pstl_generator_n(_Backend, _Iterator __first, _Size __n, _Generator __gen);
template <class _ExecutionPolicy, class _terator1, class _Iterator2, class _OutIterator, class _Comp> template <class _ExecutionPolicy, class _terator1, class _Iterator2, class _OutIterator, class _Comp>
_OutIterator __pstl_merge(_Backend, optional<_OutIterator> __pstl_merge(_Backend,
_Iterator1 __first1, _Iterator1 __first1,
_Iterator1 __last1, _Iterator1 __last1,
_Iterator2 __first2, _Iterator2 __first2,
_Iterator2 __last2, _Iterator2 __last2,
_OutIterator __result, _OutIterator __result,
_Comp __comp); _Comp __comp);
template <class _ExecutionPolicy, class _Iterator, class _OutIterator>
optional<_OutIterator> __pstl_move(_Backend, _Iterator __first, _Iterator __last, _OutIterator __result);
template <class _ExecutionPolicy, class _Iterator, class _Tp, class _BinaryOperation> template <class _ExecutionPolicy, class _Iterator, class _Tp, class _BinaryOperation>
_Tp __pstl_reduce(_Backend, _Iterator __first, _Iterator __last, _Tp __init, _BinaryOperation __op); optional<_Tp> __pstl_reduce(_Backend, _Iterator __first, _Iterator __last, _Tp __init, _BinaryOperation __op);
temlate <class _ExecutionPolicy, class _Iterator> temlate <class _ExecutionPolicy, class _Iterator>
__iter_value_type<_Iterator> __pstl_reduce(_Backend, _Iterator __first, _Iterator __last); optional<__iter_value_type<_Iterator>> __pstl_reduce(_Backend, _Iterator __first, _Iterator __last);
template <class _ExecuitonPolicy, class _Iterator, class _Tp>
__iter_diff_t<_Iterator> __pstl_count(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value);
template <class _ExecutionPolicy, class _Iterator, class _Predicate>
__iter_diff_t<_Iterator> __pstl_count_if(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred);
template <class _ExecutionPolicy, class _Iterator, class _Tp> template <class _ExecutionPolicy, class _Iterator, class _Tp>
void __pstl_replace(_Backend, _Iterator __first, _Iterator __last, const _Tp& __old_value, const _Tp& __new_value); optional<__iter_diff_t<_Iterator>> __pstl_count(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value);
template <class _ExecutionPolicy, class _Iterator, class _Predicate>
optional<__iter_diff_t<_Iterator>> __pstl_count_if(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred);
template <class _ExecutionPolicy, class _Iterator, class _Tp>
optional<__empty>
__pstl_replace(_Backend, _Iterator __first, _Iterator __last, const _Tp& __old_value, const _Tp& __new_value);
template <class _ExecutionPolicy, class _Iterator, class _Pred, class _Tp> template <class _ExecutionPolicy, class _Iterator, class _Pred, class _Tp>
void __pstl_replace_if(_Backend, _Iterator __first, _Iterator __last, _Pred __pred, const _Tp& __new_value); optional<__empty>
__pstl_replace_if(_Backend, _Iterator __first, _Iterator __last, _Pred __pred, const _Tp& __new_value);
template <class _ExecutionPolicy, class _Iterator, class _OutIterator, class _Tp> template <class _ExecutionPolicy, class _Iterator, class _OutIterator, class _Tp>
void __pstl_replace_copy(_Backend, optional<__empty> __pstl_replace_copy(_Backend,
_Iterator __first, _Iterator __first,
_Iterator __last, _Iterator __last,
_OutIterator __result, _OutIterator __result,
const _Tp& __old_value, const _Tp& __old_value,
const _Tp& __new_value); const _Tp& __new_value);
template <class _ExecutionPolicy, class _Iterator, class _OutIterator, class _Pred, class _Tp> template <class _ExecutionPolicy, class _Iterator, class _OutIterator, class _Pred, class _Tp>
void __pstl_replace_copy_if(_Backend, optional<__empty> __pstl_replace_copy_if(_Backend,
_Iterator __first, _Iterator __first,
_Iterator __last, _Iterator __last,
_OutIterator __result, _OutIterator __result,
_Pred __pred, _Pred __pred,
const _Tp& __new_value); const _Tp& __new_value);
template <class _ExecutionPolicy, class _Iterator, class _OutIterator>
optional<_Iterator> __pstl_rotate_copy(
_Backend, _Iterator __first, _Iterator __middle, _Iterator __last, _OutIterator __result);
template <class _ExecutionPolicy, class _Iterator, class _Comp> template <class _ExecutionPolicy, class _Iterator, class _Comp>
void __pstl_sort(_Backend, _Iterator __first, _Iterator __last, _Comp __comp); optional<__empty> __pstl_sort(_Backend, _Iterator __first, _Iterator __last, _Comp __comp);
template <class _ExecutionPolicy, class _Iterator1, class _Iterator2, class _Comp>
optional<bool> __pstl_equal(_Backend, _Iterator1 first1, _Iterator1 last1, _Iterator2 first2, _Comp __comp);
// TODO: Complete this list // TODO: Complete this list
Exception handling
==================
PSTL backends are expected to report errors (i.e. failure to allocate) by returning a disengaged `optional` from their
implementation. Exceptions shouldn't be used to report an internal failure-to-allocate, since all exceptions are turned
into a program termination at the front-end level. When a backend returns a disengaged `optional` to the frontend, the
frontend will turn that into a call to `std::__throw_bad_alloc();` to report the internal failure to the user.
*/ */
template <class _ExecutionPolicy> template <class _ExecutionPolicy>

View File

@ -15,10 +15,11 @@
// _Functor takes a subrange for [__first, __last) that should be executed in serial // _Functor takes a subrange for [__first, __last) that should be executed in serial
template <class _RandomAccessIterator, class _Functor> template <class _RandomAccessIterator, class _Functor>
void __parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Functor __func); optional<__empty> __parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Functor __func);
template <class _Iterator, class _UnaryOp, class _Tp, class _BinaryOp, class _Reduction> template <class _Iterator, class _UnaryOp, class _Tp, class _BinaryOp, class _Reduction>
_Tp __parallel_transform_reduce(_Iterator __first, _Iterator __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduction); optional<_Tp>
__parallel_transform_reduce(_Iterator __first, _Iterator __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduction);
// Cancel the execution of other jobs - they aren't needed anymore // Cancel the execution of other jobs - they aren't needed anymore
void __cancel_execution(); void __cancel_execution();
@ -28,7 +29,7 @@
class _RandomAccessIterator3, class _RandomAccessIterator3,
class _Compare, class _Compare,
class _LeafMerge> class _LeafMerge>
void __parallel_merge( optional<void> __parallel_merge(
_RandomAccessIterator1 __first1, _RandomAccessIterator1 __first1,
_RandomAccessIterator1 __last1, _RandomAccessIterator1 __last1,
_RandomAccessIterator2 __first2, _RandomAccessIterator2 __first2,
@ -44,6 +45,14 @@
_LeafSort __leaf_sort); _LeafSort __leaf_sort);
TODO: Document the parallel backend TODO: Document the parallel backend
Exception handling
==================
CPU backends are expected to report errors (i.e. failure to allocate) by returning a disengaged `optional` from their
implementation. Exceptions shouldn't be used to report an internal failure-to-allocate, since all exceptions are turned
into a program termination at the front-end level. When a backend returns a disengaged `optional` to the frontend, the
frontend will turn that into a call to `std::__throw_bad_alloc();` to report the internal failure to the user.
*/ */
#include <__algorithm/pstl_backends/cpu_backends/any_of.h> #include <__algorithm/pstl_backends/cpu_backends/any_of.h>

View File

@ -16,26 +16,32 @@
#include <__atomic/memory_order.h> #include <__atomic/memory_order.h>
#include <__config> #include <__config>
#include <__functional/operations.h> #include <__functional/operations.h>
#include <__iterator/iterator_traits.h> #include <__iterator/concepts.h>
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__utility/move.h>
#include <__utility/pair.h> #include <__utility/pair.h>
#include <__utility/terminate_on_exception.h>
#include <cstdint> #include <cstdint>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_PUSH_MACROS
# include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Index, class _Brick> template <class _Index, class _Brick>
_LIBCPP_HIDE_FROM_ABI bool __parallel_or(_Index __first, _Index __last, _Brick __f) { _LIBCPP_HIDE_FROM_ABI optional<bool> __parallel_or(_Index __first, _Index __last, _Brick __f) {
std::atomic<bool> __found(false); std::atomic<bool> __found(false);
__par_backend::__parallel_for(__first, __last, [__f, &__found](_Index __i, _Index __j) { auto __ret = __par_backend::__parallel_for(__first, __last, [__f, &__found](_Index __i, _Index __j) {
if (!__found.load(std::memory_order_relaxed) && __f(__i, __j)) { if (!__found.load(std::memory_order_relaxed) && __f(__i, __j)) {
__found.store(true, std::memory_order_relaxed); __found.store(true, std::memory_order_relaxed);
__par_backend::__cancel_execution(); __par_backend::__cancel_execution();
} }
}); });
return __found; if (!__ret)
return nullopt;
return static_cast<bool>(__found);
} }
// TODO: check whether __simd_first() can be used here // TODO: check whether __simd_first() can be used here
@ -64,19 +70,19 @@ _LIBCPP_HIDE_FROM_ABI bool __simd_or(_Index __first, _DifferenceType __n, _Pred
} }
template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate> template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate>
_LIBCPP_HIDE_FROM_ABI bool _LIBCPP_HIDE_FROM_ABI optional<bool>
__pstl_any_of(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { __pstl_any_of(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category<_ForwardIterator>::value) { __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
return std::__terminate_on_exception([&] { return std::__parallel_or(
return std::__parallel_or( __first, __last, [&__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) {
__first, __last, [&__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { auto __res = std::__pstl_any_of<__remove_parallel_policy_t<_ExecutionPolicy>>(
return std::__pstl_any_of<__remove_parallel_policy_t<_ExecutionPolicy>>( __cpu_backend_tag{}, __brick_first, __brick_last, __pred);
__cpu_backend_tag{}, __brick_first, __brick_last, __pred); _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!");
}); return *std::move(__res);
}); });
} else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category<_ForwardIterator>::value) { __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
return std::__simd_or(__first, __last - __first, __pred); return std::__simd_or(__first, __last - __first, __pred);
} else { } else {
return std::any_of(__first, __last, __pred); return std::any_of(__first, __last, __pred);
@ -85,6 +91,8 @@ __pstl_any_of(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __la
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H #endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H

View File

@ -12,9 +12,10 @@
#include <__algorithm/fill.h> #include <__algorithm/fill.h>
#include <__algorithm/pstl_backends/cpu_backends/backend.h> #include <__algorithm/pstl_backends/cpu_backends/backend.h>
#include <__config> #include <__config>
#include <__iterator/iterator_traits.h> #include <__iterator/concepts.h>
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__utility/terminate_on_exception.h> #include <__utility/empty.h>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@ -34,22 +35,23 @@ _LIBCPP_HIDE_FROM_ABI _Index __simd_fill_n(_Index __first, _DifferenceType __n,
} }
template <class _ExecutionPolicy, class _ForwardIterator, class _Tp> template <class _ExecutionPolicy, class _ForwardIterator, class _Tp>
_LIBCPP_HIDE_FROM_ABI void _LIBCPP_HIDE_FROM_ABI optional<__empty>
__pstl_fill(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { __pstl_fill(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category<_ForwardIterator>::value) { __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
std::__terminate_on_exception([&] { return __par_backend::__parallel_for(
__par_backend::__parallel_for( __first, __last, [&__value](_ForwardIterator __brick_first, _ForwardIterator __brick_last) {
__first, __last, [&__value](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { [[maybe_unused]] auto __res = std::__pstl_fill<__remove_parallel_policy_t<_ExecutionPolicy>>(
std::__pstl_fill<__remove_parallel_policy_t<_ExecutionPolicy>>( __cpu_backend_tag{}, __brick_first, __brick_last, __value);
__cpu_backend_tag{}, __brick_first, __brick_last, __value); _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!");
}); });
});
} else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category<_ForwardIterator>::value) { __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
std::__simd_fill_n(__first, __last - __first, __value); std::__simd_fill_n(__first, __last - __first, __value);
return __empty{};
} else { } else {
std::fill(__first, __last, __value); std::fill(__first, __last, __value);
return __empty{};
} }
} }

View File

@ -14,11 +14,13 @@
#include <__atomic/atomic.h> #include <__atomic/atomic.h>
#include <__config> #include <__config>
#include <__functional/operations.h> #include <__functional/operations.h>
#include <__iterator/concepts.h>
#include <__iterator/iterator_traits.h> #include <__iterator/iterator_traits.h>
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__utility/move.h>
#include <__utility/pair.h> #include <__utility/pair.h>
#include <__utility/terminate_on_exception.h>
#include <cstddef> #include <cstddef>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@ -26,31 +28,37 @@
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_PUSH_MACROS
# include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Index, class _Brick, class _Compare> template <class _Index, class _Brick, class _Compare>
_LIBCPP_HIDE_FROM_ABI _Index _LIBCPP_HIDE_FROM_ABI optional<_Index>
__parallel_find(_Index __first, _Index __last, _Brick __f, _Compare __comp, bool __b_first) { __parallel_find(_Index __first, _Index __last, _Brick __f, _Compare __comp, bool __b_first) {
typedef typename std::iterator_traits<_Index>::difference_type _DifferenceType; typedef typename std::iterator_traits<_Index>::difference_type _DifferenceType;
const _DifferenceType __n = __last - __first; const _DifferenceType __n = __last - __first;
_DifferenceType __initial_dist = __b_first ? __n : -1; _DifferenceType __initial_dist = __b_first ? __n : -1;
std::atomic<_DifferenceType> __extremum(__initial_dist); std::atomic<_DifferenceType> __extremum(__initial_dist);
// TODO: find out what is better here: parallel_for or parallel_reduce // TODO: find out what is better here: parallel_for or parallel_reduce
__par_backend::__parallel_for(__first, __last, [__comp, __f, __first, &__extremum](_Index __i, _Index __j) { auto __res =
// See "Reducing Contention Through Priority Updates", PPoPP '13, for discussion of __par_backend::__parallel_for(__first, __last, [__comp, __f, __first, &__extremum](_Index __i, _Index __j) {
// why using a shared variable scales fairly well in this situation. // See "Reducing Contention Through Priority Updates", PPoPP '13, for discussion of
if (__comp(__i - __first, __extremum)) { // why using a shared variable scales fairly well in this situation.
_Index __res = __f(__i, __j); if (__comp(__i - __first, __extremum)) {
// If not '__last' returned then we found what we want so put this to extremum _Index __result = __f(__i, __j);
if (__res != __j) { // If not '__last' returned then we found what we want so put this to extremum
const _DifferenceType __k = __res - __first; if (__result != __j) {
for (_DifferenceType __old = __extremum; __comp(__k, __old); __old = __extremum) { const _DifferenceType __k = __result - __first;
__extremum.compare_exchange_weak(__old, __k); for (_DifferenceType __old = __extremum; __comp(__k, __old); __old = __extremum) {
__extremum.compare_exchange_weak(__old, __k);
}
}
} }
} });
} if (!__res)
}); return nullopt;
return __extremum != __initial_dist ? __first + __extremum : __last; return __extremum.load() != __initial_dist ? __first + __extremum.load() : __last;
} }
template <class _Index, class _DifferenceType, class _Compare> template <class _Index, class _DifferenceType, class _Compare>
@ -90,23 +98,23 @@ __simd_first(_Index __first, _DifferenceType __begin, _DifferenceType __end, _Co
} }
template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate> template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate>
_LIBCPP_HIDE_FROM_ABI _ForwardIterator _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator>
__pstl_find_if(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { __pstl_find_if(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category<_ForwardIterator>::value) { __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
return std::__terminate_on_exception([&] { return std::__parallel_find(
return std::__parallel_find( __first,
__first, __last,
__last, [&__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) {
[&__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { auto __res = std::__pstl_find_if<__remove_parallel_policy_t<_ExecutionPolicy>>(
return std::__pstl_find_if<__remove_parallel_policy_t<_ExecutionPolicy>>( __cpu_backend_tag{}, __brick_first, __brick_last, __pred);
__cpu_backend_tag{}, __brick_first, __brick_last, __pred); _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!");
}, return *std::move(__res);
less<>{}, },
true); less<>{},
}); true);
} else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category<_ForwardIterator>::value) { __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
using __diff_t = __iter_diff_t<_ForwardIterator>; using __diff_t = __iter_diff_t<_ForwardIterator>;
return std::__simd_first(__first, __diff_t(0), __last - __first, [&__pred](_ForwardIterator __iter, __diff_t __i) { return std::__simd_first(__first, __diff_t(0), __last - __first, [&__pred](_ForwardIterator __iter, __diff_t __i) {
return __pred(__iter[__i]); return __pred(__iter[__i]);
@ -118,6 +126,8 @@ __pstl_find_if(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __l
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FIND_IF_H #endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FIND_IF_H

View File

@ -12,9 +12,10 @@
#include <__algorithm/for_each.h> #include <__algorithm/for_each.h>
#include <__algorithm/pstl_backends/cpu_backends/backend.h> #include <__algorithm/pstl_backends/cpu_backends/backend.h>
#include <__config> #include <__config>
#include <__iterator/iterator_traits.h> #include <__iterator/concepts.h>
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__utility/terminate_on_exception.h> #include <__utility/empty.h>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@ -25,7 +26,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Iterator, class _DifferenceType, class _Function> template <class _Iterator, class _DifferenceType, class _Function>
_LIBCPP_HIDE_FROM_ABI _Iterator __simd_walk_1(_Iterator __first, _DifferenceType __n, _Function __f) noexcept { _LIBCPP_HIDE_FROM_ABI _Iterator __simd_walk(_Iterator __first, _DifferenceType __n, _Function __f) noexcept {
_PSTL_PRAGMA_SIMD _PSTL_PRAGMA_SIMD
for (_DifferenceType __i = 0; __i < __n; ++__i) for (_DifferenceType __i = 0; __i < __n; ++__i)
__f(__first[__i]); __f(__first[__i]);
@ -34,22 +35,23 @@ _LIBCPP_HIDE_FROM_ABI _Iterator __simd_walk_1(_Iterator __first, _DifferenceType
} }
template <class _ExecutionPolicy, class _ForwardIterator, class _Functor> template <class _ExecutionPolicy, class _ForwardIterator, class _Functor>
_LIBCPP_HIDE_FROM_ABI void _LIBCPP_HIDE_FROM_ABI optional<__empty>
__pstl_for_each(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Functor __func) { __pstl_for_each(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Functor __func) {
if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category<_ForwardIterator>::value) { __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
std::__terminate_on_exception([&] { return std::__par_backend::__parallel_for(
std::__par_backend::__parallel_for( __first, __last, [__func](_ForwardIterator __brick_first, _ForwardIterator __brick_last) {
__first, __last, [__func](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { [[maybe_unused]] auto __res = std::__pstl_for_each<__remove_parallel_policy_t<_ExecutionPolicy>>(
std::__pstl_for_each<__remove_parallel_policy_t<_ExecutionPolicy>>( __cpu_backend_tag{}, __brick_first, __brick_last, __func);
__cpu_backend_tag{}, __brick_first, __brick_last, __func); _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!");
}); });
});
} else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category<_ForwardIterator>::value) { __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
std::__simd_walk_1(__first, __last - __first, __func); std::__simd_walk(__first, __last - __first, __func);
return __empty{};
} else { } else {
std::for_each(__first, __last, __func); std::for_each(__first, __last, __func);
return __empty{};
} }
} }

View File

@ -9,8 +9,10 @@
#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H #ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H
#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H #define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H
#include <__algorithm/inplace_merge.h>
#include <__algorithm/lower_bound.h> #include <__algorithm/lower_bound.h>
#include <__algorithm/max.h> #include <__algorithm/max.h>
#include <__algorithm/merge.h>
#include <__algorithm/upper_bound.h> #include <__algorithm/upper_bound.h>
#include <__atomic/atomic.h> #include <__atomic/atomic.h>
#include <__config> #include <__config>
@ -21,12 +23,13 @@
#include <__memory/construct_at.h> #include <__memory/construct_at.h>
#include <__memory/unique_ptr.h> #include <__memory/unique_ptr.h>
#include <__numeric/reduce.h> #include <__numeric/reduce.h>
#include <__utility/empty.h>
#include <__utility/exception_guard.h> #include <__utility/exception_guard.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <__utility/pair.h> #include <__utility/pair.h>
#include <__utility/terminate_on_exception.h>
#include <cstddef> #include <cstddef>
#include <new> #include <new>
#include <optional>
_LIBCPP_PUSH_MACROS _LIBCPP_PUSH_MACROS
#include <__undef_macros> #include <__undef_macros>
@ -57,13 +60,11 @@ struct __chunk_partitions {
ptrdiff_t __first_chunk_size_; ptrdiff_t __first_chunk_size_;
}; };
[[__gnu__::__const__]] _LIBCPP_EXPORTED_FROM_ABI __chunk_partitions __partition_chunks(ptrdiff_t __size); [[__gnu__::__const__]] _LIBCPP_EXPORTED_FROM_ABI __chunk_partitions __partition_chunks(ptrdiff_t __size) noexcept;
template <class _RandomAccessIterator, class _Functor> template <class _RandomAccessIterator, class _Functor>
_LIBCPP_HIDE_FROM_ABI void _LIBCPP_HIDE_FROM_ABI optional<__empty>
__parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Functor __func) { __dispatch_parallel_for(__chunk_partitions __partitions, _RandomAccessIterator __first, _Functor __func) {
auto __partitions = __libdispatch::__partition_chunks(__last - __first);
// Perform the chunked execution. // Perform the chunked execution.
__libdispatch::__dispatch_apply(__partitions.__chunk_count_, [&](size_t __chunk) { __libdispatch::__dispatch_apply(__partitions.__chunk_count_, [&](size_t __chunk) {
auto __this_chunk_size = __chunk == 0 ? __partitions.__first_chunk_size_ : __partitions.__chunk_size_; auto __this_chunk_size = __chunk == 0 ? __partitions.__first_chunk_size_ : __partitions.__chunk_size_;
@ -73,6 +74,15 @@ __parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Fun
: (__chunk * __partitions.__chunk_size_) + (__partitions.__first_chunk_size_ - __partitions.__chunk_size_); : (__chunk * __partitions.__chunk_size_) + (__partitions.__first_chunk_size_ - __partitions.__chunk_size_);
__func(__first + __index, __first + __index + __this_chunk_size); __func(__first + __index, __first + __index + __this_chunk_size);
}); });
return __empty{};
}
template <class _RandomAccessIterator, class _Functor>
_LIBCPP_HIDE_FROM_ABI optional<__empty>
__parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Functor __func) {
return __libdispatch::__dispatch_parallel_for(
__libdispatch::__partition_chunks(__last - __first), std::move(__first), std::move(__func));
} }
template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIteratorOut> template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIteratorOut>
@ -90,23 +100,23 @@ template <typename _RandomAccessIterator1,
typename _RandomAccessIterator3, typename _RandomAccessIterator3,
typename _Compare, typename _Compare,
typename _LeafMerge> typename _LeafMerge>
_LIBCPP_HIDE_FROM_ABI void __parallel_merge( _LIBCPP_HIDE_FROM_ABI optional<__empty> __parallel_merge(
_RandomAccessIterator1 __first1, _RandomAccessIterator1 __first1,
_RandomAccessIterator1 __last1, _RandomAccessIterator1 __last1,
_RandomAccessIterator2 __first2, _RandomAccessIterator2 __first2,
_RandomAccessIterator2 __last2, _RandomAccessIterator2 __last2,
_RandomAccessIterator3 __result, _RandomAccessIterator3 __result,
_Compare __comp, _Compare __comp,
_LeafMerge __leaf_merge) { _LeafMerge __leaf_merge) noexcept {
__chunk_partitions __partitions = __chunk_partitions __partitions =
__libdispatch::__partition_chunks(std::max<ptrdiff_t>(__last1 - __first1, __last2 - __first2)); __libdispatch::__partition_chunks(std::max<ptrdiff_t>(__last1 - __first1, __last2 - __first2));
if (__partitions.__chunk_count_ == 0) if (__partitions.__chunk_count_ == 0)
return; return __empty{};
if (__partitions.__chunk_count_ == 1) { if (__partitions.__chunk_count_ == 1) {
__leaf_merge(__first1, __last1, __first2, __last2, __result, __comp); __leaf_merge(__first1, __last1, __first2, __last2, __result, __comp);
return; return __empty{};
} }
using __merge_range_t = __merge_range<_RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator3>; using __merge_range_t = __merge_range<_RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator3>;
@ -117,61 +127,76 @@ _LIBCPP_HIDE_FROM_ABI void __parallel_merge(
std::destroy_n(__ptr, __n_ranges); std::destroy_n(__ptr, __n_ranges);
std::allocator<__merge_range_t>().deallocate(__ptr, __n_ranges); std::allocator<__merge_range_t>().deallocate(__ptr, __n_ranges);
}; };
unique_ptr<__merge_range_t[], decltype(__destroy)> __ranges( unique_ptr<__merge_range_t[], decltype(__destroy)> __ranges(
std::allocator<__merge_range_t>().allocate(__n_ranges), __destroy); [&]() -> __merge_range_t* {
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
try {
# endif
return std::allocator<__merge_range_t>().allocate(__n_ranges);
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
} catch (const std::bad_alloc&) {
return nullptr;
}
# endif
}(),
__destroy);
if (!__ranges)
return nullopt;
// TODO: Improve the case where the smaller range is merged into just a few (or even one) chunks of the larger case // TODO: Improve the case where the smaller range is merged into just a few (or even one) chunks of the larger case
std::__terminate_on_exception([&] { __merge_range_t* __r = __ranges.get();
__merge_range_t* __r = __ranges.get(); std::__construct_at(__r++, __first1, __first2, __result);
std::__construct_at(__r++, __first1, __first2, __result);
bool __iterate_first_range = __last1 - __first1 > __last2 - __first2; bool __iterate_first_range = __last1 - __first1 > __last2 - __first2;
auto __compute_chunk = [&](size_t __chunk_size) -> __merge_range_t { auto __compute_chunk = [&](size_t __chunk_size) -> __merge_range_t {
auto [__mid1, __mid2] = [&] { auto [__mid1, __mid2] = [&] {
if (__iterate_first_range) { if (__iterate_first_range) {
auto __m1 = __first1 + __chunk_size; auto __m1 = __first1 + __chunk_size;
auto __m2 = std::lower_bound(__first2, __last2, __m1[-1], __comp); auto __m2 = std::lower_bound(__first2, __last2, __m1[-1], __comp);
return std::make_pair(__m1, __m2); return std::make_pair(__m1, __m2);
} else { } else {
auto __m2 = __first2 + __chunk_size; auto __m2 = __first2 + __chunk_size;
auto __m1 = std::lower_bound(__first1, __last1, __m2[-1], __comp); auto __m1 = std::lower_bound(__first1, __last1, __m2[-1], __comp);
return std::make_pair(__m1, __m2); return std::make_pair(__m1, __m2);
} }
}(); }();
__result += (__mid1 - __first1) + (__mid2 - __first2); __result += (__mid1 - __first1) + (__mid2 - __first2);
__first1 = __mid1; __first1 = __mid1;
__first2 = __mid2; __first2 = __mid2;
return {std::move(__mid1), std::move(__mid2), __result}; return {std::move(__mid1), std::move(__mid2), __result};
}; };
// handle first chunk // handle first chunk
std::__construct_at(__r++, __compute_chunk(__partitions.__first_chunk_size_)); std::__construct_at(__r++, __compute_chunk(__partitions.__first_chunk_size_));
// handle 2 -> N - 1 chunks // handle 2 -> N - 1 chunks
for (ptrdiff_t __i = 0; __i != __partitions.__chunk_count_ - 2; ++__i) for (ptrdiff_t __i = 0; __i != __partitions.__chunk_count_ - 2; ++__i)
std::__construct_at(__r++, __compute_chunk(__partitions.__chunk_size_)); std::__construct_at(__r++, __compute_chunk(__partitions.__chunk_size_));
// handle last chunk // handle last chunk
std::__construct_at(__r, __last1, __last2, __result); std::__construct_at(__r, __last1, __last2, __result);
__libdispatch::__dispatch_apply(__partitions.__chunk_count_, [&](size_t __index) { __libdispatch::__dispatch_apply(__partitions.__chunk_count_, [&](size_t __index) {
auto __first_iters = __ranges[__index]; auto __first_iters = __ranges[__index];
auto __last_iters = __ranges[__index + 1]; auto __last_iters = __ranges[__index + 1];
__leaf_merge( __leaf_merge(
__first_iters.__mid1_, __first_iters.__mid1_,
__last_iters.__mid1_, __last_iters.__mid1_,
__first_iters.__mid2_, __first_iters.__mid2_,
__last_iters.__mid2_, __last_iters.__mid2_,
__first_iters.__result_, __first_iters.__result_,
__comp); __comp);
});
}); });
return __empty{};
} }
template <class _RandomAccessIterator, class _Transform, class _Value, class _Combiner, class _Reduction> template <class _RandomAccessIterator, class _Transform, class _Value, class _Combiner, class _Reduction>
_LIBCPP_HIDE_FROM_ABI _Value __parallel_transform_reduce( _LIBCPP_HIDE_FROM_ABI optional<_Value> __parallel_transform_reduce(
_RandomAccessIterator __first, _RandomAccessIterator __first,
_RandomAccessIterator __last, _RandomAccessIterator __last,
_Transform __transform, _Transform __transform,
@ -211,20 +236,101 @@ _LIBCPP_HIDE_FROM_ABI _Value __parallel_transform_reduce(
} }
}); });
return std::__terminate_on_exception([&] { return std::reduce(
return std::reduce( std::make_move_iterator(__values.get()),
std::make_move_iterator(__values.get()), std::make_move_iterator(__values.get() + __partitions.__chunk_count_),
std::make_move_iterator(__values.get() + __partitions.__chunk_count_), std::move(__init),
std::move(__init), __combiner);
__combiner);
});
} }
// TODO: parallelize this
template <class _RandomAccessIterator, class _Comp, class _LeafSort> template <class _RandomAccessIterator, class _Comp, class _LeafSort>
_LIBCPP_HIDE_FROM_ABI void __parallel_stable_sort( _LIBCPP_HIDE_FROM_ABI optional<__empty> __parallel_stable_sort(
_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp, _LeafSort __leaf_sort) { _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp, _LeafSort __leaf_sort) {
__leaf_sort(__first, __last, __comp); const auto __size = __last - __first;
auto __partitions = __libdispatch::__partition_chunks(__size);
if (__partitions.__chunk_count_ == 0)
return __empty{};
if (__partitions.__chunk_count_ == 1) {
__leaf_sort(__first, __last, __comp);
return __empty{};
}
using _Value = __iter_value_type<_RandomAccessIterator>;
auto __destroy = [__size](_Value* __ptr) {
std::destroy_n(__ptr, __size);
std::allocator<_Value>().deallocate(__ptr, __size);
};
// TODO: use __uninitialized_buffer
unique_ptr<_Value[], decltype(__destroy)> __values(std::allocator<_Value>().allocate(__size), __destroy);
// Initialize all elements to a moved-from state
// TODO: Don't do this - this can be done in the first merge - see https://llvm.org/PR63928
std::__construct_at(__values.get(), std::move(*__first));
for (__iter_diff_t<_RandomAccessIterator> __i = 1; __i != __size; ++__i) {
std::__construct_at(__values.get() + __i, std::move(__values.get()[__i - 1]));
}
*__first = std::move(__values.get()[__size - 1]);
__libdispatch::__dispatch_parallel_for(
__partitions,
__first,
[&__leaf_sort, &__comp](_RandomAccessIterator __chunk_first, _RandomAccessIterator __chunk_last) {
__leaf_sort(std::move(__chunk_first), std::move(__chunk_last), __comp);
});
bool __objects_are_in_buffer = false;
do {
const auto __old_chunk_size = __partitions.__chunk_size_;
if (__partitions.__chunk_count_ % 2 == 1) {
auto __inplace_merge_chunks = [&__comp, &__partitions](auto __first_chunk_begin) {
std::inplace_merge(
__first_chunk_begin,
__first_chunk_begin + __partitions.__first_chunk_size_,
__first_chunk_begin + __partitions.__first_chunk_size_ + __partitions.__chunk_size_,
__comp);
};
if (__objects_are_in_buffer)
__inplace_merge_chunks(__values.get());
else
__inplace_merge_chunks(__first);
__partitions.__first_chunk_size_ += 2 * __partitions.__chunk_size_;
} else {
__partitions.__first_chunk_size_ += __partitions.__chunk_size_;
}
__partitions.__chunk_size_ *= 2;
__partitions.__chunk_count_ /= 2;
auto __merge_chunks = [__partitions, __old_chunk_size, &__comp](auto __from_first, auto __to_first) {
__libdispatch::__dispatch_parallel_for(
__partitions,
__from_first,
[__old_chunk_size, &__from_first, &__to_first, &__comp](auto __chunk_first, auto __chunk_last) {
std::merge(std::make_move_iterator(__chunk_first),
std::make_move_iterator(__chunk_last - __old_chunk_size),
std::make_move_iterator(__chunk_last - __old_chunk_size),
std::make_move_iterator(__chunk_last),
__to_first + (__chunk_first - __from_first),
__comp);
});
};
if (__objects_are_in_buffer)
__merge_chunks(__values.get(), __first);
else
__merge_chunks(__first, __values.get());
__objects_are_in_buffer = !__objects_are_in_buffer;
} while (__partitions.__chunk_count_ > 1);
if (__objects_are_in_buffer) {
std::move(__values.get(), __values.get() + __size, __first);
}
return __empty{};
} }
_LIBCPP_HIDE_FROM_ABI inline void __cancel_execution() {} _LIBCPP_HIDE_FROM_ABI inline void __cancel_execution() {}

View File

@ -12,10 +12,10 @@
#include <__algorithm/merge.h> #include <__algorithm/merge.h>
#include <__algorithm/pstl_backends/cpu_backends/backend.h> #include <__algorithm/pstl_backends/cpu_backends/backend.h>
#include <__config> #include <__config>
#include <__iterator/iterator_traits.h> #include <__iterator/concepts.h>
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <__utility/terminate_on_exception.h> #include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@ -23,6 +23,9 @@
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_PUSH_MACROS
# include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _ExecutionPolicy, template <class _ExecutionPolicy,
@ -30,7 +33,7 @@ template <class _ExecutionPolicy,
class _ForwardIterator2, class _ForwardIterator2,
class _ForwardOutIterator, class _ForwardOutIterator,
class _Comp> class _Comp>
_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator __pstl_merge( _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> __pstl_merge(
__cpu_backend_tag, __cpu_backend_tag,
_ForwardIterator1 __first1, _ForwardIterator1 __first1,
_ForwardIterator1 __last1, _ForwardIterator1 __last1,
@ -39,34 +42,35 @@ _LIBCPP_HIDE_FROM_ABI _ForwardOutIterator __pstl_merge(
_ForwardOutIterator __result, _ForwardOutIterator __result,
_Comp __comp) { _Comp __comp) {
if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category<_ForwardIterator1>::value && __has_random_access_iterator_category_or_concept<_ForwardIterator1>::value &&
__has_random_access_iterator_category<_ForwardIterator2>::value && __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value &&
__has_random_access_iterator_category<_ForwardOutIterator>::value) { __has_random_access_iterator_category_or_concept<_ForwardOutIterator>::value) {
return std::__terminate_on_exception([&] { auto __res = __par_backend::__parallel_merge(
__par_backend::__parallel_merge( __first1,
__first1, __last1,
__last1, __first2,
__first2, __last2,
__last2, __result,
__result, __comp,
__comp, [](_ForwardIterator1 __g_first1,
[](_ForwardIterator1 __g_first1, _ForwardIterator1 __g_last1,
_ForwardIterator1 __g_last1, _ForwardIterator2 __g_first2,
_ForwardIterator2 __g_first2, _ForwardIterator2 __g_last2,
_ForwardIterator2 __g_last2, _ForwardOutIterator __g_result,
_ForwardOutIterator __g_result, _Comp __g_comp) {
_Comp __g_comp) { [[maybe_unused]] auto __g_res = std::__pstl_merge<__remove_parallel_policy_t<_ExecutionPolicy>>(
return std::__pstl_merge<__remove_parallel_policy_t<_ExecutionPolicy>>( __cpu_backend_tag{},
__cpu_backend_tag{}, std::move(__g_first1),
std::move(__g_first1), std::move(__g_last1),
std::move(__g_last1), std::move(__g_first2),
std::move(__g_first2), std::move(__g_last2),
std::move(__g_last2), std::move(__g_result),
std::move(__g_result), std::move(__g_comp));
std::move(__g_comp)); _LIBCPP_ASSERT_INTERNAL(__g_res, "unsed/sed should never try to allocate!");
}); });
return __result + (__last1 - __first1) + (__last2 - __first2); if (!__res)
}); return nullopt;
return __result + (__last1 - __first1) + (__last2 - __first2);
} else { } else {
return std::merge(__first1, __last1, __first2, __last2, __result, __comp); return std::merge(__first1, __last1, __first2, __last2, __result, __comp);
} }
@ -74,6 +78,8 @@ _LIBCPP_HIDE_FROM_ABI _ForwardOutIterator __pstl_merge(
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_MERGE_H #endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_MERGE_H

View File

@ -11,8 +11,10 @@
#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_SERIAL_H #define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_SERIAL_H
#include <__config> #include <__config>
#include <__utility/empty.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <cstddef> #include <cstddef>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@ -20,26 +22,32 @@
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_PUSH_MACROS
# include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
namespace __par_backend { namespace __par_backend {
inline namespace __serial_cpu_backend { inline namespace __serial_cpu_backend {
template <class _RandomAccessIterator, class _Fp> template <class _RandomAccessIterator, class _Fp>
_LIBCPP_HIDE_FROM_ABI void __parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Fp __f) { _LIBCPP_HIDE_FROM_ABI optional<__empty>
__parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Fp __f) {
__f(__first, __last); __f(__first, __last);
return __empty{};
} }
template <class _Index, class _UnaryOp, class _Tp, class _BinaryOp, class _Reduce> template <class _Index, class _UnaryOp, class _Tp, class _BinaryOp, class _Reduce>
_LIBCPP_HIDE_FROM_ABI _Tp _LIBCPP_HIDE_FROM_ABI optional<_Tp>
__parallel_transform_reduce(_Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) { __parallel_transform_reduce(_Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) {
return __reduce(std::move(__first), std::move(__last), std::move(__init)); return __reduce(std::move(__first), std::move(__last), std::move(__init));
} }
template <class _RandomAccessIterator, class _Compare, class _LeafSort> template <class _RandomAccessIterator, class _Compare, class _LeafSort>
_LIBCPP_HIDE_FROM_ABI void __parallel_stable_sort( _LIBCPP_HIDE_FROM_ABI optional<__empty> __parallel_stable_sort(
_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort) { _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort) {
__leaf_sort(__first, __last, __comp); __leaf_sort(__first, __last, __comp);
return __empty{};
} }
_LIBCPP_HIDE_FROM_ABI inline void __cancel_execution() {} _LIBCPP_HIDE_FROM_ABI inline void __cancel_execution() {}
@ -49,7 +57,7 @@ template <class _RandomAccessIterator1,
class _RandomAccessIterator3, class _RandomAccessIterator3,
class _Compare, class _Compare,
class _LeafMerge> class _LeafMerge>
_LIBCPP_HIDE_FROM_ABI void __parallel_merge( _LIBCPP_HIDE_FROM_ABI optional<__empty> __parallel_merge(
_RandomAccessIterator1 __first1, _RandomAccessIterator1 __first1,
_RandomAccessIterator1 __last1, _RandomAccessIterator1 __last1,
_RandomAccessIterator2 __first2, _RandomAccessIterator2 __first2,
@ -58,6 +66,7 @@ _LIBCPP_HIDE_FROM_ABI void __parallel_merge(
_Compare __comp, _Compare __comp,
_LeafMerge __leaf_merge) { _LeafMerge __leaf_merge) {
__leaf_merge(__first1, __last1, __first2, __last2, __outit, __comp); __leaf_merge(__first1, __last1, __first2, __last2, __outit, __comp);
return __empty{};
} }
// TODO: Complete this list // TODO: Complete this list
@ -67,6 +76,8 @@ _LIBCPP_HIDE_FROM_ABI void __parallel_merge(
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && && _LIBCPP_STD_VER >= 17
#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_SERIAL_H #endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_SERIAL_H

View File

@ -13,7 +13,8 @@
#include <__algorithm/stable_sort.h> #include <__algorithm/stable_sort.h>
#include <__config> #include <__config>
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__utility/terminate_on_exception.h> #include <__utility/empty.h>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@ -24,17 +25,16 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _ExecutionPolicy, class _RandomAccessIterator, class _Comp> template <class _ExecutionPolicy, class _RandomAccessIterator, class _Comp>
_LIBCPP_HIDE_FROM_ABI void _LIBCPP_HIDE_FROM_ABI optional<__empty>
__pstl_stable_sort(__cpu_backend_tag, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) { __pstl_stable_sort(__cpu_backend_tag, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) {
if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy>) { if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy>) {
std::__terminate_on_exception([&] { return __par_backend::__parallel_stable_sort(
__par_backend::__parallel_stable_sort( __first, __last, __comp, [](_RandomAccessIterator __g_first, _RandomAccessIterator __g_last, _Comp __g_comp) {
__first, __last, __comp, [](_RandomAccessIterator __g_first, _RandomAccessIterator __g_last, _Comp __g_comp) { std::stable_sort(__g_first, __g_last, __g_comp);
std::stable_sort(__g_first, __g_last, __g_comp); });
});
});
} else { } else {
std::stable_sort(__first, __last, __comp); std::stable_sort(__first, __last, __comp);
return __empty{};
} }
} }

View File

@ -11,8 +11,10 @@
#include <__assert> #include <__assert>
#include <__config> #include <__config>
#include <__utility/empty.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <cstddef> #include <cstddef>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@ -32,20 +34,23 @@ namespace __par_backend {
inline namespace __thread_cpu_backend { inline namespace __thread_cpu_backend {
template <class _RandomAccessIterator, class _Fp> template <class _RandomAccessIterator, class _Fp>
_LIBCPP_HIDE_FROM_ABI void __parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Fp __f) { _LIBCPP_HIDE_FROM_ABI optional<__empty>
__parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Fp __f) {
__f(__first, __last); __f(__first, __last);
return __empty{};
} }
template <class _Index, class _UnaryOp, class _Tp, class _BinaryOp, class _Reduce> template <class _Index, class _UnaryOp, class _Tp, class _BinaryOp, class _Reduce>
_LIBCPP_HIDE_FROM_ABI _Tp _LIBCPP_HIDE_FROM_ABI optional<_Tp>
__parallel_transform_reduce(_Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) { __parallel_transform_reduce(_Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) {
return __reduce(std::move(__first), std::move(__last), std::move(__init)); return __reduce(std::move(__first), std::move(__last), std::move(__init));
} }
template <class _RandomAccessIterator, class _Compare, class _LeafSort> template <class _RandomAccessIterator, class _Compare, class _LeafSort>
_LIBCPP_HIDE_FROM_ABI void __parallel_stable_sort( _LIBCPP_HIDE_FROM_ABI optional<__empty> __parallel_stable_sort(
_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort) { _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort) {
__leaf_sort(__first, __last, __comp); __leaf_sort(__first, __last, __comp);
return __empty{};
} }
_LIBCPP_HIDE_FROM_ABI inline void __cancel_execution() {} _LIBCPP_HIDE_FROM_ABI inline void __cancel_execution() {}
@ -55,7 +60,7 @@ template <class _RandomAccessIterator1,
class _RandomAccessIterator3, class _RandomAccessIterator3,
class _Compare, class _Compare,
class _LeafMerge> class _LeafMerge>
_LIBCPP_HIDE_FROM_ABI void __parallel_merge( _LIBCPP_HIDE_FROM_ABI optional<__empty> __parallel_merge(
_RandomAccessIterator1 __first1, _RandomAccessIterator1 __first1,
_RandomAccessIterator1 __last1, _RandomAccessIterator1 __last1,
_RandomAccessIterator2 __first2, _RandomAccessIterator2 __first2,
@ -64,6 +69,7 @@ _LIBCPP_HIDE_FROM_ABI void __parallel_merge(
_Compare __comp, _Compare __comp,
_LeafMerge __leaf_merge) { _LeafMerge __leaf_merge) {
__leaf_merge(__first1, __last1, __first2, __last2, __outit, __comp); __leaf_merge(__first1, __last1, __first2, __last2, __outit, __comp);
return __empty{};
} }
} // namespace __thread_cpu_backend } // namespace __thread_cpu_backend

View File

@ -12,11 +12,12 @@
#include <__algorithm/pstl_backends/cpu_backends/backend.h> #include <__algorithm/pstl_backends/cpu_backends/backend.h>
#include <__algorithm/transform.h> #include <__algorithm/transform.h>
#include <__config> #include <__config>
#include <__iterator/concepts.h>
#include <__iterator/iterator_traits.h> #include <__iterator/iterator_traits.h>
#include <__type_traits/enable_if.h> #include <__type_traits/enable_if.h>
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__type_traits/remove_cvref.h> #include <__type_traits/remove_cvref.h>
#include <__utility/terminate_on_exception.h> #include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
@ -24,11 +25,14 @@
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_PUSH_MACROS
# include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Iterator1, class _DifferenceType, class _Iterator2, class _Function> template <class _Iterator1, class _DifferenceType, class _Iterator2, class _Function>
_LIBCPP_HIDE_FROM_ABI _Iterator2 _LIBCPP_HIDE_FROM_ABI _Iterator2
__simd_walk_2(_Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Function __f) noexcept { __simd_walk(_Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Function __f) noexcept {
_PSTL_PRAGMA_SIMD _PSTL_PRAGMA_SIMD
for (_DifferenceType __i = 0; __i < __n; ++__i) for (_DifferenceType __i = 0; __i < __n; ++__i)
__f(__first1[__i], __first2[__i]); __f(__first1[__i], __first2[__i]);
@ -36,27 +40,27 @@ __simd_walk_2(_Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Fu
} }
template <class _ExecutionPolicy, class _ForwardIterator, class _ForwardOutIterator, class _UnaryOperation> template <class _ExecutionPolicy, class _ForwardIterator, class _ForwardOutIterator, class _UnaryOperation>
_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator __pstl_transform( _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> __pstl_transform(
__cpu_backend_tag, __cpu_backend_tag,
_ForwardIterator __first, _ForwardIterator __first,
_ForwardIterator __last, _ForwardIterator __last,
_ForwardOutIterator __result, _ForwardOutIterator __result,
_UnaryOperation __op) { _UnaryOperation __op) {
if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category<_ForwardIterator>::value && __has_random_access_iterator_category_or_concept<_ForwardIterator>::value &&
__has_random_access_iterator_category<_ForwardOutIterator>::value) { __has_random_access_iterator_category_or_concept<_ForwardOutIterator>::value) {
std::__terminate_on_exception([&] { std::__par_backend::__parallel_for(
std::__par_backend::__parallel_for( __first, __last, [__op, __first, __result](_ForwardIterator __brick_first, _ForwardIterator __brick_last) {
__first, __last, [__op, __first, __result](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { auto __res = std::__pstl_transform<__remove_parallel_policy_t<_ExecutionPolicy>>(
return std::__pstl_transform<__remove_parallel_policy_t<_ExecutionPolicy>>( __cpu_backend_tag{}, __brick_first, __brick_last, __result + (__brick_first - __first), __op);
__cpu_backend_tag{}, __brick_first, __brick_last, __result + (__brick_first - __first), __op); _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!");
}); return *std::move(__res);
}); });
return __result + (__last - __first); return __result + (__last - __first);
} else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category<_ForwardIterator>::value && __has_random_access_iterator_category_or_concept<_ForwardIterator>::value &&
__has_random_access_iterator_category<_ForwardOutIterator>::value) { __has_random_access_iterator_category_or_concept<_ForwardOutIterator>::value) {
return std::__simd_walk_2( return std::__simd_walk(
__first, __first,
__last - __first, __last - __first,
__result, __result,
@ -69,7 +73,7 @@ _LIBCPP_HIDE_FROM_ABI _ForwardOutIterator __pstl_transform(
} }
template <class _Iterator1, class _DifferenceType, class _Iterator2, class _Iterator3, class _Function> template <class _Iterator1, class _DifferenceType, class _Iterator2, class _Iterator3, class _Function>
_LIBCPP_HIDE_FROM_ABI _Iterator3 __simd_walk_3( _LIBCPP_HIDE_FROM_ABI _Iterator3 __simd_walk(
_Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Iterator3 __first3, _Function __f) noexcept { _Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Iterator3 __first3, _Function __f) noexcept {
_PSTL_PRAGMA_SIMD _PSTL_PRAGMA_SIMD
for (_DifferenceType __i = 0; __i < __n; ++__i) for (_DifferenceType __i = 0; __i < __n; ++__i)
@ -82,7 +86,7 @@ template <class _ExecutionPolicy,
class _ForwardOutIterator, class _ForwardOutIterator,
class _BinaryOperation, class _BinaryOperation,
enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0> enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator __pstl_transform( _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> __pstl_transform(
__cpu_backend_tag, __cpu_backend_tag,
_ForwardIterator1 __first1, _ForwardIterator1 __first1,
_ForwardIterator1 __last1, _ForwardIterator1 __last1,
@ -90,29 +94,29 @@ _LIBCPP_HIDE_FROM_ABI _ForwardOutIterator __pstl_transform(
_ForwardOutIterator __result, _ForwardOutIterator __result,
_BinaryOperation __op) { _BinaryOperation __op) {
if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category<_ForwardIterator1>::value && __has_random_access_iterator_category_or_concept<_ForwardIterator1>::value &&
__has_random_access_iterator_category<_ForwardIterator2>::value && __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value &&
__has_random_access_iterator_category<_ForwardOutIterator>::value) { __has_random_access_iterator_category_or_concept<_ForwardOutIterator>::value) {
std::__terminate_on_exception([&] { auto __res = std::__par_backend::__parallel_for(
std::__par_backend::__parallel_for( __first1,
__first1, __last1,
__last1, [__op, __first1, __first2, __result](_ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last) {
[__op, __first1, __first2, __result](_ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last) { return std::__pstl_transform<__remove_parallel_policy_t<_ExecutionPolicy>>(
return std::__pstl_transform<__remove_parallel_policy_t<_ExecutionPolicy>>( __cpu_backend_tag{},
__cpu_backend_tag{}, __brick_first,
__brick_first, __brick_last,
__brick_last, __first2 + (__brick_first - __first1),
__first2 + (__brick_first - __first1), __result + (__brick_first - __first1),
__result + (__brick_first - __first1), __op);
__op); });
}); if (!__res)
}); return nullopt;
return __result + (__last1 - __first1); return __result + (__last1 - __first1);
} else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category<_ForwardIterator1>::value && __has_random_access_iterator_category_or_concept<_ForwardIterator1>::value &&
__has_random_access_iterator_category<_ForwardIterator2>::value && __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value &&
__has_random_access_iterator_category<_ForwardOutIterator>::value) { __has_random_access_iterator_category_or_concept<_ForwardOutIterator>::value) {
return std::__simd_walk_3( return std::__simd_walk(
__first1, __first1,
__last1 - __first1, __last1 - __first1,
__first2, __first2,
@ -127,6 +131,8 @@ _LIBCPP_HIDE_FROM_ABI _ForwardOutIterator __pstl_transform(
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_H #endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_H

View File

@ -11,29 +11,35 @@
#include <__algorithm/pstl_backends/cpu_backends/backend.h> #include <__algorithm/pstl_backends/cpu_backends/backend.h>
#include <__config> #include <__config>
#include <__iterator/concepts.h>
#include <__iterator/iterator_traits.h> #include <__iterator/iterator_traits.h>
#include <__numeric/transform_reduce.h> #include <__numeric/transform_reduce.h>
#include <__type_traits/is_arithmetic.h> #include <__type_traits/is_arithmetic.h>
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__type_traits/operation_traits.h> #include <__type_traits/operation_traits.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <__utility/terminate_on_exception.h>
#include <new> #include <new>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template < template <typename _DifferenceType,
typename _DifferenceType, typename _Tp,
typename _Tp, typename _BinaryOperation,
typename _BinaryOperation, typename _UnaryOperation,
typename _UnaryOperation, typename _UnaryResult = invoke_result_t<_UnaryOperation, _DifferenceType>,
__enable_if_t<__is_trivial_plus_operation<_BinaryOperation, _Tp, _Tp>::value && is_arithmetic_v<_Tp>, int> = 0> __enable_if_t<__desugars_to<__plus_tag, _BinaryOperation, _Tp, _UnaryResult>::value && is_arithmetic_v<_Tp> &&
is_arithmetic_v<_UnaryResult>,
int> = 0>
_LIBCPP_HIDE_FROM_ABI _Tp _LIBCPP_HIDE_FROM_ABI _Tp
__simd_transform_reduce(_DifferenceType __n, _Tp __init, _BinaryOperation, _UnaryOperation __f) noexcept { __simd_transform_reduce(_DifferenceType __n, _Tp __init, _BinaryOperation, _UnaryOperation __f) noexcept {
_PSTL_PRAGMA_SIMD_REDUCTION(+ : __init) _PSTL_PRAGMA_SIMD_REDUCTION(+ : __init)
@ -42,12 +48,14 @@ __simd_transform_reduce(_DifferenceType __n, _Tp __init, _BinaryOperation, _Unar
return __init; return __init;
} }
template < template <typename _Size,
typename _Size, typename _Tp,
typename _Tp, typename _BinaryOperation,
typename _BinaryOperation, typename _UnaryOperation,
typename _UnaryOperation, typename _UnaryResult = invoke_result_t<_UnaryOperation, _Size>,
__enable_if_t<!(__is_trivial_plus_operation<_BinaryOperation, _Tp, _Tp>::value && is_arithmetic_v<_Tp>), int> = 0> __enable_if_t<!(__desugars_to<__plus_tag, _BinaryOperation, _Tp, _UnaryResult>::value &&
is_arithmetic_v<_Tp> && is_arithmetic_v<_UnaryResult>),
int> = 0>
_LIBCPP_HIDE_FROM_ABI _Tp _LIBCPP_HIDE_FROM_ABI _Tp
__simd_transform_reduce(_Size __n, _Tp __init, _BinaryOperation __binary_op, _UnaryOperation __f) noexcept { __simd_transform_reduce(_Size __n, _Tp __init, _BinaryOperation __binary_op, _UnaryOperation __f) noexcept {
const _Size __block_size = __lane_size / sizeof(_Tp); const _Size __block_size = __lane_size / sizeof(_Tp);
@ -97,7 +105,7 @@ template <class _ExecutionPolicy,
class _Tp, class _Tp,
class _BinaryOperation1, class _BinaryOperation1,
class _BinaryOperation2> class _BinaryOperation2>
_LIBCPP_HIDE_FROM_ABI _Tp __pstl_transform_reduce( _LIBCPP_HIDE_FROM_ABI optional<_Tp> __pstl_transform_reduce(
__cpu_backend_tag, __cpu_backend_tag,
_ForwardIterator1 __first1, _ForwardIterator1 __first1,
_ForwardIterator1 __last1, _ForwardIterator1 __last1,
@ -106,32 +114,30 @@ _LIBCPP_HIDE_FROM_ABI _Tp __pstl_transform_reduce(
_BinaryOperation1 __reduce, _BinaryOperation1 __reduce,
_BinaryOperation2 __transform) { _BinaryOperation2 __transform) {
if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category<_ForwardIterator1>::value && __has_random_access_iterator_category_or_concept<_ForwardIterator1>::value &&
__has_random_access_iterator_category<_ForwardIterator2>::value) { __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value) {
return std::__terminate_on_exception([&] { return __par_backend::__parallel_transform_reduce(
return __par_backend::__parallel_transform_reduce( __first1,
__first1, std::move(__last1),
std::move(__last1), [__first1, __first2, __transform](_ForwardIterator1 __iter) {
[__first1, __first2, __transform](_ForwardIterator1 __iter) { return __transform(*__iter, *(__first2 + (__iter - __first1)));
return __transform(*__iter, *(__first2 + (__iter - __first1))); },
}, std::move(__init),
std::move(__init), std::move(__reduce),
std::move(__reduce), [__first1, __first2, __reduce, __transform](
[__first1, __first2, __reduce, __transform]( _ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last, _Tp __brick_init) {
_ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last, _Tp __brick_init) { return *std::__pstl_transform_reduce<__remove_parallel_policy_t<_ExecutionPolicy>>(
return std::__pstl_transform_reduce<__remove_parallel_policy_t<_ExecutionPolicy>>( __cpu_backend_tag{},
__cpu_backend_tag{}, __brick_first,
__brick_first, std::move(__brick_last),
std::move(__brick_last), __first2 + (__brick_first - __first1),
__first2 + (__brick_first - __first1), std::move(__brick_init),
std::move(__brick_init), std::move(__reduce),
std::move(__reduce), std::move(__transform));
std::move(__transform)); });
});
});
} else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category<_ForwardIterator1>::value && __has_random_access_iterator_category_or_concept<_ForwardIterator1>::value &&
__has_random_access_iterator_category<_ForwardIterator2>::value) { __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value) {
return std::__simd_transform_reduce( return std::__simd_transform_reduce(
__last1 - __first1, std::move(__init), std::move(__reduce), [&](__iter_diff_t<_ForwardIterator1> __i) { __last1 - __first1, std::move(__init), std::move(__reduce), [&](__iter_diff_t<_ForwardIterator1> __i) {
return __transform(__first1[__i], __first2[__i]); return __transform(__first1[__i], __first2[__i]);
@ -148,7 +154,7 @@ _LIBCPP_HIDE_FROM_ABI _Tp __pstl_transform_reduce(
} }
template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation> template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation>
_LIBCPP_HIDE_FROM_ABI _Tp __pstl_transform_reduce( _LIBCPP_HIDE_FROM_ABI optional<_Tp> __pstl_transform_reduce(
__cpu_backend_tag, __cpu_backend_tag,
_ForwardIterator __first, _ForwardIterator __first,
_ForwardIterator __last, _ForwardIterator __last,
@ -156,26 +162,26 @@ _LIBCPP_HIDE_FROM_ABI _Tp __pstl_transform_reduce(
_BinaryOperation __reduce, _BinaryOperation __reduce,
_UnaryOperation __transform) { _UnaryOperation __transform) {
if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category<_ForwardIterator>::value) { __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
return std::__terminate_on_exception([&] { return __par_backend::__parallel_transform_reduce(
return __par_backend::__parallel_transform_reduce( std::move(__first),
std::move(__first), std::move(__last),
std::move(__last), [__transform](_ForwardIterator __iter) { return __transform(*__iter); },
[__transform](_ForwardIterator __iter) { return __transform(*__iter); }, std::move(__init),
std::move(__init), __reduce,
__reduce, [__transform, __reduce](auto __brick_first, auto __brick_last, _Tp __brick_init) {
[__transform, __reduce](auto __brick_first, auto __brick_last, _Tp __brick_init) { auto __res = std::__pstl_transform_reduce<__remove_parallel_policy_t<_ExecutionPolicy>>(
return std::__pstl_transform_reduce<__remove_parallel_policy_t<_ExecutionPolicy>>( __cpu_backend_tag{},
__cpu_backend_tag{}, std::move(__brick_first),
std::move(__brick_first), std::move(__brick_last),
std::move(__brick_last), std::move(__brick_init),
std::move(__brick_init), std::move(__reduce),
std::move(__reduce), std::move(__transform));
std::move(__transform)); _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!");
}); return *std::move(__res);
}); });
} else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category<_ForwardIterator>::value) { __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
return std::__simd_transform_reduce( return std::__simd_transform_reduce(
__last - __first, __last - __first,
std::move(__init), std::move(__init),
@ -191,4 +197,6 @@ _LIBCPP_END_NAMESPACE_STD
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_REDUCE_H #endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_REDUCE_H

View File

@ -10,50 +10,112 @@
#define _LIBCPP___ALGORITHM_PSTL_COPY_H #define _LIBCPP___ALGORITHM_PSTL_COPY_H
#include <__algorithm/copy_n.h> #include <__algorithm/copy_n.h>
#include <__algorithm/pstl_backend.h>
#include <__algorithm/pstl_frontend_dispatch.h>
#include <__algorithm/pstl_transform.h> #include <__algorithm/pstl_transform.h>
#include <__config> #include <__config>
#include <__functional/identity.h> #include <__functional/identity.h>
#include <__iterator/iterator_traits.h> #include <__iterator/concepts.h>
#include <__type_traits/enable_if.h> #include <__type_traits/enable_if.h>
#include <__type_traits/is_constant_evaluated.h> #include <__type_traits/is_constant_evaluated.h>
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__type_traits/is_trivially_copyable.h> #include <__type_traits/is_trivially_copyable.h>
#include <__type_traits/remove_cvref.h> #include <__type_traits/remove_cvref.h>
#include <__utility/move.h>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
// TODO: Use the std::copy/move shenanigans to forward to std::memmove // TODO: Use the std::copy/move shenanigans to forward to std::memmove
template <class>
void __pstl_copy();
template <class _ExecutionPolicy, template <class _ExecutionPolicy,
class _ForwardIterator, class _ForwardIterator,
class _ForwardOutIterator, class _ForwardOutIterator,
enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0> class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator>
__copy(_ExecutionPolicy&& __policy,
_ForwardIterator&& __first,
_ForwardIterator&& __last,
_ForwardOutIterator&& __result) noexcept {
return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_copy, _RawPolicy),
[&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _ForwardOutIterator __g_result) {
return std::__transform(__policy, __g_first, __g_last, __g_result, __identity());
},
std::move(__first),
std::move(__last),
std::move(__result));
}
template <class _ExecutionPolicy,
class _ForwardIterator,
class _ForwardOutIterator,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator _LIBCPP_HIDE_FROM_ABI _ForwardOutIterator
copy(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __result) { copy(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __result) {
return std::transform(__policy, __first, __last, __result, __identity()); auto __res = std::__copy(__policy, std::move(__first), std::move(__last), std::move(__result));
if (!__res)
std::__throw_bad_alloc();
return *std::move(__res);
}
template <class>
void __pstl_copy_n();
template <class _ExecutionPolicy,
class _ForwardIterator,
class _ForwardOutIterator,
class _Size,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> __copy_n(
_ExecutionPolicy&& __policy, _ForwardIterator&& __first, _Size&& __n, _ForwardOutIterator&& __result) noexcept {
return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_copy_n, _RawPolicy),
[&__policy](
_ForwardIterator __g_first, _Size __g_n, _ForwardOutIterator __g_result) -> optional<_ForwardIterator> {
if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value)
return std::__copy(__policy, std::move(__g_first), std::move(__g_first + __g_n), std::move(__g_result));
else
return std::copy_n(__g_first, __g_n, __g_result);
},
std::move(__first),
std::move(__n),
std::move(__result));
} }
template <class _ExecutionPolicy, template <class _ExecutionPolicy,
class _ForwardIterator, class _ForwardIterator,
class _ForwardOutIterator, class _ForwardOutIterator,
class _Size, class _Size,
enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0> class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator _LIBCPP_HIDE_FROM_ABI _ForwardOutIterator
copy_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n, _ForwardOutIterator __result) { copy_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n, _ForwardOutIterator __result) {
if constexpr (__has_random_access_iterator_category<_ForwardIterator>::value) auto __res = std::__copy_n(__policy, std::move(__first), std::move(__n), std::move(__result));
return std::copy(__policy, __first, __first + __n, __result); if (!__res)
else std::__throw_bad_alloc();
return std::copy_n(__first, __n, __result); return *std::move(__res);
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PSTL_COPY_H #endif // _LIBCPP___ALGORITHM_PSTL_COPY_H

View File

@ -23,12 +23,15 @@
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__type_traits/remove_cvref.h> #include <__type_traits/remove_cvref.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <__utility/terminate_on_exception.h> #include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
@ -41,13 +44,13 @@ template <class _ExecutionPolicy,
class _Predicate, class _Predicate,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI __iter_diff_t<_ForwardIterator> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__iter_diff_t<_ForwardIterator>> __count_if(
count_if(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { _ExecutionPolicy&& __policy, _ForwardIterator&& __first, _ForwardIterator&& __last, _Predicate&& __pred) noexcept {
using __diff_t = __iter_diff_t<_ForwardIterator>; using __diff_t = __iter_diff_t<_ForwardIterator>;
return std::__pstl_frontend_dispatch( return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_count_if), _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_count_if, _RawPolicy),
[&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) { [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) -> optional<__diff_t> {
return std::transform_reduce( return std::__transform_reduce(
__policy, __policy,
std::move(__g_first), std::move(__g_first),
std::move(__g_last), std::move(__g_last),
@ -60,6 +63,19 @@ count_if(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator
std::move(__pred)); std::move(__pred));
} }
template <class _ExecutionPolicy,
class _ForwardIterator,
class _Predicate,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI __iter_diff_t<_ForwardIterator>
count_if(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
auto __res = std::__count_if(__policy, std::move(__first), std::move(__last), std::move(__pred));
if (!__res)
std::__throw_bad_alloc();
return *std::move(__res);
}
template <class> template <class>
void __pstl_count(); // declaration needed for the frontend dispatch below void __pstl_count(); // declaration needed for the frontend dispatch below
@ -68,11 +84,12 @@ template <class _ExecutionPolicy,
class _Tp, class _Tp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI __iter_diff_t<_ForwardIterator> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__iter_diff_t<_ForwardIterator>>
count(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { __count(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
return std::__pstl_frontend_dispatch( return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_count), _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_count, _RawPolicy),
[&](_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_value) { [&](_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_value)
-> optional<__iter_diff_t<_ForwardIterator>> {
return std::count_if(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __v) { return std::count_if(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __v) {
return __v == __g_value; return __v == __g_value;
}); });
@ -82,8 +99,23 @@ count(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __
__value); __value);
} }
template <class _ExecutionPolicy,
class _ForwardIterator,
class _Tp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI __iter_diff_t<_ForwardIterator>
count(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
auto __res = std::__count(__policy, std::move(__first), std::move(__last), __value);
if (!__res)
std::__throw_bad_alloc();
return *__res;
}
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PSTL_COUNT_H #endif // _LIBCPP___ALGORITHM_PSTL_COUNT_H

View File

@ -0,0 +1,175 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___ALGORITHM_PSTL_EQUAL_H
#define _LIBCPP___ALGORITHM_PSTL_EQUAL_H
#include <__algorithm/equal.h>
#include <__algorithm/pstl_frontend_dispatch.h>
#include <__config>
#include <__functional/operations.h>
#include <__iterator/iterator_traits.h>
#include <__numeric/pstl_transform_reduce.h>
#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD
template <class>
void __pstl_equal();
template <class _ExecutionPolicy,
class _ForwardIterator1,
class _ForwardIterator2,
class _Pred,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool>
__equal(_ExecutionPolicy&& __policy,
_ForwardIterator1&& __first1,
_ForwardIterator1&& __last1,
_ForwardIterator2&& __first2,
_Pred&& __pred) noexcept {
return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_equal, _RawPolicy),
[&__policy](
_ForwardIterator1 __g_first1, _ForwardIterator1 __g_last1, _ForwardIterator2 __g_first2, _Pred __g_pred) {
return std::__transform_reduce(
__policy,
std::move(__g_first1),
std::move(__g_last1),
std::move(__g_first2),
true,
std::logical_and{},
std::move(__g_pred));
},
std::move(__first1),
std::move(__last1),
std::move(__first2),
std::move(__pred));
}
template <class _ExecutionPolicy,
class _ForwardIterator1,
class _ForwardIterator2,
class _Pred,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI bool
equal(_ExecutionPolicy&& __policy,
_ForwardIterator1 __first1,
_ForwardIterator1 __last1,
_ForwardIterator2 __first2,
_Pred __pred) {
auto __res = std::__equal(__policy, std::move(__first1), std::move(__last1), std::move(__first2), std::move(__pred));
if (!__res)
std::__throw_bad_alloc();
return *__res;
}
template <class _ExecutionPolicy,
class _ForwardIterator1,
class _ForwardIterator2,
enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0>
_LIBCPP_HIDE_FROM_ABI bool
equal(_ExecutionPolicy&& __policy, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) {
return std::equal(__policy, std::move(__first1), std::move(__last1), std::move(__first2), std::equal_to{});
}
template <class _ExecutionPolicy,
class _ForwardIterator1,
class _ForwardIterator2,
class _Pred,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool>
__equal(_ExecutionPolicy&& __policy,
_ForwardIterator1&& __first1,
_ForwardIterator1&& __last1,
_ForwardIterator2&& __first2,
_ForwardIterator2&& __last2,
_Pred&& __pred) noexcept {
return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_equal, _RawPolicy),
[&__policy](_ForwardIterator1 __g_first1,
_ForwardIterator1 __g_last1,
_ForwardIterator2 __g_first2,
_ForwardIterator2 __g_last2,
_Pred __g_pred) -> optional<bool> {
if constexpr (__has_random_access_iterator_category<_ForwardIterator1>::value &&
__has_random_access_iterator_category<_ForwardIterator2>::value) {
if (__g_last1 - __g_first1 != __g_last2 - __g_first2)
return false;
return std::__equal(
__policy, std::move(__g_first1), std::move(__g_last1), std::move(__g_first2), std::move(__g_pred));
} else {
(void)__policy; // Avoid unused lambda capture warning
return std::equal(
std::move(__g_first1),
std::move(__g_last1),
std::move(__g_first2),
std::move(__g_last2),
std::move(__g_pred));
}
},
std::move(__first1),
std::move(__last1),
std::move(__first2),
std::move(__last2),
std::move(__pred));
}
template <class _ExecutionPolicy,
class _ForwardIterator1,
class _ForwardIterator2,
class _Pred,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI bool
equal(_ExecutionPolicy&& __policy,
_ForwardIterator1 __first1,
_ForwardIterator1 __last1,
_ForwardIterator2 __first2,
_ForwardIterator2 __last2,
_Pred __pred) {
auto __res = std::__equal(
__policy, std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::move(__pred));
if (!__res)
std::__throw_bad_alloc();
return *__res;
}
template <class _ExecutionPolicy,
class _ForwardIterator1,
class _ForwardIterator2,
enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0>
_LIBCPP_HIDE_FROM_ABI bool
equal(_ExecutionPolicy&& __policy,
_ForwardIterator1 __first1,
_ForwardIterator1 __last1,
_ForwardIterator2 __first2,
_ForwardIterator2 __last2) {
return std::equal(
__policy, std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::equal_to{});
}
_LIBCPP_END_NAMESPACE_STD
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PSTL_EQUAL_H

View File

@ -13,18 +13,22 @@
#include <__algorithm/pstl_for_each.h> #include <__algorithm/pstl_for_each.h>
#include <__algorithm/pstl_frontend_dispatch.h> #include <__algorithm/pstl_frontend_dispatch.h>
#include <__config> #include <__config>
#include <__iterator/concepts.h>
#include <__iterator/cpp17_iterator_concepts.h> #include <__iterator/cpp17_iterator_concepts.h>
#include <__iterator/iterator_traits.h> #include <__iterator/iterator_traits.h>
#include <__type_traits/enable_if.h> #include <__type_traits/enable_if.h>
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__type_traits/remove_cvref.h> #include <__type_traits/remove_cvref.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <__utility/terminate_on_exception.h> #include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
@ -37,13 +41,13 @@ template <class _ExecutionPolicy,
class _Tp, class _Tp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void _LIBCPP_HIDE_FROM_ABI optional<__empty>
fill(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { __fill(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) noexcept {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
std::__pstl_frontend_dispatch( return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_fill), _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_fill, _RawPolicy),
[&](_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_value) { [&](_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_value) {
std::for_each(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __element) { return std::__for_each(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __element) {
__element = __g_value; __element = __g_value;
}); });
}, },
@ -52,6 +56,18 @@ fill(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __l
__value); __value);
} }
template <class _ExecutionPolicy,
class _ForwardIterator,
class _Tp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void
fill(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
if (!std::__fill(__policy, std::move(__first), std::move(__last), __value))
std::__throw_bad_alloc();
}
template <class> template <class>
void __pstl_fill_n(); // declaration needed for the frontend dispatch below void __pstl_fill_n(); // declaration needed for the frontend dispatch below
@ -61,24 +77,40 @@ template <class _ExecutionPolicy,
class _Tp, class _Tp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
fill_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _SizeT __n, const _Tp& __value) { __fill_n(_ExecutionPolicy&& __policy, _ForwardIterator&& __first, _SizeT&& __n, const _Tp& __value) noexcept {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
std::__pstl_frontend_dispatch( return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_fill_n), _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_fill_n, _RawPolicy),
[&](_ForwardIterator __g_first, _SizeT __g_n, const _Tp& __g_value) { [&](_ForwardIterator __g_first, _SizeT __g_n, const _Tp& __g_value) {
if constexpr (__has_random_access_iterator_category<_ForwardIterator>::value) if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value)
std::fill(__policy, __g_first, __g_first + __g_n, __g_value); std::fill(__policy, __g_first, __g_first + __g_n, __g_value);
else else
std::fill_n(__g_first, __g_n, __g_value); std::fill_n(__g_first, __g_n, __g_value);
return optional<__empty>{__empty{}};
}, },
std::move(__first), std::move(__first),
__n, std::move(__n),
__value); __value);
} }
template <class _ExecutionPolicy,
class _ForwardIterator,
class _SizeT,
class _Tp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void
fill_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _SizeT __n, const _Tp& __value) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
if (!std::__fill_n(__policy, std::move(__first), std::move(__n), __value))
std::__throw_bad_alloc();
}
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PSTL_FILL_H #endif // _LIBCPP___ALGORITHM_PSTL_FILL_H

View File

@ -15,17 +15,19 @@
#include <__algorithm/pstl_frontend_dispatch.h> #include <__algorithm/pstl_frontend_dispatch.h>
#include <__config> #include <__config>
#include <__iterator/cpp17_iterator_concepts.h> #include <__iterator/cpp17_iterator_concepts.h>
#include <__iterator/iterator_traits.h>
#include <__type_traits/enable_if.h> #include <__type_traits/enable_if.h>
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__type_traits/remove_cvref.h> #include <__type_traits/remove_cvref.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <__utility/terminate_on_exception.h> #include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
@ -35,13 +37,26 @@ template <class _ExecutionPolicy,
class _Predicate, class _Predicate,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardIterator [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__remove_cvref_t<_ForwardIterator>>
find_if(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { __find_if(_ExecutionPolicy&&, _ForwardIterator&& __first, _ForwardIterator&& __last, _Predicate&& __pred) noexcept {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
using _Backend = typename __select_backend<_RawPolicy>::type; using _Backend = typename __select_backend<_RawPolicy>::type;
return std::__pstl_find_if<_RawPolicy>(_Backend{}, std::move(__first), std::move(__last), std::move(__pred)); return std::__pstl_find_if<_RawPolicy>(_Backend{}, std::move(__first), std::move(__last), std::move(__pred));
} }
template <class _ExecutionPolicy,
class _ForwardIterator,
class _Predicate,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardIterator
find_if(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
auto __res = std::__find_if(__policy, std::move(__first), std::move(__last), std::move(__pred));
if (!__res)
std::__throw_bad_alloc();
return *std::move(__res);
}
template <class> template <class>
void __pstl_find_if_not(); void __pstl_find_if_not();
@ -50,21 +65,36 @@ template <class _ExecutionPolicy,
class _Predicate, class _Predicate,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardIterator [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__remove_cvref_t<_ForwardIterator>>
find_if_not(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { __find_if_not(_ExecutionPolicy&& __policy, _ForwardIterator&& __first, _ForwardIterator&& __last, _Predicate&& __pred) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
return std::__pstl_frontend_dispatch( return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_find_if_not), _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_find_if_not, _RawPolicy),
[&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) { [&](_ForwardIterator&& __g_first, _ForwardIterator&& __g_last, _Predicate&& __g_pred)
return std::find_if(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __value) { -> optional<__remove_cvref_t<_ForwardIterator>> {
return !__g_pred(__value); return std::__find_if(
}); __policy, __g_first, __g_last, [&](__iter_reference<__remove_cvref_t<_ForwardIterator>> __value) {
return !__g_pred(__value);
});
}, },
std::move(__first), std::move(__first),
std::move(__last), std::move(__last),
std::move(__pred)); std::move(__pred));
} }
template <class _ExecutionPolicy,
class _ForwardIterator,
class _Predicate,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardIterator
find_if_not(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
auto __res = std::__find_if_not(__policy, std::move(__first), std::move(__last), std::move(__pred));
if (!__res)
std::__throw_bad_alloc();
return *std::move(__res);
}
template <class> template <class>
void __pstl_find(); void __pstl_find();
@ -73,23 +103,39 @@ template <class _ExecutionPolicy,
class _Tp, class _Tp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardIterator [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__remove_cvref_t<_ForwardIterator>>
find(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { __find(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) noexcept {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
return std::__pstl_frontend_dispatch( return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_find), _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_find, _RawPolicy),
[&](_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_value) { [&](_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_value) -> optional<_ForwardIterator> {
return std::find_if(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __element) { return std::find_if(
return __element == __g_value; __policy, __g_first, __g_last, [&](__iter_reference<__remove_cvref_t<_ForwardIterator>> __element) {
}); return __element == __g_value;
});
}, },
std::move(__first), std::move(__first),
std::move(__last), std::move(__last),
__value); __value);
} }
template <class _ExecutionPolicy,
class _ForwardIterator,
class _Tp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardIterator
find(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
auto __res = std::__find(__policy, std::move(__first), std::move(__last), __value);
if (!__res)
std::__throw_bad_alloc();
return *std::move(__res);
}
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PSTL_FIND_H #endif // _LIBCPP___ALGORITHM_PSTL_FIND_H

View File

@ -14,19 +14,23 @@
#include <__algorithm/pstl_backend.h> #include <__algorithm/pstl_backend.h>
#include <__algorithm/pstl_frontend_dispatch.h> #include <__algorithm/pstl_frontend_dispatch.h>
#include <__config> #include <__config>
#include <__iterator/concepts.h>
#include <__iterator/cpp17_iterator_concepts.h> #include <__iterator/cpp17_iterator_concepts.h>
#include <__iterator/iterator_traits.h>
#include <__type_traits/enable_if.h> #include <__type_traits/enable_if.h>
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__type_traits/remove_cvref.h> #include <__type_traits/remove_cvref.h>
#include <__type_traits/void_t.h> #include <__type_traits/void_t.h>
#include <__utility/empty.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <__utility/terminate_on_exception.h> #include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
@ -36,16 +40,51 @@ template <class _ExecutionPolicy,
class _Function, class _Function,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
for_each(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Function __func) { __for_each(_ExecutionPolicy&&, _ForwardIterator&& __first, _ForwardIterator&& __last, _Function&& __func) noexcept {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
using _Backend = typename __select_backend<_RawPolicy>::type; using _Backend = typename __select_backend<_RawPolicy>::type;
std::__pstl_for_each<_RawPolicy>(_Backend{}, std::move(__first), std::move(__last), std::move(__func)); return std::__pstl_for_each<_RawPolicy>(_Backend{}, std::move(__first), std::move(__last), std::move(__func));
}
template <class _ExecutionPolicy,
class _ForwardIterator,
class _Function,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void
for_each(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Function __func) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
if (!std::__for_each(__policy, std::move(__first), std::move(__last), std::move(__func)))
std::__throw_bad_alloc();
} }
template <class> template <class>
void __pstl_for_each_n(); // declaration needed for the frontend dispatch below void __pstl_for_each_n(); // declaration needed for the frontend dispatch below
template <class _ExecutionPolicy,
class _ForwardIterator,
class _Size,
class _Function,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
__for_each_n(_ExecutionPolicy&& __policy, _ForwardIterator&& __first, _Size&& __size, _Function&& __func) noexcept {
return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_for_each_n, _RawPolicy),
[&](_ForwardIterator __g_first, _Size __g_size, _Function __g_func) -> optional<__empty> {
if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
std::for_each(__policy, std::move(__g_first), __g_first + __g_size, std::move(__g_func));
return __empty{};
} else {
std::for_each_n(std::move(__g_first), __g_size, std::move(__g_func));
return __empty{};
}
},
std::move(__first),
std::move(__size),
std::move(__func));
}
template <class _ExecutionPolicy, template <class _ExecutionPolicy,
class _ForwardIterator, class _ForwardIterator,
class _Size, class _Size,
@ -55,22 +94,15 @@ template <class _ExecutionPolicy,
_LIBCPP_HIDE_FROM_ABI void _LIBCPP_HIDE_FROM_ABI void
for_each_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __size, _Function __func) { for_each_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __size, _Function __func) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
return std::__pstl_frontend_dispatch( auto __res = std::__for_each_n(__policy, std::move(__first), std::move(__size), std::move(__func));
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_for_each_n), if (!__res)
[&](_ForwardIterator __g_first, _Size __g_size, _Function __g_func) { std::__throw_bad_alloc();
if constexpr (__has_random_access_iterator_category<_ForwardIterator>::value) {
std::for_each(__policy, std::move(__g_first), __g_first + __g_size, std::move(__g_func));
} else {
std::for_each_n(std::move(__g_first), __g_size, std::move(__g_func));
}
},
__first,
__size,
std::move(__func));
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PSTL_FOR_EACH_H #endif // _LIBCPP___ALGORITHM_PSTL_FOR_EACH_H

View File

@ -21,11 +21,10 @@
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
# define _LIBCPP_PSTL_CUSTOMIZATION_POINT(name) \ # define _LIBCPP_PSTL_CUSTOMIZATION_POINT(name, policy) \
[](auto&&... __args) -> decltype(std::name<_RawPolicy>(typename __select_backend<_RawPolicy>::type{}, \ [](auto&&... __args) -> decltype(std::name<policy>( \
std::forward<decltype(__args)>(__args)...)) { \ typename __select_backend<policy>::type{}, std::forward<decltype(__args)>(__args)...)) { \
return std::name<_RawPolicy>( \ return std::name<policy>(typename __select_backend<policy>::type{}, std::forward<decltype(__args)>(__args)...); \
typename __select_backend<_RawPolicy>::type{}, std::forward<decltype(__args)>(__args)...); \
} }
template <class _SpecializedImpl, class _GenericImpl, class... _Args> template <class _SpecializedImpl, class _GenericImpl, class... _Args>

View File

@ -14,15 +14,20 @@
#include <__algorithm/pstl_frontend_dispatch.h> #include <__algorithm/pstl_frontend_dispatch.h>
#include <__config> #include <__config>
#include <__iterator/cpp17_iterator_concepts.h> #include <__iterator/cpp17_iterator_concepts.h>
#include <__iterator/iterator_traits.h>
#include <__type_traits/enable_if.h> #include <__type_traits/enable_if.h>
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__type_traits/remove_cvref.h> #include <__type_traits/remove_cvref.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
@ -35,13 +40,13 @@ template <class _ExecutionPolicy,
class _Generator, class _Generator,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
generate(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Generator __gen) { __generate(_ExecutionPolicy&& __policy, _ForwardIterator&& __first, _ForwardIterator&& __last, _Generator&& __gen) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
std::__pstl_frontend_dispatch( return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_generate), _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_generate, _RawPolicy),
[&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _Generator __g_gen) { [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _Generator __g_gen) {
std::for_each( return std::__for_each(
__policy, std::move(__g_first), std::move(__g_last), [&](__iter_reference<_ForwardIterator> __element) { __policy, std::move(__g_first), std::move(__g_last), [&](__iter_reference<_ForwardIterator> __element) {
__element = __g_gen(); __element = __g_gen();
}); });
@ -51,6 +56,18 @@ generate(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator
std::move(__gen)); std::move(__gen));
} }
template <class _ExecutionPolicy,
class _ForwardIterator,
class _Generator,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void
generate(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Generator __gen) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
if (!std::__generate(__policy, std::move(__first), std::move(__last), std::move(__gen)))
std::__throw_bad_alloc();
}
template <class> template <class>
void __pstl_generate_n(); void __pstl_generate_n();
@ -60,23 +77,38 @@ template <class _ExecutionPolicy,
class _Generator, class _Generator,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
generate_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n, _Generator __gen) { __generate_n(_ExecutionPolicy&& __policy, _ForwardIterator&& __first, _Size&& __n, _Generator&& __gen) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); return std::__pstl_frontend_dispatch(
std::__pstl_frontend_dispatch( _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_generate_n, _RawPolicy),
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_generate_n),
[&__policy](_ForwardIterator __g_first, _Size __g_n, _Generator __g_gen) { [&__policy](_ForwardIterator __g_first, _Size __g_n, _Generator __g_gen) {
std::for_each_n(__policy, std::move(__g_first), __g_n, [&](__iter_reference<_ForwardIterator> __element) { return std::__for_each_n(
__element = __g_gen(); __policy, std::move(__g_first), std::move(__g_n), [&](__iter_reference<_ForwardIterator> __element) {
}); __element = __g_gen();
});
}, },
std::move(__first), std::move(__first),
__n, __n,
std::move(__gen)); std::move(__gen));
} }
template <class _ExecutionPolicy,
class _ForwardIterator,
class _Size,
class _Generator,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void
generate_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n, _Generator __gen) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
if (!std::__generate_n(__policy, std::move(__first), std::move(__n), std::move(__gen)))
std::__throw_bad_alloc();
}
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PSTL_GENERATE_H #endif // _LIBCPP___ALGORITHM_PSTL_GENERATE_H

View File

@ -18,11 +18,15 @@
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__type_traits/remove_cvref.h> #include <__type_traits/remove_cvref.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
@ -35,10 +39,10 @@ template <class _ExecutionPolicy,
class _Predicate, class _Predicate,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> __is_partitioned(
is_partitioned(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { _ExecutionPolicy&& __policy, _ForwardIterator&& __first, _ForwardIterator&& __last, _Predicate&& __pred) {
return std::__pstl_frontend_dispatch( return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_is_partitioned), _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_is_partitioned, _RawPolicy),
[&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) { [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) {
__g_first = std::find_if_not(__policy, __g_first, __g_last, __g_pred); __g_first = std::find_if_not(__policy, __g_first, __g_last, __g_pred);
if (__g_first == __g_last) if (__g_first == __g_last)
@ -51,8 +55,23 @@ is_partitioned(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIt
std::move(__pred)); std::move(__pred));
} }
template <class _ExecutionPolicy,
class _ForwardIterator,
class _Predicate,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool
is_partitioned(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
auto __res = std::__is_partitioned(__policy, std::move(__first), std::move(__last), std::move(__pred));
if (!__res)
std::__throw_bad_alloc();
return *std::move(__res);
}
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PSTL_IS_PARITTIONED #endif // _LIBCPP___ALGORITHM_PSTL_IS_PARITTIONED

View File

@ -16,11 +16,15 @@
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__type_traits/remove_cvref.h> #include <__type_traits/remove_cvref.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
@ -32,14 +36,14 @@ template <class _ExecutionPolicy,
class _Comp = std::less<>, class _Comp = std::less<>,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator>
merge(_ExecutionPolicy&&, __merge(_ExecutionPolicy&&,
_ForwardIterator1 __first1, _ForwardIterator1 __first1,
_ForwardIterator1 __last1, _ForwardIterator1 __last1,
_ForwardIterator2 __first2, _ForwardIterator2 __first2,
_ForwardIterator2 __last2, _ForwardIterator2 __last2,
_ForwardOutIterator __result, _ForwardOutIterator __result,
_Comp __comp = {}) { _Comp __comp = {}) noexcept {
using _Backend = typename __select_backend<_RawPolicy>::type; using _Backend = typename __select_backend<_RawPolicy>::type;
return std::__pstl_merge<_RawPolicy>( return std::__pstl_merge<_RawPolicy>(
_Backend{}, _Backend{},
@ -51,8 +55,38 @@ merge(_ExecutionPolicy&&,
std::move(__comp)); std::move(__comp));
} }
template <class _ExecutionPolicy,
class _ForwardIterator1,
class _ForwardIterator2,
class _ForwardOutIterator,
class _Comp = std::less<>,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator
merge(_ExecutionPolicy&& __policy,
_ForwardIterator1 __first1,
_ForwardIterator1 __last1,
_ForwardIterator2 __first2,
_ForwardIterator2 __last2,
_ForwardOutIterator __result,
_Comp __comp = {}) {
auto __res = std::__merge(
__policy,
std::move(__first1),
std::move(__last1),
std::move(__first2),
std::move(__last2),
std::move(__result),
std::move(__comp));
if (!__res)
std::__throw_bad_alloc();
return *std::move(__res);
}
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PSTL_MERGE_H #endif // _LIBCPP___ALGORITHM_PSTL_MERGE_H

View File

@ -0,0 +1,84 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___ALGORITHM_PSTL_MOVE_H
#define _LIBCPP___ALGORITHM_PSTL_MOVE_H
#include <__algorithm/copy_n.h>
#include <__algorithm/pstl_backend.h>
#include <__algorithm/pstl_frontend_dispatch.h>
#include <__algorithm/pstl_transform.h>
#include <__config>
#include <__functional/identity.h>
#include <__iterator/iterator_traits.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/is_constant_evaluated.h>
#include <__type_traits/is_execution_policy.h>
#include <__type_traits/is_trivially_copyable.h>
#include <__type_traits/remove_cvref.h>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD
// TODO: Use the std::copy/move shenanigans to forward to std::memmove
// Investigate whether we want to still forward to std::transform(policy)
// in that case for the execution::par part, or whether we actually want
// to run everything serially in that case.
template <class>
void __pstl_move();
template <class _ExecutionPolicy,
class _ForwardIterator,
class _ForwardOutIterator,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator>
__move(_ExecutionPolicy&& __policy,
_ForwardIterator&& __first,
_ForwardIterator&& __last,
_ForwardOutIterator&& __result) noexcept {
return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_move, _RawPolicy),
[&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _ForwardOutIterator __g_result) {
return std::__transform(__policy, __g_first, __g_last, __g_result, [](auto&& __v) { return std::move(__v); });
},
std::move(__first),
std::move(__last),
std::move(__result));
}
template <class _ExecutionPolicy,
class _ForwardIterator,
class _ForwardOutIterator,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator
move(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __result) {
auto __res = std::__move(__policy, std::move(__first), std::move(__last), std::move(__result));
if (!__res)
std::__throw_bad_alloc();
return *__res;
}
_LIBCPP_END_NAMESPACE_STD
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PSTL_MOVE_H

View File

@ -18,11 +18,15 @@
#include <__type_traits/enable_if.h> #include <__type_traits/enable_if.h>
#include <__type_traits/remove_cvref.h> #include <__type_traits/remove_cvref.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
@ -30,6 +34,34 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class> template <class>
void __pstl_replace_if(); void __pstl_replace_if();
template <class _ExecutionPolicy,
class _ForwardIterator,
class _Pred,
class _Tp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
__replace_if(_ExecutionPolicy&& __policy,
_ForwardIterator&& __first,
_ForwardIterator&& __last,
_Pred&& __pred,
const _Tp& __new_value) noexcept {
return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_if, _RawPolicy),
[&__policy](
_ForwardIterator&& __g_first, _ForwardIterator&& __g_last, _Pred&& __g_pred, const _Tp& __g_new_value) {
std::for_each(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __element) {
if (__g_pred(__element))
__element = __g_new_value;
});
return optional<__empty>{__empty{}};
},
std::move(__first),
std::move(__last),
std::move(__pred),
__new_value);
}
template <class _ExecutionPolicy, template <class _ExecutionPolicy,
class _ForwardIterator, class _ForwardIterator,
class _Pred, class _Pred,
@ -42,18 +74,9 @@ replace_if(_ExecutionPolicy&& __policy,
_ForwardIterator __last, _ForwardIterator __last,
_Pred __pred, _Pred __pred,
const _Tp& __new_value) { const _Tp& __new_value) {
std::__pstl_frontend_dispatch( auto __res = std::__replace_if(__policy, std::move(__first), std::move(__last), std::move(__pred), __new_value);
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_if), if (!__res)
[&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _Pred __g_pred, const _Tp& __g_new_value) { std::__throw_bad_alloc();
std::for_each(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __element) {
if (__g_pred(__element))
__element = __g_new_value;
});
},
std::move(__first),
std::move(__last),
std::move(__pred),
__new_value);
} }
template <class> template <class>
@ -64,17 +87,17 @@ template <class _ExecutionPolicy,
class _Tp, class _Tp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty>
replace(_ExecutionPolicy&& __policy, __replace(_ExecutionPolicy&& __policy,
_ForwardIterator __first, _ForwardIterator __first,
_ForwardIterator __last, _ForwardIterator __last,
const _Tp& __old_value, const _Tp& __old_value,
const _Tp& __new_value) { const _Tp& __new_value) noexcept {
std::__pstl_frontend_dispatch( return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace), _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace, _RawPolicy),
[&__policy]( [&__policy](
_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_old_value, const _Tp& __g_new_value) { _ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_old_value, const _Tp& __g_new_value) {
std::replace_if( return std::__replace_if(
__policy, __policy,
std::move(__g_first), std::move(__g_first),
std::move(__g_last), std::move(__g_last),
@ -87,9 +110,59 @@ replace(_ExecutionPolicy&& __policy,
__new_value); __new_value);
} }
template <class _ExecutionPolicy,
class _ForwardIterator,
class _Tp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void
replace(_ExecutionPolicy&& __policy,
_ForwardIterator __first,
_ForwardIterator __last,
const _Tp& __old_value,
const _Tp& __new_value) {
if (!std::__replace(__policy, std::move(__first), std::move(__last), __old_value, __new_value))
std::__throw_bad_alloc();
}
template <class> template <class>
void __pstl_replace_copy_if(); void __pstl_replace_copy_if();
template <class _ExecutionPolicy,
class _ForwardIterator,
class _ForwardOutIterator,
class _Pred,
class _Tp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> __replace_copy_if(
_ExecutionPolicy&& __policy,
_ForwardIterator&& __first,
_ForwardIterator&& __last,
_ForwardOutIterator&& __result,
_Pred&& __pred,
const _Tp& __new_value) {
return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_copy_if, _RawPolicy),
[&__policy](_ForwardIterator __g_first,
_ForwardIterator __g_last,
_ForwardOutIterator __g_result,
_Pred __g_pred,
const _Tp& __g_new_value) -> optional<__empty> {
if (!std::__transform(
__policy, __g_first, __g_last, __g_result, [&](__iter_reference<_ForwardIterator> __element) {
return __g_pred(__element) ? __g_new_value : __element;
}))
return nullopt;
return __empty{};
},
std::move(__first),
std::move(__last),
std::move(__result),
std::move(__pred),
__new_value);
}
template <class _ExecutionPolicy, template <class _ExecutionPolicy,
class _ForwardIterator, class _ForwardIterator,
class _ForwardOutIterator, class _ForwardOutIterator,
@ -104,22 +177,9 @@ _LIBCPP_HIDE_FROM_ABI void replace_copy_if(
_ForwardOutIterator __result, _ForwardOutIterator __result,
_Pred __pred, _Pred __pred,
const _Tp& __new_value) { const _Tp& __new_value) {
std::__pstl_frontend_dispatch( if (!std::__replace_copy_if(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_copy_if), __policy, std::move(__first), std::move(__last), std::move(__result), std::move(__pred), __new_value))
[&__policy](_ForwardIterator __g_first, std::__throw_bad_alloc();
_ForwardIterator __g_last,
_ForwardOutIterator __g_result,
_Pred __g_pred,
const _Tp& __g_new_value) {
std::transform(__policy, __g_first, __g_last, __g_result, [&](__iter_reference<_ForwardIterator> __element) {
return __g_pred(__element) ? __g_new_value : __element;
});
},
std::move(__first),
std::move(__last),
std::move(__result),
std::move(__pred),
__new_value);
} }
template <class> template <class>
@ -131,21 +191,21 @@ template <class _ExecutionPolicy,
class _Tp, class _Tp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void replace_copy( [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> __replace_copy(
_ExecutionPolicy&& __policy, _ExecutionPolicy&& __policy,
_ForwardIterator __first, _ForwardIterator&& __first,
_ForwardIterator __last, _ForwardIterator&& __last,
_ForwardOutIterator __result, _ForwardOutIterator&& __result,
const _Tp& __old_value, const _Tp& __old_value,
const _Tp& __new_value) { const _Tp& __new_value) noexcept {
std::__pstl_frontend_dispatch( return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_copy), _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_copy, _RawPolicy),
[&__policy](_ForwardIterator __g_first, [&__policy](_ForwardIterator __g_first,
_ForwardIterator __g_last, _ForwardIterator __g_last,
_ForwardOutIterator __g_result, _ForwardOutIterator __g_result,
const _Tp& __g_old_value, const _Tp& __g_old_value,
const _Tp& __g_new_value) { const _Tp& __g_new_value) {
return std::replace_copy_if( return std::__replace_copy_if(
__policy, __policy,
std::move(__g_first), std::move(__g_first),
std::move(__g_last), std::move(__g_last),
@ -160,8 +220,28 @@ _LIBCPP_HIDE_FROM_ABI void replace_copy(
__new_value); __new_value);
} }
template <class _ExecutionPolicy,
class _ForwardIterator,
class _ForwardOutIterator,
class _Tp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void replace_copy(
_ExecutionPolicy&& __policy,
_ForwardIterator __first,
_ForwardIterator __last,
_ForwardOutIterator __result,
const _Tp& __old_value,
const _Tp& __new_value) {
if (!std::__replace_copy(
__policy, std::move(__first), std::move(__last), std::move(__result), __old_value, __new_value))
std::__throw_bad_alloc();
}
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PSTL_REPLACE_H #endif // _LIBCPP___ALGORITHM_PSTL_REPLACE_H

View File

@ -0,0 +1,85 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___ALGORITHM_PSTL_ROTATE_COPY_H
#define _LIBCPP___ALGORITHM_PSTL_ROTATE_COPY_H
#include <__algorithm/pstl_backend.h>
#include <__algorithm/pstl_copy.h>
#include <__algorithm/pstl_frontend_dispatch.h>
#include <__type_traits/is_execution_policy.h>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD
template <class>
void __pstl_rotate_copy();
template <class _ExecutionPolicy,
class _ForwardIterator,
class _ForwardOutIterator,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator>
__rotate_copy(_ExecutionPolicy&& __policy,
_ForwardIterator&& __first,
_ForwardIterator&& __middle,
_ForwardIterator&& __last,
_ForwardOutIterator&& __result) noexcept {
return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_rotate_copy, _RawPolicy),
[&__policy](_ForwardIterator __g_first,
_ForwardIterator __g_middle,
_ForwardIterator __g_last,
_ForwardOutIterator __g_result) -> optional<_ForwardOutIterator> {
auto __result_mid =
std::__copy(__policy, _ForwardIterator(__g_middle), std::move(__g_last), std::move(__g_result));
if (!__result_mid)
return nullopt;
return std::__copy(__policy, std::move(__g_first), std::move(__g_middle), *std::move(__result_mid));
},
std::move(__first),
std::move(__middle),
std::move(__last),
std::move(__result));
}
template <class _ExecutionPolicy,
class _ForwardIterator,
class _ForwardOutIterator,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator rotate_copy(
_ExecutionPolicy&& __policy,
_ForwardIterator __first,
_ForwardIterator __middle,
_ForwardIterator __last,
_ForwardOutIterator __result) {
auto __res =
std::__rotate_copy(__policy, std::move(__first), std::move(__middle), std::move(__last), std::move(__result));
if (!__res)
std::__throw_bad_alloc();
return *__res;
}
_LIBCPP_END_NAMESPACE_STD
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PSTL_ROTATE_COPY_H

View File

@ -16,13 +16,18 @@
#include <__functional/operations.h> #include <__functional/operations.h>
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__type_traits/remove_cvref.h> #include <__type_traits/remove_cvref.h>
#include <__utility/empty.h>
#include <__utility/forward.h> #include <__utility/forward.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
@ -35,18 +40,30 @@ template <class _ExecutionPolicy,
class _Comp, class _Comp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> __sort(
sort(_ExecutionPolicy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) { _ExecutionPolicy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) noexcept {
std::__pstl_frontend_dispatch( return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_sort), _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_sort, _RawPolicy),
[&__policy](_RandomAccessIterator __g_first, _RandomAccessIterator __g_last, _Comp __g_comp) { [&__policy](_RandomAccessIterator __g_first, _RandomAccessIterator __g_last, _Comp __g_comp) {
std::stable_sort(__policy, std::move(__g_first), std::move(__g_last), std::move(__g_comp)); std::stable_sort(__policy, std::move(__g_first), std::move(__g_last), std::move(__g_comp));
return optional<__empty>{__empty{}};
}, },
std::move(__first), std::move(__first),
std::move(__last), std::move(__last),
std::move(__comp)); std::move(__comp));
} }
template <class _ExecutionPolicy,
class _RandomAccessIterator,
class _Comp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void
sort(_ExecutionPolicy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) {
if (!std::__sort(__policy, std::move(__first), std::move(__last), std::move(__comp)))
std::__throw_bad_alloc();
}
template <class _ExecutionPolicy, template <class _ExecutionPolicy,
class _RandomAccessIterator, class _RandomAccessIterator,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
@ -60,4 +77,6 @@ _LIBCPP_END_NAMESPACE_STD
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PSTL_SORT_H #endif // _LIBCPP___ALGORITHM_PSTL_SORT_H

View File

@ -15,12 +15,17 @@
#include <__type_traits/enable_if.h> #include <__type_traits/enable_if.h>
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__type_traits/remove_cvref.h> #include <__type_traits/remove_cvref.h>
#include <__utility/empty.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
@ -30,14 +35,27 @@ template <class _ExecutionPolicy,
class _Comp = less<>, class _Comp = less<>,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> __stable_sort(
stable_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp = {}) { _ExecutionPolicy&&, _RandomAccessIterator&& __first, _RandomAccessIterator&& __last, _Comp&& __comp = {}) noexcept {
using _Backend = typename __select_backend<_RawPolicy>::type; using _Backend = typename __select_backend<_RawPolicy>::type;
std::__pstl_stable_sort<_RawPolicy>(_Backend{}, std::move(__first), std::move(__last), std::move(__comp)); return std::__pstl_stable_sort<_RawPolicy>(_Backend{}, std::move(__first), std::move(__last), std::move(__comp));
}
template <class _ExecutionPolicy,
class _RandomAccessIterator,
class _Comp = less<>,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI void stable_sort(
_ExecutionPolicy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp = {}) {
if (!std::__stable_sort(__policy, std::move(__first), std::move(__last), std::move(__comp)))
std::__throw_bad_alloc();
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PSTL_STABLE_SORT_H #endif // _LIBCPP___ALGORITHM_PSTL_STABLE_SORT_H

View File

@ -12,21 +12,40 @@
#include <__algorithm/pstl_backend.h> #include <__algorithm/pstl_backend.h>
#include <__config> #include <__config>
#include <__iterator/cpp17_iterator_concepts.h> #include <__iterator/cpp17_iterator_concepts.h>
#include <__iterator/iterator_traits.h>
#include <__type_traits/enable_if.h> #include <__type_traits/enable_if.h>
#include <__type_traits/is_execution_policy.h> #include <__type_traits/is_execution_policy.h>
#include <__type_traits/remove_cvref.h> #include <__type_traits/remove_cvref.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <__utility/terminate_on_exception.h> #include <optional>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header # pragma GCC system_header
#endif #endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _ExecutionPolicy,
class _ForwardIterator,
class _ForwardOutIterator,
class _UnaryOperation,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__remove_cvref_t<_ForwardOutIterator>>
__transform(_ExecutionPolicy&&,
_ForwardIterator&& __first,
_ForwardIterator&& __last,
_ForwardOutIterator&& __result,
_UnaryOperation&& __op) noexcept {
using _Backend = typename __select_backend<_RawPolicy>::type;
return std::__pstl_transform<_RawPolicy>(
_Backend{}, std::move(__first), std::move(__last), std::move(__result), std::move(__op));
}
template <class _ExecutionPolicy, template <class _ExecutionPolicy,
class _ForwardIterator, class _ForwardIterator,
class _ForwardOutIterator, class _ForwardOutIterator,
@ -34,7 +53,7 @@ template <class _ExecutionPolicy,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator transform( _LIBCPP_HIDE_FROM_ABI _ForwardOutIterator transform(
_ExecutionPolicy&&, _ExecutionPolicy&& __policy,
_ForwardIterator __first, _ForwardIterator __first,
_ForwardIterator __last, _ForwardIterator __last,
_ForwardOutIterator __result, _ForwardOutIterator __result,
@ -42,9 +61,29 @@ _LIBCPP_HIDE_FROM_ABI _ForwardOutIterator transform(
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator);
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator); _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator);
_LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, decltype(__op(*__first))); _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, decltype(__op(*__first)));
auto __res = std::__transform(__policy, std::move(__first), std::move(__last), std::move(__result), std::move(__op));
if (!__res)
std::__throw_bad_alloc();
return *std::move(__res);
}
template <class _ExecutionPolicy,
class _ForwardIterator1,
class _ForwardIterator2,
class _ForwardOutIterator,
class _BinaryOperation,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI optional<__remove_cvref_t<_ForwardOutIterator>>
__transform(_ExecutionPolicy&&,
_ForwardIterator1&& __first1,
_ForwardIterator1&& __last1,
_ForwardIterator2&& __first2,
_ForwardOutIterator&& __result,
_BinaryOperation&& __op) noexcept {
using _Backend = typename __select_backend<_RawPolicy>::type; using _Backend = typename __select_backend<_RawPolicy>::type;
return std::__pstl_transform<_RawPolicy>( return std::__pstl_transform<_RawPolicy>(
_Backend{}, std::move(__first), std::move(__last), std::move(__result), std::move(__op)); _Backend{}, std::move(__first1), std::move(__last1), std::move(__first2), std::move(__result), std::move(__op));
} }
template <class _ExecutionPolicy, template <class _ExecutionPolicy,
@ -55,7 +94,7 @@ template <class _ExecutionPolicy,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator transform( _LIBCPP_HIDE_FROM_ABI _ForwardOutIterator transform(
_ExecutionPolicy&&, _ExecutionPolicy&& __policy,
_ForwardIterator1 __first1, _ForwardIterator1 __first1,
_ForwardIterator1 __last1, _ForwardIterator1 __last1,
_ForwardIterator2 __first2, _ForwardIterator2 __first2,
@ -65,13 +104,17 @@ _LIBCPP_HIDE_FROM_ABI _ForwardOutIterator transform(
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2); _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2);
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator); _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator);
_LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, decltype(__op(*__first1, *__first2))); _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, decltype(__op(*__first1, *__first2)));
using _Backend = typename __select_backend<_RawPolicy>::type; auto __res = std::__transform(
return std::__pstl_transform<_RawPolicy>( __policy, std::move(__first1), std::move(__last1), std::move(__first2), std::move(__result), std::move(__op));
_Backend{}, std::move(__first1), std::move(__last1), std::move(__first2), std::move(__result), std::move(__op)); if (!__res)
std::__throw_bad_alloc();
return *std::move(__res);
} }
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_PSTL_TRANSFORM_H #endif // _LIBCPP___ALGORITHM_PSTL_TRANSFORM_H

View File

@ -28,20 +28,22 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
void __sift_up(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp, __sift_up(_RandomAccessIterator __first,
typename iterator_traits<_RandomAccessIterator>::difference_type __len) { _RandomAccessIterator __last,
_Compare&& __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __len) {
using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; using value_type = typename iterator_traits<_RandomAccessIterator>::value_type;
if (__len > 1) { if (__len > 1) {
__len = (__len - 2) / 2; __len = (__len - 2) / 2;
_RandomAccessIterator __ptr = __first + __len; _RandomAccessIterator __ptr = __first + __len;
if (__comp(*__ptr, *--__last)) { if (__comp(*__ptr, *--__last)) {
value_type __t(_IterOps<_AlgPolicy>::__iter_move(__last)); value_type __t(_IterOps<_AlgPolicy>::__iter_move(__last));
do { do {
*__last = _IterOps<_AlgPolicy>::__iter_move(__ptr); *__last = _IterOps<_AlgPolicy>::__iter_move(__ptr);
__last = __ptr; __last = __ptr;
if (__len == 0) if (__len == 0)
break; break;
__len = (__len - 1) / 2; __len = (__len - 1) / 2;
@ -54,15 +56,15 @@ void __sift_up(_RandomAccessIterator __first, _RandomAccessIterator __last, _Com
} }
template <class _AlgPolicy, class _RandomAccessIterator, class _Compare> template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
void __push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) { __push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) {
typename iterator_traits<_RandomAccessIterator>::difference_type __len = __last - __first; typename iterator_traits<_RandomAccessIterator>::difference_type __len = __last - __first;
std::__sift_up<_AlgPolicy, __comp_ref_type<_Compare> >(std::move(__first), std::move(__last), __comp, __len); std::__sift_up<_AlgPolicy, __comp_ref_type<_Compare> >(std::move(__first), std::move(__last), __comp, __len);
} }
template <class _RandomAccessIterator, class _Compare> template <class _RandomAccessIterator, class _Compare>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
void push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible."); static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible.");
static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable."); static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable.");
@ -70,8 +72,8 @@ void push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Com
} }
template <class _RandomAccessIterator> template <class _RandomAccessIterator>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
void push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) {
std::push_heap(std::move(__first), std::move(__last), __less<>()); std::push_heap(std::move(__first), std::move(__last), __less<>());
} }

Some files were not shown because too many files have changed in this diff Show More