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