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, class T> 46 OutputIterator 47 exclusive_scan(InputIterator first, InputIterator last, 48 OutputIterator result, T init); // C++17 49 50template<class InputIterator, class OutputIterator, class T, class BinaryOperation> 51 OutputIterator 52 exclusive_scan(InputIterator first, InputIterator last, 53 OutputIterator result, T init, BinaryOperation binary_op); // C++17 54 55template<class InputIterator, class OutputIterator, class T, 56 class BinaryOperation, class UnaryOperation> 57 OutputIterator 58 transform_exclusive_scan(InputIterator first, InputIterator last, 59 OutputIterator result, T init, 60 BinaryOperation binary_op, UnaryOperation unary_op); // C++17 61 62template <class InputIterator, class OutputIterator> 63 OutputIterator 64 adjacent_difference(InputIterator first, InputIterator last, OutputIterator result); 65 66template <class InputIterator, class OutputIterator, class BinaryOperation> 67 OutputIterator 68 adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op); 69 70template <class ForwardIterator, class T> 71 void iota(ForwardIterator first, ForwardIterator last, T value); 72 73template <class M, class N> 74 constexpr common_type_t<M,N> gcd(M m, N n); // C++17 75 76template <class M, class N> 77 constexpr common_type_t<M,N> lcm(M m, N n); // C++17 78 79} // std 80 81*/ 82 83#include <__config> 84#include <iterator> 85#include <limits> // for numeric_limits 86#include <functional> 87 88#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 89#pragma GCC system_header 90#endif 91 92_LIBCPP_PUSH_MACROS 93#include <__undef_macros> 94 95_LIBCPP_BEGIN_NAMESPACE_STD 96 97template <class _InputIterator, class _Tp> 98inline _LIBCPP_INLINE_VISIBILITY 99_Tp 100accumulate(_InputIterator __first, _InputIterator __last, _Tp __init) 101{ 102 for (; __first != __last; ++__first) 103 __init = __init + *__first; 104 return __init; 105} 106 107template <class _InputIterator, class _Tp, class _BinaryOperation> 108inline _LIBCPP_INLINE_VISIBILITY 109_Tp 110accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOperation __binary_op) 111{ 112 for (; __first != __last; ++__first) 113 __init = __binary_op(__init, *__first); 114 return __init; 115} 116 117template <class _InputIterator1, class _InputIterator2, class _Tp> 118inline _LIBCPP_INLINE_VISIBILITY 119_Tp 120inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _Tp __init) 121{ 122 for (; __first1 != __last1; ++__first1, (void) ++__first2) 123 __init = __init + *__first1 * *__first2; 124 return __init; 125} 126 127template <class _InputIterator1, class _InputIterator2, class _Tp, class _BinaryOperation1, class _BinaryOperation2> 128inline _LIBCPP_INLINE_VISIBILITY 129_Tp 130inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, 131 _Tp __init, _BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2) 132{ 133 for (; __first1 != __last1; ++__first1, (void) ++__first2) 134 __init = __binary_op1(__init, __binary_op2(*__first1, *__first2)); 135 return __init; 136} 137 138template <class _InputIterator, class _OutputIterator> 139inline _LIBCPP_INLINE_VISIBILITY 140_OutputIterator 141partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __result) 142{ 143 if (__first != __last) 144 { 145 typename iterator_traits<_InputIterator>::value_type __t(*__first); 146 *__result = __t; 147 for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result) 148 { 149 __t = __t + *__first; 150 *__result = __t; 151 } 152 } 153 return __result; 154} 155 156template <class _InputIterator, class _OutputIterator, class _BinaryOperation> 157inline _LIBCPP_INLINE_VISIBILITY 158_OutputIterator 159partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __result, 160 _BinaryOperation __binary_op) 161{ 162 if (__first != __last) 163 { 164 typename iterator_traits<_InputIterator>::value_type __t(*__first); 165 *__result = __t; 166 for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result) 167 { 168 __t = __binary_op(__t, *__first); 169 *__result = __t; 170 } 171 } 172 return __result; 173} 174 175#if _LIBCPP_STD_VER > 14 176template <class _InputIterator, class _OutputIterator, class _Tp, class _BinaryOp> 177inline _LIBCPP_INLINE_VISIBILITY 178_OutputIterator 179exclusive_scan(_InputIterator __first, _InputIterator __last, 180 _OutputIterator __result, _Tp __init, _BinaryOp __b) 181{ 182 if (__first != __last) 183 { 184 _Tp __saved = __init; 185 do 186 { 187 __init = __b(__init, *__first); 188 *__result = __saved; 189 __saved = __init; 190 ++__result; 191 } while (++__first != __last); 192 } 193 return __result; 194} 195 196template <class _InputIterator, class _OutputIterator, class _Tp> 197inline _LIBCPP_INLINE_VISIBILITY 198_OutputIterator 199exclusive_scan(_InputIterator __first, _InputIterator __last, 200 _OutputIterator __result, _Tp __init) 201{ 202 return _VSTD::exclusive_scan(__first, __last, __result, __init, _VSTD::plus<>()); 203} 204 205template <class _InputIterator, class _OutputIterator, class _Tp, 206 class _BinaryOp, class _UnaryOp> 207inline _LIBCPP_INLINE_VISIBILITY 208_OutputIterator 209transform_exclusive_scan(_InputIterator __first, _InputIterator __last, 210 _OutputIterator __result, _Tp __init, 211 _BinaryOp __b, _UnaryOp __u) 212{ 213 if (__first != __last) 214 { 215 _Tp __saved = __init; 216 do 217 { 218 __init = __b(__init, __u(*__first)); 219 *__result = __saved; 220 __saved = __init; 221 ++__result; 222 } while (++__first != __last); 223 } 224 return __result; 225} 226#endif 227 228template <class _InputIterator, class _OutputIterator> 229inline _LIBCPP_INLINE_VISIBILITY 230_OutputIterator 231adjacent_difference(_InputIterator __first, _InputIterator __last, _OutputIterator __result) 232{ 233 if (__first != __last) 234 { 235 typename iterator_traits<_InputIterator>::value_type __t1(*__first); 236 *__result = __t1; 237 for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result) 238 { 239 typename iterator_traits<_InputIterator>::value_type __t2(*__first); 240 *__result = __t2 - __t1; 241 __t1 = _VSTD::move(__t2); 242 } 243 } 244 return __result; 245} 246 247template <class _InputIterator, class _OutputIterator, class _BinaryOperation> 248inline _LIBCPP_INLINE_VISIBILITY 249_OutputIterator 250adjacent_difference(_InputIterator __first, _InputIterator __last, _OutputIterator __result, 251 _BinaryOperation __binary_op) 252{ 253 if (__first != __last) 254 { 255 typename iterator_traits<_InputIterator>::value_type __t1(*__first); 256 *__result = __t1; 257 for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result) 258 { 259 typename iterator_traits<_InputIterator>::value_type __t2(*__first); 260 *__result = __binary_op(__t2, __t1); 261 __t1 = _VSTD::move(__t2); 262 } 263 } 264 return __result; 265} 266 267template <class _ForwardIterator, class _Tp> 268inline _LIBCPP_INLINE_VISIBILITY 269void 270iota(_ForwardIterator __first, _ForwardIterator __last, _Tp __value_) 271{ 272 for (; __first != __last; ++__first, (void) ++__value_) 273 *__first = __value_; 274} 275 276 277#if _LIBCPP_STD_VER > 14 278template <typename _Result, typename _Source, bool _IsSigned = is_signed<_Source>::value> struct __abs; 279 280template <typename _Result, typename _Source> 281struct __abs<_Result, _Source, true> { 282 _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY 283 _Result operator()(_Source __t) const noexcept 284 { 285 if (__t >= 0) return __t; 286 if (__t == numeric_limits<_Source>::min()) return -static_cast<_Result>(__t); 287 return -__t; 288 } 289}; 290 291template <typename _Result, typename _Source> 292struct __abs<_Result, _Source, false> { 293 _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY 294 _Result operator()(_Source __t) const noexcept { return __t; } 295}; 296 297 298template<class _Tp> 299_LIBCPP_CONSTEXPR _LIBCPP_HIDDEN 300_Tp __gcd(_Tp __m, _Tp __n) 301{ 302 static_assert((!is_signed<_Tp>::value), ""); 303 return __n == 0 ? __m : _VSTD::__gcd<_Tp>(__n, __m % __n); 304} 305 306 307template<class _Tp, class _Up> 308_LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY 309common_type_t<_Tp,_Up> 310gcd(_Tp __m, _Up __n) 311{ 312 static_assert((is_integral<_Tp>::value && is_integral<_Up>::value), "Arguments to gcd must be integer types"); 313 static_assert((!is_same<typename remove_cv<_Tp>::type, bool>::value), "First argument to gcd cannot be bool" ); 314 static_assert((!is_same<typename remove_cv<_Up>::type, bool>::value), "Second argument to gcd cannot be bool" ); 315 using _Rp = common_type_t<_Tp,_Up>; 316 using _Wp = make_unsigned_t<_Rp>; 317 return static_cast<_Rp>(_VSTD::__gcd( 318 static_cast<_Wp>(__abs<_Rp, _Tp>()(__m)), 319 static_cast<_Wp>(__abs<_Rp, _Up>()(__n)))); 320} 321 322template<class _Tp, class _Up> 323_LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY 324common_type_t<_Tp,_Up> 325lcm(_Tp __m, _Up __n) 326{ 327 static_assert((is_integral<_Tp>::value && is_integral<_Up>::value), "Arguments to lcm must be integer types"); 328 static_assert((!is_same<typename remove_cv<_Tp>::type, bool>::value), "First argument to lcm cannot be bool" ); 329 static_assert((!is_same<typename remove_cv<_Up>::type, bool>::value), "Second argument to lcm cannot be bool" ); 330 if (__m == 0 || __n == 0) 331 return 0; 332 333 using _Rp = common_type_t<_Tp,_Up>; 334 _Rp __val1 = __abs<_Rp, _Tp>()(__m) / _VSTD::gcd(__m, __n); 335 _Rp __val2 = __abs<_Rp, _Up>()(__n); 336 _LIBCPP_ASSERT((numeric_limits<_Rp>::max() / __val1 > __val2), "Overflow in lcm"); 337 return __val1 * __val2; 338} 339 340#endif /* _LIBCPP_STD_VER > 14 */ 341 342_LIBCPP_END_NAMESPACE_STD 343 344_LIBCPP_POP_MACROS 345 346#endif // _LIBCPP_NUMERIC 347