Home | History | Annotate | Download | only in v1
      1 // -*- C++ -*-
      2 //===---------------------------- numeric ---------------------------------===//
      3 //
      4 //                     The LLVM Compiler Infrastructure
      5 //
      6 // This file is dual licensed under the MIT and the University of Illinois Open
      7 // Source Licenses. See LICENSE.TXT for details.
      8 //
      9 //===----------------------------------------------------------------------===//
     10 
     11 #ifndef _LIBCPP_NUMERIC
     12 #define _LIBCPP_NUMERIC
     13 
     14 /*
     15     numeric synopsis
     16 
     17 namespace std
     18 {
     19 
     20 template <class InputIterator, class T>
     21     T
     22     accumulate(InputIterator first, InputIterator last, T init);
     23 
     24 template <class InputIterator, class T, class BinaryOperation>
     25     T
     26     accumulate(InputIterator first, InputIterator last, T init, BinaryOperation binary_op);
     27 
     28 template<class InputIterator>
     29     typename iterator_traits<InputIterator>::value_type
     30     reduce(InputIterator first, InputIterator last);  // C++17
     31 
     32 template<class InputIterator, class T>
     33     T
     34     reduce(InputIterator first, InputIterator last, T init);  // C++17
     35 
     36 template<class InputIterator, class T, class BinaryOperation>
     37     T
     38     reduce(InputIterator first, InputIterator last, T init, BinaryOperation binary_op);  // C++17
     39 
     40 template <class InputIterator1, class InputIterator2, class T>
     41     T
     42     inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init);
     43 
     44 template <class InputIterator1, class InputIterator2, class T, class BinaryOperation1, class BinaryOperation2>
     45     T
     46     inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2,
     47                   T init, BinaryOperation1 binary_op1, BinaryOperation2 binary_op2);
     48 
     49 
     50 template<class InputIterator1, class InputIterator2, class T>
     51     T
     52     transform_reduce(InputIterator1 first1, InputIterator1 last1,
     53                      InputIterator2 first2, T init);  // C++17
     54                      
     55 template<class InputIterator1, class InputIterator2, class T, class BinaryOperation1, class BinaryOperation2>
     56     T
     57     transform_reduce(InputIterator1 first1, InputIterator1 last1,
     58                      InputIterator2 first2, T init,
     59                      BinaryOperation1 binary_op1, BinaryOperation2 binary_op2);  // C++17
     60 
     61 template<class InputIterator, class T, class BinaryOperation, class UnaryOperation>
     62     T
     63     transform_reduce(InputIterator first, InputIterator last, T init,
     64                      BinaryOperation binary_op, UnaryOperation unary_op);  // C++17
     65 
     66 template <class InputIterator, class OutputIterator>
     67     OutputIterator
     68     partial_sum(InputIterator first, InputIterator last, OutputIterator result);
     69 
     70 template <class InputIterator, class OutputIterator, class BinaryOperation>
     71     OutputIterator
     72     partial_sum(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op);
     73 
     74 template<class InputIterator, class OutputIterator, class T>
     75     OutputIterator
     76     exclusive_scan(InputIterator first, InputIterator last,
     77                    OutputIterator result, T init); // C++17
     78                            
     79 template<class InputIterator, class OutputIterator, class T, class BinaryOperation>
     80     OutputIterator
     81     exclusive_scan(InputIterator first, InputIterator last, 
     82                    OutputIterator result, T init, BinaryOperation binary_op); // C++17
     83 
     84 template<class InputIterator, class OutputIterator, class T,
     85          class BinaryOperation, class UnaryOperation>
     86     OutputIterator
     87     transform_exclusive_scan(InputIterator first, InputIterator last,
     88                              OutputIterator result, T init,
     89                              BinaryOperation binary_op, UnaryOperation unary_op);  // C++17
     90 
     91 template <class InputIterator, class OutputIterator>
     92     OutputIterator
     93     adjacent_difference(InputIterator first, InputIterator last, OutputIterator result);
     94 
     95 template <class InputIterator, class OutputIterator, class BinaryOperation>
     96     OutputIterator
     97     adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op);
     98 
     99 template <class ForwardIterator, class T>
    100     void iota(ForwardIterator first, ForwardIterator last, T value);
    101 
    102 template <class M, class N>
    103     constexpr common_type_t<M,N> gcd(M m, N n);    // C++17
    104 
    105 template <class M, class N>
    106     constexpr common_type_t<M,N> lcm(M m, N n);    // C++17
    107 
    108 }  // std
    109 
    110 */
    111 
    112 #include <__config>
    113 #include <iterator>
    114 #include <limits> // for numeric_limits
    115 #include <functional>
    116 
    117 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
    118 #pragma GCC system_header
    119 #endif
    120 
    121 _LIBCPP_PUSH_MACROS
    122 #include <__undef_macros>
    123 
    124 _LIBCPP_BEGIN_NAMESPACE_STD
    125 
    126 template <class _InputIterator, class _Tp>
    127 inline _LIBCPP_INLINE_VISIBILITY
    128 _Tp
    129 accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
    130 {
    131     for (; __first != __last; ++__first)
    132         __init = __init + *__first;
    133     return __init;
    134 }
    135 
    136 template <class _InputIterator, class _Tp, class _BinaryOperation>
    137 inline _LIBCPP_INLINE_VISIBILITY
    138 _Tp
    139 accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOperation __binary_op)
    140 {
    141     for (; __first != __last; ++__first)
    142         __init = __binary_op(__init, *__first);
    143     return __init;
    144 }
    145 
    146 #if _LIBCPP_STD_VER > 14
    147 template <class _InputIterator, class _Tp, class _BinaryOp>
    148 inline _LIBCPP_INLINE_VISIBILITY
    149 _Tp
    150 reduce(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOp __b)
    151 {
    152     for (; __first != __last; ++__first)
    153         __init = __b(__init, *__first);
    154     return __init;
    155 }
    156 
    157 template <class _InputIterator, class _Tp>
    158 inline _LIBCPP_INLINE_VISIBILITY
    159 _Tp
    160 reduce(_InputIterator __first, _InputIterator __last, _Tp __init)
    161 {
    162     return _VSTD::reduce(__first, __last, __init, _VSTD::plus<>());
    163 }
    164 
    165 template <class _InputIterator>
    166 inline _LIBCPP_INLINE_VISIBILITY
    167 typename iterator_traits<_InputIterator>::value_type
    168 reduce(_InputIterator __first, _InputIterator __last)
    169 {
    170     return _VSTD::reduce(__first, __last, 
    171        typename iterator_traits<_InputIterator>::value_type{});
    172 }
    173 #endif
    174 
    175 template <class _InputIterator1, class _InputIterator2, class _Tp>
    176 inline _LIBCPP_INLINE_VISIBILITY
    177 _Tp
    178 inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _Tp __init)
    179 {
    180     for (; __first1 != __last1; ++__first1, (void) ++__first2)
    181         __init = __init + *__first1 * *__first2;
    182     return __init;
    183 }
    184 
    185 template <class _InputIterator1, class _InputIterator2, class _Tp, class _BinaryOperation1, class _BinaryOperation2>
    186 inline _LIBCPP_INLINE_VISIBILITY
    187 _Tp
    188 inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2,
    189               _Tp __init, _BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2)
    190 {
    191     for (; __first1 != __last1; ++__first1, (void) ++__first2)
    192         __init = __binary_op1(__init, __binary_op2(*__first1, *__first2));
    193     return __init;
    194 }
    195 
    196 #if _LIBCPP_STD_VER > 14
    197 template <class _InputIterator, class _Tp, class _BinaryOp, class _UnaryOp>
    198 inline _LIBCPP_INLINE_VISIBILITY
    199 _Tp
    200 transform_reduce(_InputIterator __first, _InputIterator __last, 
    201            _Tp __init,  _BinaryOp __b, _UnaryOp __u)
    202 {
    203     for (; __first != __last; ++__first)
    204         __init = __b(__init, __u(*__first));
    205     return __init;
    206 }
    207 
    208 template <class _InputIterator1, class _InputIterator2, 
    209           class _Tp, class _BinaryOp1, class _BinaryOp2>
    210 inline _LIBCPP_INLINE_VISIBILITY
    211 _Tp
    212 transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1,
    213                  _InputIterator2 __first2, _Tp __init,  _BinaryOp1 __b1, _BinaryOp2 __b2)
    214 {
    215     for (; __first1 != __last1; ++__first1, (void) ++__first2)
    216         __init = __b1(__init, __b2(*__first1, *__first2));
    217     return __init;
    218 }
    219 
    220 template <class _InputIterator1, class _InputIterator2, class _Tp>
    221 inline _LIBCPP_INLINE_VISIBILITY
    222 _Tp
    223 transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1, 
    224                  _InputIterator2 __first2, _Tp __init)
    225 {
    226     return _VSTD::transform_reduce(__first1, __last1, __first2, __init, 
    227                                    _VSTD::plus<>(), _VSTD::multiplies<>());
    228 }
    229 #endif
    230 
    231 template <class _InputIterator, class _OutputIterator>
    232 inline _LIBCPP_INLINE_VISIBILITY
    233 _OutputIterator
    234 partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
    235 {
    236     if (__first != __last)
    237     {
    238         typename iterator_traits<_InputIterator>::value_type __t(*__first);
    239         *__result = __t;
    240         for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result)
    241         {
    242             __t = __t + *__first;
    243             *__result = __t;
    244         }
    245     }
    246     return __result;
    247 }
    248 
    249 template <class _InputIterator, class _OutputIterator, class _BinaryOperation>
    250 inline _LIBCPP_INLINE_VISIBILITY
    251 _OutputIterator
    252 partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __result,
    253               _BinaryOperation __binary_op)
    254 {
    255     if (__first != __last)
    256     {
    257         typename iterator_traits<_InputIterator>::value_type __t(*__first);
    258         *__result = __t;
    259         for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result)
    260         {
    261             __t = __binary_op(__t, *__first);
    262             *__result = __t;
    263         }
    264     }
    265     return __result;
    266 }
    267 
    268 #if _LIBCPP_STD_VER > 14
    269 template <class _InputIterator, class _OutputIterator, class _Tp, class _BinaryOp>
    270 inline _LIBCPP_INLINE_VISIBILITY
    271 _OutputIterator
    272 exclusive_scan(_InputIterator __first, _InputIterator __last, 
    273                _OutputIterator __result, _Tp __init, _BinaryOp __b)
    274 {
    275     if (__first != __last)
    276     {
    277         _Tp __saved = __init;
    278         do
    279         {
    280             __init = __b(__init, *__first);
    281             *__result = __saved;
    282             __saved = __init;
    283             ++__result;
    284         } while (++__first != __last);
    285     }
    286     return __result;
    287 }
    288 
    289 template <class _InputIterator, class _OutputIterator, class _Tp>
    290 inline _LIBCPP_INLINE_VISIBILITY
    291 _OutputIterator
    292 exclusive_scan(_InputIterator __first, _InputIterator __last, 
    293                _OutputIterator __result, _Tp __init)
    294 {
    295     return _VSTD::exclusive_scan(__first, __last, __result, __init, _VSTD::plus<>());
    296 }
    297 
    298 template <class _InputIterator, class _OutputIterator, class _Tp, 
    299           class _BinaryOp, class _UnaryOp>
    300 inline _LIBCPP_INLINE_VISIBILITY
    301 _OutputIterator
    302 transform_exclusive_scan(_InputIterator __first, _InputIterator __last, 
    303                            _OutputIterator __result, _Tp __init,
    304                            _BinaryOp __b, _UnaryOp __u)
    305 {
    306     if (__first != __last)
    307     {
    308         _Tp __saved = __init;
    309         do
    310         {
    311             __init = __b(__init, __u(*__first));
    312             *__result = __saved;
    313             __saved = __init;
    314             ++__result;
    315         } while (++__first != __last);
    316     }
    317     return __result;
    318 }
    319 #endif
    320 
    321 template <class _InputIterator, class _OutputIterator>
    322 inline _LIBCPP_INLINE_VISIBILITY
    323 _OutputIterator
    324 adjacent_difference(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
    325 {
    326     if (__first != __last)
    327     {
    328         typename iterator_traits<_InputIterator>::value_type __t1(*__first);
    329         *__result = __t1;
    330         for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result)
    331         {
    332             typename iterator_traits<_InputIterator>::value_type __t2(*__first);
    333             *__result = __t2 - __t1;
    334             __t1 = _VSTD::move(__t2);
    335         }
    336     }
    337     return __result;
    338 }
    339 
    340 template <class _InputIterator, class _OutputIterator, class _BinaryOperation>
    341 inline _LIBCPP_INLINE_VISIBILITY
    342 _OutputIterator
    343 adjacent_difference(_InputIterator __first, _InputIterator __last, _OutputIterator __result,
    344                       _BinaryOperation __binary_op)
    345 {
    346     if (__first != __last)
    347     {
    348         typename iterator_traits<_InputIterator>::value_type __t1(*__first);
    349         *__result = __t1;
    350         for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result)
    351         {
    352             typename iterator_traits<_InputIterator>::value_type __t2(*__first);
    353             *__result = __binary_op(__t2, __t1);
    354             __t1 = _VSTD::move(__t2);
    355         }
    356     }
    357     return __result;
    358 }
    359 
    360 template <class _ForwardIterator, class _Tp>
    361 inline _LIBCPP_INLINE_VISIBILITY
    362 void
    363 iota(_ForwardIterator __first, _ForwardIterator __last, _Tp __value_)
    364 {
    365     for (; __first != __last; ++__first, (void) ++__value_)
    366         *__first = __value_;
    367 }
    368 
    369 
    370 #if _LIBCPP_STD_VER > 14
    371 template <typename _Result, typename _Source, bool _IsSigned = is_signed<_Source>::value> struct __abs;
    372 
    373 template <typename _Result, typename _Source>
    374 struct __abs<_Result, _Source, true> {
    375     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    376     _Result operator()(_Source __t) const noexcept
    377     {
    378     if (__t >= 0) return __t;
    379     if (__t == numeric_limits<_Source>::min()) return -static_cast<_Result>(__t);
    380     return -__t;
    381     }
    382 };
    383 
    384 template <typename _Result, typename _Source>
    385 struct __abs<_Result, _Source, false> {
    386     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    387     _Result operator()(_Source __t) const noexcept { return __t; }
    388 };
    389 
    390 
    391 template<class _Tp>
    392 _LIBCPP_CONSTEXPR _LIBCPP_HIDDEN
    393 _Tp __gcd(_Tp __m, _Tp __n)
    394 {
    395     static_assert((!is_signed<_Tp>::value), "");
    396     return __n == 0 ? __m : _VSTD::__gcd<_Tp>(__n, __m % __n);
    397 }
    398 
    399 
    400 template<class _Tp, class _Up>
    401 _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    402 common_type_t<_Tp,_Up>
    403 gcd(_Tp __m, _Up __n)
    404 {
    405     static_assert((is_integral<_Tp>::value && is_integral<_Up>::value), "Arguments to gcd must be integer types");
    406     static_assert((!is_same<typename remove_cv<_Tp>::type, bool>::value), "First argument to gcd cannot be bool" );
    407     static_assert((!is_same<typename remove_cv<_Up>::type, bool>::value), "Second argument to gcd cannot be bool" );
    408     using _Rp = common_type_t<_Tp,_Up>;
    409     using _Wp = make_unsigned_t<_Rp>;
    410     return static_cast<_Rp>(_VSTD::__gcd(
    411         static_cast<_Wp>(__abs<_Rp, _Tp>()(__m)),
    412         static_cast<_Wp>(__abs<_Rp, _Up>()(__n))));
    413 }
    414 
    415 template<class _Tp, class _Up>
    416 _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    417 common_type_t<_Tp,_Up>
    418 lcm(_Tp __m, _Up __n)
    419 {
    420     static_assert((is_integral<_Tp>::value && is_integral<_Up>::value), "Arguments to lcm must be integer types");
    421     static_assert((!is_same<typename remove_cv<_Tp>::type, bool>::value), "First argument to lcm cannot be bool" );
    422     static_assert((!is_same<typename remove_cv<_Up>::type, bool>::value), "Second argument to lcm cannot be bool" );
    423     if (__m == 0 || __n == 0)
    424         return 0;
    425 
    426     using _Rp = common_type_t<_Tp,_Up>;
    427     _Rp __val1 = __abs<_Rp, _Tp>()(__m) / _VSTD::gcd(__m, __n);
    428     _Rp __val2 = __abs<_Rp, _Up>()(__n);
    429     _LIBCPP_ASSERT((numeric_limits<_Rp>::max() / __val1 > __val2), "Overflow in lcm");
    430     return __val1 * __val2;
    431 }
    432 
    433 #endif /* _LIBCPP_STD_VER > 14 */
    434 
    435 _LIBCPP_END_NAMESPACE_STD
    436 
    437 _LIBCPP_POP_MACROS
    438 
    439 #endif  // _LIBCPP_NUMERIC
    440