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
__except_handler(_Fp __f)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
__invoke_if(std::true_type,_Fp __f)41 __invoke_if(std::true_type, _Fp __f)
42 {
43 __f();
44 }
45
46 template <typename _Fp>
47 void
__invoke_if(std::false_type,_Fp __f)48 __invoke_if(std::false_type, _Fp __f)
49 {
50 }
51
52 template <typename _Fp>
53 void
__invoke_if_not(std::false_type,_Fp __f)54 __invoke_if_not(std::false_type, _Fp __f)
55 {
56 __f();
57 }
58
59 template <typename _Fp>
60 void
__invoke_if_not(std::true_type,_Fp __f)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
__invoke_if_else(std::true_type,_F1 __f1,_F2 __f2)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
__invoke_if_else(std::false_type,_F1 __f1,_F2 __f2)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&&
operator__no_op84 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:
__not_pred(_Pred __pred)97 explicit __not_pred(_Pred __pred) : _M_pred(__pred) {}
98
99 template <typename... _Args>
100 bool
operator()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:
__reorder_pred(_Pred __pred)113 explicit __reorder_pred(_Pred __pred) : _M_pred(__pred) {}
114
115 template <typename _FTp, typename _STp>
116 bool
operator()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:
__pstl_equal()129 explicit __pstl_equal() {}
130
131 template <typename _Xp, typename _Yp>
132 bool
operator()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:
__pstl_less()143 explicit __pstl_less() {}
144
145 template <typename _Xp, typename _Yp>
146 bool
operator()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:
__equal_value_by_pred(const _Tp & __value,_Predicate __pred)161 __equal_value_by_pred(const _Tp& __value, _Predicate __pred) : _M_value(__value), _M_pred(__pred) {}
162
163 template <typename _Arg>
164 bool
operator()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:
__equal_value(const _Tp & __value)178 explicit __equal_value(const _Tp& __value) : _M_value(__value) {}
179
180 template <typename _Arg>
181 bool
operator()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:
__not_equal_value(const _Tp & __value)195 explicit __not_equal_value(const _Tp& __value) : _M_value(__value) {}
196
197 template <typename _Arg>
198 bool
operator()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
__cmp_iterators_by_values(_ForwardIterator __a,_ForwardIterator __b,_Compare __comp)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