1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H
10 #define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H
12 #include <__algorithm/any_of.h>
13 #include <__algorithm/find_if.h>
14 #include <__algorithm/pstl_backends/cpu_backends/backend.h>
15 #include <__atomic/atomic.h>
16 #include <__atomic/memory_order.h>
18 #include <__functional/operations.h>
19 #include <__iterator/concepts.h>
20 #include <__type_traits/is_execution_policy.h>
21 #include <__utility/move.h>
22 #include <__utility/pair.h>
26 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
29 # include <__undef_macros>
31 _LIBCPP_BEGIN_NAMESPACE_STD
33 template <class _Index
, class _Brick
>
34 _LIBCPP_HIDE_FROM_ABI optional
<bool> __parallel_or(_Index __first
, _Index __last
, _Brick __f
) {
35 std::atomic
<bool> __found(false);
36 auto __ret
= __par_backend::__parallel_for(__first
, __last
, [__f
, &__found
](_Index __i
, _Index __j
) {
37 if (!__found
.load(std::memory_order_relaxed
) && __f(__i
, __j
)) {
38 __found
.store(true, std::memory_order_relaxed
);
39 __par_backend::__cancel_execution();
44 return static_cast<bool>(__found
);
47 // TODO: check whether __simd_first() can be used here
48 template <class _Index
, class _DifferenceType
, class _Pred
>
49 _LIBCPP_HIDE_FROM_ABI
bool __simd_or(_Index __first
, _DifferenceType __n
, _Pred __pred
) noexcept
{
50 _DifferenceType __block_size
= 4 < __n
? 4 : __n
;
51 const _Index __last
= __first
+ __n
;
52 while (__last
!= __first
) {
54 _PSTL_PRAGMA_SIMD_REDUCTION(& : __flag
)
55 for (_DifferenceType __i
= 0; __i
< __block_size
; ++__i
)
56 if (__pred(*(__first
+ __i
)))
61 __first
+= __block_size
;
62 if (__last
- __first
>= __block_size
<< 1) {
63 // Double the block _Size. Any unnecessary iterations can be amortized against work done so far.
66 __block_size
= __last
- __first
;
72 template <class _ExecutionPolicy
, class _ForwardIterator
, class _Predicate
>
73 _LIBCPP_HIDE_FROM_ABI optional
<bool>
74 __pstl_any_of(__cpu_backend_tag
, _ForwardIterator __first
, _ForwardIterator __last
, _Predicate __pred
) {
75 if constexpr (__is_parallel_execution_policy_v
<_ExecutionPolicy
> &&
76 __has_random_access_iterator_category_or_concept
<_ForwardIterator
>::value
) {
77 return std::__parallel_or(
78 __first
, __last
, [&__pred
](_ForwardIterator __brick_first
, _ForwardIterator __brick_last
) {
79 auto __res
= std::__pstl_any_of
<__remove_parallel_policy_t
<_ExecutionPolicy
>>(
80 __cpu_backend_tag
{}, __brick_first
, __brick_last
, __pred
);
81 _LIBCPP_ASSERT_INTERNAL(__res
, "unseq/seq should never try to allocate!");
82 return *std::move(__res
);
84 } else if constexpr (__is_unsequenced_execution_policy_v
<_ExecutionPolicy
> &&
85 __has_random_access_iterator_category_or_concept
<_ForwardIterator
>::value
) {
86 return std::__simd_or(__first
, __last
- __first
, __pred
);
88 return std::any_of(__first
, __last
, __pred
);
92 _LIBCPP_END_NAMESPACE_STD
96 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
98 #endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H