Home | History | Annotate | Line # | Download | only in pstl
      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     auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2);
     58 
     59     typedef typename iterator_traits<_ForwardIterator1>::value_type _InputType;
     60     return __pstl::__internal::__pattern_transform_reduce(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
     61                                                           __first1, __last1, __first2, __init, std::plus<_InputType>(),
     62                                                           std::multiplies<_InputType>());
     63 }
     64 
     65 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation1,
     66           class _BinaryOperation2>
     67 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Tp>
     68 transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
     69                  _ForwardIterator2 __first2, _Tp __init, _BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2)
     70 {
     71     auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2);
     72     return __pstl::__internal::__pattern_transform_reduce(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
     73                                                           __first1, __last1, __first2, __init, __binary_op1,
     74                                                           __binary_op2);
     75 }
     76 
     77 template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation>
     78 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Tp>
     79 transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Tp __init,
     80                  _BinaryOperation __binary_op, _UnaryOperation __unary_op)
     81 {
     82     auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
     83     return __pstl::__internal::__pattern_transform_reduce(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
     84                                                           __first, __last, __init, __binary_op, __unary_op);
     85 }
     86 
     87 // [exclusive.scan]
     88 
     89 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp>
     90 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
     91 exclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
     92                _ForwardIterator2 __result, _Tp __init)
     93 {
     94     auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
     95 
     96     using namespace __pstl;
     97     return __internal::__pattern_transform_scan(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
     98                                                 __result, __pstl::__internal::__no_op(), __init, std::plus<_Tp>(),
     99                                                 /*inclusive=*/std::false_type());
    100 }
    101 
    102 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation>
    103 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
    104 exclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
    105                _ForwardIterator2 __result, _Tp __init, _BinaryOperation __binary_op)
    106 {
    107     auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
    108 
    109     using namespace __pstl;
    110     return __internal::__pattern_transform_scan(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
    111                                                 __result, __pstl::__internal::__no_op(), std::move(__init), __binary_op,
    112                                                 /*inclusive=*/std::false_type());
    113 }
    114 
    115 // [inclusive.scan]
    116 
    117 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2>
    118 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
    119 inclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
    120                _ForwardIterator2 __result)
    121 {
    122     typedef typename iterator_traits<_ForwardIterator1>::value_type _InputType;
    123     return transform_inclusive_scan(std::forward<_ExecutionPolicy>(__exec), __first, __last, __result,
    124                                     std::plus<_InputType>(), __pstl::__internal::__no_op());
    125 }
    126 
    127 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryOperation>
    128 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
    129 inclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
    130                _ForwardIterator2 __result, _BinaryOperation __binary_op)
    131 {
    132     return transform_inclusive_scan(std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __binary_op,
    133                                     __pstl::__internal::__no_op());
    134 }
    135 
    136 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation>
    137 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
    138 inclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
    139                _ForwardIterator2 __result, _BinaryOperation __binary_op, _Tp __init)
    140 {
    141     return transform_inclusive_scan(std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __binary_op,
    142                                     __pstl::__internal::__no_op(), __init);
    143 }
    144 
    145 // [transform.exclusive.scan]
    146 
    147 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation,
    148           class _UnaryOperation>
    149 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
    150 transform_exclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
    151                          _ForwardIterator2 __result, _Tp __init, _BinaryOperation __binary_op,
    152                          _UnaryOperation __unary_op)
    153 {
    154     auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
    155 
    156     return __pstl::__internal::__pattern_transform_scan(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
    157                                                         __last, __result, __unary_op, __init, __binary_op,
    158                                                         /*inclusive=*/std::false_type());
    159 }
    160 
    161 // [transform.inclusive.scan]
    162 
    163 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryOperation,
    164           class _UnaryOperation, class _Tp>
    165 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
    166 transform_inclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
    167                          _ForwardIterator2 __result, _BinaryOperation __binary_op, _UnaryOperation __unary_op,
    168                          _Tp __init)
    169 {
    170     auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
    171 
    172     return __pstl::__internal::__pattern_transform_scan(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
    173                                                         __last, __result, __unary_op, __init, __binary_op,
    174                                                         /*inclusive=*/std::true_type());
    175 }
    176 
    177 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _UnaryOperation,
    178           class _BinaryOperation>
    179 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
    180 transform_inclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
    181                          _ForwardIterator2 __result, _BinaryOperation __binary_op, _UnaryOperation __unary_op)
    182 {
    183     if (__first != __last)
    184     {
    185         auto __tmp = __unary_op(*__first);
    186         *__result = __tmp;
    187         return transform_inclusive_scan(std::forward<_ExecutionPolicy>(__exec), ++__first, __last, ++__result,
    188                                         __binary_op, __unary_op, __tmp);
    189     }
    190     else
    191     {
    192         return __result;
    193     }
    194 }
    195 
    196 // [adjacent.difference]
    197 
    198 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryOperation>
    199 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
    200 adjacent_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
    201                     _ForwardIterator2 __d_first, _BinaryOperation __op)
    202 {
    203 
    204     if (__first == __last)
    205         return __d_first;
    206 
    207     auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __d_first);
    208 
    209     return __pstl::__internal::__pattern_adjacent_difference(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
    210                                                              __first, __last, __d_first, __op);
    211 }
    212 
    213 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2>
    214 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
    215 adjacent_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
    216                     _ForwardIterator2 __d_first)
    217 {
    218     typedef typename iterator_traits<_ForwardIterator1>::value_type _ValueType;
    219     return adjacent_difference(std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first,
    220                                std::minus<_ValueType>());
    221 }
    222 
    223 } // namespace std
    224 
    225 #endif /* _PSTL_GLUE_NUMERIC_IMPL_H_ */
    226