summaryrefslogtreecommitdiffstats
path: root/library/core/src/iter/traits/accum.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/core/src/iter/traits/accum.rs')
-rw-r--r--library/core/src/iter/traits/accum.rs231
1 files changed, 231 insertions, 0 deletions
diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs
new file mode 100644
index 000000000..84d83ee39
--- /dev/null
+++ b/library/core/src/iter/traits/accum.rs
@@ -0,0 +1,231 @@
+use crate::iter;
+use crate::num::Wrapping;
+
+/// Trait to represent types that can be created by summing up an iterator.
+///
+/// This trait is used to implement [`Iterator::sum()`]. Types which implement
+/// this trait can be generated by using the [`sum()`] method on an iterator.
+/// Like [`FromIterator`], this trait should rarely be called directly.
+///
+/// [`sum()`]: Iterator::sum
+/// [`FromIterator`]: iter::FromIterator
+#[stable(feature = "iter_arith_traits", since = "1.12.0")]
+pub trait Sum<A = Self>: Sized {
+ /// Method which takes an iterator and generates `Self` from the elements by
+ /// "summing up" the items.
+ #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+ fn sum<I: Iterator<Item = A>>(iter: I) -> Self;
+}
+
+/// Trait to represent types that can be created by multiplying elements of an
+/// iterator.
+///
+/// This trait is used to implement [`Iterator::product()`]. Types which implement
+/// this trait can be generated by using the [`product()`] method on an iterator.
+/// Like [`FromIterator`], this trait should rarely be called directly.
+///
+/// [`product()`]: Iterator::product
+/// [`FromIterator`]: iter::FromIterator
+#[stable(feature = "iter_arith_traits", since = "1.12.0")]
+pub trait Product<A = Self>: Sized {
+ /// Method which takes an iterator and generates `Self` from the elements by
+ /// multiplying the items.
+ #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+ fn product<I: Iterator<Item = A>>(iter: I) -> Self;
+}
+
+macro_rules! integer_sum_product {
+ (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($(
+ #[$attr]
+ impl Sum for $a {
+ fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
+ iter.fold(
+ $zero,
+ #[rustc_inherit_overflow_checks]
+ |a, b| a + b,
+ )
+ }
+ }
+
+ #[$attr]
+ impl Product for $a {
+ fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
+ iter.fold(
+ $one,
+ #[rustc_inherit_overflow_checks]
+ |a, b| a * b,
+ )
+ }
+ }
+
+ #[$attr]
+ impl<'a> Sum<&'a $a> for $a {
+ fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
+ iter.fold(
+ $zero,
+ #[rustc_inherit_overflow_checks]
+ |a, b| a + b,
+ )
+ }
+ }
+
+ #[$attr]
+ impl<'a> Product<&'a $a> for $a {
+ fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
+ iter.fold(
+ $one,
+ #[rustc_inherit_overflow_checks]
+ |a, b| a * b,
+ )
+ }
+ }
+ )*);
+ ($($a:ty)*) => (
+ integer_sum_product!(@impls 0, 1,
+ #[stable(feature = "iter_arith_traits", since = "1.12.0")],
+ $($a)*);
+ integer_sum_product!(@impls Wrapping(0), Wrapping(1),
+ #[stable(feature = "wrapping_iter_arith", since = "1.14.0")],
+ $(Wrapping<$a>)*);
+ );
+}
+
+macro_rules! float_sum_product {
+ ($($a:ident)*) => ($(
+ #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+ impl Sum for $a {
+ fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
+ iter.fold(
+ 0.0,
+ #[rustc_inherit_overflow_checks]
+ |a, b| a + b,
+ )
+ }
+ }
+
+ #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+ impl Product for $a {
+ fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
+ iter.fold(
+ 1.0,
+ #[rustc_inherit_overflow_checks]
+ |a, b| a * b,
+ )
+ }
+ }
+
+ #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+ impl<'a> Sum<&'a $a> for $a {
+ fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
+ iter.fold(
+ 0.0,
+ #[rustc_inherit_overflow_checks]
+ |a, b| a + b,
+ )
+ }
+ }
+
+ #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+ impl<'a> Product<&'a $a> for $a {
+ fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
+ iter.fold(
+ 1.0,
+ #[rustc_inherit_overflow_checks]
+ |a, b| a * b,
+ )
+ }
+ }
+ )*)
+}
+
+integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
+float_sum_product! { f32 f64 }
+
+#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
+impl<T, U, E> Sum<Result<U, E>> for Result<T, E>
+where
+ T: Sum<U>,
+{
+ /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
+ /// elements are taken, and the [`Err`] is returned. Should no [`Err`]
+ /// occur, the sum of all elements is returned.
+ ///
+ /// # Examples
+ ///
+ /// This sums up every integer in a vector, rejecting the sum if a negative
+ /// element is encountered:
+ ///
+ /// ```
+ /// let v = vec![1, 2];
+ /// let res: Result<i32, &'static str> = v.iter().map(|&x: &i32|
+ /// if x < 0 { Err("Negative element found") }
+ /// else { Ok(x) }
+ /// ).sum();
+ /// assert_eq!(res, Ok(3));
+ /// ```
+ fn sum<I>(iter: I) -> Result<T, E>
+ where
+ I: Iterator<Item = Result<U, E>>,
+ {
+ iter::try_process(iter, |i| i.sum())
+ }
+}
+
+#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
+impl<T, U, E> Product<Result<U, E>> for Result<T, E>
+where
+ T: Product<U>,
+{
+ /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
+ /// elements are taken, and the [`Err`] is returned. Should no [`Err`]
+ /// occur, the product of all elements is returned.
+ fn product<I>(iter: I) -> Result<T, E>
+ where
+ I: Iterator<Item = Result<U, E>>,
+ {
+ iter::try_process(iter, |i| i.product())
+ }
+}
+
+#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
+impl<T, U> Sum<Option<U>> for Option<T>
+where
+ T: Sum<U>,
+{
+ /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
+ /// elements are taken, and the [`None`] is returned. Should no [`None`]
+ /// occur, the sum of all elements is returned.
+ ///
+ /// # Examples
+ ///
+ /// This sums up the position of the character 'a' in a vector of strings,
+ /// if a word did not have the character 'a' the operation returns `None`:
+ ///
+ /// ```
+ /// let words = vec!["have", "a", "great", "day"];
+ /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
+ /// assert_eq!(total, Some(5));
+ /// ```
+ fn sum<I>(iter: I) -> Option<T>
+ where
+ I: Iterator<Item = Option<U>>,
+ {
+ iter::try_process(iter, |i| i.sum())
+ }
+}
+
+#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
+impl<T, U> Product<Option<U>> for Option<T>
+where
+ T: Product<U>,
+{
+ /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
+ /// elements are taken, and the [`None`] is returned. Should no [`None`]
+ /// occur, the product of all elements is returned.
+ fn product<I>(iter: I) -> Option<T>
+ where
+ I: Iterator<Item = Option<U>>,
+ {
+ iter::try_process(iter, |i| i.product())
+ }
+}