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 <type_traits>
      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 */