1use crate::iter;
2use crate::num::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_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 /// Method which takes an iterator and generates `Self` from the elements by
19 /// "summing up" 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#[rustc_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 /// Method which takes an iterator and generates `Self` from the elements by
40 /// multiplying 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 fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
50 iter.fold(
51 $zero,
52 #[rustc_inherit_overflow_checks]
53 |a, b| a + b,
54 )
55 }
56 }
57
58 #[$attr]
59 impl Product for $a {
60 fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
61 iter.fold(
62 $one,
63 #[rustc_inherit_overflow_checks]
64 |a, b| a * b,
65 )
66 }
67 }
68
69 #[$attr]
70 impl<'a> Sum<&'a $a> for $a {
71 fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
72 iter.fold(
73 $zero,
74 #[rustc_inherit_overflow_checks]
75 |a, b| a + b,
76 )
77 }
78 }
79
80 #[$attr]
81 impl<'a> Product<&'a $a> for $a {
82 fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
83 iter.fold(
84 $one,
85 #[rustc_inherit_overflow_checks]
86 |a, b| a * b,
87 )
88 }
89 }
90 )*);
91 ($($a:ty)*) => (
92 integer_sum_product!(@impls 0, 1,
93 #[stable(feature = "iter_arith_traits", since = "1.12.0")],
94 $($a)*);
95 integer_sum_product!(@impls Wrapping(0), Wrapping(1),
96 #[stable(feature = "wrapping_iter_arith", since = "1.14.0")],
97 $(Wrapping<$a>)*);
98 );
99}
100
101macro_rules! float_sum_product {
102 ($($a:ident)*) => ($(
103 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
104 impl Sum for $a {
105 fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
106 iter.fold(
107 0.0,
108 #[rustc_inherit_overflow_checks]
109 |a, b| a + b,
110 )
111 }
112 }
113
114 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
115 impl Product for $a {
116 fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
117 iter.fold(
118 1.0,
119 #[rustc_inherit_overflow_checks]
120 |a, b| a * b,
121 )
122 }
123 }
124
125 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
126 impl<'a> Sum<&'a $a> for $a {
127 fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
128 iter.fold(
129 0.0,
130 #[rustc_inherit_overflow_checks]
131 |a, b| a + b,
132 )
133 }
134 }
135
136 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
137 impl<'a> Product<&'a $a> for $a {
138 fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
139 iter.fold(
140 1.0,
141 #[rustc_inherit_overflow_checks]
142 |a, b| a * b,
143 )
144 }
145 }
146 )*)
147}
148
149integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
150float_sum_product! { f32 f64 }
151
152#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
153impl<T, U, E> Sum<Result<U, E>> for Result<T, E>
154where
155 T: Sum<U>,
156{
157 /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
158 /// elements are taken, and the [`Err`] is returned. Should no [`Err`]
159 /// occur, the sum of all elements is returned.
160 ///
161 /// # Examples
162 ///
163 /// This sums up every integer in a vector, rejecting the sum if a negative
164 /// element is encountered:
165 ///
166 /// ```
167 /// let f = |&x: &i32| if x < 0 { Err("Negative element found") } else { Ok(x) };
168 /// let v = vec![1, 2];
169 /// let res: Result<i32, _> = v.iter().map(f).sum();
170 /// assert_eq!(res, Ok(3));
171 /// let v = vec![1, -2];
172 /// let res: Result<i32, _> = v.iter().map(f).sum();
173 /// assert_eq!(res, Err("Negative element found"));
174 /// ```
175 fn sum<I>(iter: I) -> Result<T, E>
176 where
177 I: Iterator<Item = Result<U, E>>,
178 {
179 iter::try_process(iter, |i| i.sum())
180 }
181}
182
183#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
184impl<T, U, E> Product<Result<U, E>> for Result<T, E>
185where
186 T: Product<U>,
187{
188 /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
189 /// elements are taken, and the [`Err`] is returned. Should no [`Err`]
190 /// occur, the product of all elements is returned.
191 ///
192 /// # Examples
193 ///
194 /// This multiplies each number in a vector of strings,
195 /// if a string could not be parsed the operation returns `Err`:
196 ///
197 /// ```
198 /// let nums = vec!["5", "10", "1", "2"];
199 /// let total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product();
200 /// assert_eq!(total, Ok(100));
201 /// let nums = vec!["5", "10", "one", "2"];
202 /// let total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product();
203 /// assert!(total.is_err());
204 /// ```
205 fn product<I>(iter: I) -> Result<T, E>
206 where
207 I: Iterator<Item = Result<U, E>>,
208 {
209 iter::try_process(iter, |i| i.product())
210 }
211}
212
213#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
214impl<T, U> Sum<Option<U>> for Option<T>
215where
216 T: Sum<U>,
217{
218 /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
219 /// elements are taken, and the [`None`] is returned. Should no [`None`]
220 /// occur, the sum of all elements is returned.
221 ///
222 /// # Examples
223 ///
224 /// This sums up the position of the character 'a' in a vector of strings,
225 /// if a word did not have the character 'a' the operation returns `None`:
226 ///
227 /// ```
228 /// let words = vec!["have", "a", "great", "day"];
229 /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
230 /// assert_eq!(total, Some(5));
231 /// let words = vec!["have", "a", "good", "day"];
232 /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
233 /// assert_eq!(total, None);
234 /// ```
235 fn sum<I>(iter: I) -> Option<T>
236 where
237 I: Iterator<Item = Option<U>>,
238 {
239 iter::try_process(iter, |i| i.sum())
240 }
241}
242
243#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
244impl<T, U> Product<Option<U>> for Option<T>
245where
246 T: Product<U>,
247{
248 /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
249 /// elements are taken, and the [`None`] is returned. Should no [`None`]
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 `None`:
256 ///
257 /// ```
258 /// let nums = vec!["5", "10", "1", "2"];
259 /// let total: Option<usize> = nums.iter().map(|w| w.parse::<usize>().ok()).product();
260 /// assert_eq!(total, Some(100));
261 /// let nums = vec!["5", "10", "one", "2"];
262 /// let total: Option<usize> = nums.iter().map(|w| w.parse::<usize>().ok()).product();
263 /// assert_eq!(total, None);
264 /// ```
265 fn product<I>(iter: I) -> Option<T>
266 where
267 I: Iterator<Item = Option<U>>,
268 {
269 iter::try_process(iter, |i| i.product())
270 }
271}
272