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