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