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