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