You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
4.5KB

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