core/iter/traits/accum.rs
1use crate::iter;
2use crate::num::{Saturating, Wrapping};
3
4/// Trait to represent types that can be created by summing up an iterator.
5///
6/// This trait is used to implement [`Iterator::sum()`]. Types which implement
7/// this trait can be generated by using the [`sum()`] method on an iterator.
8/// Like [`FromIterator`], this trait should rarely be called directly.
9///
10/// [`sum()`]: Iterator::sum
11/// [`FromIterator`]: iter::FromIterator
12#[stable(feature = "iter_arith_traits", since = "1.12.0")]
13#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
14#[diagnostic::on_unimplemented(
15 message = "a value of type `{Self}` cannot be made by summing an iterator over elements of type `{A}`",
16 label = "value of type `{Self}` cannot be made by summing a `std::iter::Iterator<Item={A}>`"
17)]
18pub const trait Sum<A = Self>: Sized {
19 /// Takes an iterator and generates `Self` from the elements by "summing up"
20 /// the items.
21 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
22 fn sum<I: Iterator<Item = A>>(iter: I) -> Self;
23}
24
25/// Trait to represent types that can be created by multiplying elements of an
26/// iterator.
27///
28/// This trait is used to implement [`Iterator::product()`]. Types which implement
29/// this trait can be generated by using the [`product()`] method on an iterator.
30/// Like [`FromIterator`], this trait should rarely be called directly.
31///
32/// [`product()`]: Iterator::product
33/// [`FromIterator`]: iter::FromIterator
34#[stable(feature = "iter_arith_traits", since = "1.12.0")]
35#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
36#[diagnostic::on_unimplemented(
37 message = "a value of type `{Self}` cannot be made by multiplying all elements of type `{A}` from an iterator",
38 label = "value of type `{Self}` cannot be made by multiplying all elements from a `std::iter::Iterator<Item={A}>`"
39)]
40pub const trait Product<A = Self>: Sized {
41 /// Takes an iterator and generates `Self` from the elements by multiplying
42 /// the items.
43 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
44 fn product<I: Iterator<Item = A>>(iter: I) -> Self;
45}
46
47macro_rules! integer_sum_product {
48 (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($(
49 #[$attr]
50 impl Sum for $a {
51 #[ferrocene::prevalidated]
52 fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
53 iter.fold(
54 $zero,
55 #[rustc_inherit_overflow_checks]
56 |a, b| a + b,
57 )
58 }
59 }
60
61 #[$attr]
62 impl Product for $a {
63 fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
64 iter.fold(
65 $one,
66 #[rustc_inherit_overflow_checks]
67 |a, b| a * b,
68 )
69 }
70 }
71
72 #[$attr]
73 impl<'a> Sum<&'a $a> for $a {
74 #[ferrocene::prevalidated]
75 fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
76 iter.fold(
77 $zero,
78 #[rustc_inherit_overflow_checks]
79 |a, b| a + b,
80 )
81 }
82 }
83
84 #[$attr]
85 impl<'a> Product<&'a $a> for $a {
86 fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
87 iter.fold(
88 $one,
89 #[rustc_inherit_overflow_checks]
90 |a, b| a * b,
91 )
92 }
93 }
94 )*);
95 ($($a:ty)*) => (
96 integer_sum_product!(@impls 0, 1,
97 #[stable(feature = "iter_arith_traits", since = "1.12.0")],
98 $($a)*);
99 integer_sum_product!(@impls Wrapping(0), Wrapping(1),
100 #[stable(feature = "wrapping_iter_arith", since = "1.14.0")],
101 $(Wrapping<$a>)*);
102 );
103}
104
105macro_rules! saturating_integer_sum_product {
106 (@impls $zero:expr, $one:expr, $doc:expr, #[$attr:meta], $($a:ty)*) => ($(
107 #[$attr]
108 #[doc = $doc]
109 impl Sum for $a {
110 fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
111 iter.fold(
112 $zero,
113 |a, b| a + b,
114 )
115 }
116 }
117
118 #[$attr]
119 #[doc = $doc]
120 impl Product for $a {
121 fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
122 iter.fold(
123 $one,
124 |a, b| a * b,
125 )
126 }
127 }
128
129 #[$attr]
130 #[doc = $doc]
131 impl<'a> Sum<&'a $a> for $a {
132 fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
133 iter.fold(
134 $zero,
135 |a, b| a + b,
136 )
137 }
138 }
139
140 #[$attr]
141 #[doc = $doc]
142 impl<'a> Product<&'a $a> for $a {
143 fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
144 iter.fold(
145 $one,
146 |a, b| a * b,
147 )
148 }
149 }
150 )*);
151 ($($a:ty)*) => (
152 saturating_integer_sum_product!(@impls Saturating(0), Saturating(1),
153 "The short-circuiting behavior of this implementation is unspecified. If you care about \
154 short-circuiting, use [`Iterator::fold`] directly.",
155 #[stable(feature = "saturating_iter_arith", since = "1.91.0")],
156 $(Saturating<$a>)*);
157 );
158}
159
160macro_rules! float_sum_product {
161 ($($a:ident)*) => ($(
162 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
163 impl Sum for $a {
164 #[ferrocene::prevalidated]
165 fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
166 iter.fold(
167 -0.0,
168 #[rustc_inherit_overflow_checks]
169 |a, b| a + b,
170 )
171 }
172 }
173
174 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
175 impl Product for $a {
176 fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
177 iter.fold(
178 1.0,
179 #[rustc_inherit_overflow_checks]
180 |a, b| a * b,
181 )
182 }
183 }
184
185 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
186 impl<'a> Sum<&'a $a> for $a {
187 #[ferrocene::prevalidated]
188 fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
189 iter.fold(
190 -0.0,
191 #[rustc_inherit_overflow_checks]
192 |a, b| a + b,
193 )
194 }
195 }
196
197 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
198 impl<'a> Product<&'a $a> for $a {
199 fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
200 iter.fold(
201 1.0,
202 #[rustc_inherit_overflow_checks]
203 |a, b| a * b,
204 )
205 }
206 }
207 )*)
208}
209
210integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
211saturating_integer_sum_product! { u8 u16 u32 u64 u128 usize }
212float_sum_product! { f16 f32 f64 f128 }
213
214#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
215impl<T, U, E> Sum<Result<U, E>> for Result<T, E>
216where
217 T: Sum<U>,
218{
219 /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
220 /// elements are taken, and the [`Err`] is returned. Should no [`Err`]
221 /// occur, the sum of all elements is returned.
222 ///
223 /// # Examples
224 ///
225 /// This sums up every integer in a vector, rejecting the sum if a negative
226 /// element is encountered:
227 ///
228 /// ```
229 /// let f = |&x: &i32| if x < 0 { Err("Negative element found") } else { Ok(x) };
230 /// let v = vec![1, 2];
231 /// let res: Result<i32, _> = v.iter().map(f).sum();
232 /// assert_eq!(res, Ok(3));
233 /// let v = vec![1, -2];
234 /// let res: Result<i32, _> = v.iter().map(f).sum();
235 /// assert_eq!(res, Err("Negative element found"));
236 /// ```
237 fn sum<I>(iter: I) -> Result<T, E>
238 where
239 I: Iterator<Item = Result<U, E>>,
240 {
241 iter::try_process(iter, |i| i.sum())
242 }
243}
244
245#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
246impl<T, U, E> Product<Result<U, E>> for Result<T, E>
247where
248 T: Product<U>,
249{
250 /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
251 /// elements are taken, and the [`Err`] is returned. Should no [`Err`]
252 /// occur, the product of all elements is returned.
253 ///
254 /// # Examples
255 ///
256 /// This multiplies each number in a vector of strings,
257 /// if a string could not be parsed the operation returns `Err`:
258 ///
259 /// ```
260 /// let nums = vec!["5", "10", "1", "2"];
261 /// let total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product();
262 /// assert_eq!(total, Ok(100));
263 /// let nums = vec!["5", "10", "one", "2"];
264 /// let total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product();
265 /// assert!(total.is_err());
266 /// ```
267 fn product<I>(iter: I) -> Result<T, E>
268 where
269 I: Iterator<Item = Result<U, E>>,
270 {
271 iter::try_process(iter, |i| i.product())
272 }
273}
274
275#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
276impl<T, U> Sum<Option<U>> for Option<T>
277where
278 T: Sum<U>,
279{
280 /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
281 /// elements are taken, and the [`None`] is returned. Should no [`None`]
282 /// occur, the sum of all elements is returned.
283 ///
284 /// # Examples
285 ///
286 /// This sums up the position of the character 'a' in a vector of strings,
287 /// if a word did not have the character 'a' the operation returns `None`:
288 ///
289 /// ```
290 /// let words = vec!["have", "a", "great", "day"];
291 /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
292 /// assert_eq!(total, Some(5));
293 /// let words = vec!["have", "a", "good", "day"];
294 /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
295 /// assert_eq!(total, None);
296 /// ```
297 fn sum<I>(iter: I) -> Option<T>
298 where
299 I: Iterator<Item = Option<U>>,
300 {
301 iter::try_process(iter, |i| i.sum())
302 }
303}
304
305#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
306impl<T, U> Product<Option<U>> for Option<T>
307where
308 T: Product<U>,
309{
310 /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
311 /// elements are taken, and the [`None`] is returned. Should no [`None`]
312 /// occur, the product of all elements is returned.
313 ///
314 /// # Examples
315 ///
316 /// This multiplies each number in a vector of strings,
317 /// if a string could not be parsed the operation returns `None`:
318 ///
319 /// ```
320 /// let nums = vec!["5", "10", "1", "2"];
321 /// let total: Option<usize> = nums.iter().map(|w| w.parse::<usize>().ok()).product();
322 /// assert_eq!(total, Some(100));
323 /// let nums = vec!["5", "10", "one", "2"];
324 /// let total: Option<usize> = nums.iter().map(|w| w.parse::<usize>().ok()).product();
325 /// assert_eq!(total, None);
326 /// ```
327 fn product<I>(iter: I) -> Option<T>
328 where
329 I: Iterator<Item = Option<U>>,
330 {
331 iter::try_process(iter, |i| i.product())
332 }
333}