xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/std/numeric (revision b1e838363e3c6fc78a55519254d99869742dd33c)
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