1e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===// 2e78f53d1SNikolas Klauser // 3e78f53d1SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e78f53d1SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information. 5e78f53d1SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e78f53d1SNikolas Klauser // 7e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===// 8e78f53d1SNikolas Klauser 9*ce777190SNikolas Klauser #ifndef _LIBCPP___CXX03___PSTL_BACKENDS_DEFAULT_H 10*ce777190SNikolas Klauser #define _LIBCPP___CXX03___PSTL_BACKENDS_DEFAULT_H 11e78f53d1SNikolas Klauser 1273fbae83SNikolas Klauser #include <__cxx03/__algorithm/copy_n.h> 1373fbae83SNikolas Klauser #include <__cxx03/__algorithm/equal.h> 1473fbae83SNikolas Klauser #include <__cxx03/__algorithm/fill_n.h> 1573fbae83SNikolas Klauser #include <__cxx03/__algorithm/for_each_n.h> 1673fbae83SNikolas Klauser #include <__cxx03/__config> 1773fbae83SNikolas Klauser #include <__cxx03/__functional/identity.h> 1873fbae83SNikolas Klauser #include <__cxx03/__functional/not_fn.h> 1973fbae83SNikolas Klauser #include <__cxx03/__functional/operations.h> 2073fbae83SNikolas Klauser #include <__cxx03/__iterator/concepts.h> 2173fbae83SNikolas Klauser #include <__cxx03/__iterator/iterator_traits.h> 2273fbae83SNikolas Klauser #include <__cxx03/__pstl/backend_fwd.h> 2373fbae83SNikolas Klauser #include <__cxx03/__pstl/dispatch.h> 2473fbae83SNikolas Klauser #include <__cxx03/__utility/empty.h> 2573fbae83SNikolas Klauser #include <__cxx03/__utility/forward.h> 2673fbae83SNikolas Klauser #include <__cxx03/__utility/move.h> 2773fbae83SNikolas Klauser #include <__cxx03/optional> 28e78f53d1SNikolas Klauser 29e78f53d1SNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 30e78f53d1SNikolas Klauser # pragma GCC system_header 31e78f53d1SNikolas Klauser #endif 32e78f53d1SNikolas Klauser 33e78f53d1SNikolas Klauser _LIBCPP_PUSH_MACROS 3473fbae83SNikolas Klauser #include <__cxx03/__undef_macros> 35e78f53d1SNikolas Klauser 36e78f53d1SNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD 37e78f53d1SNikolas Klauser namespace __pstl { 38e78f53d1SNikolas Klauser 39e78f53d1SNikolas Klauser // 40e78f53d1SNikolas Klauser // This file provides an incomplete PSTL backend that implements all of the PSTL algorithms 41e78f53d1SNikolas Klauser // based on a smaller set of basis operations. 42e78f53d1SNikolas Klauser // 43e78f53d1SNikolas Klauser // It is intended as a building block for other PSTL backends that implement some operations more 44e78f53d1SNikolas Klauser // efficiently but may not want to define the full set of PSTL algorithms. 45e78f53d1SNikolas Klauser // 46e78f53d1SNikolas Klauser // This backend implements all the PSTL algorithms based on the following basis operations: 47e78f53d1SNikolas Klauser // 48e78f53d1SNikolas Klauser // find_if family 49e78f53d1SNikolas Klauser // -------------- 50e78f53d1SNikolas Klauser // - find 51e78f53d1SNikolas Klauser // - find_if_not 52e78f53d1SNikolas Klauser // - any_of 53e78f53d1SNikolas Klauser // - all_of 54e78f53d1SNikolas Klauser // - none_of 55e78f53d1SNikolas Klauser // - is_partitioned 56e78f53d1SNikolas Klauser // 57e78f53d1SNikolas Klauser // for_each family 58e78f53d1SNikolas Klauser // --------------- 59e78f53d1SNikolas Klauser // - for_each_n 60e78f53d1SNikolas Klauser // - fill 61e78f53d1SNikolas Klauser // - fill_n 62e78f53d1SNikolas Klauser // - replace 63e78f53d1SNikolas Klauser // - replace_if 64e78f53d1SNikolas Klauser // - generate 65e78f53d1SNikolas Klauser // - generate_n 66e78f53d1SNikolas Klauser // 67e78f53d1SNikolas Klauser // merge family 68e78f53d1SNikolas Klauser // ------------ 69e78f53d1SNikolas Klauser // No other algorithms based on merge 70e78f53d1SNikolas Klauser // 71e78f53d1SNikolas Klauser // stable_sort family 72e78f53d1SNikolas Klauser // ------------------ 73e78f53d1SNikolas Klauser // - sort 74e78f53d1SNikolas Klauser // 75e78f53d1SNikolas Klauser // transform_reduce and transform_reduce_binary family 76e78f53d1SNikolas Klauser // --------------------------------------------------- 77e78f53d1SNikolas Klauser // - count_if 78e78f53d1SNikolas Klauser // - count 79e78f53d1SNikolas Klauser // - equal(3 legs) 80e78f53d1SNikolas Klauser // - equal 81e78f53d1SNikolas Klauser // - reduce 82e78f53d1SNikolas Klauser // 83e78f53d1SNikolas Klauser // transform and transform_binary family 84e78f53d1SNikolas Klauser // ------------------------------------- 85e78f53d1SNikolas Klauser // - replace_copy_if 86e78f53d1SNikolas Klauser // - replace_copy 87e78f53d1SNikolas Klauser // - move 88e78f53d1SNikolas Klauser // - copy 89e78f53d1SNikolas Klauser // - copy_n 90e78f53d1SNikolas Klauser // - rotate_copy 91e78f53d1SNikolas Klauser // 92e78f53d1SNikolas Klauser 93e78f53d1SNikolas Klauser ////////////////////////////////////////////////////////////// 94e78f53d1SNikolas Klauser // find_if family 95e78f53d1SNikolas Klauser ////////////////////////////////////////////////////////////// 96e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 97e78f53d1SNikolas Klauser struct __find<__default_backend_tag, _ExecutionPolicy> { 98e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _Tp> 99e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator> 100e78f53d1SNikolas Klauser operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) const noexcept { 101e78f53d1SNikolas Klauser using _FindIf = __dispatch<__find_if, __current_configuration, _ExecutionPolicy>; 102e78f53d1SNikolas Klauser return _FindIf()( 103e78f53d1SNikolas Klauser __policy, std::move(__first), std::move(__last), [&](__iter_reference<_ForwardIterator> __element) { 104e78f53d1SNikolas Klauser return __element == __value; 105e78f53d1SNikolas Klauser }); 106e78f53d1SNikolas Klauser } 107e78f53d1SNikolas Klauser }; 108e78f53d1SNikolas Klauser 109e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 110e78f53d1SNikolas Klauser struct __find_if_not<__default_backend_tag, _ExecutionPolicy> { 111e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _Pred> 112e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator> 113e78f53d1SNikolas Klauser operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { 114e78f53d1SNikolas Klauser using _FindIf = __dispatch<__find_if, __current_configuration, _ExecutionPolicy>; 115e78f53d1SNikolas Klauser return _FindIf()(__policy, __first, __last, std::not_fn(std::forward<_Pred>(__pred))); 116e78f53d1SNikolas Klauser } 117e78f53d1SNikolas Klauser }; 118e78f53d1SNikolas Klauser 119e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 120e78f53d1SNikolas Klauser struct __any_of<__default_backend_tag, _ExecutionPolicy> { 121e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _Pred> 122e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 123e78f53d1SNikolas Klauser operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { 124e78f53d1SNikolas Klauser using _FindIf = __dispatch<__find_if, __current_configuration, _ExecutionPolicy>; 125e78f53d1SNikolas Klauser auto __res = _FindIf()(__policy, __first, __last, std::forward<_Pred>(__pred)); 126e78f53d1SNikolas Klauser if (!__res) 127e78f53d1SNikolas Klauser return nullopt; 128e78f53d1SNikolas Klauser return *__res != __last; 129e78f53d1SNikolas Klauser } 130e78f53d1SNikolas Klauser }; 131e78f53d1SNikolas Klauser 132e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 133e78f53d1SNikolas Klauser struct __all_of<__default_backend_tag, _ExecutionPolicy> { 134e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _Pred> 135e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 136e78f53d1SNikolas Klauser operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { 137e78f53d1SNikolas Klauser using _AnyOf = __dispatch<__any_of, __current_configuration, _ExecutionPolicy>; 138e78f53d1SNikolas Klauser auto __res = _AnyOf()(__policy, __first, __last, [&](__iter_reference<_ForwardIterator> __value) { 139e78f53d1SNikolas Klauser return !__pred(__value); 140e78f53d1SNikolas Klauser }); 141e78f53d1SNikolas Klauser if (!__res) 142e78f53d1SNikolas Klauser return nullopt; 143e78f53d1SNikolas Klauser return !*__res; 144e78f53d1SNikolas Klauser } 145e78f53d1SNikolas Klauser }; 146e78f53d1SNikolas Klauser 147e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 148e78f53d1SNikolas Klauser struct __none_of<__default_backend_tag, _ExecutionPolicy> { 149e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _Pred> 150e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 151e78f53d1SNikolas Klauser operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { 152e78f53d1SNikolas Klauser using _AnyOf = __dispatch<__any_of, __current_configuration, _ExecutionPolicy>; 153e78f53d1SNikolas Klauser auto __res = _AnyOf()(__policy, __first, __last, std::forward<_Pred>(__pred)); 154e78f53d1SNikolas Klauser if (!__res) 155e78f53d1SNikolas Klauser return nullopt; 156e78f53d1SNikolas Klauser return !*__res; 157e78f53d1SNikolas Klauser } 158e78f53d1SNikolas Klauser }; 159e78f53d1SNikolas Klauser 160e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 161e78f53d1SNikolas Klauser struct __is_partitioned<__default_backend_tag, _ExecutionPolicy> { 162e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _Pred> 163e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 164e78f53d1SNikolas Klauser operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { 165e78f53d1SNikolas Klauser using _FindIfNot = __dispatch<__find_if_not, __current_configuration, _ExecutionPolicy>; 166e78f53d1SNikolas Klauser auto __maybe_first = _FindIfNot()(__policy, std::move(__first), std::move(__last), __pred); 167e78f53d1SNikolas Klauser if (__maybe_first == nullopt) 168e78f53d1SNikolas Klauser return nullopt; 169e78f53d1SNikolas Klauser 170e78f53d1SNikolas Klauser __first = *__maybe_first; 171e78f53d1SNikolas Klauser if (__first == __last) 172e78f53d1SNikolas Klauser return true; 173e78f53d1SNikolas Klauser ++__first; 174e78f53d1SNikolas Klauser using _NoneOf = __dispatch<__none_of, __current_configuration, _ExecutionPolicy>; 175e78f53d1SNikolas Klauser return _NoneOf()(__policy, std::move(__first), std::move(__last), __pred); 176e78f53d1SNikolas Klauser } 177e78f53d1SNikolas Klauser }; 178e78f53d1SNikolas Klauser 179e78f53d1SNikolas Klauser ////////////////////////////////////////////////////////////// 180e78f53d1SNikolas Klauser // for_each family 181e78f53d1SNikolas Klauser ////////////////////////////////////////////////////////////// 182e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 183e78f53d1SNikolas Klauser struct __for_each_n<__default_backend_tag, _ExecutionPolicy> { 184e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _Size, class _Function> 185e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 186e78f53d1SNikolas Klauser operator()(_Policy&& __policy, _ForwardIterator __first, _Size __size, _Function __func) const noexcept { 187e78f53d1SNikolas Klauser if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { 188e78f53d1SNikolas Klauser using _ForEach = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>; 189e78f53d1SNikolas Klauser _ForwardIterator __last = __first + __size; 190e78f53d1SNikolas Klauser return _ForEach()(__policy, std::move(__first), std::move(__last), std::move(__func)); 191e78f53d1SNikolas Klauser } else { 192e78f53d1SNikolas Klauser // Otherwise, use the serial algorithm to avoid doing two passes over the input 193e78f53d1SNikolas Klauser std::for_each_n(std::move(__first), __size, std::move(__func)); 194e78f53d1SNikolas Klauser return __empty{}; 195e78f53d1SNikolas Klauser } 196e78f53d1SNikolas Klauser } 197e78f53d1SNikolas Klauser }; 198e78f53d1SNikolas Klauser 199e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 200e78f53d1SNikolas Klauser struct __fill<__default_backend_tag, _ExecutionPolicy> { 201e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _Tp> 202e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 203e78f53d1SNikolas Klauser operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp const& __value) const noexcept { 204e78f53d1SNikolas Klauser using _ForEach = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>; 205e78f53d1SNikolas Klauser using _Ref = __iter_reference<_ForwardIterator>; 206e78f53d1SNikolas Klauser return _ForEach()(__policy, std::move(__first), std::move(__last), [&](_Ref __element) { __element = __value; }); 207e78f53d1SNikolas Klauser } 208e78f53d1SNikolas Klauser }; 209e78f53d1SNikolas Klauser 210e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 211e78f53d1SNikolas Klauser struct __fill_n<__default_backend_tag, _ExecutionPolicy> { 212e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _Size, class _Tp> 213e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 214e78f53d1SNikolas Klauser operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, _Tp const& __value) const noexcept { 215e78f53d1SNikolas Klauser if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { 216e78f53d1SNikolas Klauser using _Fill = __dispatch<__fill, __current_configuration, _ExecutionPolicy>; 217e78f53d1SNikolas Klauser _ForwardIterator __last = __first + __n; 218e78f53d1SNikolas Klauser return _Fill()(__policy, std::move(__first), std::move(__last), __value); 219e78f53d1SNikolas Klauser } else { 220e78f53d1SNikolas Klauser // Otherwise, use the serial algorithm to avoid doing two passes over the input 221e78f53d1SNikolas Klauser std::fill_n(std::move(__first), __n, __value); 222e78f53d1SNikolas Klauser return optional<__empty>{__empty{}}; 223e78f53d1SNikolas Klauser } 224e78f53d1SNikolas Klauser } 225e78f53d1SNikolas Klauser }; 226e78f53d1SNikolas Klauser 227e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 228e78f53d1SNikolas Klauser struct __replace<__default_backend_tag, _ExecutionPolicy> { 229e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _Tp> 230e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 231e78f53d1SNikolas Klauser operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp const& __old, _Tp const& __new) 232e78f53d1SNikolas Klauser const noexcept { 233e78f53d1SNikolas Klauser using _ReplaceIf = __dispatch<__replace_if, __current_configuration, _ExecutionPolicy>; 234e78f53d1SNikolas Klauser using _Ref = __iter_reference<_ForwardIterator>; 235e78f53d1SNikolas Klauser return _ReplaceIf()( 236e78f53d1SNikolas Klauser __policy, std::move(__first), std::move(__last), [&](_Ref __element) { return __element == __old; }, __new); 237e78f53d1SNikolas Klauser } 238e78f53d1SNikolas Klauser }; 239e78f53d1SNikolas Klauser 240e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 241e78f53d1SNikolas Klauser struct __replace_if<__default_backend_tag, _ExecutionPolicy> { 242e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _Pred, class _Tp> 243e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> operator()( 244e78f53d1SNikolas Klauser _Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred, _Tp const& __new_value) 245e78f53d1SNikolas Klauser const noexcept { 246e78f53d1SNikolas Klauser using _ForEach = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>; 247e78f53d1SNikolas Klauser using _Ref = __iter_reference<_ForwardIterator>; 248e78f53d1SNikolas Klauser return _ForEach()(__policy, std::move(__first), std::move(__last), [&](_Ref __element) { 249e78f53d1SNikolas Klauser if (__pred(__element)) 250e78f53d1SNikolas Klauser __element = __new_value; 251e78f53d1SNikolas Klauser }); 252e78f53d1SNikolas Klauser } 253e78f53d1SNikolas Klauser }; 254e78f53d1SNikolas Klauser 255e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 256e78f53d1SNikolas Klauser struct __generate<__default_backend_tag, _ExecutionPolicy> { 257e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _Generator> 258e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 259e78f53d1SNikolas Klauser operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Generator&& __gen) const noexcept { 260e78f53d1SNikolas Klauser using _ForEach = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>; 261e78f53d1SNikolas Klauser using _Ref = __iter_reference<_ForwardIterator>; 262e78f53d1SNikolas Klauser return _ForEach()(__policy, std::move(__first), std::move(__last), [&](_Ref __element) { __element = __gen(); }); 263e78f53d1SNikolas Klauser } 264e78f53d1SNikolas Klauser }; 265e78f53d1SNikolas Klauser 266e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 267e78f53d1SNikolas Klauser struct __generate_n<__default_backend_tag, _ExecutionPolicy> { 268e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _Size, class _Generator> 269e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 270e78f53d1SNikolas Klauser operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, _Generator&& __gen) const noexcept { 271e78f53d1SNikolas Klauser using _ForEachN = __dispatch<__for_each_n, __current_configuration, _ExecutionPolicy>; 272e78f53d1SNikolas Klauser using _Ref = __iter_reference<_ForwardIterator>; 273e78f53d1SNikolas Klauser return _ForEachN()(__policy, std::move(__first), __n, [&](_Ref __element) { __element = __gen(); }); 274e78f53d1SNikolas Klauser } 275e78f53d1SNikolas Klauser }; 276e78f53d1SNikolas Klauser 277e78f53d1SNikolas Klauser ////////////////////////////////////////////////////////////// 278e78f53d1SNikolas Klauser // stable_sort family 279e78f53d1SNikolas Klauser ////////////////////////////////////////////////////////////// 280e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 281e78f53d1SNikolas Klauser struct __sort<__default_backend_tag, _ExecutionPolicy> { 282e78f53d1SNikolas Klauser template <class _Policy, class _RandomAccessIterator, class _Comp> 283e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI optional<__empty> operator()( 284e78f53d1SNikolas Klauser _Policy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp&& __comp) const noexcept { 285e78f53d1SNikolas Klauser using _StableSort = __dispatch<__stable_sort, __current_configuration, _ExecutionPolicy>; 286e78f53d1SNikolas Klauser return _StableSort()(__policy, std::move(__first), std::move(__last), std::forward<_Comp>(__comp)); 287e78f53d1SNikolas Klauser } 288e78f53d1SNikolas Klauser }; 289e78f53d1SNikolas Klauser 290e78f53d1SNikolas Klauser ////////////////////////////////////////////////////////////// 291e78f53d1SNikolas Klauser // transform_reduce family 292e78f53d1SNikolas Klauser ////////////////////////////////////////////////////////////// 293e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 294e78f53d1SNikolas Klauser struct __count_if<__default_backend_tag, _ExecutionPolicy> { 295e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _Predicate> 296e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__iter_diff_t<_ForwardIterator>> operator()( 297e78f53d1SNikolas Klauser _Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate&& __pred) const noexcept { 298e78f53d1SNikolas Klauser using _TransformReduce = __dispatch<__transform_reduce, __current_configuration, _ExecutionPolicy>; 299e78f53d1SNikolas Klauser using _DiffT = __iter_diff_t<_ForwardIterator>; 300e78f53d1SNikolas Klauser using _Ref = __iter_reference<_ForwardIterator>; 301e78f53d1SNikolas Klauser return _TransformReduce()( 302e78f53d1SNikolas Klauser __policy, std::move(__first), std::move(__last), _DiffT{}, std::plus{}, [&](_Ref __element) -> _DiffT { 303e78f53d1SNikolas Klauser return __pred(__element) ? _DiffT(1) : _DiffT(0); 304e78f53d1SNikolas Klauser }); 305e78f53d1SNikolas Klauser } 306e78f53d1SNikolas Klauser }; 307e78f53d1SNikolas Klauser 308e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 309e78f53d1SNikolas Klauser struct __count<__default_backend_tag, _ExecutionPolicy> { 310e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _Tp> 311e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__iter_diff_t<_ForwardIterator>> 312e78f53d1SNikolas Klauser operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp const& __value) const noexcept { 313e78f53d1SNikolas Klauser using _CountIf = __dispatch<__count_if, __current_configuration, _ExecutionPolicy>; 314e78f53d1SNikolas Klauser using _Ref = __iter_reference<_ForwardIterator>; 315e78f53d1SNikolas Klauser return _CountIf()(__policy, std::move(__first), std::move(__last), [&](_Ref __element) -> bool { 316e78f53d1SNikolas Klauser return __element == __value; 317e78f53d1SNikolas Klauser }); 318e78f53d1SNikolas Klauser } 319e78f53d1SNikolas Klauser }; 320e78f53d1SNikolas Klauser 321e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 322e78f53d1SNikolas Klauser struct __equal_3leg<__default_backend_tag, _ExecutionPolicy> { 323e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate> 324e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 325e78f53d1SNikolas Klauser operator()(_Policy&& __policy, 326e78f53d1SNikolas Klauser _ForwardIterator1 __first1, 327e78f53d1SNikolas Klauser _ForwardIterator1 __last1, 328e78f53d1SNikolas Klauser _ForwardIterator2 __first2, 329e78f53d1SNikolas Klauser _Predicate&& __pred) const noexcept { 330e78f53d1SNikolas Klauser using _TransformReduce = __dispatch<__transform_reduce_binary, __current_configuration, _ExecutionPolicy>; 331e78f53d1SNikolas Klauser return _TransformReduce()( 332e78f53d1SNikolas Klauser __policy, 333e78f53d1SNikolas Klauser std::move(__first1), 334e78f53d1SNikolas Klauser std::move(__last1), 335e78f53d1SNikolas Klauser std::move(__first2), 336e78f53d1SNikolas Klauser true, 337e78f53d1SNikolas Klauser std::logical_and{}, 338e78f53d1SNikolas Klauser std::forward<_Predicate>(__pred)); 339e78f53d1SNikolas Klauser } 340e78f53d1SNikolas Klauser }; 341e78f53d1SNikolas Klauser 342e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 343e78f53d1SNikolas Klauser struct __equal<__default_backend_tag, _ExecutionPolicy> { 344e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate> 345e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 346e78f53d1SNikolas Klauser operator()(_Policy&& __policy, 347e78f53d1SNikolas Klauser _ForwardIterator1 __first1, 348e78f53d1SNikolas Klauser _ForwardIterator1 __last1, 349e78f53d1SNikolas Klauser _ForwardIterator2 __first2, 350e78f53d1SNikolas Klauser _ForwardIterator2 __last2, 351e78f53d1SNikolas Klauser _Predicate&& __pred) const noexcept { 352e78f53d1SNikolas Klauser if constexpr (__has_random_access_iterator_category<_ForwardIterator1>::value && 353e78f53d1SNikolas Klauser __has_random_access_iterator_category<_ForwardIterator2>::value) { 354e78f53d1SNikolas Klauser if (__last1 - __first1 != __last2 - __first2) 355e78f53d1SNikolas Klauser return false; 356e78f53d1SNikolas Klauser // Fall back to the 3 legged algorithm 357e78f53d1SNikolas Klauser using _Equal3Leg = __dispatch<__equal_3leg, __current_configuration, _ExecutionPolicy>; 358e78f53d1SNikolas Klauser return _Equal3Leg()( 359e78f53d1SNikolas Klauser __policy, std::move(__first1), std::move(__last1), std::move(__first2), std::forward<_Predicate>(__pred)); 360e78f53d1SNikolas Klauser } else { 361e78f53d1SNikolas Klauser // If we don't have random access, fall back to the serial algorithm cause we can't do much 362e78f53d1SNikolas Klauser return std::equal( 363e78f53d1SNikolas Klauser std::move(__first1), 364e78f53d1SNikolas Klauser std::move(__last1), 365e78f53d1SNikolas Klauser std::move(__first2), 366e78f53d1SNikolas Klauser std::move(__last2), 367e78f53d1SNikolas Klauser std::forward<_Predicate>(__pred)); 368e78f53d1SNikolas Klauser } 369e78f53d1SNikolas Klauser } 370e78f53d1SNikolas Klauser }; 371e78f53d1SNikolas Klauser 372e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 373e78f53d1SNikolas Klauser struct __reduce<__default_backend_tag, _ExecutionPolicy> { 374e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _Tp, class _BinaryOperation> 375e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_Tp> 376e78f53d1SNikolas Klauser operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp __init, _BinaryOperation&& __op) 377e78f53d1SNikolas Klauser const noexcept { 378e78f53d1SNikolas Klauser using _TransformReduce = __dispatch<__transform_reduce, __current_configuration, _ExecutionPolicy>; 379e78f53d1SNikolas Klauser return _TransformReduce()( 380e78f53d1SNikolas Klauser __policy, 381e78f53d1SNikolas Klauser std::move(__first), 382e78f53d1SNikolas Klauser std::move(__last), 383e78f53d1SNikolas Klauser std::move(__init), 384e78f53d1SNikolas Klauser std::forward<_BinaryOperation>(__op), 385e78f53d1SNikolas Klauser __identity{}); 386e78f53d1SNikolas Klauser } 387e78f53d1SNikolas Klauser }; 388e78f53d1SNikolas Klauser 389e78f53d1SNikolas Klauser ////////////////////////////////////////////////////////////// 390e78f53d1SNikolas Klauser // transform family 391e78f53d1SNikolas Klauser ////////////////////////////////////////////////////////////// 392e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 393e78f53d1SNikolas Klauser struct __replace_copy_if<__default_backend_tag, _ExecutionPolicy> { 394e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _ForwardOutIterator, class _Pred, class _Tp> 395e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 396e78f53d1SNikolas Klauser operator()(_Policy&& __policy, 397e78f53d1SNikolas Klauser _ForwardIterator __first, 398e78f53d1SNikolas Klauser _ForwardIterator __last, 399e78f53d1SNikolas Klauser _ForwardOutIterator __out_it, 400e78f53d1SNikolas Klauser _Pred&& __pred, 401e78f53d1SNikolas Klauser _Tp const& __new_value) const noexcept { 402e78f53d1SNikolas Klauser using _Transform = __dispatch<__transform, __current_configuration, _ExecutionPolicy>; 403e78f53d1SNikolas Klauser using _Ref = __iter_reference<_ForwardIterator>; 404e78f53d1SNikolas Klauser auto __res = 405e78f53d1SNikolas Klauser _Transform()(__policy, std::move(__first), std::move(__last), std::move(__out_it), [&](_Ref __element) { 406e78f53d1SNikolas Klauser return __pred(__element) ? __new_value : __element; 407e78f53d1SNikolas Klauser }); 408e78f53d1SNikolas Klauser if (__res == nullopt) 409e78f53d1SNikolas Klauser return nullopt; 410e78f53d1SNikolas Klauser return __empty{}; 411e78f53d1SNikolas Klauser } 412e78f53d1SNikolas Klauser }; 413e78f53d1SNikolas Klauser 414e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 415e78f53d1SNikolas Klauser struct __replace_copy<__default_backend_tag, _ExecutionPolicy> { 416e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _ForwardOutIterator, class _Tp> 417e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> 418e78f53d1SNikolas Klauser operator()(_Policy&& __policy, 419e78f53d1SNikolas Klauser _ForwardIterator __first, 420e78f53d1SNikolas Klauser _ForwardIterator __last, 421e78f53d1SNikolas Klauser _ForwardOutIterator __out_it, 422e78f53d1SNikolas Klauser _Tp const& __old_value, 423e78f53d1SNikolas Klauser _Tp const& __new_value) const noexcept { 424e78f53d1SNikolas Klauser using _ReplaceCopyIf = __dispatch<__replace_copy_if, __current_configuration, _ExecutionPolicy>; 425e78f53d1SNikolas Klauser using _Ref = __iter_reference<_ForwardIterator>; 426e78f53d1SNikolas Klauser return _ReplaceCopyIf()( 427e78f53d1SNikolas Klauser __policy, 428e78f53d1SNikolas Klauser std::move(__first), 429e78f53d1SNikolas Klauser std::move(__last), 430e78f53d1SNikolas Klauser std::move(__out_it), 431e78f53d1SNikolas Klauser [&](_Ref __element) { return __element == __old_value; }, 432e78f53d1SNikolas Klauser __new_value); 433e78f53d1SNikolas Klauser } 434e78f53d1SNikolas Klauser }; 435e78f53d1SNikolas Klauser 436e78f53d1SNikolas Klauser // TODO: Use the std::copy/move shenanigans to forward to std::memmove 437e78f53d1SNikolas Klauser // Investigate whether we want to still forward to std::transform(policy) 438e78f53d1SNikolas Klauser // in that case for the execution::par part, or whether we actually want 439e78f53d1SNikolas Klauser // to run everything serially in that case. 440e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 441e78f53d1SNikolas Klauser struct __move<__default_backend_tag, _ExecutionPolicy> { 442e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _ForwardOutIterator> 443e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> 444e78f53d1SNikolas Klauser operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __out_it) 445e78f53d1SNikolas Klauser const noexcept { 446e78f53d1SNikolas Klauser using _Transform = __dispatch<__transform, __current_configuration, _ExecutionPolicy>; 447e78f53d1SNikolas Klauser return _Transform()(__policy, std::move(__first), std::move(__last), std::move(__out_it), [&](auto&& __element) { 448e78f53d1SNikolas Klauser return std::move(__element); 449e78f53d1SNikolas Klauser }); 450e78f53d1SNikolas Klauser } 451e78f53d1SNikolas Klauser }; 452e78f53d1SNikolas Klauser 453e78f53d1SNikolas Klauser // TODO: Use the std::copy/move shenanigans to forward to std::memmove 454e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 455e78f53d1SNikolas Klauser struct __copy<__default_backend_tag, _ExecutionPolicy> { 456e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _ForwardOutIterator> 457e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> 458e78f53d1SNikolas Klauser operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __out_it) 459e78f53d1SNikolas Klauser const noexcept { 460e78f53d1SNikolas Klauser using _Transform = __dispatch<__transform, __current_configuration, _ExecutionPolicy>; 461e78f53d1SNikolas Klauser return _Transform()(__policy, std::move(__first), std::move(__last), std::move(__out_it), __identity()); 462e78f53d1SNikolas Klauser } 463e78f53d1SNikolas Klauser }; 464e78f53d1SNikolas Klauser 465e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 466e78f53d1SNikolas Klauser struct __copy_n<__default_backend_tag, _ExecutionPolicy> { 467e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _Size, class _ForwardOutIterator> 468e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> 469e78f53d1SNikolas Klauser operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, _ForwardOutIterator __out_it) const noexcept { 470e78f53d1SNikolas Klauser if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { 471e78f53d1SNikolas Klauser using _Copy = __dispatch<__copy, __current_configuration, _ExecutionPolicy>; 472e78f53d1SNikolas Klauser _ForwardIterator __last = __first + __n; 473e78f53d1SNikolas Klauser return _Copy()(__policy, std::move(__first), std::move(__last), std::move(__out_it)); 474e78f53d1SNikolas Klauser } else { 475e78f53d1SNikolas Klauser // Otherwise, use the serial algorithm to avoid doing two passes over the input 476e78f53d1SNikolas Klauser return std::copy_n(std::move(__first), __n, std::move(__out_it)); 477e78f53d1SNikolas Klauser } 478e78f53d1SNikolas Klauser } 479e78f53d1SNikolas Klauser }; 480e78f53d1SNikolas Klauser 481e78f53d1SNikolas Klauser template <class _ExecutionPolicy> 482e78f53d1SNikolas Klauser struct __rotate_copy<__default_backend_tag, _ExecutionPolicy> { 483e78f53d1SNikolas Klauser template <class _Policy, class _ForwardIterator, class _ForwardOutIterator> 484e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> 485e78f53d1SNikolas Klauser operator()(_Policy&& __policy, 486e78f53d1SNikolas Klauser _ForwardIterator __first, 487e78f53d1SNikolas Klauser _ForwardIterator __middle, 488e78f53d1SNikolas Klauser _ForwardIterator __last, 489e78f53d1SNikolas Klauser _ForwardOutIterator __out_it) const noexcept { 490e78f53d1SNikolas Klauser using _Copy = __dispatch<__copy, __current_configuration, _ExecutionPolicy>; 491e78f53d1SNikolas Klauser auto __result_mid = _Copy()(__policy, __middle, std::move(__last), std::move(__out_it)); 492e78f53d1SNikolas Klauser if (__result_mid == nullopt) 493e78f53d1SNikolas Klauser return nullopt; 494e78f53d1SNikolas Klauser return _Copy()(__policy, std::move(__first), std::move(__middle), *std::move(__result_mid)); 495e78f53d1SNikolas Klauser } 496e78f53d1SNikolas Klauser }; 497e78f53d1SNikolas Klauser 498e78f53d1SNikolas Klauser } // namespace __pstl 499e78f53d1SNikolas Klauser _LIBCPP_END_NAMESPACE_STD 500e78f53d1SNikolas Klauser 501e78f53d1SNikolas Klauser _LIBCPP_POP_MACROS 502e78f53d1SNikolas Klauser 503*ce777190SNikolas Klauser #endif // _LIBCPP___CXX03___PSTL_BACKENDS_DEFAULT_H 504