1  // -*- C++ -*-
       2  //===-- glue_numeric_impl.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_GLUE_NUMERIC_IMPL_H
      11  #define _PSTL_GLUE_NUMERIC_IMPL_H
      12  
      13  #include <functional>
      14  
      15  #include "utils.h"
      16  #include "numeric_fwd.h"
      17  
      18  namespace std
      19  {
      20  
      21  // [reduce]
      22  
      23  template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation>
      24  __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Tp>
      25  reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Tp __init,
      26         _BinaryOperation __binary_op)
      27  {
      28      return transform_reduce(std::forward<_ExecutionPolicy>(__exec), __first, __last, __init, __binary_op,
      29                              __pstl::__internal::__no_op());
      30  }
      31  
      32  template <class _ExecutionPolicy, class _ForwardIterator, class _Tp>
      33  __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Tp>
      34  reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Tp __init)
      35  {
      36      return transform_reduce(std::forward<_ExecutionPolicy>(__exec), __first, __last, __init, std::plus<_Tp>(),
      37                              __pstl::__internal::__no_op());
      38  }
      39  
      40  template <class _ExecutionPolicy, class _ForwardIterator>
      41  __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy,
      42                                                   typename iterator_traits<_ForwardIterator>::value_type>
      43  reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last)
      44  {
      45      typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
      46      return transform_reduce(std::forward<_ExecutionPolicy>(__exec), __first, __last, _ValueType{},
      47                              std::plus<_ValueType>(), __pstl::__internal::__no_op());
      48  }
      49  
      50  // [transform.reduce]
      51  
      52  template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp>
      53  __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Tp>
      54  transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
      55                   _ForwardIterator2 __first2, _Tp __init)
      56  {
      57      typedef typename iterator_traits<_ForwardIterator1>::value_type _InputType;
      58      return __pstl::__internal::__pattern_transform_reduce(
      59          std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __init, std::plus<_InputType>(),
      60          std::multiplies<_InputType>(),
      61          __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
      62              __exec),
      63          __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
      64              __exec));
      65  }
      66  
      67  template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation1,
      68            class _BinaryOperation2>
      69  __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Tp>
      70  transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
      71                   _ForwardIterator2 __first2, _Tp __init, _BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2)
      72  {
      73      return __pstl::__internal::__pattern_transform_reduce(
      74          std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __init, __binary_op1, __binary_op2,
      75          __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
      76              __exec),
      77          __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
      78              __exec));
      79  }
      80  
      81  template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation>
      82  __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Tp>
      83  transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Tp __init,
      84                   _BinaryOperation __binary_op, _UnaryOperation __unary_op)
      85  {
      86      return __pstl::__internal::__pattern_transform_reduce(
      87          std::forward<_ExecutionPolicy>(__exec), __first, __last, __init, __binary_op, __unary_op,
      88          __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
      89          __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
      90  }
      91  
      92  // [exclusive.scan]
      93  
      94  template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp>
      95  __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
      96  exclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
      97                 _ForwardIterator2 __result, _Tp __init)
      98  {
      99      using namespace __pstl;
     100      return __internal::__pattern_transform_scan(
     101          std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __pstl::__internal::__no_op(), __init,
     102          std::plus<_Tp>(), /*inclusive=*/std::false_type(),
     103          __internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(__exec),
     104          __internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(__exec));
     105  }
     106  
     107  template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation>
     108  __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
     109  exclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
     110                 _ForwardIterator2 __result, _Tp __init, _BinaryOperation __binary_op)
     111  {
     112      using namespace __pstl;
     113      return __internal::__pattern_transform_scan(
     114          std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __pstl::__internal::__no_op(), __init,
     115          __binary_op, /*inclusive=*/std::false_type(),
     116          __internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(__exec),
     117          __internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(__exec));
     118  }
     119  
     120  // [inclusive.scan]
     121  
     122  template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2>
     123  __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
     124  inclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
     125                 _ForwardIterator2 __result)
     126  {
     127      typedef typename iterator_traits<_ForwardIterator1>::value_type _InputType;
     128      return transform_inclusive_scan(std::forward<_ExecutionPolicy>(__exec), __first, __last, __result,
     129                                      std::plus<_InputType>(), __pstl::__internal::__no_op());
     130  }
     131  
     132  template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryOperation>
     133  __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
     134  inclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
     135                 _ForwardIterator2 __result, _BinaryOperation __binary_op)
     136  {
     137      return transform_inclusive_scan(std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __binary_op,
     138                                      __pstl::__internal::__no_op());
     139  }
     140  
     141  template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation>
     142  __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
     143  inclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
     144                 _ForwardIterator2 __result, _BinaryOperation __binary_op, _Tp __init)
     145  {
     146      return transform_inclusive_scan(std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __binary_op,
     147                                      __pstl::__internal::__no_op(), __init);
     148  }
     149  
     150  // [transform.exclusive.scan]
     151  
     152  template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation,
     153            class _UnaryOperation>
     154  __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
     155  transform_exclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
     156                           _ForwardIterator2 __result, _Tp __init, _BinaryOperation __binary_op,
     157                           _UnaryOperation __unary_op)
     158  {
     159      return __pstl::__internal::__pattern_transform_scan(
     160          std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __unary_op, __init, __binary_op,
     161          /*inclusive=*/std::false_type(),
     162          __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
     163              __exec),
     164          __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
     165              __exec));
     166  }
     167  
     168  // [transform.inclusive.scan]
     169  
     170  template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryOperation,
     171            class _UnaryOperation, class _Tp>
     172  __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
     173  transform_inclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
     174                           _ForwardIterator2 __result, _BinaryOperation __binary_op, _UnaryOperation __unary_op,
     175                           _Tp __init)
     176  {
     177      return __pstl::__internal::__pattern_transform_scan(
     178          std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __unary_op, __init, __binary_op,
     179          /*inclusive=*/std::true_type(),
     180          __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
     181              __exec),
     182          __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
     183              __exec));
     184  }
     185  
     186  template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _UnaryOperation,
     187            class _BinaryOperation>
     188  __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
     189  transform_inclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
     190                           _ForwardIterator2 __result, _BinaryOperation __binary_op, _UnaryOperation __unary_op)
     191  {
     192      if (__first != __last)
     193      {
     194          auto __tmp = __unary_op(*__first);
     195          *__result = __tmp;
     196          return transform_inclusive_scan(std::forward<_ExecutionPolicy>(__exec), ++__first, __last, ++__result,
     197                                          __binary_op, __unary_op, __tmp);
     198      }
     199      else
     200      {
     201          return __result;
     202      }
     203  }
     204  
     205  // [adjacent.difference]
     206  
     207  template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryOperation>
     208  __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
     209  adjacent_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
     210                      _ForwardIterator2 __d_first, _BinaryOperation __op)
     211  {
     212  
     213      if (__first == __last)
     214          return __d_first;
     215  
     216      return __pstl::__internal::__pattern_adjacent_difference(
     217          std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first, __op,
     218          __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
     219              __exec),
     220          __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
     221              __exec));
     222  }
     223  
     224  template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2>
     225  __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
     226  adjacent_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
     227                      _ForwardIterator2 __d_first)
     228  {
     229      typedef typename iterator_traits<_ForwardIterator1>::value_type _ValueType;
     230      return adjacent_difference(std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first,
     231                                 std::minus<_ValueType>());
     232  }
     233  
     234  } // namespace std
     235  
     236  #endif /* _PSTL_GLUE_NUMERIC_IMPL_H_ */