1 | // -*- C++ -*- |
2 | //===-- utils.h -----------------------------------------------------------===// |
3 | // |
4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef _PSTL_UTILS_H |
11 | #define _PSTL_UTILS_H |
12 | |
13 | #include <new> |
14 | #include <iterator> |
15 | |
16 | namespace __pstl |
17 | { |
18 | namespace __internal |
19 | { |
20 | |
21 | template <typename _Fp> |
22 | typename std::result_of<_Fp()>::type |
23 | __except_handler(_Fp __f) |
24 | { |
25 | try |
26 | { |
27 | return __f(); |
28 | } |
29 | catch (const std::bad_alloc&) |
30 | { |
31 | throw; // re-throw bad_alloc according to the standard [algorithms.parallel.exceptions] |
32 | } |
33 | catch (...) |
34 | { |
35 | std::terminate(); // Good bye according to the standard [algorithms.parallel.exceptions] |
36 | } |
37 | } |
38 | |
39 | template <typename _Fp> |
40 | void |
41 | __invoke_if(std::true_type, _Fp __f) |
42 | { |
43 | __f(); |
44 | } |
45 | |
46 | template <typename _Fp> |
47 | void |
48 | __invoke_if(std::false_type, _Fp __f) |
49 | { |
50 | } |
51 | |
52 | template <typename _Fp> |
53 | void |
54 | __invoke_if_not(std::false_type, _Fp __f) |
55 | { |
56 | __f(); |
57 | } |
58 | |
59 | template <typename _Fp> |
60 | void |
61 | __invoke_if_not(std::true_type, _Fp __f) |
62 | { |
63 | } |
64 | |
65 | template <typename _F1, typename _F2> |
66 | typename std::result_of<_F1()>::type |
67 | __invoke_if_else(std::true_type, _F1 __f1, _F2 __f2) |
68 | { |
69 | return __f1(); |
70 | } |
71 | |
72 | template <typename _F1, typename _F2> |
73 | typename std::result_of<_F2()>::type |
74 | __invoke_if_else(std::false_type, _F1 __f1, _F2 __f2) |
75 | { |
76 | return __f2(); |
77 | } |
78 | |
79 | //! Unary operator that returns reference to its argument. |
80 | struct __no_op |
81 | { |
82 | template <typename _Tp> |
83 | _Tp&& |
84 | operator()(_Tp&& __a) const |
85 | { |
86 | return std::forward<_Tp>(__a); |
87 | } |
88 | }; |
89 | |
90 | //! Logical negation of a predicate |
91 | template <typename _Pred> |
92 | class __not_pred |
93 | { |
94 | _Pred _M_pred; |
95 | |
96 | public: |
97 | explicit __not_pred(_Pred __pred) : _M_pred(__pred) {} |
98 | |
99 | template <typename... _Args> |
100 | bool |
101 | operator()(_Args&&... __args) |
102 | { |
103 | return !_M_pred(std::forward<_Args>(__args)...); |
104 | } |
105 | }; |
106 | |
107 | template <typename _Pred> |
108 | class __reorder_pred |
109 | { |
110 | _Pred _M_pred; |
111 | |
112 | public: |
113 | explicit __reorder_pred(_Pred __pred) : _M_pred(__pred) {} |
114 | |
115 | template <typename _FTp, typename _STp> |
116 | bool |
117 | operator()(_FTp&& __a, _STp&& __b) |
118 | { |
119 | return _M_pred(std::forward<_STp>(__b), std::forward<_FTp>(__a)); |
120 | } |
121 | }; |
122 | |
123 | //! "==" comparison. |
124 | /** Not called "equal" to avoid (possibly unfounded) concerns about accidental invocation via |
125 | argument-dependent name lookup by code expecting to find the usual std::equal. */ |
126 | class __pstl_equal |
127 | { |
128 | public: |
129 | explicit __pstl_equal() {} |
130 | |
131 | template <typename _Xp, typename _Yp> |
132 | bool |
133 | operator()(_Xp&& __x, _Yp&& __y) const |
134 | { |
135 | return std::forward<_Xp>(__x) == std::forward<_Yp>(__y); |
136 | } |
137 | }; |
138 | |
139 | //! "<" comparison. |
140 | class __pstl_less |
141 | { |
142 | public: |
143 | explicit __pstl_less() {} |
144 | |
145 | template <typename _Xp, typename _Yp> |
146 | bool |
147 | operator()(_Xp&& __x, _Yp&& __y) const |
148 | { |
149 | return std::forward<_Xp>(__x) < std::forward<_Yp>(__y); |
150 | } |
151 | }; |
152 | |
153 | //! Like a polymorphic lambda for pred(...,value) |
154 | template <typename _Tp, typename _Predicate> |
155 | class __equal_value_by_pred |
156 | { |
157 | const _Tp& _M_value; |
158 | _Predicate _M_pred; |
159 | |
160 | public: |
161 | __equal_value_by_pred(const _Tp& __value, _Predicate __pred) : _M_value(__value), _M_pred(__pred) {} |
162 | |
163 | template <typename _Arg> |
164 | bool |
165 | operator()(_Arg&& __arg) |
166 | { |
167 | return _M_pred(std::forward<_Arg>(__arg), _M_value); |
168 | } |
169 | }; |
170 | |
171 | //! Like a polymorphic lambda for ==value |
172 | template <typename _Tp> |
173 | class __equal_value |
174 | { |
175 | const _Tp& _M_value; |
176 | |
177 | public: |
178 | explicit __equal_value(const _Tp& __value) : _M_value(__value) {} |
179 | |
180 | template <typename _Arg> |
181 | bool |
182 | operator()(_Arg&& __arg) const |
183 | { |
184 | return std::forward<_Arg>(__arg) == _M_value; |
185 | } |
186 | }; |
187 | |
188 | //! Logical negation of ==value |
189 | template <typename _Tp> |
190 | class __not_equal_value |
191 | { |
192 | const _Tp& _M_value; |
193 | |
194 | public: |
195 | explicit __not_equal_value(const _Tp& __value) : _M_value(__value) {} |
196 | |
197 | template <typename _Arg> |
198 | bool |
199 | operator()(_Arg&& __arg) const |
200 | { |
201 | return !(std::forward<_Arg>(__arg) == _M_value); |
202 | } |
203 | }; |
204 | |
205 | template <typename _ForwardIterator, typename _Compare> |
206 | _ForwardIterator |
207 | __cmp_iterators_by_values(_ForwardIterator __a, _ForwardIterator __b, _Compare __comp) |
208 | { |
209 | if (__a < __b) |
210 | { // we should return closer iterator |
211 | return __comp(*__b, *__a) ? __b : __a; |
212 | } |
213 | else |
214 | { |
215 | return __comp(*__a, *__b) ? __a : __b; |
216 | } |
217 | } |
218 | |
219 | } // namespace __internal |
220 | } // namespace __pstl |
221 | |
222 | #endif /* _PSTL_UTILS_H */ |
223 | |