xref: /llvm-project/libcxx/include/__cxx03/__pstl/backends/default.h (revision ce7771902dc50d900de639d499a60486b83f70e0)
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