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
16namespace __pstl
17{
18namespace __internal
19{
20
21template <typename _Fp>
22typename 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
39template <typename _Fp>
40void
41__invoke_if(std::true_type, _Fp __f)
42{
43    __f();
44}
45
46template <typename _Fp>
47void
48__invoke_if(std::false_type, _Fp __f)
49{
50}
51
52template <typename _Fp>
53void
54__invoke_if_not(std::false_type, _Fp __f)
55{
56    __f();
57}
58
59template <typename _Fp>
60void
61__invoke_if_not(std::true_type, _Fp __f)
62{
63}
64
65template <typename _F1, typename _F2>
66typename std::result_of<_F1()>::type
67__invoke_if_else(std::true_type, _F1 __f1, _F2 __f2)
68{
69    return __f1();
70}
71
72template <typename _F1, typename _F2>
73typename 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.
80struct __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
91template <typename _Pred>
92class __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
107template <typename _Pred>
108class __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. */
126class __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.
140class __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)
154template <typename _Tp, typename _Predicate>
155class __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
172template <typename _Tp>
173class __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
189template <typename _Tp>
190class __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
205template <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