2 use crate::num::Wrapping;
3 use crate::ops::{Add, Mul};
5 /// Trait to represent types that can be created by summing up an iterator.
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()`].
12 /// [`sum()`]: Sum::sum
13 /// [`FromIterator`]: iter::FromIterator
14 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
15 pub trait Sum<A = Self>: Sized {
16 /// Method which takes an iterator and generates `Self` from the elements by
17 /// "summing up" the items.
18 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
19 fn sum<I: Iterator<Item = A>>(iter: I) -> Self;
22 /// Trait to represent types that can be created by multiplying elements of an
25 /// This trait is used to implement the [`product()`] method on iterators. Types
26 /// which implement the trait can be generated by the [`product()`] method. Like
27 /// [`FromIterator`] this trait should rarely be called directly and instead
28 /// interacted with through [`Iterator::product()`].
30 /// [`product()`]: Product::product
31 /// [`FromIterator`]: iter::FromIterator
32 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
33 pub trait Product<A = Self>: Sized {
34 /// Method which takes an iterator and generates `Self` from the elements by
35 /// multiplying the items.
36 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
37 fn product<I: Iterator<Item = A>>(iter: I) -> Self;
40 // N.B., explicitly use Add and Mul here to inherit overflow checks
41 macro_rules! integer_sum_product {
42 (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($(
45 fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
46 iter.fold($zero, Add::add)
52 fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
53 iter.fold($one, Mul::mul)
58 impl<'a> Sum<&'a $a> for $a {
59 fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
60 iter.fold($zero, Add::add)
65 impl<'a> Product<&'a $a> for $a {
66 fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
67 iter.fold($one, Mul::mul)
72 integer_sum_product!(@impls 0, 1,
73 #[stable(feature = "iter_arith_traits", since = "1.12.0")],
75 integer_sum_product!(@impls Wrapping(0), Wrapping(1),
76 #[stable(feature = "wrapping_iter_arith", since = "1.14.0")],
81 macro_rules! float_sum_product {
83 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
85 fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
86 iter.fold(0.0, Add::add)
90 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
92 fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
93 iter.fold(1.0, Mul::mul)
97 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
98 impl<'a> Sum<&'a $a> for $a {
99 fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
100 iter.fold(0.0, Add::add)
104 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
105 impl<'a> Product<&'a $a> for $a {
106 fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
107 iter.fold(1.0, Mul::mul)
113 integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
114 float_sum_product! { f32 f64 }
116 #[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
117 impl<T, U, E> Sum<Result<U, E>> for Result<T, E>
121 /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
122 /// elements are taken, and the [`Err`] is returned. Should no [`Err`]
123 /// occur, the sum of all elements is returned.
127 /// This sums up every integer in a vector, rejecting the sum if a negative
128 /// element is encountered:
131 /// let v = vec![1, 2];
132 /// let res: Result<i32, &'static str> = v.iter().map(|&x: &i32|
133 /// if x < 0 { Err("Negative element found") }
136 /// assert_eq!(res, Ok(3));
138 fn sum<I>(iter: I) -> Result<T, E>
140 I: Iterator<Item = Result<U, E>>,
142 iter::process_results(iter, |i| i.sum())
146 #[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
147 impl<T, U, E> Product<Result<U, E>> for Result<T, E>
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 product of all elements is returned.
154 fn product<I>(iter: I) -> Result<T, E>
156 I: Iterator<Item = Result<U, E>>,
158 iter::process_results(iter, |i| i.product())
162 #[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
163 impl<T, U> Sum<Option<U>> for Option<T>
167 /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
168 /// elements are taken, and the [`None`] is returned. Should no [`None`]
169 /// occur, the sum of all elements is returned.
173 /// This sums up the position of the character 'a' in a vector of strings,
174 /// if a word did not have the character 'a' the operation returns `None`:
177 /// let words = vec!["have", "a", "great", "day"];
178 /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
179 /// assert_eq!(total, Some(5));
181 fn sum<I>(iter: I) -> Option<T>
183 I: Iterator<Item = Option<U>>,
185 iter.map(|x| x.ok_or(())).sum::<Result<_, _>>().ok()
189 #[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
190 impl<T, U> Product<Option<U>> for Option<T>
194 /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
195 /// elements are taken, and the [`None`] is returned. Should no [`None`]
196 /// occur, the product of all elements is returned.
197 fn product<I>(iter: I) -> Option<T>
199 I: Iterator<Item = Option<U>>,
201 iter.map(|x| x.ok_or(())).product::<Result<_, _>>().ok()