11debfc3dSmrg// <numeric> -*- C++ -*- 21debfc3dSmrg 38feb0f0bSmrg// Copyright (C) 2001-2020 Free Software Foundation, Inc. 41debfc3dSmrg// 51debfc3dSmrg// This file is part of the GNU ISO C++ Library. This library is free 61debfc3dSmrg// software; you can redistribute it and/or modify it under the 71debfc3dSmrg// terms of the GNU General Public License as published by the 81debfc3dSmrg// Free Software Foundation; either version 3, or (at your option) 91debfc3dSmrg// any later version. 101debfc3dSmrg 111debfc3dSmrg// This library is distributed in the hope that it will be useful, 121debfc3dSmrg// but WITHOUT ANY WARRANTY; without even the implied warranty of 131debfc3dSmrg// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141debfc3dSmrg// GNU General Public License for more details. 151debfc3dSmrg 161debfc3dSmrg// Under Section 7 of GPL version 3, you are granted additional 171debfc3dSmrg// permissions described in the GCC Runtime Library Exception, version 181debfc3dSmrg// 3.1, as published by the Free Software Foundation. 191debfc3dSmrg 201debfc3dSmrg// You should have received a copy of the GNU General Public License and 211debfc3dSmrg// a copy of the GCC Runtime Library Exception along with this program; 221debfc3dSmrg// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 231debfc3dSmrg// <http://www.gnu.org/licenses/>. 241debfc3dSmrg 251debfc3dSmrg/* 261debfc3dSmrg * 271debfc3dSmrg * Copyright (c) 1994 281debfc3dSmrg * Hewlett-Packard Company 291debfc3dSmrg * 301debfc3dSmrg * Permission to use, copy, modify, distribute and sell this software 311debfc3dSmrg * and its documentation for any purpose is hereby granted without fee, 321debfc3dSmrg * provided that the above copyright notice appear in all copies and 331debfc3dSmrg * that both that copyright notice and this permission notice appear 341debfc3dSmrg * in supporting documentation. Hewlett-Packard Company makes no 351debfc3dSmrg * representations about the suitability of this software for any 361debfc3dSmrg * purpose. It is provided "as is" without express or implied warranty. 371debfc3dSmrg * 381debfc3dSmrg * 391debfc3dSmrg * Copyright (c) 1996,1997 401debfc3dSmrg * Silicon Graphics Computer Systems, Inc. 411debfc3dSmrg * 421debfc3dSmrg * Permission to use, copy, modify, distribute and sell this software 431debfc3dSmrg * and its documentation for any purpose is hereby granted without fee, 441debfc3dSmrg * provided that the above copyright notice appear in all copies and 451debfc3dSmrg * that both that copyright notice and this permission notice appear 461debfc3dSmrg * in supporting documentation. Silicon Graphics makes no 471debfc3dSmrg * representations about the suitability of this software for any 481debfc3dSmrg * purpose. It is provided "as is" without express or implied warranty. 491debfc3dSmrg */ 501debfc3dSmrg 511debfc3dSmrg/** @file include/numeric 521debfc3dSmrg * This is a Standard C++ Library header. 531debfc3dSmrg */ 541debfc3dSmrg 551debfc3dSmrg#ifndef _GLIBCXX_NUMERIC 561debfc3dSmrg#define _GLIBCXX_NUMERIC 1 571debfc3dSmrg 581debfc3dSmrg#pragma GCC system_header 591debfc3dSmrg 601debfc3dSmrg#include <bits/c++config.h> 611debfc3dSmrg#include <bits/stl_iterator_base_types.h> 621debfc3dSmrg#include <bits/stl_numeric.h> 638feb0f0bSmrg#include <ext/numeric_traits.h> 641debfc3dSmrg 651debfc3dSmrg#ifdef _GLIBCXX_PARALLEL 661debfc3dSmrg# include <parallel/numeric> 671debfc3dSmrg#endif 681debfc3dSmrg 691debfc3dSmrg/** 701debfc3dSmrg * @defgroup numerics Numerics 711debfc3dSmrg * 721debfc3dSmrg * Components for performing numeric operations. Includes support for 73c0a68be4Smrg * complex number types, random number generation, numeric (n-at-a-time) 74c0a68be4Smrg * arrays, generalized numeric algorithms, and mathematical special functions. 751debfc3dSmrg */ 761debfc3dSmrg 771debfc3dSmrg#if __cplusplus >= 201402L 781debfc3dSmrg#include <type_traits> 79*23f5f463Smrg#include <ext/numeric_traits.h> 801debfc3dSmrg 811debfc3dSmrgnamespace std _GLIBCXX_VISIBILITY(default) 821debfc3dSmrg{ 831debfc3dSmrg_GLIBCXX_BEGIN_NAMESPACE_VERSION 841debfc3dSmrg 85a2dc1f3fSmrgnamespace __detail 86a2dc1f3fSmrg{ 87*23f5f463Smrg // Like std::abs, but supports unsigned types and returns the specified type, 88*23f5f463Smrg // so |std::numeric_limits<_Tp>::min()| is OK if representable in _Res. 89*23f5f463Smrg template<typename _Res, typename _Tp> 90*23f5f463Smrg constexpr _Res 91*23f5f463Smrg __abs_r(_Tp __val) 921debfc3dSmrg { 93*23f5f463Smrg static_assert(sizeof(_Res) >= sizeof(_Tp), 948feb0f0bSmrg "result type must be at least as wide as the input type"); 95*23f5f463Smrg 96*23f5f463Smrg if (__val >= 0) 97*23f5f463Smrg return __val; 98*23f5f463Smrg#if defined _GLIBCXX_ASSERTIONS && defined _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED 99*23f5f463Smrg if (!__builtin_is_constant_evaluated()) // overflow already detected in constexpr 100*23f5f463Smrg __glibcxx_assert(__val != __gnu_cxx::__int_traits<_Res>::__min); 101*23f5f463Smrg#endif 102*23f5f463Smrg return -static_cast<_Res>(__val); 1031debfc3dSmrg } 1041debfc3dSmrg 105*23f5f463Smrg template<typename> void __abs_r(bool) = delete; 1068feb0f0bSmrg 1078feb0f0bSmrg // GCD implementation 1088feb0f0bSmrg template<typename _Tp> 1098feb0f0bSmrg constexpr _Tp 1108feb0f0bSmrg __gcd(_Tp __m, _Tp __n) 1118feb0f0bSmrg { 1128feb0f0bSmrg static_assert(is_unsigned<_Tp>::value, "type must be unsigned"); 1138feb0f0bSmrg return __m == 0 ? __n 1148feb0f0bSmrg : __n == 0 ? __m 1158feb0f0bSmrg : __detail::__gcd(__n, _Tp(__m % __n)); 1168feb0f0bSmrg } 117a2dc1f3fSmrg} // namespace __detail 1181debfc3dSmrg 119c0a68be4Smrg#if __cplusplus >= 201703L 1201debfc3dSmrg 1211debfc3dSmrg#define __cpp_lib_gcd_lcm 201606 1221debfc3dSmrg// These were used in drafts of SD-6: 1231debfc3dSmrg#define __cpp_lib_gcd 201606 1241debfc3dSmrg#define __cpp_lib_lcm 201606 1251debfc3dSmrg 1261debfc3dSmrg /// Greatest common divisor 1271debfc3dSmrg template<typename _Mn, typename _Nn> 1281debfc3dSmrg constexpr common_type_t<_Mn, _Nn> 1298feb0f0bSmrg gcd(_Mn __m, _Nn __n) noexcept 1301debfc3dSmrg { 131*23f5f463Smrg static_assert(is_integral_v<_Mn> && is_integral_v<_Nn>, 132*23f5f463Smrg "std::gcd arguments must be integers"); 133*23f5f463Smrg static_assert(_Mn(2) == 2 && _Nn(2) == 2, 134*23f5f463Smrg "std::gcd arguments must not be bool"); 135*23f5f463Smrg using _Ct = common_type_t<_Mn, _Nn>; 136*23f5f463Smrg const _Ct __m2 = __detail::__abs_r<_Ct>(__m); 137*23f5f463Smrg const _Ct __n2 = __detail::__abs_r<_Ct>(__n); 138*23f5f463Smrg return __detail::__gcd<make_unsigned_t<_Ct>>(__m2, __n2); 1391debfc3dSmrg } 1401debfc3dSmrg 1411debfc3dSmrg /// Least common multiple 1421debfc3dSmrg template<typename _Mn, typename _Nn> 1431debfc3dSmrg constexpr common_type_t<_Mn, _Nn> 1448feb0f0bSmrg lcm(_Mn __m, _Nn __n) noexcept 1451debfc3dSmrg { 146*23f5f463Smrg static_assert(is_integral_v<_Mn> && is_integral_v<_Nn>, 147*23f5f463Smrg "std::lcm arguments must be integers"); 148*23f5f463Smrg static_assert(_Mn(2) == 2 && _Nn(2) == 2, 149*23f5f463Smrg "std::lcm arguments must not be bool"); 150*23f5f463Smrg using _Ct = common_type_t<_Mn, _Nn>; 151*23f5f463Smrg const _Ct __m2 = __detail::__abs_r<_Ct>(__m); 152*23f5f463Smrg const _Ct __n2 = __detail::__abs_r<_Ct>(__n); 153*23f5f463Smrg if (__m2 == 0 || __n2 == 0) 154*23f5f463Smrg return 0; 155*23f5f463Smrg _Ct __r = __m2 / __detail::__gcd<make_unsigned_t<_Ct>>(__m2, __n2); 156*23f5f463Smrg 157*23f5f463Smrg#if defined _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED 158*23f5f463Smrg if constexpr (is_signed_v<_Ct>) 159*23f5f463Smrg if (__builtin_is_constant_evaluated()) 160*23f5f463Smrg return __r * __n2; // constant evaluation can detect overflow here. 161*23f5f463Smrg#endif 162*23f5f463Smrg 163*23f5f463Smrg bool __overflow = __builtin_mul_overflow(__r, __n2, &__r); 164*23f5f463Smrg#if defined _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED 165*23f5f463Smrg if (__builtin_is_constant_evaluated()) 166*23f5f463Smrg if (__overflow) 167*23f5f463Smrg _GLIBCXX_THROW_OR_ABORT("std::lcm result is out of range of type"); 168*23f5f463Smrg#endif 169*23f5f463Smrg __glibcxx_assert(!__overflow); 170*23f5f463Smrg return __r; 1711debfc3dSmrg } 1721debfc3dSmrg 1731debfc3dSmrg#endif // C++17 1741debfc3dSmrg 1751debfc3dSmrg_GLIBCXX_END_NAMESPACE_VERSION 1761debfc3dSmrg} // namespace std 1771debfc3dSmrg 1781debfc3dSmrg#endif // C++14 1791debfc3dSmrg 180c0a68be4Smrg#if __cplusplus > 201703L 181c0a68be4Smrg#include <limits> 182c0a68be4Smrg 183c0a68be4Smrgnamespace std _GLIBCXX_VISIBILITY(default) 184c0a68be4Smrg{ 185c0a68be4Smrg_GLIBCXX_BEGIN_NAMESPACE_VERSION 186c0a68be4Smrg // midpoint 187c0a68be4Smrg# define __cpp_lib_interpolate 201902L 188c0a68be4Smrg 189c0a68be4Smrg template<typename _Tp> 190c0a68be4Smrg constexpr 191c0a68be4Smrg enable_if_t<__and_v<is_arithmetic<_Tp>, is_same<remove_cv_t<_Tp>, _Tp>, 192c0a68be4Smrg __not_<is_same<_Tp, bool>>>, 193c0a68be4Smrg _Tp> 194c0a68be4Smrg midpoint(_Tp __a, _Tp __b) noexcept 195c0a68be4Smrg { 196c0a68be4Smrg if constexpr (is_integral_v<_Tp>) 197c0a68be4Smrg { 198c0a68be4Smrg using _Up = make_unsigned_t<_Tp>; 199c0a68be4Smrg 200c0a68be4Smrg int __k = 1; 201c0a68be4Smrg _Up __m = __a; 202c0a68be4Smrg _Up __M = __b; 203c0a68be4Smrg if (__a > __b) 204c0a68be4Smrg { 205c0a68be4Smrg __k = -1; 206c0a68be4Smrg __m = __b; 207c0a68be4Smrg __M = __a; 208c0a68be4Smrg } 209c0a68be4Smrg return __a + __k * _Tp(_Up(__M - __m) / 2); 210c0a68be4Smrg } 211c0a68be4Smrg else // is_floating 212c0a68be4Smrg { 213c0a68be4Smrg constexpr _Tp __lo = numeric_limits<_Tp>::min() * 2; 214c0a68be4Smrg constexpr _Tp __hi = numeric_limits<_Tp>::max() / 2; 215c0a68be4Smrg const _Tp __abs_a = __a < 0 ? -__a : __a; 216c0a68be4Smrg const _Tp __abs_b = __b < 0 ? -__b : __b; 217c0a68be4Smrg if (__abs_a <= __hi && __abs_b <= __hi) [[likely]] 218c0a68be4Smrg return (__a + __b) / 2; // always correctly rounded 219c0a68be4Smrg if (__abs_a < __lo) // not safe to halve __a 220c0a68be4Smrg return __a + __b/2; 221c0a68be4Smrg if (__abs_b < __lo) // not safe to halve __b 222c0a68be4Smrg return __a/2 + __b; 223c0a68be4Smrg return __a/2 + __b/2; // otherwise correctly rounded 224c0a68be4Smrg } 225c0a68be4Smrg } 226c0a68be4Smrg 227c0a68be4Smrg template<typename _Tp> 2288feb0f0bSmrg constexpr enable_if_t<is_object_v<_Tp>, _Tp*> 229c0a68be4Smrg midpoint(_Tp* __a, _Tp* __b) noexcept 230c0a68be4Smrg { 2318feb0f0bSmrg static_assert( sizeof(_Tp) != 0, "type must be complete" ); 232c0a68be4Smrg return __a + (__b - __a) / 2; 233c0a68be4Smrg } 234c0a68be4Smrg_GLIBCXX_END_NAMESPACE_VERSION 235c0a68be4Smrg} // namespace std 236c0a68be4Smrg 237c0a68be4Smrg#endif // C++20 238c0a68be4Smrg 239c0a68be4Smrg#if __cplusplus > 201402L 240c0a68be4Smrg#include <bits/stl_function.h> 241c0a68be4Smrg 242c0a68be4Smrgnamespace std _GLIBCXX_VISIBILITY(default) 243c0a68be4Smrg{ 244c0a68be4Smrg_GLIBCXX_BEGIN_NAMESPACE_VERSION 245c0a68be4Smrg 2468feb0f0bSmrg#if __cplusplus > 201703L 2478feb0f0bSmrg#define __cpp_lib_constexpr_numeric 201911L 2488feb0f0bSmrg#endif 2498feb0f0bSmrg 250c0a68be4Smrg /// @addtogroup numeric_ops 251c0a68be4Smrg /// @{ 252c0a68be4Smrg 253c0a68be4Smrg /** 254c0a68be4Smrg * @brief Calculate reduction of values in a range. 255c0a68be4Smrg * 256c0a68be4Smrg * @param __first Start of range. 257c0a68be4Smrg * @param __last End of range. 258c0a68be4Smrg * @param __init Starting value to add other values to. 259c0a68be4Smrg * @param __binary_op A binary function object. 260c0a68be4Smrg * @return The final sum. 261c0a68be4Smrg * 262c0a68be4Smrg * Reduce the values in the range `[first,last)` using a binary operation. 263c0a68be4Smrg * The initial value is `init`. The values are not necessarily processed 264c0a68be4Smrg * in order. 265c0a68be4Smrg * 266c0a68be4Smrg * This algorithm is similar to `std::accumulate` but is not required to 267c0a68be4Smrg * perform the operations in order from first to last. For operations 268c0a68be4Smrg * that are commutative and associative the result will be the same as 269c0a68be4Smrg * for `std::accumulate`, but for other operations (such as floating point 270c0a68be4Smrg * arithmetic) the result can be different. 271c0a68be4Smrg */ 272c0a68be4Smrg template<typename _InputIterator, typename _Tp, typename _BinaryOperation> 2738feb0f0bSmrg _GLIBCXX20_CONSTEXPR 274c0a68be4Smrg _Tp 275c0a68be4Smrg reduce(_InputIterator __first, _InputIterator __last, _Tp __init, 276c0a68be4Smrg _BinaryOperation __binary_op) 277c0a68be4Smrg { 2788feb0f0bSmrg using __ref = typename iterator_traits<_InputIterator>::reference; 2798feb0f0bSmrg static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, _Tp&, __ref>); 2808feb0f0bSmrg static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, __ref, _Tp&>); 281c0a68be4Smrg static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, _Tp&, _Tp&>); 2828feb0f0bSmrg static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, __ref, __ref>); 283c0a68be4Smrg if constexpr (__is_random_access_iter<_InputIterator>::value) 284c0a68be4Smrg { 285c0a68be4Smrg while ((__last - __first) >= 4) 286c0a68be4Smrg { 287c0a68be4Smrg _Tp __v1 = __binary_op(__first[0], __first[1]); 288c0a68be4Smrg _Tp __v2 = __binary_op(__first[2], __first[3]); 289c0a68be4Smrg _Tp __v3 = __binary_op(__v1, __v2); 290c0a68be4Smrg __init = __binary_op(__init, __v3); 291c0a68be4Smrg __first += 4; 292c0a68be4Smrg } 293c0a68be4Smrg } 294c0a68be4Smrg for (; __first != __last; ++__first) 295c0a68be4Smrg __init = __binary_op(__init, *__first); 296c0a68be4Smrg return __init; 297c0a68be4Smrg } 298c0a68be4Smrg 299c0a68be4Smrg /** 300c0a68be4Smrg * @brief Calculate reduction of values in a range. 301c0a68be4Smrg * 302c0a68be4Smrg * @param __first Start of range. 303c0a68be4Smrg * @param __last End of range. 304c0a68be4Smrg * @param __init Starting value to add other values to. 305c0a68be4Smrg * @return The final sum. 306c0a68be4Smrg * 307c0a68be4Smrg * Reduce the values in the range `[first,last)` using addition. 308c0a68be4Smrg * Equivalent to calling `std::reduce(first, last, init, std::plus<>())`. 309c0a68be4Smrg */ 310c0a68be4Smrg template<typename _InputIterator, typename _Tp> 3118feb0f0bSmrg _GLIBCXX20_CONSTEXPR 312c0a68be4Smrg inline _Tp 313c0a68be4Smrg reduce(_InputIterator __first, _InputIterator __last, _Tp __init) 314c0a68be4Smrg { return std::reduce(__first, __last, std::move(__init), plus<>()); } 315c0a68be4Smrg 316c0a68be4Smrg /** 317c0a68be4Smrg * @brief Calculate reduction of values in a range. 318c0a68be4Smrg * 319c0a68be4Smrg * @param __first Start of range. 320c0a68be4Smrg * @param __last End of range. 321c0a68be4Smrg * @return The final sum. 322c0a68be4Smrg * 323c0a68be4Smrg * Reduce the values in the range `[first,last)` using addition, with 324c0a68be4Smrg * an initial value of `T{}`, where `T` is the iterator's value type. 325c0a68be4Smrg * Equivalent to calling `std::reduce(first, last, T{}, std::plus<>())`. 326c0a68be4Smrg */ 327c0a68be4Smrg template<typename _InputIterator> 3288feb0f0bSmrg _GLIBCXX20_CONSTEXPR 329c0a68be4Smrg inline typename iterator_traits<_InputIterator>::value_type 330c0a68be4Smrg reduce(_InputIterator __first, _InputIterator __last) 331c0a68be4Smrg { 332c0a68be4Smrg using value_type = typename iterator_traits<_InputIterator>::value_type; 333c0a68be4Smrg return std::reduce(__first, __last, value_type{}, plus<>()); 334c0a68be4Smrg } 335c0a68be4Smrg 336c0a68be4Smrg /** 337c0a68be4Smrg * @brief Combine elements from two ranges and reduce 338c0a68be4Smrg * 339c0a68be4Smrg * @param __first1 Start of first range. 340c0a68be4Smrg * @param __last1 End of first range. 341c0a68be4Smrg * @param __first2 Start of second range. 342c0a68be4Smrg * @param __init Starting value to add other values to. 343c0a68be4Smrg * @param __binary_op1 The function used to perform reduction. 344c0a68be4Smrg * @param __binary_op2 The function used to combine values from the ranges. 345c0a68be4Smrg * @return The final sum. 346c0a68be4Smrg * 347c0a68be4Smrg * Call `binary_op2(first1[n],first2[n])` for each `n` in `[0,last1-first1)` 348c0a68be4Smrg * and then use `binary_op1` to reduce the values returned by `binary_op2` 349c0a68be4Smrg * to a single value of type `T`. 350c0a68be4Smrg * 351c0a68be4Smrg * The range beginning at `first2` must contain at least `last1-first1` 352c0a68be4Smrg * elements. 353c0a68be4Smrg */ 354c0a68be4Smrg template<typename _InputIterator1, typename _InputIterator2, typename _Tp, 355c0a68be4Smrg typename _BinaryOperation1, typename _BinaryOperation2> 3568feb0f0bSmrg _GLIBCXX20_CONSTEXPR 357c0a68be4Smrg _Tp 358c0a68be4Smrg transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1, 359c0a68be4Smrg _InputIterator2 __first2, _Tp __init, 360c0a68be4Smrg _BinaryOperation1 __binary_op1, 361c0a68be4Smrg _BinaryOperation2 __binary_op2) 362c0a68be4Smrg { 363c0a68be4Smrg if constexpr (__and_v<__is_random_access_iter<_InputIterator1>, 364c0a68be4Smrg __is_random_access_iter<_InputIterator2>>) 365c0a68be4Smrg { 366c0a68be4Smrg while ((__last1 - __first1) >= 4) 367c0a68be4Smrg { 368c0a68be4Smrg _Tp __v1 = __binary_op1(__binary_op2(__first1[0], __first2[0]), 369c0a68be4Smrg __binary_op2(__first1[1], __first2[1])); 370c0a68be4Smrg _Tp __v2 = __binary_op1(__binary_op2(__first1[2], __first2[2]), 371c0a68be4Smrg __binary_op2(__first1[3], __first2[3])); 372c0a68be4Smrg _Tp __v3 = __binary_op1(__v1, __v2); 373c0a68be4Smrg __init = __binary_op1(__init, __v3); 374c0a68be4Smrg __first1 += 4; 375c0a68be4Smrg __first2 += 4; 376c0a68be4Smrg } 377c0a68be4Smrg } 378c0a68be4Smrg for (; __first1 != __last1; ++__first1, (void) ++__first2) 379c0a68be4Smrg __init = __binary_op1(__init, __binary_op2(*__first1, *__first2)); 380c0a68be4Smrg return __init; 381c0a68be4Smrg } 382c0a68be4Smrg 383c0a68be4Smrg /** 384c0a68be4Smrg * @brief Combine elements from two ranges and reduce 385c0a68be4Smrg * 386c0a68be4Smrg * @param __first1 Start of first range. 387c0a68be4Smrg * @param __last1 End of first range. 388c0a68be4Smrg * @param __first2 Start of second range. 389c0a68be4Smrg * @param __init Starting value to add other values to. 390c0a68be4Smrg * @return The final sum. 391c0a68be4Smrg * 392c0a68be4Smrg * Call `first1[n]*first2[n]` for each `n` in `[0,last1-first1)` and then 393c0a68be4Smrg * use addition to sum those products to a single value of type `T`. 394c0a68be4Smrg * 395c0a68be4Smrg * The range beginning at `first2` must contain at least `last1-first1` 396c0a68be4Smrg * elements. 397c0a68be4Smrg */ 398c0a68be4Smrg template<typename _InputIterator1, typename _InputIterator2, typename _Tp> 3998feb0f0bSmrg _GLIBCXX20_CONSTEXPR 400c0a68be4Smrg inline _Tp 401c0a68be4Smrg transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1, 402c0a68be4Smrg _InputIterator2 __first2, _Tp __init) 403c0a68be4Smrg { 404c0a68be4Smrg return std::transform_reduce(__first1, __last1, __first2, 405c0a68be4Smrg std::move(__init), 406c0a68be4Smrg plus<>(), multiplies<>()); 407c0a68be4Smrg } 408c0a68be4Smrg 409c0a68be4Smrg /** 410c0a68be4Smrg * @brief Transform the elements of a range and reduce 411c0a68be4Smrg * 412c0a68be4Smrg * @param __first Start of range. 413c0a68be4Smrg * @param __last End of range. 414c0a68be4Smrg * @param __init Starting value to add other values to. 415c0a68be4Smrg * @param __binary_op The function used to perform reduction. 416c0a68be4Smrg * @param __unary_op The function used to transform values from the range. 417c0a68be4Smrg * @return The final sum. 418c0a68be4Smrg * 419c0a68be4Smrg * Call `unary_op(first[n])` for each `n` in `[0,last-first)` and then 420c0a68be4Smrg * use `binary_op` to reduce the values returned by `unary_op` 421c0a68be4Smrg * to a single value of type `T`. 422c0a68be4Smrg */ 423c0a68be4Smrg template<typename _InputIterator, typename _Tp, 424c0a68be4Smrg typename _BinaryOperation, typename _UnaryOperation> 4258feb0f0bSmrg _GLIBCXX20_CONSTEXPR 426c0a68be4Smrg _Tp 427c0a68be4Smrg transform_reduce(_InputIterator __first, _InputIterator __last, _Tp __init, 428c0a68be4Smrg _BinaryOperation __binary_op, _UnaryOperation __unary_op) 429c0a68be4Smrg { 430c0a68be4Smrg if constexpr (__is_random_access_iter<_InputIterator>::value) 431c0a68be4Smrg { 432c0a68be4Smrg while ((__last - __first) >= 4) 433c0a68be4Smrg { 434c0a68be4Smrg _Tp __v1 = __binary_op(__unary_op(__first[0]), 435c0a68be4Smrg __unary_op(__first[1])); 436c0a68be4Smrg _Tp __v2 = __binary_op(__unary_op(__first[2]), 437c0a68be4Smrg __unary_op(__first[3])); 438c0a68be4Smrg _Tp __v3 = __binary_op(__v1, __v2); 439c0a68be4Smrg __init = __binary_op(__init, __v3); 440c0a68be4Smrg __first += 4; 441c0a68be4Smrg } 442c0a68be4Smrg } 443c0a68be4Smrg for (; __first != __last; ++__first) 444c0a68be4Smrg __init = __binary_op(__init, __unary_op(*__first)); 445c0a68be4Smrg return __init; 446c0a68be4Smrg } 447c0a68be4Smrg 448c0a68be4Smrg /** @brief Output the cumulative sum of one range to a second range 449c0a68be4Smrg * 450c0a68be4Smrg * @param __first Start of input range. 451c0a68be4Smrg * @param __last End of input range. 452c0a68be4Smrg * @param __result Start of output range. 453c0a68be4Smrg * @param __init Initial value. 454c0a68be4Smrg * @param __binary_op Function to perform summation. 455c0a68be4Smrg * @return The end of the output range. 456c0a68be4Smrg * 457c0a68be4Smrg * Write the cumulative sum (aka prefix sum, aka scan) of the input range 458c0a68be4Smrg * to the output range. Each element of the output range contains the 459c0a68be4Smrg * running total of all earlier elements (and the initial value), 460c0a68be4Smrg * using `binary_op` for summation. 461c0a68be4Smrg * 462c0a68be4Smrg * This function generates an "exclusive" scan, meaning the Nth element 463c0a68be4Smrg * of the output range is the sum of the first N-1 input elements, 464c0a68be4Smrg * so the Nth input element is not included. 465c0a68be4Smrg */ 466c0a68be4Smrg template<typename _InputIterator, typename _OutputIterator, typename _Tp, 467c0a68be4Smrg typename _BinaryOperation> 4688feb0f0bSmrg _GLIBCXX20_CONSTEXPR 469c0a68be4Smrg _OutputIterator 470c0a68be4Smrg exclusive_scan(_InputIterator __first, _InputIterator __last, 471c0a68be4Smrg _OutputIterator __result, _Tp __init, 472c0a68be4Smrg _BinaryOperation __binary_op) 473c0a68be4Smrg { 474c0a68be4Smrg while (__first != __last) 475c0a68be4Smrg { 476c0a68be4Smrg auto __v = __init; 477c0a68be4Smrg __init = __binary_op(__init, *__first); 478c0a68be4Smrg ++__first; 479c0a68be4Smrg *__result++ = std::move(__v); 480c0a68be4Smrg } 481c0a68be4Smrg return __result; 482c0a68be4Smrg } 483c0a68be4Smrg 484c0a68be4Smrg /** @brief Output the cumulative sum of one range to a second range 485c0a68be4Smrg * 486c0a68be4Smrg * @param __first Start of input range. 487c0a68be4Smrg * @param __last End of input range. 488c0a68be4Smrg * @param __result Start of output range. 489c0a68be4Smrg * @param __init Initial value. 490c0a68be4Smrg * @return The end of the output range. 491c0a68be4Smrg * 492c0a68be4Smrg * Write the cumulative sum (aka prefix sum, aka scan) of the input range 493c0a68be4Smrg * to the output range. Each element of the output range contains the 494c0a68be4Smrg * running total of all earlier elements (and the initial value), 495c0a68be4Smrg * using `std::plus<>` for summation. 496c0a68be4Smrg * 497c0a68be4Smrg * This function generates an "exclusive" scan, meaning the Nth element 498c0a68be4Smrg * of the output range is the sum of the first N-1 input elements, 499c0a68be4Smrg * so the Nth input element is not included. 500c0a68be4Smrg */ 501c0a68be4Smrg template<typename _InputIterator, typename _OutputIterator, typename _Tp> 5028feb0f0bSmrg _GLIBCXX20_CONSTEXPR 503c0a68be4Smrg inline _OutputIterator 504c0a68be4Smrg exclusive_scan(_InputIterator __first, _InputIterator __last, 505c0a68be4Smrg _OutputIterator __result, _Tp __init) 506c0a68be4Smrg { 507c0a68be4Smrg return std::exclusive_scan(__first, __last, __result, std::move(__init), 508c0a68be4Smrg plus<>()); 509c0a68be4Smrg } 510c0a68be4Smrg 511c0a68be4Smrg /** @brief Output the cumulative sum of one range to a second range 512c0a68be4Smrg * 513c0a68be4Smrg * @param __first Start of input range. 514c0a68be4Smrg * @param __last End of input range. 515c0a68be4Smrg * @param __result Start of output range. 516c0a68be4Smrg * @param __binary_op Function to perform summation. 517c0a68be4Smrg * @param __init Initial value. 518c0a68be4Smrg * @return The end of the output range. 519c0a68be4Smrg * 520c0a68be4Smrg * Write the cumulative sum (aka prefix sum, aka scan) of the input range 521c0a68be4Smrg * to the output range. Each element of the output range contains the 522c0a68be4Smrg * running total of all earlier elements (and the initial value), 523c0a68be4Smrg * using `binary_op` for summation. 524c0a68be4Smrg * 525c0a68be4Smrg * This function generates an "inclusive" scan, meaning the Nth element 526c0a68be4Smrg * of the output range is the sum of the first N input elements, 527c0a68be4Smrg * so the Nth input element is included. 528c0a68be4Smrg */ 529c0a68be4Smrg template<typename _InputIterator, typename _OutputIterator, 530c0a68be4Smrg typename _BinaryOperation, typename _Tp> 5318feb0f0bSmrg _GLIBCXX20_CONSTEXPR 532c0a68be4Smrg _OutputIterator 533c0a68be4Smrg inclusive_scan(_InputIterator __first, _InputIterator __last, 534c0a68be4Smrg _OutputIterator __result, _BinaryOperation __binary_op, 535c0a68be4Smrg _Tp __init) 536c0a68be4Smrg { 537c0a68be4Smrg for (; __first != __last; ++__first) 538c0a68be4Smrg *__result++ = __init = __binary_op(__init, *__first); 539c0a68be4Smrg return __result; 540c0a68be4Smrg } 541c0a68be4Smrg 542c0a68be4Smrg /** @brief Output the cumulative sum of one range to a second range 543c0a68be4Smrg * 544c0a68be4Smrg * @param __first Start of input range. 545c0a68be4Smrg * @param __last End of input range. 546c0a68be4Smrg * @param __result Start of output range. 547c0a68be4Smrg * @param __binary_op Function to perform summation. 548c0a68be4Smrg * @return The end of the output range. 549c0a68be4Smrg * 550c0a68be4Smrg * Write the cumulative sum (aka prefix sum, aka scan) of the input range 551c0a68be4Smrg * to the output range. Each element of the output range contains the 552c0a68be4Smrg * running total of all earlier elements, using `binary_op` for summation. 553c0a68be4Smrg * 554c0a68be4Smrg * This function generates an "inclusive" scan, meaning the Nth element 555c0a68be4Smrg * of the output range is the sum of the first N input elements, 556c0a68be4Smrg * so the Nth input element is included. 557c0a68be4Smrg */ 558c0a68be4Smrg template<typename _InputIterator, typename _OutputIterator, 559c0a68be4Smrg typename _BinaryOperation> 5608feb0f0bSmrg _GLIBCXX20_CONSTEXPR 561c0a68be4Smrg _OutputIterator 562c0a68be4Smrg inclusive_scan(_InputIterator __first, _InputIterator __last, 563c0a68be4Smrg _OutputIterator __result, _BinaryOperation __binary_op) 564c0a68be4Smrg { 565c0a68be4Smrg if (__first != __last) 566c0a68be4Smrg { 567c0a68be4Smrg auto __init = *__first; 568c0a68be4Smrg *__result++ = __init; 569c0a68be4Smrg ++__first; 570c0a68be4Smrg if (__first != __last) 571c0a68be4Smrg __result = std::inclusive_scan(__first, __last, __result, 572c0a68be4Smrg __binary_op, std::move(__init)); 573c0a68be4Smrg } 574c0a68be4Smrg return __result; 575c0a68be4Smrg } 576c0a68be4Smrg 577c0a68be4Smrg /** @brief Output the cumulative sum of one range to a second range 578c0a68be4Smrg * 579c0a68be4Smrg * @param __first Start of input range. 580c0a68be4Smrg * @param __last End of input range. 581c0a68be4Smrg * @param __result Start of output range. 582c0a68be4Smrg * @return The end of the output range. 583c0a68be4Smrg * 584c0a68be4Smrg * Write the cumulative sum (aka prefix sum, aka scan) of the input range 585c0a68be4Smrg * to the output range. Each element of the output range contains the 586c0a68be4Smrg * running total of all earlier elements, using `std::plus<>` for summation. 587c0a68be4Smrg * 588c0a68be4Smrg * This function generates an "inclusive" scan, meaning the Nth element 589c0a68be4Smrg * of the output range is the sum of the first N input elements, 590c0a68be4Smrg * so the Nth input element is included. 591c0a68be4Smrg */ 592c0a68be4Smrg template<typename _InputIterator, typename _OutputIterator> 5938feb0f0bSmrg _GLIBCXX20_CONSTEXPR 594c0a68be4Smrg inline _OutputIterator 595c0a68be4Smrg inclusive_scan(_InputIterator __first, _InputIterator __last, 596c0a68be4Smrg _OutputIterator __result) 597c0a68be4Smrg { return std::inclusive_scan(__first, __last, __result, plus<>()); } 598c0a68be4Smrg 599c0a68be4Smrg /** @brief Output the cumulative sum of one range to a second range 600c0a68be4Smrg * 601c0a68be4Smrg * @param __first Start of input range. 602c0a68be4Smrg * @param __last End of input range. 603c0a68be4Smrg * @param __result Start of output range. 604c0a68be4Smrg * @param __init Initial value. 605c0a68be4Smrg * @param __binary_op Function to perform summation. 606c0a68be4Smrg * @param __unary_op Function to transform elements of the input range. 607c0a68be4Smrg * @return The end of the output range. 608c0a68be4Smrg * 609c0a68be4Smrg * Write the cumulative sum (aka prefix sum, aka scan) of the input range 610c0a68be4Smrg * to the output range. Each element of the output range contains the 611c0a68be4Smrg * running total of all earlier elements (and the initial value), 612c0a68be4Smrg * using `__unary_op` to transform the input elements 613c0a68be4Smrg * and using `__binary_op` for summation. 614c0a68be4Smrg * 615c0a68be4Smrg * This function generates an "exclusive" scan, meaning the Nth element 616c0a68be4Smrg * of the output range is the sum of the first N-1 input elements, 617c0a68be4Smrg * so the Nth input element is not included. 618c0a68be4Smrg */ 619c0a68be4Smrg template<typename _InputIterator, typename _OutputIterator, typename _Tp, 620c0a68be4Smrg typename _BinaryOperation, typename _UnaryOperation> 6218feb0f0bSmrg _GLIBCXX20_CONSTEXPR 622c0a68be4Smrg _OutputIterator 623c0a68be4Smrg transform_exclusive_scan(_InputIterator __first, _InputIterator __last, 624c0a68be4Smrg _OutputIterator __result, _Tp __init, 625c0a68be4Smrg _BinaryOperation __binary_op, 626c0a68be4Smrg _UnaryOperation __unary_op) 627c0a68be4Smrg { 628c0a68be4Smrg while (__first != __last) 629c0a68be4Smrg { 630c0a68be4Smrg auto __v = __init; 631c0a68be4Smrg __init = __binary_op(__init, __unary_op(*__first)); 632c0a68be4Smrg ++__first; 633c0a68be4Smrg *__result++ = std::move(__v); 634c0a68be4Smrg } 635c0a68be4Smrg return __result; 636c0a68be4Smrg } 637c0a68be4Smrg 638c0a68be4Smrg /** @brief Output the cumulative sum of one range to a second range 639c0a68be4Smrg * 640c0a68be4Smrg * @param __first Start of input range. 641c0a68be4Smrg * @param __last End of input range. 642c0a68be4Smrg * @param __result Start of output range. 643c0a68be4Smrg * @param __binary_op Function to perform summation. 644c0a68be4Smrg * @param __unary_op Function to transform elements of the input range. 645c0a68be4Smrg * @param __init Initial value. 646c0a68be4Smrg * @return The end of the output range. 647c0a68be4Smrg * 648c0a68be4Smrg * Write the cumulative sum (aka prefix sum, aka scan) of the input range 649c0a68be4Smrg * to the output range. Each element of the output range contains the 650c0a68be4Smrg * running total of all earlier elements (and the initial value), 651c0a68be4Smrg * using `__unary_op` to transform the input elements 652c0a68be4Smrg * and using `__binary_op` for summation. 653c0a68be4Smrg * 654c0a68be4Smrg * This function generates an "inclusive" scan, meaning the Nth element 655c0a68be4Smrg * of the output range is the sum of the first N input elements, 656c0a68be4Smrg * so the Nth input element is included. 657c0a68be4Smrg */ 658c0a68be4Smrg template<typename _InputIterator, typename _OutputIterator, 659c0a68be4Smrg typename _BinaryOperation, typename _UnaryOperation, typename _Tp> 6608feb0f0bSmrg _GLIBCXX20_CONSTEXPR 661c0a68be4Smrg _OutputIterator 662c0a68be4Smrg transform_inclusive_scan(_InputIterator __first, _InputIterator __last, 663c0a68be4Smrg _OutputIterator __result, 664c0a68be4Smrg _BinaryOperation __binary_op, 665c0a68be4Smrg _UnaryOperation __unary_op, 666c0a68be4Smrg _Tp __init) 667c0a68be4Smrg { 668c0a68be4Smrg for (; __first != __last; ++__first) 669c0a68be4Smrg *__result++ = __init = __binary_op(__init, __unary_op(*__first)); 670c0a68be4Smrg return __result; 671c0a68be4Smrg } 672c0a68be4Smrg 673c0a68be4Smrg /** @brief Output the cumulative sum of one range to a second range 674c0a68be4Smrg * 675c0a68be4Smrg * @param __first Start of input range. 676c0a68be4Smrg * @param __last End of input range. 677c0a68be4Smrg * @param __result Start of output range. 678c0a68be4Smrg * @param __binary_op Function to perform summation. 679c0a68be4Smrg * @param __unary_op Function to transform elements of the input range. 680c0a68be4Smrg * @return The end of the output range. 681c0a68be4Smrg * 682c0a68be4Smrg * Write the cumulative sum (aka prefix sum, aka scan) of the input range 683c0a68be4Smrg * to the output range. Each element of the output range contains the 684c0a68be4Smrg * running total of all earlier elements, 685c0a68be4Smrg * using `__unary_op` to transform the input elements 686c0a68be4Smrg * and using `__binary_op` for summation. 687c0a68be4Smrg * 688c0a68be4Smrg * This function generates an "inclusive" scan, meaning the Nth element 689c0a68be4Smrg * of the output range is the sum of the first N input elements, 690c0a68be4Smrg * so the Nth input element is included. 691c0a68be4Smrg */ 692c0a68be4Smrg template<typename _InputIterator, typename _OutputIterator, 693c0a68be4Smrg typename _BinaryOperation, typename _UnaryOperation> 6948feb0f0bSmrg _GLIBCXX20_CONSTEXPR 695c0a68be4Smrg _OutputIterator 696c0a68be4Smrg transform_inclusive_scan(_InputIterator __first, _InputIterator __last, 697c0a68be4Smrg _OutputIterator __result, 698c0a68be4Smrg _BinaryOperation __binary_op, 699c0a68be4Smrg _UnaryOperation __unary_op) 700c0a68be4Smrg { 701c0a68be4Smrg if (__first != __last) 702c0a68be4Smrg { 703c0a68be4Smrg auto __init = __unary_op(*__first); 704c0a68be4Smrg *__result++ = __init; 705c0a68be4Smrg ++__first; 706c0a68be4Smrg if (__first != __last) 707c0a68be4Smrg __result = std::transform_inclusive_scan(__first, __last, __result, 708c0a68be4Smrg __binary_op, __unary_op, 709c0a68be4Smrg std::move(__init)); 710c0a68be4Smrg } 711c0a68be4Smrg return __result; 712c0a68be4Smrg } 713c0a68be4Smrg 7148feb0f0bSmrg /// @} group numeric_ops 715c0a68be4Smrg 716c0a68be4Smrg_GLIBCXX_END_NAMESPACE_VERSION 717c0a68be4Smrg} // namespace std 718c0a68be4Smrg 719c0a68be4Smrg// Parallel STL algorithms 7208feb0f0bSmrg# if _PSTL_EXECUTION_POLICIES_DEFINED 721c0a68be4Smrg// If <execution> has already been included, pull in implementations 722c0a68be4Smrg# include <pstl/glue_numeric_impl.h> 723c0a68be4Smrg# else 724c0a68be4Smrg// Otherwise just pull in forward declarations 725c0a68be4Smrg# include <pstl/glue_numeric_defs.h> 7268feb0f0bSmrg# define _PSTL_NUMERIC_FORWARD_DECLARED 1 727c0a68be4Smrg# endif 728c0a68be4Smrg 729c0a68be4Smrg// Feature test macro for parallel algorithms 730c0a68be4Smrg# define __cpp_lib_parallel_algorithm 201603L 731c0a68be4Smrg#endif // C++17 7321debfc3dSmrg 7331debfc3dSmrg#endif /* _GLIBCXX_NUMERIC */ 734