|
libstdc++
|
00001 // <numeric> -*- C++ -*- 00002 00003 // Copyright (C) 2001-2019 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /* 00026 * 00027 * Copyright (c) 1994 00028 * Hewlett-Packard Company 00029 * 00030 * Permission to use, copy, modify, distribute and sell this software 00031 * and its documentation for any purpose is hereby granted without fee, 00032 * provided that the above copyright notice appear in all copies and 00033 * that both that copyright notice and this permission notice appear 00034 * in supporting documentation. Hewlett-Packard Company makes no 00035 * representations about the suitability of this software for any 00036 * purpose. It is provided "as is" without express or implied warranty. 00037 * 00038 * 00039 * Copyright (c) 1996,1997 00040 * Silicon Graphics Computer Systems, Inc. 00041 * 00042 * Permission to use, copy, modify, distribute and sell this software 00043 * and its documentation for any purpose is hereby granted without fee, 00044 * provided that the above copyright notice appear in all copies and 00045 * that both that copyright notice and this permission notice appear 00046 * in supporting documentation. Silicon Graphics makes no 00047 * representations about the suitability of this software for any 00048 * purpose. It is provided "as is" without express or implied warranty. 00049 */ 00050 00051 /** @file include/numeric 00052 * This is a Standard C++ Library header. 00053 */ 00054 00055 #ifndef _GLIBCXX_NUMERIC 00056 #define _GLIBCXX_NUMERIC 1 00057 00058 #pragma GCC system_header 00059 00060 #include <bits/c++config.h> 00061 #include <bits/stl_iterator_base_types.h> 00062 #include <bits/stl_numeric.h> 00063 00064 #ifdef _GLIBCXX_PARALLEL 00065 # include <parallel/numeric> 00066 #endif 00067 00068 /** 00069 * @defgroup numerics Numerics 00070 * 00071 * Components for performing numeric operations. Includes support for 00072 * complex number types, random number generation, numeric (n-at-a-time) 00073 * arrays, generalized numeric algorithms, and mathematical special functions. 00074 */ 00075 00076 #if __cplusplus >= 201402L 00077 #include <type_traits> 00078 00079 namespace std _GLIBCXX_VISIBILITY(default) 00080 { 00081 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00082 00083 namespace __detail 00084 { 00085 // std::abs is not constexpr and doesn't support unsigned integers. 00086 template<typename _Tp> 00087 constexpr 00088 enable_if_t<__and_<is_integral<_Tp>, is_signed<_Tp>>::value, _Tp> 00089 __abs_integral(_Tp __val) 00090 { return __val < 0 ? -__val : __val; } 00091 00092 template<typename _Tp> 00093 constexpr 00094 enable_if_t<__and_<is_integral<_Tp>, is_unsigned<_Tp>>::value, _Tp> 00095 __abs_integral(_Tp __val) 00096 { return __val; } 00097 00098 void __abs_integral(bool) = delete; 00099 00100 template<typename _Mn, typename _Nn> 00101 constexpr common_type_t<_Mn, _Nn> 00102 __gcd(_Mn __m, _Nn __n) 00103 { 00104 return __m == 0 ? __detail::__abs_integral(__n) 00105 : __n == 0 ? __detail::__abs_integral(__m) 00106 : __detail::__gcd(__n, __m % __n); 00107 } 00108 00109 /// Least common multiple 00110 template<typename _Mn, typename _Nn> 00111 constexpr common_type_t<_Mn, _Nn> 00112 __lcm(_Mn __m, _Nn __n) 00113 { 00114 return (__m != 0 && __n != 0) 00115 ? (__detail::__abs_integral(__m) / __detail::__gcd(__m, __n)) 00116 * __detail::__abs_integral(__n) 00117 : 0; 00118 } 00119 } // namespace __detail 00120 00121 #if __cplusplus >= 201703L 00122 00123 #define __cpp_lib_gcd_lcm 201606 00124 // These were used in drafts of SD-6: 00125 #define __cpp_lib_gcd 201606 00126 #define __cpp_lib_lcm 201606 00127 00128 /// Greatest common divisor 00129 template<typename _Mn, typename _Nn> 00130 constexpr common_type_t<_Mn, _Nn> 00131 gcd(_Mn __m, _Nn __n) 00132 { 00133 static_assert(is_integral_v<_Mn>, "gcd arguments are integers"); 00134 static_assert(is_integral_v<_Nn>, "gcd arguments are integers"); 00135 static_assert(!is_same_v<remove_cv_t<_Mn>, bool>, 00136 "gcd arguments are not bools"); 00137 static_assert(!is_same_v<remove_cv_t<_Nn>, bool>, 00138 "gcd arguments are not bools"); 00139 return __detail::__gcd(__m, __n); 00140 } 00141 00142 /// Least common multiple 00143 template<typename _Mn, typename _Nn> 00144 constexpr common_type_t<_Mn, _Nn> 00145 lcm(_Mn __m, _Nn __n) 00146 { 00147 static_assert(is_integral_v<_Mn>, "lcm arguments are integers"); 00148 static_assert(is_integral_v<_Nn>, "lcm arguments are integers"); 00149 static_assert(!is_same_v<remove_cv_t<_Mn>, bool>, 00150 "lcm arguments are not bools"); 00151 static_assert(!is_same_v<remove_cv_t<_Nn>, bool>, 00152 "lcm arguments are not bools"); 00153 return __detail::__lcm(__m, __n); 00154 } 00155 00156 #endif // C++17 00157 00158 _GLIBCXX_END_NAMESPACE_VERSION 00159 } // namespace std 00160 00161 #endif // C++14 00162 00163 #if __cplusplus > 201703L 00164 #include <limits> 00165 00166 namespace std _GLIBCXX_VISIBILITY(default) 00167 { 00168 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00169 // midpoint 00170 # define __cpp_lib_interpolate 201902L 00171 00172 template<typename _Tp> 00173 constexpr 00174 enable_if_t<__and_v<is_arithmetic<_Tp>, is_same<remove_cv_t<_Tp>, _Tp>, 00175 __not_<is_same<_Tp, bool>>>, 00176 _Tp> 00177 midpoint(_Tp __a, _Tp __b) noexcept 00178 { 00179 if constexpr (is_integral_v<_Tp>) 00180 { 00181 using _Up = make_unsigned_t<_Tp>; 00182 00183 int __k = 1; 00184 _Up __m = __a; 00185 _Up __M = __b; 00186 if (__a > __b) 00187 { 00188 __k = -1; 00189 __m = __b; 00190 __M = __a; 00191 } 00192 return __a + __k * _Tp(_Up(__M - __m) / 2); 00193 } 00194 else // is_floating 00195 { 00196 constexpr _Tp __lo = numeric_limits<_Tp>::min() * 2; 00197 constexpr _Tp __hi = numeric_limits<_Tp>::max() / 2; 00198 const _Tp __abs_a = __a < 0 ? -__a : __a; 00199 const _Tp __abs_b = __b < 0 ? -__b : __b; 00200 if (__abs_a <= __hi && __abs_b <= __hi) [[likely]] 00201 return (__a + __b) / 2; // always correctly rounded 00202 if (__abs_a < __lo) // not safe to halve __a 00203 return __a + __b/2; 00204 if (__abs_b < __lo) // not safe to halve __b 00205 return __a/2 + __b; 00206 return __a/2 + __b/2; // otherwise correctly rounded 00207 } 00208 } 00209 00210 template<typename _Tp> 00211 constexpr 00212 enable_if_t<__and_v<is_object<_Tp>, bool_constant<sizeof(_Tp) != 0>>, _Tp*> 00213 midpoint(_Tp* __a, _Tp* __b) noexcept 00214 { 00215 return __a + (__b - __a) / 2; 00216 } 00217 _GLIBCXX_END_NAMESPACE_VERSION 00218 } // namespace std 00219 00220 #endif // C++20 00221 00222 #if __cplusplus > 201402L 00223 #include <bits/stl_function.h> 00224 00225 namespace std _GLIBCXX_VISIBILITY(default) 00226 { 00227 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00228 00229 /// @addtogroup numeric_ops 00230 /// @{ 00231 00232 /// @cond undocumented 00233 template<typename _It, typename _Traits = iterator_traits<_It>, 00234 typename _Cat = typename _Traits::iterator_category> 00235 using __is_random_access_iter 00236 = is_base_of<random_access_iterator_tag, _Cat>; 00237 /// @endcond 00238 00239 /** 00240 * @brief Calculate reduction of values in a range. 00241 * 00242 * @param __first Start of range. 00243 * @param __last End of range. 00244 * @param __init Starting value to add other values to. 00245 * @param __binary_op A binary function object. 00246 * @return The final sum. 00247 * 00248 * Reduce the values in the range `[first,last)` using a binary operation. 00249 * The initial value is `init`. The values are not necessarily processed 00250 * in order. 00251 * 00252 * This algorithm is similar to `std::accumulate` but is not required to 00253 * perform the operations in order from first to last. For operations 00254 * that are commutative and associative the result will be the same as 00255 * for `std::accumulate`, but for other operations (such as floating point 00256 * arithmetic) the result can be different. 00257 */ 00258 template<typename _InputIterator, typename _Tp, typename _BinaryOperation> 00259 _Tp 00260 reduce(_InputIterator __first, _InputIterator __last, _Tp __init, 00261 _BinaryOperation __binary_op) 00262 { 00263 using value_type = typename iterator_traits<_InputIterator>::value_type; 00264 static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, _Tp&, _Tp&>); 00265 static_assert(is_convertible_v<value_type, _Tp>); 00266 if constexpr (__is_random_access_iter<_InputIterator>::value) 00267 { 00268 while ((__last - __first) >= 4) 00269 { 00270 _Tp __v1 = __binary_op(__first[0], __first[1]); 00271 _Tp __v2 = __binary_op(__first[2], __first[3]); 00272 _Tp __v3 = __binary_op(__v1, __v2); 00273 __init = __binary_op(__init, __v3); 00274 __first += 4; 00275 } 00276 } 00277 for (; __first != __last; ++__first) 00278 __init = __binary_op(__init, *__first); 00279 return __init; 00280 } 00281 00282 /** 00283 * @brief Calculate reduction of values in a range. 00284 * 00285 * @param __first Start of range. 00286 * @param __last End of range. 00287 * @param __init Starting value to add other values to. 00288 * @return The final sum. 00289 * 00290 * Reduce the values in the range `[first,last)` using addition. 00291 * Equivalent to calling `std::reduce(first, last, init, std::plus<>())`. 00292 */ 00293 template<typename _InputIterator, typename _Tp> 00294 inline _Tp 00295 reduce(_InputIterator __first, _InputIterator __last, _Tp __init) 00296 { return std::reduce(__first, __last, std::move(__init), plus<>()); } 00297 00298 /** 00299 * @brief Calculate reduction of values in a range. 00300 * 00301 * @param __first Start of range. 00302 * @param __last End of range. 00303 * @return The final sum. 00304 * 00305 * Reduce the values in the range `[first,last)` using addition, with 00306 * an initial value of `T{}`, where `T` is the iterator's value type. 00307 * Equivalent to calling `std::reduce(first, last, T{}, std::plus<>())`. 00308 */ 00309 template<typename _InputIterator> 00310 inline typename iterator_traits<_InputIterator>::value_type 00311 reduce(_InputIterator __first, _InputIterator __last) 00312 { 00313 using value_type = typename iterator_traits<_InputIterator>::value_type; 00314 return std::reduce(__first, __last, value_type{}, plus<>()); 00315 } 00316 00317 /** 00318 * @brief Combine elements from two ranges and reduce 00319 * 00320 * @param __first1 Start of first range. 00321 * @param __last1 End of first range. 00322 * @param __first2 Start of second range. 00323 * @param __init Starting value to add other values to. 00324 * @param __binary_op1 The function used to perform reduction. 00325 * @param __binary_op2 The function used to combine values from the ranges. 00326 * @return The final sum. 00327 * 00328 * Call `binary_op2(first1[n],first2[n])` for each `n` in `[0,last1-first1)` 00329 * and then use `binary_op1` to reduce the values returned by `binary_op2` 00330 * to a single value of type `T`. 00331 * 00332 * The range beginning at `first2` must contain at least `last1-first1` 00333 * elements. 00334 */ 00335 template<typename _InputIterator1, typename _InputIterator2, typename _Tp, 00336 typename _BinaryOperation1, typename _BinaryOperation2> 00337 _Tp 00338 transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1, 00339 _InputIterator2 __first2, _Tp __init, 00340 _BinaryOperation1 __binary_op1, 00341 _BinaryOperation2 __binary_op2) 00342 { 00343 if constexpr (__and_v<__is_random_access_iter<_InputIterator1>, 00344 __is_random_access_iter<_InputIterator2>>) 00345 { 00346 while ((__last1 - __first1) >= 4) 00347 { 00348 _Tp __v1 = __binary_op1(__binary_op2(__first1[0], __first2[0]), 00349 __binary_op2(__first1[1], __first2[1])); 00350 _Tp __v2 = __binary_op1(__binary_op2(__first1[2], __first2[2]), 00351 __binary_op2(__first1[3], __first2[3])); 00352 _Tp __v3 = __binary_op1(__v1, __v2); 00353 __init = __binary_op1(__init, __v3); 00354 __first1 += 4; 00355 __first2 += 4; 00356 } 00357 } 00358 for (; __first1 != __last1; ++__first1, (void) ++__first2) 00359 __init = __binary_op1(__init, __binary_op2(*__first1, *__first2)); 00360 return __init; 00361 } 00362 00363 /** 00364 * @brief Combine elements from two ranges and reduce 00365 * 00366 * @param __first1 Start of first range. 00367 * @param __last1 End of first range. 00368 * @param __first2 Start of second range. 00369 * @param __init Starting value to add other values to. 00370 * @return The final sum. 00371 * 00372 * Call `first1[n]*first2[n]` for each `n` in `[0,last1-first1)` and then 00373 * use addition to sum those products to a single value of type `T`. 00374 * 00375 * The range beginning at `first2` must contain at least `last1-first1` 00376 * elements. 00377 */ 00378 template<typename _InputIterator1, typename _InputIterator2, typename _Tp> 00379 inline _Tp 00380 transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1, 00381 _InputIterator2 __first2, _Tp __init) 00382 { 00383 return std::transform_reduce(__first1, __last1, __first2, 00384 std::move(__init), 00385 plus<>(), multiplies<>()); 00386 } 00387 00388 /** 00389 * @brief Transform the elements of a range and reduce 00390 * 00391 * @param __first Start of range. 00392 * @param __last End of range. 00393 * @param __init Starting value to add other values to. 00394 * @param __binary_op The function used to perform reduction. 00395 * @param __unary_op The function used to transform values from the range. 00396 * @return The final sum. 00397 * 00398 * Call `unary_op(first[n])` for each `n` in `[0,last-first)` and then 00399 * use `binary_op` to reduce the values returned by `unary_op` 00400 * to a single value of type `T`. 00401 */ 00402 template<typename _InputIterator, typename _Tp, 00403 typename _BinaryOperation, typename _UnaryOperation> 00404 _Tp 00405 transform_reduce(_InputIterator __first, _InputIterator __last, _Tp __init, 00406 _BinaryOperation __binary_op, _UnaryOperation __unary_op) 00407 { 00408 if constexpr (__is_random_access_iter<_InputIterator>::value) 00409 { 00410 while ((__last - __first) >= 4) 00411 { 00412 _Tp __v1 = __binary_op(__unary_op(__first[0]), 00413 __unary_op(__first[1])); 00414 _Tp __v2 = __binary_op(__unary_op(__first[2]), 00415 __unary_op(__first[3])); 00416 _Tp __v3 = __binary_op(__v1, __v2); 00417 __init = __binary_op(__init, __v3); 00418 __first += 4; 00419 } 00420 } 00421 for (; __first != __last; ++__first) 00422 __init = __binary_op(__init, __unary_op(*__first)); 00423 return __init; 00424 } 00425 00426 /** @brief Output the cumulative sum of one range to a second range 00427 * 00428 * @param __first Start of input range. 00429 * @param __last End of input range. 00430 * @param __result Start of output range. 00431 * @param __init Initial value. 00432 * @param __binary_op Function to perform summation. 00433 * @return The end of the output range. 00434 * 00435 * Write the cumulative sum (aka prefix sum, aka scan) of the input range 00436 * to the output range. Each element of the output range contains the 00437 * running total of all earlier elements (and the initial value), 00438 * using `binary_op` for summation. 00439 * 00440 * This function generates an "exclusive" scan, meaning the Nth element 00441 * of the output range is the sum of the first N-1 input elements, 00442 * so the Nth input element is not included. 00443 */ 00444 template<typename _InputIterator, typename _OutputIterator, typename _Tp, 00445 typename _BinaryOperation> 00446 _OutputIterator 00447 exclusive_scan(_InputIterator __first, _InputIterator __last, 00448 _OutputIterator __result, _Tp __init, 00449 _BinaryOperation __binary_op) 00450 { 00451 while (__first != __last) 00452 { 00453 auto __v = __init; 00454 __init = __binary_op(__init, *__first); 00455 ++__first; 00456 *__result++ = std::move(__v); 00457 } 00458 return __result; 00459 } 00460 00461 /** @brief Output the cumulative sum of one range to a second range 00462 * 00463 * @param __first Start of input range. 00464 * @param __last End of input range. 00465 * @param __result Start of output range. 00466 * @param __init Initial value. 00467 * @return The end of the output range. 00468 * 00469 * Write the cumulative sum (aka prefix sum, aka scan) of the input range 00470 * to the output range. Each element of the output range contains the 00471 * running total of all earlier elements (and the initial value), 00472 * using `std::plus<>` for summation. 00473 * 00474 * This function generates an "exclusive" scan, meaning the Nth element 00475 * of the output range is the sum of the first N-1 input elements, 00476 * so the Nth input element is not included. 00477 */ 00478 template<typename _InputIterator, typename _OutputIterator, typename _Tp> 00479 inline _OutputIterator 00480 exclusive_scan(_InputIterator __first, _InputIterator __last, 00481 _OutputIterator __result, _Tp __init) 00482 { 00483 return std::exclusive_scan(__first, __last, __result, std::move(__init), 00484 plus<>()); 00485 } 00486 00487 /** @brief Output the cumulative sum of one range to a second range 00488 * 00489 * @param __first Start of input range. 00490 * @param __last End of input range. 00491 * @param __result Start of output range. 00492 * @param __binary_op Function to perform summation. 00493 * @param __init Initial value. 00494 * @return The end of the output range. 00495 * 00496 * Write the cumulative sum (aka prefix sum, aka scan) of the input range 00497 * to the output range. Each element of the output range contains the 00498 * running total of all earlier elements (and the initial value), 00499 * using `binary_op` for summation. 00500 * 00501 * This function generates an "inclusive" scan, meaning the Nth element 00502 * of the output range is the sum of the first N input elements, 00503 * so the Nth input element is included. 00504 */ 00505 template<typename _InputIterator, typename _OutputIterator, 00506 typename _BinaryOperation, typename _Tp> 00507 _OutputIterator 00508 inclusive_scan(_InputIterator __first, _InputIterator __last, 00509 _OutputIterator __result, _BinaryOperation __binary_op, 00510 _Tp __init) 00511 { 00512 for (; __first != __last; ++__first) 00513 *__result++ = __init = __binary_op(__init, *__first); 00514 return __result; 00515 } 00516 00517 /** @brief Output the cumulative sum of one range to a second range 00518 * 00519 * @param __first Start of input range. 00520 * @param __last End of input range. 00521 * @param __result Start of output range. 00522 * @param __binary_op Function to perform summation. 00523 * @return The end of the output range. 00524 * 00525 * Write the cumulative sum (aka prefix sum, aka scan) of the input range 00526 * to the output range. Each element of the output range contains the 00527 * running total of all earlier elements, using `binary_op` for summation. 00528 * 00529 * This function generates an "inclusive" scan, meaning the Nth element 00530 * of the output range is the sum of the first N input elements, 00531 * so the Nth input element is included. 00532 */ 00533 template<typename _InputIterator, typename _OutputIterator, 00534 typename _BinaryOperation> 00535 _OutputIterator 00536 inclusive_scan(_InputIterator __first, _InputIterator __last, 00537 _OutputIterator __result, _BinaryOperation __binary_op) 00538 { 00539 if (__first != __last) 00540 { 00541 auto __init = *__first; 00542 *__result++ = __init; 00543 ++__first; 00544 if (__first != __last) 00545 __result = std::inclusive_scan(__first, __last, __result, 00546 __binary_op, std::move(__init)); 00547 } 00548 return __result; 00549 } 00550 00551 /** @brief Output the cumulative sum of one range to a second range 00552 * 00553 * @param __first Start of input range. 00554 * @param __last End of input range. 00555 * @param __result Start of output range. 00556 * @return The end of the output range. 00557 * 00558 * Write the cumulative sum (aka prefix sum, aka scan) of the input range 00559 * to the output range. Each element of the output range contains the 00560 * running total of all earlier elements, using `std::plus<>` for summation. 00561 * 00562 * This function generates an "inclusive" scan, meaning the Nth element 00563 * of the output range is the sum of the first N input elements, 00564 * so the Nth input element is included. 00565 */ 00566 template<typename _InputIterator, typename _OutputIterator> 00567 inline _OutputIterator 00568 inclusive_scan(_InputIterator __first, _InputIterator __last, 00569 _OutputIterator __result) 00570 { return std::inclusive_scan(__first, __last, __result, plus<>()); } 00571 00572 /** @brief Output the cumulative sum of one range to a second range 00573 * 00574 * @param __first Start of input range. 00575 * @param __last End of input range. 00576 * @param __result Start of output range. 00577 * @param __init Initial value. 00578 * @param __binary_op Function to perform summation. 00579 * @param __unary_op Function to transform elements of the input range. 00580 * @return The end of the output range. 00581 * 00582 * Write the cumulative sum (aka prefix sum, aka scan) of the input range 00583 * to the output range. Each element of the output range contains the 00584 * running total of all earlier elements (and the initial value), 00585 * using `__unary_op` to transform the input elements 00586 * and using `__binary_op` for summation. 00587 * 00588 * This function generates an "exclusive" scan, meaning the Nth element 00589 * of the output range is the sum of the first N-1 input elements, 00590 * so the Nth input element is not included. 00591 */ 00592 template<typename _InputIterator, typename _OutputIterator, typename _Tp, 00593 typename _BinaryOperation, typename _UnaryOperation> 00594 _OutputIterator 00595 transform_exclusive_scan(_InputIterator __first, _InputIterator __last, 00596 _OutputIterator __result, _Tp __init, 00597 _BinaryOperation __binary_op, 00598 _UnaryOperation __unary_op) 00599 { 00600 while (__first != __last) 00601 { 00602 auto __v = __init; 00603 __init = __binary_op(__init, __unary_op(*__first)); 00604 ++__first; 00605 *__result++ = std::move(__v); 00606 } 00607 return __result; 00608 } 00609 00610 /** @brief Output the cumulative sum of one range to a second range 00611 * 00612 * @param __first Start of input range. 00613 * @param __last End of input range. 00614 * @param __result Start of output range. 00615 * @param __binary_op Function to perform summation. 00616 * @param __unary_op Function to transform elements of the input range. 00617 * @param __init Initial value. 00618 * @return The end of the output range. 00619 * 00620 * Write the cumulative sum (aka prefix sum, aka scan) of the input range 00621 * to the output range. Each element of the output range contains the 00622 * running total of all earlier elements (and the initial value), 00623 * using `__unary_op` to transform the input elements 00624 * and using `__binary_op` for summation. 00625 * 00626 * This function generates an "inclusive" scan, meaning the Nth element 00627 * of the output range is the sum of the first N input elements, 00628 * so the Nth input element is included. 00629 */ 00630 template<typename _InputIterator, typename _OutputIterator, 00631 typename _BinaryOperation, typename _UnaryOperation, typename _Tp> 00632 _OutputIterator 00633 transform_inclusive_scan(_InputIterator __first, _InputIterator __last, 00634 _OutputIterator __result, 00635 _BinaryOperation __binary_op, 00636 _UnaryOperation __unary_op, 00637 _Tp __init) 00638 { 00639 for (; __first != __last; ++__first) 00640 *__result++ = __init = __binary_op(__init, __unary_op(*__first)); 00641 return __result; 00642 } 00643 00644 /** @brief Output the cumulative sum of one range to a second range 00645 * 00646 * @param __first Start of input range. 00647 * @param __last End of input range. 00648 * @param __result Start of output range. 00649 * @param __binary_op Function to perform summation. 00650 * @param __unary_op Function to transform elements of the input range. 00651 * @return The end of the output range. 00652 * 00653 * Write the cumulative sum (aka prefix sum, aka scan) of the input range 00654 * to the output range. Each element of the output range contains the 00655 * running total of all earlier elements, 00656 * using `__unary_op` to transform the input elements 00657 * and using `__binary_op` for summation. 00658 * 00659 * This function generates an "inclusive" scan, meaning the Nth element 00660 * of the output range is the sum of the first N input elements, 00661 * so the Nth input element is included. 00662 */ 00663 template<typename _InputIterator, typename _OutputIterator, 00664 typename _BinaryOperation, typename _UnaryOperation> 00665 _OutputIterator 00666 transform_inclusive_scan(_InputIterator __first, _InputIterator __last, 00667 _OutputIterator __result, 00668 _BinaryOperation __binary_op, 00669 _UnaryOperation __unary_op) 00670 { 00671 if (__first != __last) 00672 { 00673 auto __init = __unary_op(*__first); 00674 *__result++ = __init; 00675 ++__first; 00676 if (__first != __last) 00677 __result = std::transform_inclusive_scan(__first, __last, __result, 00678 __binary_op, __unary_op, 00679 std::move(__init)); 00680 } 00681 return __result; 00682 } 00683 00684 // @} group numeric_ops 00685 00686 _GLIBCXX_END_NAMESPACE_VERSION 00687 } // namespace std 00688 00689 // Parallel STL algorithms 00690 # if __PSTL_EXECUTION_POLICIES_DEFINED 00691 // If <execution> has already been included, pull in implementations 00692 # include <pstl/glue_numeric_impl.h> 00693 # else 00694 // Otherwise just pull in forward declarations 00695 # include <pstl/glue_numeric_defs.h> 00696 # define __PSTL_NUMERIC_FORWARD_DECLARED 1 00697 # endif 00698 00699 // Feature test macro for parallel algorithms 00700 # define __cpp_lib_parallel_algorithm 201603L 00701 #endif // C++17 00702 00703 #endif /* _GLIBCXX_NUMERIC */