19540950aSLouis Dionne //===----------------------------------------------------------------------===// 29540950aSLouis Dionne // 39540950aSLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 49540950aSLouis Dionne // See https://llvm.org/LICENSE.txt for license information. 59540950aSLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 69540950aSLouis Dionne // 79540950aSLouis Dionne //===----------------------------------------------------------------------===// 89540950aSLouis Dionne 99540950aSLouis Dionne #ifndef _LIBCPP___PSTL_BACKENDS_DEFAULT_H 109540950aSLouis Dionne #define _LIBCPP___PSTL_BACKENDS_DEFAULT_H 119540950aSLouis Dionne 129540950aSLouis Dionne #include <__algorithm/copy_n.h> 139540950aSLouis Dionne #include <__algorithm/equal.h> 149540950aSLouis Dionne #include <__algorithm/fill_n.h> 159540950aSLouis Dionne #include <__algorithm/for_each_n.h> 169540950aSLouis Dionne #include <__config> 179540950aSLouis Dionne #include <__functional/identity.h> 189540950aSLouis Dionne #include <__functional/not_fn.h> 199540950aSLouis Dionne #include <__functional/operations.h> 209540950aSLouis Dionne #include <__iterator/concepts.h> 219540950aSLouis Dionne #include <__iterator/iterator_traits.h> 229540950aSLouis Dionne #include <__pstl/backend_fwd.h> 239540950aSLouis Dionne #include <__pstl/dispatch.h> 249540950aSLouis Dionne #include <__utility/empty.h> 259540950aSLouis Dionne #include <__utility/forward.h> 269540950aSLouis Dionne #include <__utility/move.h> 279540950aSLouis Dionne #include <optional> 289540950aSLouis Dionne 299540950aSLouis Dionne #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 309540950aSLouis Dionne # pragma GCC system_header 319540950aSLouis Dionne #endif 329540950aSLouis Dionne 339540950aSLouis Dionne _LIBCPP_PUSH_MACROS 349540950aSLouis Dionne #include <__undef_macros> 359540950aSLouis Dionne 36*bbff52bfSLouis Dionne #if _LIBCPP_STD_VER >= 17 37*bbff52bfSLouis Dionne 389540950aSLouis Dionne _LIBCPP_BEGIN_NAMESPACE_STD 399540950aSLouis Dionne namespace __pstl { 409540950aSLouis Dionne 419540950aSLouis Dionne // 429540950aSLouis Dionne // This file provides an incomplete PSTL backend that implements all of the PSTL algorithms 439540950aSLouis Dionne // based on a smaller set of basis operations. 449540950aSLouis Dionne // 459540950aSLouis Dionne // It is intended as a building block for other PSTL backends that implement some operations more 469540950aSLouis Dionne // efficiently but may not want to define the full set of PSTL algorithms. 479540950aSLouis Dionne // 489540950aSLouis Dionne // This backend implements all the PSTL algorithms based on the following basis operations: 499540950aSLouis Dionne // 509540950aSLouis Dionne // find_if family 519540950aSLouis Dionne // -------------- 529540950aSLouis Dionne // - find 539540950aSLouis Dionne // - find_if_not 549540950aSLouis Dionne // - any_of 559540950aSLouis Dionne // - all_of 569540950aSLouis Dionne // - none_of 579540950aSLouis Dionne // - is_partitioned 589540950aSLouis Dionne // 599540950aSLouis Dionne // for_each family 609540950aSLouis Dionne // --------------- 619540950aSLouis Dionne // - for_each_n 629540950aSLouis Dionne // - fill 639540950aSLouis Dionne // - fill_n 649540950aSLouis Dionne // - replace 659540950aSLouis Dionne // - replace_if 669540950aSLouis Dionne // - generate 679540950aSLouis Dionne // - generate_n 689540950aSLouis Dionne // 699540950aSLouis Dionne // merge family 709540950aSLouis Dionne // ------------ 719540950aSLouis Dionne // No other algorithms based on merge 729540950aSLouis Dionne // 739540950aSLouis Dionne // stable_sort family 749540950aSLouis Dionne // ------------------ 759540950aSLouis Dionne // - sort 769540950aSLouis Dionne // 779540950aSLouis Dionne // transform_reduce and transform_reduce_binary family 789540950aSLouis Dionne // --------------------------------------------------- 799540950aSLouis Dionne // - count_if 809540950aSLouis Dionne // - count 819540950aSLouis Dionne // - equal(3 legs) 829540950aSLouis Dionne // - equal 839540950aSLouis Dionne // - reduce 849540950aSLouis Dionne // 859540950aSLouis Dionne // transform and transform_binary family 869540950aSLouis Dionne // ------------------------------------- 879540950aSLouis Dionne // - replace_copy_if 889540950aSLouis Dionne // - replace_copy 899540950aSLouis Dionne // - move 909540950aSLouis Dionne // - copy 919540950aSLouis Dionne // - copy_n 929540950aSLouis Dionne // - rotate_copy 939540950aSLouis Dionne // 949540950aSLouis Dionne 959540950aSLouis Dionne ////////////////////////////////////////////////////////////// 969540950aSLouis Dionne // find_if family 979540950aSLouis Dionne ////////////////////////////////////////////////////////////// 989540950aSLouis Dionne template <class _ExecutionPolicy> 999540950aSLouis Dionne struct __find<__default_backend_tag, _ExecutionPolicy> { 1009540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _Tp> 1019540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator> 1029540950aSLouis Dionne operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) const noexcept { 1039540950aSLouis Dionne using _FindIf = __dispatch<__find_if, __current_configuration, _ExecutionPolicy>; 1049540950aSLouis Dionne return _FindIf()( 1059540950aSLouis Dionne __policy, std::move(__first), std::move(__last), [&](__iter_reference<_ForwardIterator> __element) { 1069540950aSLouis Dionne return __element == __value; 1079540950aSLouis Dionne }); 1089540950aSLouis Dionne } 1099540950aSLouis Dionne }; 1109540950aSLouis Dionne 1119540950aSLouis Dionne template <class _ExecutionPolicy> 1129540950aSLouis Dionne struct __find_if_not<__default_backend_tag, _ExecutionPolicy> { 1139540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _Pred> 1149540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator> 1159540950aSLouis Dionne operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { 1169540950aSLouis Dionne using _FindIf = __dispatch<__find_if, __current_configuration, _ExecutionPolicy>; 1179540950aSLouis Dionne return _FindIf()(__policy, __first, __last, std::not_fn(std::forward<_Pred>(__pred))); 1189540950aSLouis Dionne } 1199540950aSLouis Dionne }; 1209540950aSLouis Dionne 1219540950aSLouis Dionne template <class _ExecutionPolicy> 1229540950aSLouis Dionne struct __any_of<__default_backend_tag, _ExecutionPolicy> { 1239540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _Pred> 1249540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 1259540950aSLouis Dionne operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { 1269540950aSLouis Dionne using _FindIf = __dispatch<__find_if, __current_configuration, _ExecutionPolicy>; 1279540950aSLouis Dionne auto __res = _FindIf()(__policy, __first, __last, std::forward<_Pred>(__pred)); 1289540950aSLouis Dionne if (!__res) 1299540950aSLouis Dionne return nullopt; 1309540950aSLouis Dionne return *__res != __last; 1319540950aSLouis Dionne } 1329540950aSLouis Dionne }; 1339540950aSLouis Dionne 1349540950aSLouis Dionne template <class _ExecutionPolicy> 1359540950aSLouis Dionne struct __all_of<__default_backend_tag, _ExecutionPolicy> { 1369540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _Pred> 1379540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 1389540950aSLouis Dionne operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { 1399540950aSLouis Dionne using _AnyOf = __dispatch<__any_of, __current_configuration, _ExecutionPolicy>; 1409540950aSLouis Dionne auto __res = _AnyOf()(__policy, __first, __last, [&](__iter_reference<_ForwardIterator> __value) { 1419540950aSLouis Dionne return !__pred(__value); 1429540950aSLouis Dionne }); 1439540950aSLouis Dionne if (!__res) 1449540950aSLouis Dionne return nullopt; 1459540950aSLouis Dionne return !*__res; 1469540950aSLouis Dionne } 1479540950aSLouis Dionne }; 1489540950aSLouis Dionne 1499540950aSLouis Dionne template <class _ExecutionPolicy> 1509540950aSLouis Dionne struct __none_of<__default_backend_tag, _ExecutionPolicy> { 1519540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _Pred> 1529540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 1539540950aSLouis Dionne operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { 1549540950aSLouis Dionne using _AnyOf = __dispatch<__any_of, __current_configuration, _ExecutionPolicy>; 1559540950aSLouis Dionne auto __res = _AnyOf()(__policy, __first, __last, std::forward<_Pred>(__pred)); 1569540950aSLouis Dionne if (!__res) 1579540950aSLouis Dionne return nullopt; 1589540950aSLouis Dionne return !*__res; 1599540950aSLouis Dionne } 1609540950aSLouis Dionne }; 1619540950aSLouis Dionne 1629540950aSLouis Dionne template <class _ExecutionPolicy> 1639540950aSLouis Dionne struct __is_partitioned<__default_backend_tag, _ExecutionPolicy> { 1649540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _Pred> 1659540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 1669540950aSLouis Dionne operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { 1679540950aSLouis Dionne using _FindIfNot = __dispatch<__find_if_not, __current_configuration, _ExecutionPolicy>; 168f73050e7SLouis Dionne auto __maybe_first = _FindIfNot()(__policy, std::move(__first), __last, __pred); 1699540950aSLouis Dionne if (__maybe_first == nullopt) 1709540950aSLouis Dionne return nullopt; 1719540950aSLouis Dionne 1729540950aSLouis Dionne __first = *__maybe_first; 1739540950aSLouis Dionne if (__first == __last) 1749540950aSLouis Dionne return true; 1759540950aSLouis Dionne ++__first; 1769540950aSLouis Dionne using _NoneOf = __dispatch<__none_of, __current_configuration, _ExecutionPolicy>; 1779540950aSLouis Dionne return _NoneOf()(__policy, std::move(__first), std::move(__last), __pred); 1789540950aSLouis Dionne } 1799540950aSLouis Dionne }; 1809540950aSLouis Dionne 1819540950aSLouis Dionne ////////////////////////////////////////////////////////////// 1829540950aSLouis Dionne // for_each family 1839540950aSLouis Dionne ////////////////////////////////////////////////////////////// 1849540950aSLouis Dionne template <class _ExecutionPolicy> 1859540950aSLouis Dionne struct __for_each_n<__default_backend_tag, _ExecutionPolicy> { 1869540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _Size, class _Function> 1879540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 1889540950aSLouis Dionne operator()(_Policy&& __policy, _ForwardIterator __first, _Size __size, _Function __func) const noexcept { 1899540950aSLouis Dionne if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { 1909540950aSLouis Dionne using _ForEach = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>; 1919540950aSLouis Dionne _ForwardIterator __last = __first + __size; 1929540950aSLouis Dionne return _ForEach()(__policy, std::move(__first), std::move(__last), std::move(__func)); 1939540950aSLouis Dionne } else { 1949540950aSLouis Dionne // Otherwise, use the serial algorithm to avoid doing two passes over the input 1959540950aSLouis Dionne std::for_each_n(std::move(__first), __size, std::move(__func)); 1969540950aSLouis Dionne return __empty{}; 1979540950aSLouis Dionne } 1989540950aSLouis Dionne } 1999540950aSLouis Dionne }; 2009540950aSLouis Dionne 2019540950aSLouis Dionne template <class _ExecutionPolicy> 2029540950aSLouis Dionne struct __fill<__default_backend_tag, _ExecutionPolicy> { 2039540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _Tp> 2049540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 2059540950aSLouis Dionne operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp const& __value) const noexcept { 2069540950aSLouis Dionne using _ForEach = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>; 2079540950aSLouis Dionne using _Ref = __iter_reference<_ForwardIterator>; 2089540950aSLouis Dionne return _ForEach()(__policy, std::move(__first), std::move(__last), [&](_Ref __element) { __element = __value; }); 2099540950aSLouis Dionne } 2109540950aSLouis Dionne }; 2119540950aSLouis Dionne 2129540950aSLouis Dionne template <class _ExecutionPolicy> 2139540950aSLouis Dionne struct __fill_n<__default_backend_tag, _ExecutionPolicy> { 2149540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _Size, class _Tp> 2159540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 2169540950aSLouis Dionne operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, _Tp const& __value) const noexcept { 2179540950aSLouis Dionne if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { 2189540950aSLouis Dionne using _Fill = __dispatch<__fill, __current_configuration, _ExecutionPolicy>; 2199540950aSLouis Dionne _ForwardIterator __last = __first + __n; 2209540950aSLouis Dionne return _Fill()(__policy, std::move(__first), std::move(__last), __value); 2219540950aSLouis Dionne } else { 2229540950aSLouis Dionne // Otherwise, use the serial algorithm to avoid doing two passes over the input 2239540950aSLouis Dionne std::fill_n(std::move(__first), __n, __value); 2249540950aSLouis Dionne return optional<__empty>{__empty{}}; 2259540950aSLouis Dionne } 2269540950aSLouis Dionne } 2279540950aSLouis Dionne }; 2289540950aSLouis Dionne 2299540950aSLouis Dionne template <class _ExecutionPolicy> 2309540950aSLouis Dionne struct __replace<__default_backend_tag, _ExecutionPolicy> { 2319540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _Tp> 2329540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 2339540950aSLouis Dionne operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp const& __old, _Tp const& __new) 2349540950aSLouis Dionne const noexcept { 2359540950aSLouis Dionne using _ReplaceIf = __dispatch<__replace_if, __current_configuration, _ExecutionPolicy>; 2369540950aSLouis Dionne using _Ref = __iter_reference<_ForwardIterator>; 2379540950aSLouis Dionne return _ReplaceIf()( 2389540950aSLouis Dionne __policy, std::move(__first), std::move(__last), [&](_Ref __element) { return __element == __old; }, __new); 2399540950aSLouis Dionne } 2409540950aSLouis Dionne }; 2419540950aSLouis Dionne 2429540950aSLouis Dionne template <class _ExecutionPolicy> 2439540950aSLouis Dionne struct __replace_if<__default_backend_tag, _ExecutionPolicy> { 2449540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _Pred, class _Tp> 2459540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> operator()( 2469540950aSLouis Dionne _Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred, _Tp const& __new_value) 2479540950aSLouis Dionne const noexcept { 2489540950aSLouis Dionne using _ForEach = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>; 2499540950aSLouis Dionne using _Ref = __iter_reference<_ForwardIterator>; 2509540950aSLouis Dionne return _ForEach()(__policy, std::move(__first), std::move(__last), [&](_Ref __element) { 2519540950aSLouis Dionne if (__pred(__element)) 2529540950aSLouis Dionne __element = __new_value; 2539540950aSLouis Dionne }); 2549540950aSLouis Dionne } 2559540950aSLouis Dionne }; 2569540950aSLouis Dionne 2579540950aSLouis Dionne template <class _ExecutionPolicy> 2589540950aSLouis Dionne struct __generate<__default_backend_tag, _ExecutionPolicy> { 2599540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _Generator> 2609540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 2619540950aSLouis Dionne operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Generator&& __gen) const noexcept { 2629540950aSLouis Dionne using _ForEach = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>; 2639540950aSLouis Dionne using _Ref = __iter_reference<_ForwardIterator>; 2649540950aSLouis Dionne return _ForEach()(__policy, std::move(__first), std::move(__last), [&](_Ref __element) { __element = __gen(); }); 2659540950aSLouis Dionne } 2669540950aSLouis Dionne }; 2679540950aSLouis Dionne 2689540950aSLouis Dionne template <class _ExecutionPolicy> 2699540950aSLouis Dionne struct __generate_n<__default_backend_tag, _ExecutionPolicy> { 2709540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _Size, class _Generator> 2719540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 2729540950aSLouis Dionne operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, _Generator&& __gen) const noexcept { 2739540950aSLouis Dionne using _ForEachN = __dispatch<__for_each_n, __current_configuration, _ExecutionPolicy>; 2749540950aSLouis Dionne using _Ref = __iter_reference<_ForwardIterator>; 2759540950aSLouis Dionne return _ForEachN()(__policy, std::move(__first), __n, [&](_Ref __element) { __element = __gen(); }); 2769540950aSLouis Dionne } 2779540950aSLouis Dionne }; 2789540950aSLouis Dionne 2799540950aSLouis Dionne ////////////////////////////////////////////////////////////// 2809540950aSLouis Dionne // stable_sort family 2819540950aSLouis Dionne ////////////////////////////////////////////////////////////// 2829540950aSLouis Dionne template <class _ExecutionPolicy> 2839540950aSLouis Dionne struct __sort<__default_backend_tag, _ExecutionPolicy> { 2849540950aSLouis Dionne template <class _Policy, class _RandomAccessIterator, class _Comp> 2859540950aSLouis Dionne _LIBCPP_HIDE_FROM_ABI optional<__empty> operator()( 2869540950aSLouis Dionne _Policy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp&& __comp) const noexcept { 2879540950aSLouis Dionne using _StableSort = __dispatch<__stable_sort, __current_configuration, _ExecutionPolicy>; 2889540950aSLouis Dionne return _StableSort()(__policy, std::move(__first), std::move(__last), std::forward<_Comp>(__comp)); 2899540950aSLouis Dionne } 2909540950aSLouis Dionne }; 2919540950aSLouis Dionne 2929540950aSLouis Dionne ////////////////////////////////////////////////////////////// 2939540950aSLouis Dionne // transform_reduce family 2949540950aSLouis Dionne ////////////////////////////////////////////////////////////// 2959540950aSLouis Dionne template <class _ExecutionPolicy> 2969540950aSLouis Dionne struct __count_if<__default_backend_tag, _ExecutionPolicy> { 2979540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _Predicate> 2989540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__iter_diff_t<_ForwardIterator>> operator()( 2999540950aSLouis Dionne _Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate&& __pred) const noexcept { 3009540950aSLouis Dionne using _TransformReduce = __dispatch<__transform_reduce, __current_configuration, _ExecutionPolicy>; 3019540950aSLouis Dionne using _DiffT = __iter_diff_t<_ForwardIterator>; 3029540950aSLouis Dionne using _Ref = __iter_reference<_ForwardIterator>; 3039540950aSLouis Dionne return _TransformReduce()( 3049540950aSLouis Dionne __policy, std::move(__first), std::move(__last), _DiffT{}, std::plus{}, [&](_Ref __element) -> _DiffT { 3059540950aSLouis Dionne return __pred(__element) ? _DiffT(1) : _DiffT(0); 3069540950aSLouis Dionne }); 3079540950aSLouis Dionne } 3089540950aSLouis Dionne }; 3099540950aSLouis Dionne 3109540950aSLouis Dionne template <class _ExecutionPolicy> 3119540950aSLouis Dionne struct __count<__default_backend_tag, _ExecutionPolicy> { 3129540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _Tp> 3139540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__iter_diff_t<_ForwardIterator>> 3149540950aSLouis Dionne operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp const& __value) const noexcept { 3159540950aSLouis Dionne using _CountIf = __dispatch<__count_if, __current_configuration, _ExecutionPolicy>; 3169540950aSLouis Dionne using _Ref = __iter_reference<_ForwardIterator>; 3179540950aSLouis Dionne return _CountIf()(__policy, std::move(__first), std::move(__last), [&](_Ref __element) -> bool { 3189540950aSLouis Dionne return __element == __value; 3199540950aSLouis Dionne }); 3209540950aSLouis Dionne } 3219540950aSLouis Dionne }; 3229540950aSLouis Dionne 3239540950aSLouis Dionne template <class _ExecutionPolicy> 3249540950aSLouis Dionne struct __equal_3leg<__default_backend_tag, _ExecutionPolicy> { 3259540950aSLouis Dionne template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate> 3269540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 3279540950aSLouis Dionne operator()(_Policy&& __policy, 3289540950aSLouis Dionne _ForwardIterator1 __first1, 3299540950aSLouis Dionne _ForwardIterator1 __last1, 3309540950aSLouis Dionne _ForwardIterator2 __first2, 3319540950aSLouis Dionne _Predicate&& __pred) const noexcept { 3329540950aSLouis Dionne using _TransformReduce = __dispatch<__transform_reduce_binary, __current_configuration, _ExecutionPolicy>; 3339540950aSLouis Dionne return _TransformReduce()( 3349540950aSLouis Dionne __policy, 3359540950aSLouis Dionne std::move(__first1), 3369540950aSLouis Dionne std::move(__last1), 3379540950aSLouis Dionne std::move(__first2), 3389540950aSLouis Dionne true, 3399540950aSLouis Dionne std::logical_and{}, 3409540950aSLouis Dionne std::forward<_Predicate>(__pred)); 3419540950aSLouis Dionne } 3429540950aSLouis Dionne }; 3439540950aSLouis Dionne 3449540950aSLouis Dionne template <class _ExecutionPolicy> 3459540950aSLouis Dionne struct __equal<__default_backend_tag, _ExecutionPolicy> { 3469540950aSLouis Dionne template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate> 3479540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 3489540950aSLouis Dionne operator()(_Policy&& __policy, 3499540950aSLouis Dionne _ForwardIterator1 __first1, 3509540950aSLouis Dionne _ForwardIterator1 __last1, 3519540950aSLouis Dionne _ForwardIterator2 __first2, 3529540950aSLouis Dionne _ForwardIterator2 __last2, 3539540950aSLouis Dionne _Predicate&& __pred) const noexcept { 3549540950aSLouis Dionne if constexpr (__has_random_access_iterator_category<_ForwardIterator1>::value && 3559540950aSLouis Dionne __has_random_access_iterator_category<_ForwardIterator2>::value) { 3569540950aSLouis Dionne if (__last1 - __first1 != __last2 - __first2) 3579540950aSLouis Dionne return false; 3589540950aSLouis Dionne // Fall back to the 3 legged algorithm 3599540950aSLouis Dionne using _Equal3Leg = __dispatch<__equal_3leg, __current_configuration, _ExecutionPolicy>; 3609540950aSLouis Dionne return _Equal3Leg()( 3619540950aSLouis Dionne __policy, std::move(__first1), std::move(__last1), std::move(__first2), std::forward<_Predicate>(__pred)); 3629540950aSLouis Dionne } else { 3639540950aSLouis Dionne // If we don't have random access, fall back to the serial algorithm cause we can't do much 3649540950aSLouis Dionne return std::equal( 3659540950aSLouis Dionne std::move(__first1), 3669540950aSLouis Dionne std::move(__last1), 3679540950aSLouis Dionne std::move(__first2), 3689540950aSLouis Dionne std::move(__last2), 3699540950aSLouis Dionne std::forward<_Predicate>(__pred)); 3709540950aSLouis Dionne } 3719540950aSLouis Dionne } 3729540950aSLouis Dionne }; 3739540950aSLouis Dionne 3749540950aSLouis Dionne template <class _ExecutionPolicy> 3759540950aSLouis Dionne struct __reduce<__default_backend_tag, _ExecutionPolicy> { 3769540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _Tp, class _BinaryOperation> 3779540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_Tp> 3789540950aSLouis Dionne operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp __init, _BinaryOperation&& __op) 3799540950aSLouis Dionne const noexcept { 3809540950aSLouis Dionne using _TransformReduce = __dispatch<__transform_reduce, __current_configuration, _ExecutionPolicy>; 3819540950aSLouis Dionne return _TransformReduce()( 3829540950aSLouis Dionne __policy, 3839540950aSLouis Dionne std::move(__first), 3849540950aSLouis Dionne std::move(__last), 3859540950aSLouis Dionne std::move(__init), 3869540950aSLouis Dionne std::forward<_BinaryOperation>(__op), 3879540950aSLouis Dionne __identity{}); 3889540950aSLouis Dionne } 3899540950aSLouis Dionne }; 3909540950aSLouis Dionne 3919540950aSLouis Dionne ////////////////////////////////////////////////////////////// 3929540950aSLouis Dionne // transform family 3939540950aSLouis Dionne ////////////////////////////////////////////////////////////// 3949540950aSLouis Dionne template <class _ExecutionPolicy> 3959540950aSLouis Dionne struct __replace_copy_if<__default_backend_tag, _ExecutionPolicy> { 3969540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _ForwardOutIterator, class _Pred, class _Tp> 3979540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 3989540950aSLouis Dionne operator()(_Policy&& __policy, 3999540950aSLouis Dionne _ForwardIterator __first, 4009540950aSLouis Dionne _ForwardIterator __last, 4019540950aSLouis Dionne _ForwardOutIterator __out_it, 4029540950aSLouis Dionne _Pred&& __pred, 4039540950aSLouis Dionne _Tp const& __new_value) const noexcept { 4049540950aSLouis Dionne using _Transform = __dispatch<__transform, __current_configuration, _ExecutionPolicy>; 4059540950aSLouis Dionne using _Ref = __iter_reference<_ForwardIterator>; 4069540950aSLouis Dionne auto __res = 4079540950aSLouis Dionne _Transform()(__policy, std::move(__first), std::move(__last), std::move(__out_it), [&](_Ref __element) { 4089540950aSLouis Dionne return __pred(__element) ? __new_value : __element; 4099540950aSLouis Dionne }); 4109540950aSLouis Dionne if (__res == nullopt) 4119540950aSLouis Dionne return nullopt; 4129540950aSLouis Dionne return __empty{}; 4139540950aSLouis Dionne } 4149540950aSLouis Dionne }; 4159540950aSLouis Dionne 4169540950aSLouis Dionne template <class _ExecutionPolicy> 4179540950aSLouis Dionne struct __replace_copy<__default_backend_tag, _ExecutionPolicy> { 4189540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _ForwardOutIterator, class _Tp> 4199540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 4209540950aSLouis Dionne operator()(_Policy&& __policy, 4219540950aSLouis Dionne _ForwardIterator __first, 4229540950aSLouis Dionne _ForwardIterator __last, 4239540950aSLouis Dionne _ForwardOutIterator __out_it, 4249540950aSLouis Dionne _Tp const& __old_value, 4259540950aSLouis Dionne _Tp const& __new_value) const noexcept { 4269540950aSLouis Dionne using _ReplaceCopyIf = __dispatch<__replace_copy_if, __current_configuration, _ExecutionPolicy>; 4279540950aSLouis Dionne using _Ref = __iter_reference<_ForwardIterator>; 4289540950aSLouis Dionne return _ReplaceCopyIf()( 4299540950aSLouis Dionne __policy, 4309540950aSLouis Dionne std::move(__first), 4319540950aSLouis Dionne std::move(__last), 4329540950aSLouis Dionne std::move(__out_it), 4339540950aSLouis Dionne [&](_Ref __element) { return __element == __old_value; }, 4349540950aSLouis Dionne __new_value); 4359540950aSLouis Dionne } 4369540950aSLouis Dionne }; 4379540950aSLouis Dionne 4389540950aSLouis Dionne // TODO: Use the std::copy/move shenanigans to forward to std::memmove 4399540950aSLouis Dionne // Investigate whether we want to still forward to std::transform(policy) 4409540950aSLouis Dionne // in that case for the execution::par part, or whether we actually want 4419540950aSLouis Dionne // to run everything serially in that case. 4429540950aSLouis Dionne template <class _ExecutionPolicy> 4439540950aSLouis Dionne struct __move<__default_backend_tag, _ExecutionPolicy> { 4449540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _ForwardOutIterator> 4459540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> 4469540950aSLouis Dionne operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __out_it) 4479540950aSLouis Dionne const noexcept { 4489540950aSLouis Dionne using _Transform = __dispatch<__transform, __current_configuration, _ExecutionPolicy>; 4499540950aSLouis Dionne return _Transform()(__policy, std::move(__first), std::move(__last), std::move(__out_it), [&](auto&& __element) { 4509540950aSLouis Dionne return std::move(__element); 4519540950aSLouis Dionne }); 4529540950aSLouis Dionne } 4539540950aSLouis Dionne }; 4549540950aSLouis Dionne 4559540950aSLouis Dionne // TODO: Use the std::copy/move shenanigans to forward to std::memmove 4569540950aSLouis Dionne template <class _ExecutionPolicy> 4579540950aSLouis Dionne struct __copy<__default_backend_tag, _ExecutionPolicy> { 4589540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _ForwardOutIterator> 4599540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> 4609540950aSLouis Dionne operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __out_it) 4619540950aSLouis Dionne const noexcept { 4629540950aSLouis Dionne using _Transform = __dispatch<__transform, __current_configuration, _ExecutionPolicy>; 4639540950aSLouis Dionne return _Transform()(__policy, std::move(__first), std::move(__last), std::move(__out_it), __identity()); 4649540950aSLouis Dionne } 4659540950aSLouis Dionne }; 4669540950aSLouis Dionne 4679540950aSLouis Dionne template <class _ExecutionPolicy> 4689540950aSLouis Dionne struct __copy_n<__default_backend_tag, _ExecutionPolicy> { 4699540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _Size, class _ForwardOutIterator> 4709540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> 4719540950aSLouis Dionne operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, _ForwardOutIterator __out_it) const noexcept { 4729540950aSLouis Dionne if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { 4739540950aSLouis Dionne using _Copy = __dispatch<__copy, __current_configuration, _ExecutionPolicy>; 4749540950aSLouis Dionne _ForwardIterator __last = __first + __n; 4759540950aSLouis Dionne return _Copy()(__policy, std::move(__first), std::move(__last), std::move(__out_it)); 4769540950aSLouis Dionne } else { 4779540950aSLouis Dionne // Otherwise, use the serial algorithm to avoid doing two passes over the input 4789540950aSLouis Dionne return std::copy_n(std::move(__first), __n, std::move(__out_it)); 4799540950aSLouis Dionne } 4809540950aSLouis Dionne } 4819540950aSLouis Dionne }; 4829540950aSLouis Dionne 4839540950aSLouis Dionne template <class _ExecutionPolicy> 4849540950aSLouis Dionne struct __rotate_copy<__default_backend_tag, _ExecutionPolicy> { 4859540950aSLouis Dionne template <class _Policy, class _ForwardIterator, class _ForwardOutIterator> 4869540950aSLouis Dionne [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> 4879540950aSLouis Dionne operator()(_Policy&& __policy, 4889540950aSLouis Dionne _ForwardIterator __first, 4899540950aSLouis Dionne _ForwardIterator __middle, 4909540950aSLouis Dionne _ForwardIterator __last, 4919540950aSLouis Dionne _ForwardOutIterator __out_it) const noexcept { 4929540950aSLouis Dionne using _Copy = __dispatch<__copy, __current_configuration, _ExecutionPolicy>; 4939540950aSLouis Dionne auto __result_mid = _Copy()(__policy, __middle, std::move(__last), std::move(__out_it)); 4949540950aSLouis Dionne if (__result_mid == nullopt) 4959540950aSLouis Dionne return nullopt; 4969540950aSLouis Dionne return _Copy()(__policy, std::move(__first), std::move(__middle), *std::move(__result_mid)); 4979540950aSLouis Dionne } 4989540950aSLouis Dionne }; 4999540950aSLouis Dionne 5009540950aSLouis Dionne } // namespace __pstl 5019540950aSLouis Dionne _LIBCPP_END_NAMESPACE_STD 5029540950aSLouis Dionne 503*bbff52bfSLouis Dionne #endif // _LIBCPP_STD_VER >= 17 504*bbff52bfSLouis Dionne 5059540950aSLouis Dionne _LIBCPP_POP_MACROS 5069540950aSLouis Dionne 5079540950aSLouis Dionne #endif // _LIBCPP___PSTL_BACKENDS_DEFAULT_H 508