1// Numeric functions implementation -*- C++ -*-
2
3// Copyright (C) 2001-2022 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library.  This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23// <http://www.gnu.org/licenses/>.
24
25/*
26 *
27 * Copyright (c) 1994
28 * Hewlett-Packard Company
29 *
30 * Permission to use, copy, modify, distribute and sell this software
31 * and its documentation for any purpose is hereby granted without fee,
32 * provided that the above copyright notice appear in all copies and
33 * that both that copyright notice and this permission notice appear
34 * in supporting documentation.  Hewlett-Packard Company makes no
35 * representations about the suitability of this software for any
36 * purpose.  It is provided "as is" without express or implied warranty.
37 *
38 *
39 * Copyright (c) 1996,1997
40 * Silicon Graphics Computer Systems, Inc.
41 *
42 * Permission to use, copy, modify, distribute and sell this software
43 * and its documentation for any purpose is hereby granted without fee,
44 * provided that the above copyright notice appear in all copies and
45 * that both that copyright notice and this permission notice appear
46 * in supporting documentation.  Silicon Graphics makes no
47 * representations about the suitability of this software for any
48 * purpose.  It is provided "as is" without express or implied warranty.
49 */
50
51/** @file bits/stl_numeric.h
52 *  This is an internal header file, included by other library headers.
53 *  Do not attempt to use it directly. @headername{numeric}
54 */
55
56#ifndef _STL_NUMERIC_H
57#define _STL_NUMERIC_H 1
58
59#include <bits/concept_check.h>
60#include <debug/debug.h>
61#include <bits/move.h> // For _GLIBCXX_MOVE
62
63
64namespace std _GLIBCXX_VISIBILITY(default)
65{
66_GLIBCXX_BEGIN_NAMESPACE_VERSION
67
68  /** @defgroup numeric_ops Generalized Numeric operations
69   *  @ingroup algorithms
70   */
71
72#if __cplusplus >= 201103L
73  /**
74   *  @brief  Create a range of sequentially increasing values.
75   *
76   *  For each element in the range @p [first,last) assigns @p value and
77   *  increments @p value as if by @p ++value.
78   *
79   *  @param  __first  Start of range.
80   *  @param  __last  End of range.
81   *  @param  __value  Starting value.
82   *  @return  Nothing.
83   *  @ingroup numeric_ops
84   */
85  template<typename _ForwardIterator, typename _Tp>
86    _GLIBCXX20_CONSTEXPR
87    void
88    iota(_ForwardIterator __first, _ForwardIterator __last, _Tp __value)
89    {
90      // concept requirements
91      __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
92				  _ForwardIterator>)
93      __glibcxx_function_requires(_ConvertibleConcept<_Tp,
94	    typename iterator_traits<_ForwardIterator>::value_type>)
95      __glibcxx_requires_valid_range(__first, __last);
96
97      for (; __first != __last; ++__first)
98	{
99	  *__first = __value;
100	  ++__value;
101	}
102    }
103#endif
104
105_GLIBCXX_END_NAMESPACE_VERSION
106
107_GLIBCXX_BEGIN_NAMESPACE_ALGO
108
109#if __cplusplus > 201703L
110// _GLIBCXX_RESOLVE_LIB_DEFECTS
111// DR 2055. std::move in std::accumulate and other algorithms
112# define _GLIBCXX_MOVE_IF_20(_E) std::move(_E)
113#else
114# define _GLIBCXX_MOVE_IF_20(_E) _E
115#endif
116
117  /// @addtogroup numeric_ops
118  /// @{
119
120  /**
121   *  @brief  Accumulate values in a range.
122   *
123   *  Accumulates the values in the range [first,last) using operator+().  The
124   *  initial value is @a init.  The values are processed in order.
125   *
126   *  @param  __first  Start of range.
127   *  @param  __last  End of range.
128   *  @param  __init  Starting value to add other values to.
129   *  @return  The final sum.
130   */
131  template<typename _InputIterator, typename _Tp>
132    _GLIBCXX20_CONSTEXPR
133    inline _Tp
134    accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
135    {
136      // concept requirements
137      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
138      __glibcxx_requires_valid_range(__first, __last);
139
140      for (; __first != __last; ++__first)
141	__init = _GLIBCXX_MOVE_IF_20(__init) + *__first;
142      return __init;
143    }
144
145  /**
146   *  @brief  Accumulate values in a range with operation.
147   *
148   *  Accumulates the values in the range `[first,last)` using the function
149   *  object `__binary_op`.  The initial value is `__init`.  The values are
150   *  processed in order.
151   *
152   *  @param  __first  Start of range.
153   *  @param  __last  End of range.
154   *  @param  __init  Starting value to add other values to.
155   *  @param  __binary_op  Function object to accumulate with.
156   *  @return  The final sum.
157   */
158  template<typename _InputIterator, typename _Tp, typename _BinaryOperation>
159    _GLIBCXX20_CONSTEXPR
160    inline _Tp
161    accumulate(_InputIterator __first, _InputIterator __last, _Tp __init,
162	       _BinaryOperation __binary_op)
163    {
164      // concept requirements
165      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
166      __glibcxx_requires_valid_range(__first, __last);
167
168      for (; __first != __last; ++__first)
169	__init = __binary_op(_GLIBCXX_MOVE_IF_20(__init), *__first);
170      return __init;
171    }
172
173  /**
174   *  @brief  Compute inner product of two ranges.
175   *
176   *  Starting with an initial value of @p __init, multiplies successive
177   *  elements from the two ranges and adds each product into the accumulated
178   *  value using operator+().  The values in the ranges are processed in
179   *  order.
180   *
181   *  @param  __first1  Start of range 1.
182   *  @param  __last1  End of range 1.
183   *  @param  __first2  Start of range 2.
184   *  @param  __init  Starting value to add other values to.
185   *  @return  The final inner product.
186   */
187  template<typename _InputIterator1, typename _InputIterator2, typename _Tp>
188    _GLIBCXX20_CONSTEXPR
189    inline _Tp
190    inner_product(_InputIterator1 __first1, _InputIterator1 __last1,
191		  _InputIterator2 __first2, _Tp __init)
192    {
193      // concept requirements
194      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
195      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
196      __glibcxx_requires_valid_range(__first1, __last1);
197
198      for (; __first1 != __last1; ++__first1, (void)++__first2)
199	__init = _GLIBCXX_MOVE_IF_20(__init) + (*__first1 * *__first2);
200      return __init;
201    }
202
203  /**
204   *  @brief  Compute inner product of two ranges.
205   *
206   *  Starting with an initial value of @p __init, applies @p __binary_op2 to
207   *  successive elements from the two ranges and accumulates each result into
208   *  the accumulated value using @p __binary_op1.  The values in the ranges are
209   *  processed in order.
210   *
211   *  @param  __first1  Start of range 1.
212   *  @param  __last1  End of range 1.
213   *  @param  __first2  Start of range 2.
214   *  @param  __init  Starting value to add other values to.
215   *  @param  __binary_op1  Function object to accumulate with.
216   *  @param  __binary_op2  Function object to apply to pairs of input values.
217   *  @return  The final inner product.
218   */
219  template<typename _InputIterator1, typename _InputIterator2, typename _Tp,
220	   typename _BinaryOperation1, typename _BinaryOperation2>
221    _GLIBCXX20_CONSTEXPR
222    inline _Tp
223    inner_product(_InputIterator1 __first1, _InputIterator1 __last1,
224		  _InputIterator2 __first2, _Tp __init,
225		  _BinaryOperation1 __binary_op1,
226		  _BinaryOperation2 __binary_op2)
227    {
228      // concept requirements
229      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
230      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
231      __glibcxx_requires_valid_range(__first1, __last1);
232
233      for (; __first1 != __last1; ++__first1, (void)++__first2)
234	__init = __binary_op1(_GLIBCXX_MOVE_IF_20(__init),
235			      __binary_op2(*__first1, *__first2));
236      return __init;
237    }
238
239  /**
240   *  @brief  Return list of partial sums
241   *
242   *  Accumulates the values in the range [first,last) using the @c + operator.
243   *  As each successive input value is added into the total, that partial sum
244   *  is written to @p __result.  Therefore, the first value in @p __result is
245   *  the first value of the input, the second value in @p __result is the sum
246   *  of the first and second input values, and so on.
247   *
248   *  @param  __first  Start of input range.
249   *  @param  __last  End of input range.
250   *  @param  __result  Output sum.
251   *  @return  Iterator pointing just beyond the values written to __result.
252   */
253  template<typename _InputIterator, typename _OutputIterator>
254    _GLIBCXX20_CONSTEXPR
255    _OutputIterator
256    partial_sum(_InputIterator __first, _InputIterator __last,
257		_OutputIterator __result)
258    {
259      typedef typename iterator_traits<_InputIterator>::value_type _ValueType;
260
261      // concept requirements
262      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
263      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
264				                         _ValueType>)
265      __glibcxx_requires_valid_range(__first, __last);
266
267      if (__first == __last)
268	return __result;
269      _ValueType __value = *__first;
270      *__result = __value;
271      while (++__first != __last)
272	{
273	  __value = _GLIBCXX_MOVE_IF_20(__value) + *__first;
274	  *++__result = __value;
275	}
276      return ++__result;
277    }
278
279  /**
280   *  @brief  Return list of partial sums
281   *
282   *  Accumulates the values in the range [first,last) using @p __binary_op.
283   *  As each successive input value is added into the total, that partial sum
284   *  is written to @p __result.  Therefore, the first value in @p __result is
285   *  the first value of the input, the second value in @p __result is the sum
286   *  of the first and second input values, and so on.
287   *
288   *  @param  __first  Start of input range.
289   *  @param  __last  End of input range.
290   *  @param  __result  Output sum.
291   *  @param  __binary_op  Function object.
292   *  @return  Iterator pointing just beyond the values written to __result.
293   */
294  template<typename _InputIterator, typename _OutputIterator,
295	   typename _BinaryOperation>
296    _GLIBCXX20_CONSTEXPR
297    _OutputIterator
298    partial_sum(_InputIterator __first, _InputIterator __last,
299		_OutputIterator __result, _BinaryOperation __binary_op)
300    {
301      typedef typename iterator_traits<_InputIterator>::value_type _ValueType;
302
303      // concept requirements
304      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
305      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
306				                         _ValueType>)
307      __glibcxx_requires_valid_range(__first, __last);
308
309      if (__first == __last)
310	return __result;
311      _ValueType __value = *__first;
312      *__result = __value;
313      while (++__first != __last)
314	{
315	  __value = __binary_op(_GLIBCXX_MOVE_IF_20(__value), *__first);
316	  *++__result = __value;
317	}
318      return ++__result;
319    }
320
321  /**
322   *  @brief  Return differences between adjacent values.
323   *
324   *  Computes the difference between adjacent values in the range
325   *  [first,last) using operator-() and writes the result to @p __result.
326   *
327   *  @param  __first  Start of input range.
328   *  @param  __last  End of input range.
329   *  @param  __result  Output sums.
330   *  @return  Iterator pointing just beyond the values written to result.
331   */
332  // _GLIBCXX_RESOLVE_LIB_DEFECTS
333  // DR 539. partial_sum and adjacent_difference should mention requirements
334  template<typename _InputIterator, typename _OutputIterator>
335    _GLIBCXX20_CONSTEXPR
336    _OutputIterator
337    adjacent_difference(_InputIterator __first,
338			_InputIterator __last, _OutputIterator __result)
339    {
340      typedef typename iterator_traits<_InputIterator>::value_type _ValueType;
341
342      // concept requirements
343      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
344      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
345				                         _ValueType>)
346      __glibcxx_requires_valid_range(__first, __last);
347
348      if (__first == __last)
349	return __result;
350      _ValueType __value = *__first;
351      *__result = __value;
352      while (++__first != __last)
353	{
354	  _ValueType __tmp = *__first;
355	  *++__result = __tmp - _GLIBCXX_MOVE_IF_20(__value);
356	  __value = _GLIBCXX_MOVE(__tmp);
357	}
358      return ++__result;
359    }
360
361  /**
362   *  @brief  Return differences between adjacent values.
363   *
364   *  Computes the difference between adjacent values in the range
365   *  [__first,__last) using the function object @p __binary_op and writes the
366   *  result to @p __result.
367   *
368   *  @param  __first  Start of input range.
369   *  @param  __last  End of input range.
370   *  @param  __result  Output sum.
371   *  @param  __binary_op Function object.
372   *  @return  Iterator pointing just beyond the values written to result.
373   */
374  // _GLIBCXX_RESOLVE_LIB_DEFECTS
375  // DR 539. partial_sum and adjacent_difference should mention requirements
376  template<typename _InputIterator, typename _OutputIterator,
377	   typename _BinaryOperation>
378    _GLIBCXX20_CONSTEXPR
379    _OutputIterator
380    adjacent_difference(_InputIterator __first, _InputIterator __last,
381			_OutputIterator __result, _BinaryOperation __binary_op)
382    {
383      typedef typename iterator_traits<_InputIterator>::value_type _ValueType;
384
385      // concept requirements
386      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
387      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
388				                         _ValueType>)
389      __glibcxx_requires_valid_range(__first, __last);
390
391      if (__first == __last)
392	return __result;
393      _ValueType __value = *__first;
394      *__result = __value;
395      while (++__first != __last)
396	{
397	  _ValueType __tmp = *__first;
398	  *++__result = __binary_op(__tmp, _GLIBCXX_MOVE_IF_20(__value));
399	  __value = _GLIBCXX_MOVE(__tmp);
400	}
401      return ++__result;
402    }
403
404  /// @} group numeric_ops
405
406#undef _GLIBCXX_MOVE_IF_20
407
408_GLIBCXX_END_NAMESPACE_ALGO
409} // namespace std
410
411#endif /* _STL_NUMERIC_H */
412