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