]>
Commit | Line | Data |
---|---|---|
416331ca | 1 | use crate::iter; |
60c5eb7d XL |
2 | use crate::num::Wrapping; |
3 | use crate::ops::{Add, Mul}; | |
9fa01778 XL |
4 | |
5 | /// Trait to represent types that can be created by summing up an iterator. | |
6 | /// | |
7 | /// This trait is used to implement the [`sum`] method on iterators. Types which | |
8 | /// implement the trait can be generated by the [`sum`] method. Like | |
9 | /// [`FromIterator`] this trait should rarely be called directly and instead | |
10 | /// interacted with through [`Iterator::sum`]. | |
11 | /// | |
12 | /// [`sum`]: ../../std/iter/trait.Sum.html#tymethod.sum | |
13 | /// [`FromIterator`]: ../../std/iter/trait.FromIterator.html | |
14 | /// [`Iterator::sum`]: ../../std/iter/trait.Iterator.html#method.sum | |
15 | #[stable(feature = "iter_arith_traits", since = "1.12.0")] | |
16 | pub trait Sum<A = Self>: Sized { | |
17 | /// Method which takes an iterator and generates `Self` from the elements by | |
18 | /// "summing up" the items. | |
19 | #[stable(feature = "iter_arith_traits", since = "1.12.0")] | |
60c5eb7d | 20 | fn sum<I: Iterator<Item = A>>(iter: I) -> Self; |
9fa01778 XL |
21 | } |
22 | ||
23 | /// Trait to represent types that can be created by multiplying elements of an | |
24 | /// iterator. | |
25 | /// | |
26 | /// This trait is used to implement the [`product`] method on iterators. Types | |
27 | /// which implement the trait can be generated by the [`product`] method. Like | |
28 | /// [`FromIterator`] this trait should rarely be called directly and instead | |
29 | /// interacted with through [`Iterator::product`]. | |
30 | /// | |
31 | /// [`product`]: ../../std/iter/trait.Product.html#tymethod.product | |
32 | /// [`FromIterator`]: ../../std/iter/trait.FromIterator.html | |
33 | /// [`Iterator::product`]: ../../std/iter/trait.Iterator.html#method.product | |
34 | #[stable(feature = "iter_arith_traits", since = "1.12.0")] | |
35 | pub trait Product<A = Self>: Sized { | |
36 | /// Method which takes an iterator and generates `Self` from the elements by | |
37 | /// multiplying the items. | |
38 | #[stable(feature = "iter_arith_traits", since = "1.12.0")] | |
60c5eb7d | 39 | fn product<I: Iterator<Item = A>>(iter: I) -> Self; |
9fa01778 XL |
40 | } |
41 | ||
42 | // N.B., explicitly use Add and Mul here to inherit overflow checks | |
43 | macro_rules! integer_sum_product { | |
44 | (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($( | |
45 | #[$attr] | |
46 | impl Sum for $a { | |
47 | fn sum<I: Iterator<Item=$a>>(iter: I) -> $a { | |
48 | iter.fold($zero, Add::add) | |
49 | } | |
50 | } | |
51 | ||
52 | #[$attr] | |
53 | impl Product for $a { | |
54 | fn product<I: Iterator<Item=$a>>(iter: I) -> $a { | |
55 | iter.fold($one, Mul::mul) | |
56 | } | |
57 | } | |
58 | ||
59 | #[$attr] | |
60 | impl<'a> Sum<&'a $a> for $a { | |
61 | fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a { | |
62 | iter.fold($zero, Add::add) | |
63 | } | |
64 | } | |
65 | ||
66 | #[$attr] | |
67 | impl<'a> Product<&'a $a> for $a { | |
68 | fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a { | |
69 | iter.fold($one, Mul::mul) | |
70 | } | |
71 | } | |
72 | )*); | |
73 | ($($a:ty)*) => ( | |
74 | integer_sum_product!(@impls 0, 1, | |
75 | #[stable(feature = "iter_arith_traits", since = "1.12.0")], | |
dc9dc135 | 76 | $($a)*); |
9fa01778 XL |
77 | integer_sum_product!(@impls Wrapping(0), Wrapping(1), |
78 | #[stable(feature = "wrapping_iter_arith", since = "1.14.0")], | |
dc9dc135 | 79 | $(Wrapping<$a>)*); |
9fa01778 XL |
80 | ); |
81 | } | |
82 | ||
83 | macro_rules! float_sum_product { | |
84 | ($($a:ident)*) => ($( | |
85 | #[stable(feature = "iter_arith_traits", since = "1.12.0")] | |
86 | impl Sum for $a { | |
87 | fn sum<I: Iterator<Item=$a>>(iter: I) -> $a { | |
e1599b0c | 88 | iter.fold(0.0, Add::add) |
9fa01778 XL |
89 | } |
90 | } | |
91 | ||
92 | #[stable(feature = "iter_arith_traits", since = "1.12.0")] | |
93 | impl Product for $a { | |
94 | fn product<I: Iterator<Item=$a>>(iter: I) -> $a { | |
e1599b0c | 95 | iter.fold(1.0, Mul::mul) |
9fa01778 XL |
96 | } |
97 | } | |
98 | ||
99 | #[stable(feature = "iter_arith_traits", since = "1.12.0")] | |
100 | impl<'a> Sum<&'a $a> for $a { | |
101 | fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a { | |
e1599b0c | 102 | iter.fold(0.0, Add::add) |
9fa01778 XL |
103 | } |
104 | } | |
105 | ||
106 | #[stable(feature = "iter_arith_traits", since = "1.12.0")] | |
107 | impl<'a> Product<&'a $a> for $a { | |
108 | fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a { | |
e1599b0c | 109 | iter.fold(1.0, Mul::mul) |
9fa01778 XL |
110 | } |
111 | } | |
112 | )*) | |
113 | } | |
114 | ||
115 | integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } | |
116 | float_sum_product! { f32 f64 } | |
117 | ||
60c5eb7d | 118 | #[stable(feature = "iter_arith_traits_result", since = "1.16.0")] |
9fa01778 | 119 | impl<T, U, E> Sum<Result<U, E>> for Result<T, E> |
60c5eb7d XL |
120 | where |
121 | T: Sum<U>, | |
9fa01778 XL |
122 | { |
123 | /// Takes each element in the `Iterator`: if it is an `Err`, no further | |
124 | /// elements are taken, and the `Err` is returned. Should no `Err` occur, | |
125 | /// the sum of all elements is returned. | |
126 | /// | |
127 | /// # Examples | |
128 | /// | |
129 | /// This sums up every integer in a vector, rejecting the sum if a negative | |
130 | /// element is encountered: | |
131 | /// | |
132 | /// ``` | |
133 | /// let v = vec![1, 2]; | |
134 | /// let res: Result<i32, &'static str> = v.iter().map(|&x: &i32| | |
135 | /// if x < 0 { Err("Negative element found") } | |
136 | /// else { Ok(x) } | |
137 | /// ).sum(); | |
138 | /// assert_eq!(res, Ok(3)); | |
139 | /// ``` | |
140 | fn sum<I>(iter: I) -> Result<T, E> | |
60c5eb7d XL |
141 | where |
142 | I: Iterator<Item = Result<U, E>>, | |
9fa01778 | 143 | { |
416331ca | 144 | iter::process_results(iter, |i| i.sum()) |
9fa01778 XL |
145 | } |
146 | } | |
147 | ||
60c5eb7d | 148 | #[stable(feature = "iter_arith_traits_result", since = "1.16.0")] |
9fa01778 | 149 | impl<T, U, E> Product<Result<U, E>> for Result<T, E> |
60c5eb7d XL |
150 | where |
151 | T: Product<U>, | |
9fa01778 XL |
152 | { |
153 | /// Takes each element in the `Iterator`: if it is an `Err`, no further | |
154 | /// elements are taken, and the `Err` is returned. Should no `Err` occur, | |
155 | /// the product of all elements is returned. | |
156 | fn product<I>(iter: I) -> Result<T, E> | |
60c5eb7d XL |
157 | where |
158 | I: Iterator<Item = Result<U, E>>, | |
9fa01778 | 159 | { |
416331ca | 160 | iter::process_results(iter, |i| i.product()) |
dc9dc135 XL |
161 | } |
162 | } | |
163 | ||
164 | #[stable(feature = "iter_arith_traits_option", since = "1.37.0")] | |
165 | impl<T, U> Sum<Option<U>> for Option<T> | |
166 | where | |
167 | T: Sum<U>, | |
168 | { | |
169 | /// Takes each element in the `Iterator`: if it is a `None`, no further | |
170 | /// elements are taken, and the `None` is returned. Should no `None` occur, | |
171 | /// the sum of all elements is returned. | |
172 | /// | |
173 | /// # Examples | |
174 | /// | |
175 | /// This sums up the position of the character 'a' in a vector of strings, | |
176 | /// if a word did not have the character 'a' the operation returns `None`: | |
177 | /// | |
178 | /// ``` | |
179 | /// let words = vec!["have", "a", "great", "day"]; | |
180 | /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum(); | |
181 | /// assert_eq!(total, Some(5)); | |
182 | /// ``` | |
183 | fn sum<I>(iter: I) -> Option<T> | |
184 | where | |
185 | I: Iterator<Item = Option<U>>, | |
186 | { | |
416331ca | 187 | iter.map(|x| x.ok_or(())).sum::<Result<_, _>>().ok() |
dc9dc135 XL |
188 | } |
189 | } | |
190 | ||
191 | #[stable(feature = "iter_arith_traits_option", since = "1.37.0")] | |
192 | impl<T, U> Product<Option<U>> for Option<T> | |
193 | where | |
194 | T: Product<U>, | |
195 | { | |
196 | /// Takes each element in the `Iterator`: if it is a `None`, no further | |
197 | /// elements are taken, and the `None` is returned. Should no `None` occur, | |
198 | /// the product of all elements is returned. | |
199 | fn product<I>(iter: I) -> Option<T> | |
200 | where | |
201 | I: Iterator<Item = Option<U>>, | |
202 | { | |
416331ca | 203 | iter.map(|x| x.ok_or(())).product::<Result<_, _>>().ok() |
dc9dc135 XL |
204 | } |
205 | } |