]> git.proxmox.com Git - rustc.git/blame - src/libcore/iter/traits/accum.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / libcore / iter / traits / accum.rs
CommitLineData
416331ca 1use crate::iter;
60c5eb7d
XL
2use crate::num::Wrapping;
3use 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")]
16pub 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")]
35pub 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
43macro_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
83macro_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
115integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
116float_sum_product! { f32 f64 }
117
60c5eb7d 118#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
9fa01778 119impl<T, U, E> Sum<Result<U, E>> for Result<T, E>
60c5eb7d
XL
120where
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 149impl<T, U, E> Product<Result<U, E>> for Result<T, E>
60c5eb7d
XL
150where
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")]
165impl<T, U> Sum<Option<U>> for Option<T>
166where
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")]
192impl<T, U> Product<Option<U>> for Option<T>
193where
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}