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 //===----------------------------------------------------------------------===// 8 9 #ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_H 10 #define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_H 11 12 #include <__algorithm/pstl_backends/cpu_backends/backend.h> 13 #include <__algorithm/transform.h> 14 #include <__config> 15 #include <__iterator/iterator_traits.h> 16 #include <__type_traits/enable_if.h> 17 #include <__type_traits/is_execution_policy.h> 18 #include <__type_traits/remove_cvref.h> 19 #include <__utility/terminate_on_exception.h> 20 21 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 22 # pragma GCC system_header 23 #endif 24 25 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 26 27 _LIBCPP_BEGIN_NAMESPACE_STD 28 29 template <class _Iterator1, class _DifferenceType, class _Iterator2, class _Function> 30 _LIBCPP_HIDE_FROM_ABI _Iterator2 31 __simd_walk_2(_Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Function __f) noexcept { 32 _PSTL_PRAGMA_SIMD 33 for (_DifferenceType __i = 0; __i < __n; ++__i) 34 __f(__first1[__i], __first2[__i]); 35 return __first2 + __n; 36 } 37 38 template <class _ExecutionPolicy, class _ForwardIterator, class _ForwardOutIterator, class _UnaryOperation> 39 _LIBCPP_HIDE_FROM_ABI _ForwardOutIterator __pstl_transform( 40 __cpu_backend_tag, 41 _ForwardIterator __first, 42 _ForwardIterator __last, 43 _ForwardOutIterator __result, 44 _UnaryOperation __op) { 45 if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && 46 __has_random_access_iterator_category<_ForwardIterator>::value && 47 __has_random_access_iterator_category<_ForwardOutIterator>::value) { 48 std::__terminate_on_exception([&] { 49 std::__par_backend::__parallel_for( 50 __first, __last, [__op, __first, __result](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { 51 return std::__pstl_transform<__remove_parallel_policy_t<_ExecutionPolicy>>( 52 __cpu_backend_tag{}, __brick_first, __brick_last, __result + (__brick_first - __first), __op); 53 }); 54 }); 55 return __result + (__last - __first); 56 } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && 57 __has_random_access_iterator_category<_ForwardIterator>::value && 58 __has_random_access_iterator_category<_ForwardOutIterator>::value) { 59 return std::__simd_walk_2( 60 __first, 61 __last - __first, 62 __result, 63 [&](__iter_reference<_ForwardIterator> __in_value, __iter_reference<_ForwardOutIterator> __out_value) { 64 __out_value = __op(__in_value); 65 }); 66 } else { 67 return std::transform(__first, __last, __result, __op); 68 } 69 } 70 71 template <class _Iterator1, class _DifferenceType, class _Iterator2, class _Iterator3, class _Function> 72 _LIBCPP_HIDE_FROM_ABI _Iterator3 __simd_walk_3( 73 _Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Iterator3 __first3, _Function __f) noexcept { 74 _PSTL_PRAGMA_SIMD 75 for (_DifferenceType __i = 0; __i < __n; ++__i) 76 __f(__first1[__i], __first2[__i], __first3[__i]); 77 return __first3 + __n; 78 } 79 template <class _ExecutionPolicy, 80 class _ForwardIterator1, 81 class _ForwardIterator2, 82 class _ForwardOutIterator, 83 class _BinaryOperation, 84 enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0> 85 _LIBCPP_HIDE_FROM_ABI _ForwardOutIterator __pstl_transform( 86 __cpu_backend_tag, 87 _ForwardIterator1 __first1, 88 _ForwardIterator1 __last1, 89 _ForwardIterator2 __first2, 90 _ForwardOutIterator __result, 91 _BinaryOperation __op) { 92 if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && 93 __has_random_access_iterator_category<_ForwardIterator1>::value && 94 __has_random_access_iterator_category<_ForwardIterator2>::value && 95 __has_random_access_iterator_category<_ForwardOutIterator>::value) { 96 std::__terminate_on_exception([&] { 97 std::__par_backend::__parallel_for( 98 __first1, 99 __last1, 100 [__op, __first1, __first2, __result](_ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last) { 101 return std::__pstl_transform<__remove_parallel_policy_t<_ExecutionPolicy>>( 102 __cpu_backend_tag{}, 103 __brick_first, 104 __brick_last, 105 __first2 + (__brick_first - __first1), 106 __result + (__brick_first - __first1), 107 __op); 108 }); 109 }); 110 return __result + (__last1 - __first1); 111 } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && 112 __has_random_access_iterator_category<_ForwardIterator1>::value && 113 __has_random_access_iterator_category<_ForwardIterator2>::value && 114 __has_random_access_iterator_category<_ForwardOutIterator>::value) { 115 return std::__simd_walk_3( 116 __first1, 117 __last1 - __first1, 118 __first2, 119 __result, 120 [&](__iter_reference<_ForwardIterator1> __in1, 121 __iter_reference<_ForwardIterator2> __in2, 122 __iter_reference<_ForwardOutIterator> __out_value) { __out_value = __op(__in1, __in2); }); 123 } else { 124 return std::transform(__first1, __last1, __first2, __result, __op); 125 } 126 } 127 128 _LIBCPP_END_NAMESPACE_STD 129 130 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 131 132 #endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_H 133