14fee23f9Smrg// <numeric> -*- C++ -*- 24fee23f9Smrg 3*b1e83836Smrg// Copyright (C) 2001-2022 Free Software Foundation, Inc. 44fee23f9Smrg// 54fee23f9Smrg// This file is part of the GNU ISO C++ Library. This library is free 64fee23f9Smrg// software; you can redistribute it and/or modify it under the 74fee23f9Smrg// terms of the GNU General Public License as published by the 84fee23f9Smrg// Free Software Foundation; either version 3, or (at your option) 94fee23f9Smrg// any later version. 104fee23f9Smrg 114fee23f9Smrg// This library is distributed in the hope that it will be useful, 124fee23f9Smrg// but WITHOUT ANY WARRANTY; without even the implied warranty of 134fee23f9Smrg// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 144fee23f9Smrg// GNU General Public License for more details. 154fee23f9Smrg 164fee23f9Smrg// Under Section 7 of GPL version 3, you are granted additional 174fee23f9Smrg// permissions described in the GCC Runtime Library Exception, version 184fee23f9Smrg// 3.1, as published by the Free Software Foundation. 194fee23f9Smrg 204fee23f9Smrg// You should have received a copy of the GNU General Public License and 214fee23f9Smrg// a copy of the GCC Runtime Library Exception along with this program; 224fee23f9Smrg// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 234fee23f9Smrg// <http://www.gnu.org/licenses/>. 244fee23f9Smrg 254fee23f9Smrg/* 264fee23f9Smrg * 274fee23f9Smrg * Copyright (c) 1994 284fee23f9Smrg * Hewlett-Packard Company 294fee23f9Smrg * 304fee23f9Smrg * Permission to use, copy, modify, distribute and sell this software 314fee23f9Smrg * and its documentation for any purpose is hereby granted without fee, 324fee23f9Smrg * provided that the above copyright notice appear in all copies and 334fee23f9Smrg * that both that copyright notice and this permission notice appear 344fee23f9Smrg * in supporting documentation. Hewlett-Packard Company makes no 354fee23f9Smrg * representations about the suitability of this software for any 364fee23f9Smrg * purpose. It is provided "as is" without express or implied warranty. 374fee23f9Smrg * 384fee23f9Smrg * 394fee23f9Smrg * Copyright (c) 1996,1997 404fee23f9Smrg * Silicon Graphics Computer Systems, Inc. 414fee23f9Smrg * 424fee23f9Smrg * Permission to use, copy, modify, distribute and sell this software 434fee23f9Smrg * and its documentation for any purpose is hereby granted without fee, 444fee23f9Smrg * provided that the above copyright notice appear in all copies and 454fee23f9Smrg * that both that copyright notice and this permission notice appear 464fee23f9Smrg * in supporting documentation. Silicon Graphics makes no 474fee23f9Smrg * representations about the suitability of this software for any 484fee23f9Smrg * purpose. It is provided "as is" without express or implied warranty. 494fee23f9Smrg */ 504fee23f9Smrg 514fee23f9Smrg/** @file include/numeric 524fee23f9Smrg * This is a Standard C++ Library header. 534fee23f9Smrg */ 544fee23f9Smrg 554fee23f9Smrg#ifndef _GLIBCXX_NUMERIC 564fee23f9Smrg#define _GLIBCXX_NUMERIC 1 574fee23f9Smrg 584fee23f9Smrg#pragma GCC system_header 594fee23f9Smrg 604fee23f9Smrg#include <bits/c++config.h> 614fee23f9Smrg#include <bits/stl_iterator_base_types.h> 624fee23f9Smrg#include <bits/stl_numeric.h> 634fee23f9Smrg 644fee23f9Smrg#ifdef _GLIBCXX_PARALLEL 654fee23f9Smrg# include <parallel/numeric> 664fee23f9Smrg#endif 674fee23f9Smrg 68*b1e83836Smrg#if __cplusplus >= 201402L 69*b1e83836Smrg# include <type_traits> 70*b1e83836Smrg# include <bit> 71*b1e83836Smrg# include <ext/numeric_traits.h> 72*b1e83836Smrg#endif 73*b1e83836Smrg 74*b1e83836Smrg#if __cplusplus >= 201703L 75*b1e83836Smrg# include <bits/stl_function.h> 76*b1e83836Smrg#endif 77*b1e83836Smrg 78*b1e83836Smrg#if __cplusplus > 201703L 79*b1e83836Smrg# include <limits> 80*b1e83836Smrg#endif 81*b1e83836Smrg 824fee23f9Smrg/** 834fee23f9Smrg * @defgroup numerics Numerics 844fee23f9Smrg * 854fee23f9Smrg * Components for performing numeric operations. Includes support for 86181254a7Smrg * complex number types, random number generation, numeric (n-at-a-time) 87181254a7Smrg * arrays, generalized numeric algorithms, and mathematical special functions. 884fee23f9Smrg */ 894fee23f9Smrg 90b17d1066Smrgnamespace std _GLIBCXX_VISIBILITY(default) 91b17d1066Smrg{ 928b6133e5Smrg_GLIBCXX_BEGIN_NAMESPACE_VERSION 938b6133e5Smrg 94*b1e83836Smrg#if __cplusplus >= 201402L 95a3e9eb18Smrgnamespace __detail 96a3e9eb18Smrg{ 977d4dc15bSmrg // Like std::abs, but supports unsigned types and returns the specified type, 987d4dc15bSmrg // so |std::numeric_limits<_Tp>::min()| is OK if representable in _Res. 997d4dc15bSmrg template<typename _Res, typename _Tp> 1007d4dc15bSmrg constexpr _Res 1017d4dc15bSmrg __abs_r(_Tp __val) 102b17d1066Smrg { 1037d4dc15bSmrg static_assert(sizeof(_Res) >= sizeof(_Tp), 104fb8a8121Smrg "result type must be at least as wide as the input type"); 1057d4dc15bSmrg 1067d4dc15bSmrg if (__val >= 0) 1077d4dc15bSmrg return __val; 108*b1e83836Smrg#ifdef _GLIBCXX_ASSERTIONS 109*b1e83836Smrg if (!__is_constant_evaluated()) // overflow already detected in constexpr 1107d4dc15bSmrg __glibcxx_assert(__val != __gnu_cxx::__int_traits<_Res>::__min); 1117d4dc15bSmrg#endif 1127d4dc15bSmrg return -static_cast<_Res>(__val); 113b17d1066Smrg } 114b17d1066Smrg 1157d4dc15bSmrg template<typename> void __abs_r(bool) = delete; 116fb8a8121Smrg 117*b1e83836Smrg // GCD implementation, using Stein's algorithm 118fb8a8121Smrg template<typename _Tp> 119fb8a8121Smrg constexpr _Tp 120fb8a8121Smrg __gcd(_Tp __m, _Tp __n) 121fb8a8121Smrg { 122fb8a8121Smrg static_assert(is_unsigned<_Tp>::value, "type must be unsigned"); 123*b1e83836Smrg 124*b1e83836Smrg if (__m == 0) 125*b1e83836Smrg return __n; 126*b1e83836Smrg if (__n == 0) 127*b1e83836Smrg return __m; 128*b1e83836Smrg 129*b1e83836Smrg const int __i = std::__countr_zero(__m); 130*b1e83836Smrg __m >>= __i; 131*b1e83836Smrg const int __j = std::__countr_zero(__n); 132*b1e83836Smrg __n >>= __j; 133*b1e83836Smrg const int __k = __i < __j ? __i : __j; // min(i, j) 134*b1e83836Smrg 135*b1e83836Smrg while (true) 136*b1e83836Smrg { 137*b1e83836Smrg if (__m > __n) 138*b1e83836Smrg { 139*b1e83836Smrg _Tp __tmp = __m; 140*b1e83836Smrg __m = __n; 141*b1e83836Smrg __n = __tmp; 142*b1e83836Smrg } 143*b1e83836Smrg 144*b1e83836Smrg __n -= __m; 145*b1e83836Smrg 146*b1e83836Smrg if (__n == 0) 147*b1e83836Smrg return __m << __k; 148*b1e83836Smrg 149*b1e83836Smrg __n >>= std::__countr_zero(__n); 150*b1e83836Smrg } 151fb8a8121Smrg } 152a3e9eb18Smrg} // namespace __detail 153b17d1066Smrg 154181254a7Smrg#if __cplusplus >= 201703L 155b17d1066Smrg 156*b1e83836Smrg#define __cpp_lib_gcd_lcm 201606L 157b17d1066Smrg// These were used in drafts of SD-6: 158*b1e83836Smrg#define __cpp_lib_gcd 201606L 159*b1e83836Smrg#define __cpp_lib_lcm 201606L 160b17d1066Smrg 161b17d1066Smrg /// Greatest common divisor 162b17d1066Smrg template<typename _Mn, typename _Nn> 163b17d1066Smrg constexpr common_type_t<_Mn, _Nn> 164fb8a8121Smrg gcd(_Mn __m, _Nn __n) noexcept 165b17d1066Smrg { 1667d4dc15bSmrg static_assert(is_integral_v<_Mn> && is_integral_v<_Nn>, 1677d4dc15bSmrg "std::gcd arguments must be integers"); 1687d4dc15bSmrg static_assert(_Mn(2) == 2 && _Nn(2) == 2, 1697d4dc15bSmrg "std::gcd arguments must not be bool"); 1707d4dc15bSmrg using _Ct = common_type_t<_Mn, _Nn>; 1717d4dc15bSmrg const _Ct __m2 = __detail::__abs_r<_Ct>(__m); 1727d4dc15bSmrg const _Ct __n2 = __detail::__abs_r<_Ct>(__n); 1737d4dc15bSmrg return __detail::__gcd<make_unsigned_t<_Ct>>(__m2, __n2); 174b17d1066Smrg } 175b17d1066Smrg 176b17d1066Smrg /// Least common multiple 177b17d1066Smrg template<typename _Mn, typename _Nn> 178b17d1066Smrg constexpr common_type_t<_Mn, _Nn> 179fb8a8121Smrg lcm(_Mn __m, _Nn __n) noexcept 180b17d1066Smrg { 1817d4dc15bSmrg static_assert(is_integral_v<_Mn> && is_integral_v<_Nn>, 1827d4dc15bSmrg "std::lcm arguments must be integers"); 1837d4dc15bSmrg static_assert(_Mn(2) == 2 && _Nn(2) == 2, 1847d4dc15bSmrg "std::lcm arguments must not be bool"); 1857d4dc15bSmrg using _Ct = common_type_t<_Mn, _Nn>; 1867d4dc15bSmrg const _Ct __m2 = __detail::__abs_r<_Ct>(__m); 1877d4dc15bSmrg const _Ct __n2 = __detail::__abs_r<_Ct>(__n); 1887d4dc15bSmrg if (__m2 == 0 || __n2 == 0) 1897d4dc15bSmrg return 0; 1907d4dc15bSmrg _Ct __r = __m2 / __detail::__gcd<make_unsigned_t<_Ct>>(__m2, __n2); 1917d4dc15bSmrg 1927d4dc15bSmrg if constexpr (is_signed_v<_Ct>) 193*b1e83836Smrg if (__is_constant_evaluated()) 1947d4dc15bSmrg return __r * __n2; // constant evaluation can detect overflow here. 1957d4dc15bSmrg 1967d4dc15bSmrg bool __overflow = __builtin_mul_overflow(__r, __n2, &__r); 1977d4dc15bSmrg __glibcxx_assert(!__overflow); 1987d4dc15bSmrg return __r; 199b17d1066Smrg } 200b17d1066Smrg 201b17d1066Smrg#endif // C++17 202b17d1066Smrg#endif // C++14 203b17d1066Smrg 204181254a7Smrg#if __cplusplus > 201703L 205181254a7Smrg 206181254a7Smrg // midpoint 207181254a7Smrg# define __cpp_lib_interpolate 201902L 208181254a7Smrg 209181254a7Smrg template<typename _Tp> 210181254a7Smrg constexpr 211181254a7Smrg enable_if_t<__and_v<is_arithmetic<_Tp>, is_same<remove_cv_t<_Tp>, _Tp>, 212181254a7Smrg __not_<is_same<_Tp, bool>>>, 213181254a7Smrg _Tp> 214181254a7Smrg midpoint(_Tp __a, _Tp __b) noexcept 215181254a7Smrg { 216181254a7Smrg if constexpr (is_integral_v<_Tp>) 217181254a7Smrg { 218181254a7Smrg using _Up = make_unsigned_t<_Tp>; 219181254a7Smrg 220181254a7Smrg int __k = 1; 221181254a7Smrg _Up __m = __a; 222181254a7Smrg _Up __M = __b; 223181254a7Smrg if (__a > __b) 224181254a7Smrg { 225181254a7Smrg __k = -1; 226181254a7Smrg __m = __b; 227181254a7Smrg __M = __a; 228181254a7Smrg } 229181254a7Smrg return __a + __k * _Tp(_Up(__M - __m) / 2); 230181254a7Smrg } 231181254a7Smrg else // is_floating 232181254a7Smrg { 233181254a7Smrg constexpr _Tp __lo = numeric_limits<_Tp>::min() * 2; 234181254a7Smrg constexpr _Tp __hi = numeric_limits<_Tp>::max() / 2; 235181254a7Smrg const _Tp __abs_a = __a < 0 ? -__a : __a; 236181254a7Smrg const _Tp __abs_b = __b < 0 ? -__b : __b; 237181254a7Smrg if (__abs_a <= __hi && __abs_b <= __hi) [[likely]] 238181254a7Smrg return (__a + __b) / 2; // always correctly rounded 239181254a7Smrg if (__abs_a < __lo) // not safe to halve __a 240181254a7Smrg return __a + __b/2; 241181254a7Smrg if (__abs_b < __lo) // not safe to halve __b 242181254a7Smrg return __a/2 + __b; 243181254a7Smrg return __a/2 + __b/2; // otherwise correctly rounded 244181254a7Smrg } 245181254a7Smrg } 246181254a7Smrg 247181254a7Smrg template<typename _Tp> 248fb8a8121Smrg constexpr enable_if_t<is_object_v<_Tp>, _Tp*> 249181254a7Smrg midpoint(_Tp* __a, _Tp* __b) noexcept 250181254a7Smrg { 251fb8a8121Smrg static_assert( sizeof(_Tp) != 0, "type must be complete" ); 252181254a7Smrg return __a + (__b - __a) / 2; 253181254a7Smrg } 254181254a7Smrg#endif // C++20 255181254a7Smrg 256*b1e83836Smrg#if __cplusplus >= 201703L 257181254a7Smrg 258fb8a8121Smrg#if __cplusplus > 201703L 259fb8a8121Smrg#define __cpp_lib_constexpr_numeric 201911L 260fb8a8121Smrg#endif 261fb8a8121Smrg 262181254a7Smrg /// @addtogroup numeric_ops 263181254a7Smrg /// @{ 264181254a7Smrg 265181254a7Smrg /** 266181254a7Smrg * @brief Calculate reduction of values in a range. 267181254a7Smrg * 268181254a7Smrg * @param __first Start of range. 269181254a7Smrg * @param __last End of range. 270181254a7Smrg * @param __init Starting value to add other values to. 271181254a7Smrg * @param __binary_op A binary function object. 272181254a7Smrg * @return The final sum. 273181254a7Smrg * 274181254a7Smrg * Reduce the values in the range `[first,last)` using a binary operation. 275181254a7Smrg * The initial value is `init`. The values are not necessarily processed 276181254a7Smrg * in order. 277181254a7Smrg * 278181254a7Smrg * This algorithm is similar to `std::accumulate` but is not required to 279181254a7Smrg * perform the operations in order from first to last. For operations 280181254a7Smrg * that are commutative and associative the result will be the same as 281181254a7Smrg * for `std::accumulate`, but for other operations (such as floating point 282181254a7Smrg * arithmetic) the result can be different. 283181254a7Smrg */ 284181254a7Smrg template<typename _InputIterator, typename _Tp, typename _BinaryOperation> 285fb8a8121Smrg _GLIBCXX20_CONSTEXPR 286181254a7Smrg _Tp 287181254a7Smrg reduce(_InputIterator __first, _InputIterator __last, _Tp __init, 288181254a7Smrg _BinaryOperation __binary_op) 289181254a7Smrg { 290a448f87cSmrg using __ref = typename iterator_traits<_InputIterator>::reference; 291a448f87cSmrg static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, _Tp&, __ref>); 292a448f87cSmrg static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, __ref, _Tp&>); 293181254a7Smrg static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, _Tp&, _Tp&>); 294a448f87cSmrg static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, __ref, __ref>); 295181254a7Smrg if constexpr (__is_random_access_iter<_InputIterator>::value) 296181254a7Smrg { 297181254a7Smrg while ((__last - __first) >= 4) 298181254a7Smrg { 299181254a7Smrg _Tp __v1 = __binary_op(__first[0], __first[1]); 300181254a7Smrg _Tp __v2 = __binary_op(__first[2], __first[3]); 301181254a7Smrg _Tp __v3 = __binary_op(__v1, __v2); 302181254a7Smrg __init = __binary_op(__init, __v3); 303181254a7Smrg __first += 4; 304181254a7Smrg } 305181254a7Smrg } 306181254a7Smrg for (; __first != __last; ++__first) 307181254a7Smrg __init = __binary_op(__init, *__first); 308181254a7Smrg return __init; 309181254a7Smrg } 310181254a7Smrg 311181254a7Smrg /** 312181254a7Smrg * @brief Calculate reduction of values in a range. 313181254a7Smrg * 314181254a7Smrg * @param __first Start of range. 315181254a7Smrg * @param __last End of range. 316181254a7Smrg * @param __init Starting value to add other values to. 317181254a7Smrg * @return The final sum. 318181254a7Smrg * 319181254a7Smrg * Reduce the values in the range `[first,last)` using addition. 320181254a7Smrg * Equivalent to calling `std::reduce(first, last, init, std::plus<>())`. 321181254a7Smrg */ 322181254a7Smrg template<typename _InputIterator, typename _Tp> 323fb8a8121Smrg _GLIBCXX20_CONSTEXPR 324181254a7Smrg inline _Tp 325181254a7Smrg reduce(_InputIterator __first, _InputIterator __last, _Tp __init) 326181254a7Smrg { return std::reduce(__first, __last, std::move(__init), plus<>()); } 327181254a7Smrg 328181254a7Smrg /** 329181254a7Smrg * @brief Calculate reduction of values in a range. 330181254a7Smrg * 331181254a7Smrg * @param __first Start of range. 332181254a7Smrg * @param __last End of range. 333181254a7Smrg * @return The final sum. 334181254a7Smrg * 335181254a7Smrg * Reduce the values in the range `[first,last)` using addition, with 336181254a7Smrg * an initial value of `T{}`, where `T` is the iterator's value type. 337181254a7Smrg * Equivalent to calling `std::reduce(first, last, T{}, std::plus<>())`. 338181254a7Smrg */ 339181254a7Smrg template<typename _InputIterator> 340fb8a8121Smrg _GLIBCXX20_CONSTEXPR 341181254a7Smrg inline typename iterator_traits<_InputIterator>::value_type 342181254a7Smrg reduce(_InputIterator __first, _InputIterator __last) 343181254a7Smrg { 344181254a7Smrg using value_type = typename iterator_traits<_InputIterator>::value_type; 345181254a7Smrg return std::reduce(__first, __last, value_type{}, plus<>()); 346181254a7Smrg } 347181254a7Smrg 348181254a7Smrg /** 349181254a7Smrg * @brief Combine elements from two ranges and reduce 350181254a7Smrg * 351181254a7Smrg * @param __first1 Start of first range. 352181254a7Smrg * @param __last1 End of first range. 353181254a7Smrg * @param __first2 Start of second range. 354181254a7Smrg * @param __init Starting value to add other values to. 355181254a7Smrg * @param __binary_op1 The function used to perform reduction. 356181254a7Smrg * @param __binary_op2 The function used to combine values from the ranges. 357181254a7Smrg * @return The final sum. 358181254a7Smrg * 359181254a7Smrg * Call `binary_op2(first1[n],first2[n])` for each `n` in `[0,last1-first1)` 360181254a7Smrg * and then use `binary_op1` to reduce the values returned by `binary_op2` 361181254a7Smrg * to a single value of type `T`. 362181254a7Smrg * 363181254a7Smrg * The range beginning at `first2` must contain at least `last1-first1` 364181254a7Smrg * elements. 365181254a7Smrg */ 366181254a7Smrg template<typename _InputIterator1, typename _InputIterator2, typename _Tp, 367181254a7Smrg typename _BinaryOperation1, typename _BinaryOperation2> 368fb8a8121Smrg _GLIBCXX20_CONSTEXPR 369181254a7Smrg _Tp 370181254a7Smrg transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1, 371181254a7Smrg _InputIterator2 __first2, _Tp __init, 372181254a7Smrg _BinaryOperation1 __binary_op1, 373181254a7Smrg _BinaryOperation2 __binary_op2) 374181254a7Smrg { 375181254a7Smrg if constexpr (__and_v<__is_random_access_iter<_InputIterator1>, 376181254a7Smrg __is_random_access_iter<_InputIterator2>>) 377181254a7Smrg { 378181254a7Smrg while ((__last1 - __first1) >= 4) 379181254a7Smrg { 380181254a7Smrg _Tp __v1 = __binary_op1(__binary_op2(__first1[0], __first2[0]), 381181254a7Smrg __binary_op2(__first1[1], __first2[1])); 382181254a7Smrg _Tp __v2 = __binary_op1(__binary_op2(__first1[2], __first2[2]), 383181254a7Smrg __binary_op2(__first1[3], __first2[3])); 384181254a7Smrg _Tp __v3 = __binary_op1(__v1, __v2); 385181254a7Smrg __init = __binary_op1(__init, __v3); 386181254a7Smrg __first1 += 4; 387181254a7Smrg __first2 += 4; 388181254a7Smrg } 389181254a7Smrg } 390181254a7Smrg for (; __first1 != __last1; ++__first1, (void) ++__first2) 391181254a7Smrg __init = __binary_op1(__init, __binary_op2(*__first1, *__first2)); 392181254a7Smrg return __init; 393181254a7Smrg } 394181254a7Smrg 395181254a7Smrg /** 396181254a7Smrg * @brief Combine elements from two ranges and reduce 397181254a7Smrg * 398181254a7Smrg * @param __first1 Start of first range. 399181254a7Smrg * @param __last1 End of first range. 400181254a7Smrg * @param __first2 Start of second range. 401181254a7Smrg * @param __init Starting value to add other values to. 402181254a7Smrg * @return The final sum. 403181254a7Smrg * 404181254a7Smrg * Call `first1[n]*first2[n]` for each `n` in `[0,last1-first1)` and then 405181254a7Smrg * use addition to sum those products to a single value of type `T`. 406181254a7Smrg * 407181254a7Smrg * The range beginning at `first2` must contain at least `last1-first1` 408181254a7Smrg * elements. 409181254a7Smrg */ 410181254a7Smrg template<typename _InputIterator1, typename _InputIterator2, typename _Tp> 411fb8a8121Smrg _GLIBCXX20_CONSTEXPR 412181254a7Smrg inline _Tp 413181254a7Smrg transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1, 414181254a7Smrg _InputIterator2 __first2, _Tp __init) 415181254a7Smrg { 416181254a7Smrg return std::transform_reduce(__first1, __last1, __first2, 417181254a7Smrg std::move(__init), 418181254a7Smrg plus<>(), multiplies<>()); 419181254a7Smrg } 420181254a7Smrg 421181254a7Smrg /** 422181254a7Smrg * @brief Transform the elements of a range and reduce 423181254a7Smrg * 424181254a7Smrg * @param __first Start of range. 425181254a7Smrg * @param __last End of range. 426181254a7Smrg * @param __init Starting value to add other values to. 427181254a7Smrg * @param __binary_op The function used to perform reduction. 428181254a7Smrg * @param __unary_op The function used to transform values from the range. 429181254a7Smrg * @return The final sum. 430181254a7Smrg * 431181254a7Smrg * Call `unary_op(first[n])` for each `n` in `[0,last-first)` and then 432181254a7Smrg * use `binary_op` to reduce the values returned by `unary_op` 433181254a7Smrg * to a single value of type `T`. 434181254a7Smrg */ 435181254a7Smrg template<typename _InputIterator, typename _Tp, 436181254a7Smrg typename _BinaryOperation, typename _UnaryOperation> 437fb8a8121Smrg _GLIBCXX20_CONSTEXPR 438181254a7Smrg _Tp 439181254a7Smrg transform_reduce(_InputIterator __first, _InputIterator __last, _Tp __init, 440181254a7Smrg _BinaryOperation __binary_op, _UnaryOperation __unary_op) 441181254a7Smrg { 442181254a7Smrg if constexpr (__is_random_access_iter<_InputIterator>::value) 443181254a7Smrg { 444181254a7Smrg while ((__last - __first) >= 4) 445181254a7Smrg { 446181254a7Smrg _Tp __v1 = __binary_op(__unary_op(__first[0]), 447181254a7Smrg __unary_op(__first[1])); 448181254a7Smrg _Tp __v2 = __binary_op(__unary_op(__first[2]), 449181254a7Smrg __unary_op(__first[3])); 450181254a7Smrg _Tp __v3 = __binary_op(__v1, __v2); 451181254a7Smrg __init = __binary_op(__init, __v3); 452181254a7Smrg __first += 4; 453181254a7Smrg } 454181254a7Smrg } 455181254a7Smrg for (; __first != __last; ++__first) 456181254a7Smrg __init = __binary_op(__init, __unary_op(*__first)); 457181254a7Smrg return __init; 458181254a7Smrg } 459181254a7Smrg 460181254a7Smrg /** @brief Output the cumulative sum of one range to a second range 461181254a7Smrg * 462181254a7Smrg * @param __first Start of input range. 463181254a7Smrg * @param __last End of input range. 464181254a7Smrg * @param __result Start of output range. 465181254a7Smrg * @param __init Initial value. 466181254a7Smrg * @param __binary_op Function to perform summation. 467181254a7Smrg * @return The end of the output range. 468181254a7Smrg * 469181254a7Smrg * Write the cumulative sum (aka prefix sum, aka scan) of the input range 470181254a7Smrg * to the output range. Each element of the output range contains the 471181254a7Smrg * running total of all earlier elements (and the initial value), 472181254a7Smrg * using `binary_op` for summation. 473181254a7Smrg * 474181254a7Smrg * This function generates an "exclusive" scan, meaning the Nth element 475181254a7Smrg * of the output range is the sum of the first N-1 input elements, 476181254a7Smrg * so the Nth input element is not included. 477181254a7Smrg */ 478181254a7Smrg template<typename _InputIterator, typename _OutputIterator, typename _Tp, 479181254a7Smrg typename _BinaryOperation> 480fb8a8121Smrg _GLIBCXX20_CONSTEXPR 481181254a7Smrg _OutputIterator 482181254a7Smrg exclusive_scan(_InputIterator __first, _InputIterator __last, 483181254a7Smrg _OutputIterator __result, _Tp __init, 484181254a7Smrg _BinaryOperation __binary_op) 485181254a7Smrg { 486181254a7Smrg while (__first != __last) 487181254a7Smrg { 488181254a7Smrg auto __v = __init; 489181254a7Smrg __init = __binary_op(__init, *__first); 490181254a7Smrg ++__first; 491181254a7Smrg *__result++ = std::move(__v); 492181254a7Smrg } 493181254a7Smrg return __result; 494181254a7Smrg } 495181254a7Smrg 496181254a7Smrg /** @brief Output the cumulative sum of one range to a second range 497181254a7Smrg * 498181254a7Smrg * @param __first Start of input range. 499181254a7Smrg * @param __last End of input range. 500181254a7Smrg * @param __result Start of output range. 501181254a7Smrg * @param __init Initial value. 502181254a7Smrg * @return The end of the output range. 503181254a7Smrg * 504181254a7Smrg * Write the cumulative sum (aka prefix sum, aka scan) of the input range 505181254a7Smrg * to the output range. Each element of the output range contains the 506181254a7Smrg * running total of all earlier elements (and the initial value), 507181254a7Smrg * using `std::plus<>` for summation. 508181254a7Smrg * 509181254a7Smrg * This function generates an "exclusive" scan, meaning the Nth element 510181254a7Smrg * of the output range is the sum of the first N-1 input elements, 511181254a7Smrg * so the Nth input element is not included. 512181254a7Smrg */ 513181254a7Smrg template<typename _InputIterator, typename _OutputIterator, typename _Tp> 514fb8a8121Smrg _GLIBCXX20_CONSTEXPR 515181254a7Smrg inline _OutputIterator 516181254a7Smrg exclusive_scan(_InputIterator __first, _InputIterator __last, 517181254a7Smrg _OutputIterator __result, _Tp __init) 518181254a7Smrg { 519181254a7Smrg return std::exclusive_scan(__first, __last, __result, std::move(__init), 520181254a7Smrg plus<>()); 521181254a7Smrg } 522181254a7Smrg 523181254a7Smrg /** @brief Output the cumulative sum of one range to a second range 524181254a7Smrg * 525181254a7Smrg * @param __first Start of input range. 526181254a7Smrg * @param __last End of input range. 527181254a7Smrg * @param __result Start of output range. 528181254a7Smrg * @param __binary_op Function to perform summation. 529181254a7Smrg * @param __init Initial value. 530181254a7Smrg * @return The end of the output range. 531181254a7Smrg * 532181254a7Smrg * Write the cumulative sum (aka prefix sum, aka scan) of the input range 533181254a7Smrg * to the output range. Each element of the output range contains the 534181254a7Smrg * running total of all earlier elements (and the initial value), 535181254a7Smrg * using `binary_op` for summation. 536181254a7Smrg * 537181254a7Smrg * This function generates an "inclusive" scan, meaning the Nth element 538181254a7Smrg * of the output range is the sum of the first N input elements, 539181254a7Smrg * so the Nth input element is included. 540181254a7Smrg */ 541181254a7Smrg template<typename _InputIterator, typename _OutputIterator, 542181254a7Smrg typename _BinaryOperation, typename _Tp> 543fb8a8121Smrg _GLIBCXX20_CONSTEXPR 544181254a7Smrg _OutputIterator 545181254a7Smrg inclusive_scan(_InputIterator __first, _InputIterator __last, 546181254a7Smrg _OutputIterator __result, _BinaryOperation __binary_op, 547181254a7Smrg _Tp __init) 548181254a7Smrg { 549181254a7Smrg for (; __first != __last; ++__first) 550181254a7Smrg *__result++ = __init = __binary_op(__init, *__first); 551181254a7Smrg return __result; 552181254a7Smrg } 553181254a7Smrg 554181254a7Smrg /** @brief Output the cumulative sum of one range to a second range 555181254a7Smrg * 556181254a7Smrg * @param __first Start of input range. 557181254a7Smrg * @param __last End of input range. 558181254a7Smrg * @param __result Start of output range. 559181254a7Smrg * @param __binary_op Function to perform summation. 560181254a7Smrg * @return The end of the output range. 561181254a7Smrg * 562181254a7Smrg * Write the cumulative sum (aka prefix sum, aka scan) of the input range 563181254a7Smrg * to the output range. Each element of the output range contains the 564181254a7Smrg * running total of all earlier elements, using `binary_op` for summation. 565181254a7Smrg * 566181254a7Smrg * This function generates an "inclusive" scan, meaning the Nth element 567181254a7Smrg * of the output range is the sum of the first N input elements, 568181254a7Smrg * so the Nth input element is included. 569181254a7Smrg */ 570181254a7Smrg template<typename _InputIterator, typename _OutputIterator, 571181254a7Smrg typename _BinaryOperation> 572fb8a8121Smrg _GLIBCXX20_CONSTEXPR 573181254a7Smrg _OutputIterator 574181254a7Smrg inclusive_scan(_InputIterator __first, _InputIterator __last, 575181254a7Smrg _OutputIterator __result, _BinaryOperation __binary_op) 576181254a7Smrg { 577181254a7Smrg if (__first != __last) 578181254a7Smrg { 579181254a7Smrg auto __init = *__first; 580181254a7Smrg *__result++ = __init; 581181254a7Smrg ++__first; 582181254a7Smrg if (__first != __last) 583181254a7Smrg __result = std::inclusive_scan(__first, __last, __result, 584181254a7Smrg __binary_op, std::move(__init)); 585181254a7Smrg } 586181254a7Smrg return __result; 587181254a7Smrg } 588181254a7Smrg 589181254a7Smrg /** @brief Output the cumulative sum of one range to a second range 590181254a7Smrg * 591181254a7Smrg * @param __first Start of input range. 592181254a7Smrg * @param __last End of input range. 593181254a7Smrg * @param __result Start of output range. 594181254a7Smrg * @return The end of the output range. 595181254a7Smrg * 596181254a7Smrg * Write the cumulative sum (aka prefix sum, aka scan) of the input range 597181254a7Smrg * to the output range. Each element of the output range contains the 598181254a7Smrg * running total of all earlier elements, using `std::plus<>` for summation. 599181254a7Smrg * 600181254a7Smrg * This function generates an "inclusive" scan, meaning the Nth element 601181254a7Smrg * of the output range is the sum of the first N input elements, 602181254a7Smrg * so the Nth input element is included. 603181254a7Smrg */ 604181254a7Smrg template<typename _InputIterator, typename _OutputIterator> 605fb8a8121Smrg _GLIBCXX20_CONSTEXPR 606181254a7Smrg inline _OutputIterator 607181254a7Smrg inclusive_scan(_InputIterator __first, _InputIterator __last, 608181254a7Smrg _OutputIterator __result) 609181254a7Smrg { return std::inclusive_scan(__first, __last, __result, plus<>()); } 610181254a7Smrg 611181254a7Smrg /** @brief Output the cumulative sum of one range to a second range 612181254a7Smrg * 613181254a7Smrg * @param __first Start of input range. 614181254a7Smrg * @param __last End of input range. 615181254a7Smrg * @param __result Start of output range. 616181254a7Smrg * @param __init Initial value. 617181254a7Smrg * @param __binary_op Function to perform summation. 618181254a7Smrg * @param __unary_op Function to transform elements of the input range. 619181254a7Smrg * @return The end of the output range. 620181254a7Smrg * 621181254a7Smrg * Write the cumulative sum (aka prefix sum, aka scan) of the input range 622181254a7Smrg * to the output range. Each element of the output range contains the 623181254a7Smrg * running total of all earlier elements (and the initial value), 624181254a7Smrg * using `__unary_op` to transform the input elements 625181254a7Smrg * and using `__binary_op` for summation. 626181254a7Smrg * 627181254a7Smrg * This function generates an "exclusive" scan, meaning the Nth element 628181254a7Smrg * of the output range is the sum of the first N-1 input elements, 629181254a7Smrg * so the Nth input element is not included. 630181254a7Smrg */ 631181254a7Smrg template<typename _InputIterator, typename _OutputIterator, typename _Tp, 632181254a7Smrg typename _BinaryOperation, typename _UnaryOperation> 633fb8a8121Smrg _GLIBCXX20_CONSTEXPR 634181254a7Smrg _OutputIterator 635181254a7Smrg transform_exclusive_scan(_InputIterator __first, _InputIterator __last, 636181254a7Smrg _OutputIterator __result, _Tp __init, 637181254a7Smrg _BinaryOperation __binary_op, 638181254a7Smrg _UnaryOperation __unary_op) 639181254a7Smrg { 640181254a7Smrg while (__first != __last) 641181254a7Smrg { 642181254a7Smrg auto __v = __init; 643181254a7Smrg __init = __binary_op(__init, __unary_op(*__first)); 644181254a7Smrg ++__first; 645181254a7Smrg *__result++ = std::move(__v); 646181254a7Smrg } 647181254a7Smrg return __result; 648181254a7Smrg } 649181254a7Smrg 650181254a7Smrg /** @brief Output the cumulative sum of one range to a second range 651181254a7Smrg * 652181254a7Smrg * @param __first Start of input range. 653181254a7Smrg * @param __last End of input range. 654181254a7Smrg * @param __result Start of output range. 655181254a7Smrg * @param __binary_op Function to perform summation. 656181254a7Smrg * @param __unary_op Function to transform elements of the input range. 657181254a7Smrg * @param __init Initial value. 658181254a7Smrg * @return The end of the output range. 659181254a7Smrg * 660181254a7Smrg * Write the cumulative sum (aka prefix sum, aka scan) of the input range 661181254a7Smrg * to the output range. Each element of the output range contains the 662181254a7Smrg * running total of all earlier elements (and the initial value), 663181254a7Smrg * using `__unary_op` to transform the input elements 664181254a7Smrg * and using `__binary_op` for summation. 665181254a7Smrg * 666181254a7Smrg * This function generates an "inclusive" scan, meaning the Nth element 667181254a7Smrg * of the output range is the sum of the first N input elements, 668181254a7Smrg * so the Nth input element is included. 669181254a7Smrg */ 670181254a7Smrg template<typename _InputIterator, typename _OutputIterator, 671181254a7Smrg typename _BinaryOperation, typename _UnaryOperation, typename _Tp> 672fb8a8121Smrg _GLIBCXX20_CONSTEXPR 673181254a7Smrg _OutputIterator 674181254a7Smrg transform_inclusive_scan(_InputIterator __first, _InputIterator __last, 675181254a7Smrg _OutputIterator __result, 676181254a7Smrg _BinaryOperation __binary_op, 677181254a7Smrg _UnaryOperation __unary_op, 678181254a7Smrg _Tp __init) 679181254a7Smrg { 680181254a7Smrg for (; __first != __last; ++__first) 681181254a7Smrg *__result++ = __init = __binary_op(__init, __unary_op(*__first)); 682181254a7Smrg return __result; 683181254a7Smrg } 684181254a7Smrg 685181254a7Smrg /** @brief Output the cumulative sum of one range to a second range 686181254a7Smrg * 687181254a7Smrg * @param __first Start of input range. 688181254a7Smrg * @param __last End of input range. 689181254a7Smrg * @param __result Start of output range. 690181254a7Smrg * @param __binary_op Function to perform summation. 691181254a7Smrg * @param __unary_op Function to transform elements of the input range. 692181254a7Smrg * @return The end of the output range. 693181254a7Smrg * 694181254a7Smrg * Write the cumulative sum (aka prefix sum, aka scan) of the input range 695181254a7Smrg * to the output range. Each element of the output range contains the 696181254a7Smrg * running total of all earlier elements, 697181254a7Smrg * using `__unary_op` to transform the input elements 698181254a7Smrg * and using `__binary_op` for summation. 699181254a7Smrg * 700181254a7Smrg * This function generates an "inclusive" scan, meaning the Nth element 701181254a7Smrg * of the output range is the sum of the first N input elements, 702181254a7Smrg * so the Nth input element is included. 703181254a7Smrg */ 704181254a7Smrg template<typename _InputIterator, typename _OutputIterator, 705181254a7Smrg typename _BinaryOperation, typename _UnaryOperation> 706fb8a8121Smrg _GLIBCXX20_CONSTEXPR 707181254a7Smrg _OutputIterator 708181254a7Smrg transform_inclusive_scan(_InputIterator __first, _InputIterator __last, 709181254a7Smrg _OutputIterator __result, 710181254a7Smrg _BinaryOperation __binary_op, 711181254a7Smrg _UnaryOperation __unary_op) 712181254a7Smrg { 713181254a7Smrg if (__first != __last) 714181254a7Smrg { 715181254a7Smrg auto __init = __unary_op(*__first); 716181254a7Smrg *__result++ = __init; 717181254a7Smrg ++__first; 718181254a7Smrg if (__first != __last) 719181254a7Smrg __result = std::transform_inclusive_scan(__first, __last, __result, 720181254a7Smrg __binary_op, __unary_op, 721181254a7Smrg std::move(__init)); 722181254a7Smrg } 723181254a7Smrg return __result; 724181254a7Smrg } 725181254a7Smrg 726a448f87cSmrg /// @} group numeric_ops 727*b1e83836Smrg#endif // C++17 728181254a7Smrg 729181254a7Smrg_GLIBCXX_END_NAMESPACE_VERSION 730181254a7Smrg} // namespace std 731181254a7Smrg 732*b1e83836Smrg#if __cplusplus >= 201703L 733181254a7Smrg// Parallel STL algorithms 734fb8a8121Smrg# if _PSTL_EXECUTION_POLICIES_DEFINED 735181254a7Smrg// If <execution> has already been included, pull in implementations 736181254a7Smrg# include <pstl/glue_numeric_impl.h> 737181254a7Smrg# else 738181254a7Smrg// Otherwise just pull in forward declarations 739181254a7Smrg# include <pstl/glue_numeric_defs.h> 740fb8a8121Smrg# define _PSTL_NUMERIC_FORWARD_DECLARED 1 741181254a7Smrg# endif 742181254a7Smrg 743181254a7Smrg// Feature test macro for parallel algorithms 744181254a7Smrg# define __cpp_lib_parallel_algorithm 201603L 745181254a7Smrg#endif // C++17 746b17d1066Smrg 7474fee23f9Smrg#endif /* _GLIBCXX_NUMERIC */ 748