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 InputIterator1, class InputIterator2, class T>
     29     T
     30     inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init);
     31 
     32 template <class InputIterator1, class InputIterator2, class T, class BinaryOperation1, class BinaryOperation2>
     33     T
     34     inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2,
     35                   T init, BinaryOperation1 binary_op1, BinaryOperation2 binary_op2);
     36 
     37 template <class InputIterator, class OutputIterator>
     38     OutputIterator
     39     partial_sum(InputIterator first, InputIterator last, OutputIterator result);
     40 
     41 template <class InputIterator, class OutputIterator, class BinaryOperation>
     42     OutputIterator
     43     partial_sum(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op);
     44 
     45 template <class InputIterator, class OutputIterator>
     46     OutputIterator
     47     adjacent_difference(InputIterator first, InputIterator last, OutputIterator result);
     48 
     49 template <class InputIterator, class OutputIterator, class BinaryOperation>
     50     OutputIterator
     51     adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op);
     52 
     53 template <class ForwardIterator, class T>
     54     void iota(ForwardIterator first, ForwardIterator last, T value);
     55 
     56 template <class M, class N>
     57     constexpr common_type_t<M,N> gcd(M m, N n);    // C++17
     58 
     59 template <class M, class N>
     60     constexpr common_type_t<M,N> lcm(M m, N n);    // C++17
     61 
     62 }  // std
     63 
     64 */
     65 
     66 #include <__config>
     67 #include <iterator>
     68 #include <limits> // for numeric_limits
     69 
     70 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
     71 #pragma GCC system_header
     72 #endif
     73 
     74 _LIBCPP_BEGIN_NAMESPACE_STD
     75 
     76 template <class _InputIterator, class _Tp>
     77 inline _LIBCPP_INLINE_VISIBILITY
     78 _Tp
     79 accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
     80 {
     81     for (; __first != __last; ++__first)
     82         __init = __init + *__first;
     83     return __init;
     84 }
     85 
     86 template <class _InputIterator, class _Tp, class _BinaryOperation>
     87 inline _LIBCPP_INLINE_VISIBILITY
     88 _Tp
     89 accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOperation __binary_op)
     90 {
     91     for (; __first != __last; ++__first)
     92         __init = __binary_op(__init, *__first);
     93     return __init;
     94 }
     95 
     96 template <class _InputIterator1, class _InputIterator2, class _Tp>
     97 inline _LIBCPP_INLINE_VISIBILITY
     98 _Tp
     99 inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _Tp __init)
    100 {
    101     for (; __first1 != __last1; ++__first1, (void) ++__first2)
    102         __init = __init + *__first1 * *__first2;
    103     return __init;
    104 }
    105 
    106 template <class _InputIterator1, class _InputIterator2, class _Tp, class _BinaryOperation1, class _BinaryOperation2>
    107 inline _LIBCPP_INLINE_VISIBILITY
    108 _Tp
    109 inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2,
    110               _Tp __init, _BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2)
    111 {
    112     for (; __first1 != __last1; ++__first1, (void) ++__first2)
    113         __init = __binary_op1(__init, __binary_op2(*__first1, *__first2));
    114     return __init;
    115 }
    116 
    117 template <class _InputIterator, class _OutputIterator>
    118 inline _LIBCPP_INLINE_VISIBILITY
    119 _OutputIterator
    120 partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
    121 {
    122     if (__first != __last)
    123     {
    124         typename iterator_traits<_InputIterator>::value_type __t(*__first);
    125         *__result = __t;
    126         for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result)
    127         {
    128             __t = __t + *__first;
    129             *__result = __t;
    130         }
    131     }
    132     return __result;
    133 }
    134 
    135 template <class _InputIterator, class _OutputIterator, class _BinaryOperation>
    136 inline _LIBCPP_INLINE_VISIBILITY
    137 _OutputIterator
    138 partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __result,
    139               _BinaryOperation __binary_op)
    140 {
    141     if (__first != __last)
    142     {
    143         typename iterator_traits<_InputIterator>::value_type __t(*__first);
    144         *__result = __t;
    145         for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result)
    146         {
    147             __t = __binary_op(__t, *__first);
    148             *__result = __t;
    149         }
    150     }
    151     return __result;
    152 }
    153 
    154 template <class _InputIterator, class _OutputIterator>
    155 inline _LIBCPP_INLINE_VISIBILITY
    156 _OutputIterator
    157 adjacent_difference(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
    158 {
    159     if (__first != __last)
    160     {
    161         typename iterator_traits<_InputIterator>::value_type __t1(*__first);
    162         *__result = __t1;
    163         for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result)
    164         {
    165             typename iterator_traits<_InputIterator>::value_type __t2(*__first);
    166             *__result = __t2 - __t1;
    167             __t1 = _VSTD::move(__t2);
    168         }
    169     }
    170     return __result;
    171 }
    172 
    173 template <class _InputIterator, class _OutputIterator, class _BinaryOperation>
    174 inline _LIBCPP_INLINE_VISIBILITY
    175 _OutputIterator
    176 adjacent_difference(_InputIterator __first, _InputIterator __last, _OutputIterator __result,
    177                       _BinaryOperation __binary_op)
    178 {
    179     if (__first != __last)
    180     {
    181         typename iterator_traits<_InputIterator>::value_type __t1(*__first);
    182         *__result = __t1;
    183         for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result)
    184         {
    185             typename iterator_traits<_InputIterator>::value_type __t2(*__first);
    186             *__result = __binary_op(__t2, __t1);
    187             __t1 = _VSTD::move(__t2);
    188         }
    189     }
    190     return __result;
    191 }
    192 
    193 template <class _ForwardIterator, class _Tp>
    194 inline _LIBCPP_INLINE_VISIBILITY
    195 void
    196 iota(_ForwardIterator __first, _ForwardIterator __last, _Tp __value_)
    197 {
    198     for (; __first != __last; ++__first, (void) ++__value_)
    199         *__first = __value_;
    200 }
    201 
    202 
    203 #if _LIBCPP_STD_VER > 14
    204 template <typename _Result, typename _Source, bool _IsSigned = is_signed<_Source>::value> struct __abs;
    205 
    206 template <typename _Result, typename _Source>
    207 struct __abs<_Result, _Source, true> {
    208     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    209     _Result operator()(_Source __t) const noexcept
    210     {
    211     if (__t >= 0) return __t;
    212     if (__t == numeric_limits<_Source>::min()) return -static_cast<_Result>(__t);
    213     return -__t;
    214     }
    215 };
    216 
    217 template <typename _Result, typename _Source>
    218 struct __abs<_Result, _Source, false> {
    219     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    220     _Result operator()(_Source __t) const noexcept { return __t; }
    221 };
    222 
    223 
    224 template<class _Tp>
    225 _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    226 _Tp __gcd(_Tp __m, _Tp __n)
    227 {
    228     static_assert((!is_signed<_Tp>::value), "");
    229     return __n == 0 ? __m : __gcd<_Tp>(__n, __m % __n);
    230 }
    231 
    232 
    233 template<class _Tp, class _Up>
    234 _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    235 common_type_t<_Tp,_Up>
    236 gcd(_Tp __m, _Up __n)
    237 {
    238     static_assert((is_integral<_Tp>::value && is_integral<_Up>::value), "Arguments to gcd must be integer types");
    239     static_assert((!is_same<typename remove_cv<_Tp>::type, bool>::value), "First argument to gcd cannot be bool" );
    240     static_assert((!is_same<typename remove_cv<_Up>::type, bool>::value), "Second argument to gcd cannot be bool" );
    241     using _Rp = common_type_t<_Tp,_Up>;
    242     using _Wp = make_unsigned_t<_Rp>;
    243     return static_cast<_Rp>(__gcd(static_cast<_Wp>(__abs<_Rp, _Tp>()(__m)),
    244                                   static_cast<_Wp>(__abs<_Rp, _Up>()(__n))));
    245 }
    246 
    247 template<class _Tp, class _Up>
    248 _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    249 common_type_t<_Tp,_Up>
    250 lcm(_Tp __m, _Up __n)
    251 {
    252     static_assert((is_integral<_Tp>::value && is_integral<_Up>::value), "Arguments to lcm must be integer types");
    253     static_assert((!is_same<typename remove_cv<_Tp>::type, bool>::value), "First argument to lcm cannot be bool" );
    254     static_assert((!is_same<typename remove_cv<_Up>::type, bool>::value), "Second argument to lcm cannot be bool" );
    255     if (__m == 0 || __n == 0)
    256         return 0;
    257 
    258     using _Rp = common_type_t<_Tp,_Up>;
    259     _Rp __val1 = __abs<_Rp, _Tp>()(__m) / gcd(__m, __n);
    260     _Rp __val2 = __abs<_Rp, _Up>()(__n);
    261     _LIBCPP_ASSERT((numeric_limits<_Rp>::max() / __val1 > __val2), "Overflow in lcm");
    262     return __val1 * __val2;
    263 }
    264 
    265 #endif /* _LIBCPP_STD_VER > 14 */
    266 
    267 _LIBCPP_END_NAMESPACE_STD
    268 
    269 #endif  // _LIBCPP_NUMERIC
    270