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_EQUAL_H 10 #define _LIBCPP___ALGORITHM_PSTL_EQUAL_H 11 12 #include <__algorithm/equal.h> 13 #include <__algorithm/pstl_frontend_dispatch.h> 14 #include <__config> 15 #include <__functional/operations.h> 16 #include <__iterator/iterator_traits.h> 17 #include <__numeric/pstl_transform_reduce.h> 18 #include <__utility/move.h> 19 20 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 21 # pragma GCC system_header 22 #endif 23 24 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 25 26 _LIBCPP_BEGIN_NAMESPACE_STD 27 28 template <class> 29 void __pstl_equal(); 30 31 template <class _ExecutionPolicy, 32 class _ForwardIterator1, 33 class _ForwardIterator2, 34 class _Pred, 35 class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, 36 enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> 37 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 38 __equal(_ExecutionPolicy&& __policy, 39 _ForwardIterator1&& __first1, 40 _ForwardIterator1&& __last1, 41 _ForwardIterator2&& __first2, 42 _Pred&& __pred) noexcept { 43 return std::__pstl_frontend_dispatch( 44 _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_equal, _RawPolicy), 45 [&__policy]( 46 _ForwardIterator1 __g_first1, _ForwardIterator1 __g_last1, _ForwardIterator2 __g_first2, _Pred __g_pred) { 47 return std::__transform_reduce( 48 __policy, 49 std::move(__g_first1), 50 std::move(__g_last1), 51 std::move(__g_first2), 52 true, 53 std::logical_and{}, 54 std::move(__g_pred)); 55 }, 56 std::move(__first1), 57 std::move(__last1), 58 std::move(__first2), 59 std::move(__pred)); 60 } 61 62 template <class _ExecutionPolicy, 63 class _ForwardIterator1, 64 class _ForwardIterator2, 65 class _Pred, 66 class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, 67 enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> 68 _LIBCPP_HIDE_FROM_ABI bool 69 equal(_ExecutionPolicy&& __policy, 70 _ForwardIterator1 __first1, 71 _ForwardIterator1 __last1, 72 _ForwardIterator2 __first2, 73 _Pred __pred) { 74 auto __res = std::__equal(__policy, std::move(__first1), std::move(__last1), std::move(__first2), std::move(__pred)); 75 if (!__res) 76 std::__throw_bad_alloc(); 77 return *__res; 78 } 79 80 template <class _ExecutionPolicy, 81 class _ForwardIterator1, 82 class _ForwardIterator2, 83 enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0> 84 _LIBCPP_HIDE_FROM_ABI bool 85 equal(_ExecutionPolicy&& __policy, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { 86 return std::equal(__policy, std::move(__first1), std::move(__last1), std::move(__first2), std::equal_to{}); 87 } 88 89 template <class _ExecutionPolicy, 90 class _ForwardIterator1, 91 class _ForwardIterator2, 92 class _Pred, 93 class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, 94 enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> 95 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool> 96 __equal(_ExecutionPolicy&& __policy, 97 _ForwardIterator1&& __first1, 98 _ForwardIterator1&& __last1, 99 _ForwardIterator2&& __first2, 100 _ForwardIterator2&& __last2, 101 _Pred&& __pred) noexcept { 102 return std::__pstl_frontend_dispatch( 103 _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_equal, _RawPolicy), 104 [&__policy](_ForwardIterator1 __g_first1, 105 _ForwardIterator1 __g_last1, 106 _ForwardIterator2 __g_first2, 107 _ForwardIterator2 __g_last2, 108 _Pred __g_pred) -> optional<bool> { 109 if constexpr (__has_random_access_iterator_category<_ForwardIterator1>::value && 110 __has_random_access_iterator_category<_ForwardIterator2>::value) { 111 if (__g_last1 - __g_first1 != __g_last2 - __g_first2) 112 return false; 113 return std::__equal( 114 __policy, std::move(__g_first1), std::move(__g_last1), std::move(__g_first2), std::move(__g_pred)); 115 } else { 116 (void)__policy; // Avoid unused lambda capture warning 117 return std::equal( 118 std::move(__g_first1), 119 std::move(__g_last1), 120 std::move(__g_first2), 121 std::move(__g_last2), 122 std::move(__g_pred)); 123 } 124 }, 125 std::move(__first1), 126 std::move(__last1), 127 std::move(__first2), 128 std::move(__last2), 129 std::move(__pred)); 130 } 131 132 template <class _ExecutionPolicy, 133 class _ForwardIterator1, 134 class _ForwardIterator2, 135 class _Pred, 136 class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, 137 enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> 138 _LIBCPP_HIDE_FROM_ABI bool 139 equal(_ExecutionPolicy&& __policy, 140 _ForwardIterator1 __first1, 141 _ForwardIterator1 __last1, 142 _ForwardIterator2 __first2, 143 _ForwardIterator2 __last2, 144 _Pred __pred) { 145 auto __res = std::__equal( 146 __policy, std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::move(__pred)); 147 if (!__res) 148 std::__throw_bad_alloc(); 149 return *__res; 150 } 151 152 template <class _ExecutionPolicy, 153 class _ForwardIterator1, 154 class _ForwardIterator2, 155 enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0> 156 _LIBCPP_HIDE_FROM_ABI bool 157 equal(_ExecutionPolicy&& __policy, 158 _ForwardIterator1 __first1, 159 _ForwardIterator1 __last1, 160 _ForwardIterator2 __first2, 161 _ForwardIterator2 __last2) { 162 return std::equal( 163 __policy, std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::equal_to{}); 164 } 165 166 _LIBCPP_END_NAMESPACE_STD 167 168 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 169 170 #endif // _LIBCPP___ALGORITHM_PSTL_EQUAL_H 171