1 | // Numeric functions implementation -*- C++ -*- |
2 | |
3 | // Copyright (C) 2001-2024 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 | |
64 | namespace 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 | |