Skip to content

Commit 0492ebe

Browse files
authored
Unrolled build for #144275
Rollup merge of #144275 - Qelxiros:saturating-arithmetic, r=tgross35 implement Sum and Product for Saturating(u*) ACP: rust-lang/libs-team#604 `@rustbot` label +needs-fcp
2 parents ef8d1d6 + 1a33d62 commit 0492ebe

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed

library/core/src/iter/traits/accum.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::iter;
2-
use crate::num::Wrapping;
2+
use crate::num::{Saturating, Wrapping};
33

44
/// Trait to represent types that can be created by summing up an iterator.
55
///
@@ -98,6 +98,61 @@ macro_rules! integer_sum_product {
9898
);
9999
}
100100

101+
macro_rules! saturating_integer_sum_product {
102+
(@impls $zero:expr, $one:expr, $doc:expr, #[$attr:meta], $($a:ty)*) => ($(
103+
#[$attr]
104+
#[doc = $doc]
105+
impl Sum for $a {
106+
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
107+
iter.fold(
108+
$zero,
109+
|a, b| a + b,
110+
)
111+
}
112+
}
113+
114+
#[$attr]
115+
#[doc = $doc]
116+
impl Product for $a {
117+
fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
118+
iter.fold(
119+
$one,
120+
|a, b| a * b,
121+
)
122+
}
123+
}
124+
125+
#[$attr]
126+
#[doc = $doc]
127+
impl<'a> Sum<&'a $a> for $a {
128+
fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
129+
iter.fold(
130+
$zero,
131+
|a, b| a + b,
132+
)
133+
}
134+
}
135+
136+
#[$attr]
137+
#[doc = $doc]
138+
impl<'a> Product<&'a $a> for $a {
139+
fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
140+
iter.fold(
141+
$one,
142+
|a, b| a * b,
143+
)
144+
}
145+
}
146+
)*);
147+
($($a:ty)*) => (
148+
saturating_integer_sum_product!(@impls Saturating(0), Saturating(1),
149+
"The short-circuiting behavior of this implementation is unspecified. If you care about \
150+
short-circuiting, use [`Iterator::fold`] directly.",
151+
#[stable(feature = "saturating_iter_arith", since = "CURRENT_RUSTC_VERSION")],
152+
$(Saturating<$a>)*);
153+
);
154+
}
155+
101156
macro_rules! float_sum_product {
102157
($($a:ident)*) => ($(
103158
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
@@ -147,6 +202,7 @@ macro_rules! float_sum_product {
147202
}
148203

149204
integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
205+
saturating_integer_sum_product! { u8 u16 u32 u64 u128 usize }
150206
float_sum_product! { f32 f64 }
151207

152208
#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]

library/coretests/tests/iter/traits/accum.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::iter::*;
2+
use std::num::Saturating;
23

34
#[test]
45
fn test_iterator_sum() {
@@ -64,3 +65,38 @@ fn test_iterator_product_option() {
6465
let v: &[Option<i32>] = &[Some(1), None, Some(3), Some(4)];
6566
assert_eq!(v.iter().cloned().product::<Option<i32>>(), None);
6667
}
68+
69+
#[test]
70+
fn test_saturating_sum_product() {
71+
let v = (1u32..=10).map(|i| Saturating(i));
72+
assert_eq!(v.sum::<Saturating<u32>>(), Saturating(55));
73+
let v = (1u32..=10).map(|i| Saturating(i));
74+
assert_eq!(v.product::<Saturating<u32>>(), Saturating(3628800));
75+
let v = [Saturating(usize::MAX), Saturating(2)];
76+
assert_eq!(v.iter().copied().sum::<Saturating<usize>>(), Saturating(usize::MAX));
77+
assert_eq!(v.iter().copied().product::<Saturating<usize>>(), Saturating(usize::MAX));
78+
79+
let mut cnt = 0;
80+
let v = 250..=u8::MAX;
81+
assert_eq!(
82+
v.map(|i| {
83+
cnt += 1;
84+
Saturating(i)
85+
})
86+
.sum::<Saturating<u8>>(),
87+
Saturating(u8::MAX)
88+
);
89+
assert_eq!(cnt, 6); // no short-circuiting
90+
91+
let mut cnt = 0;
92+
let v = (250..=u8::MAX).chain(0..5);
93+
assert_eq!(
94+
v.map(|i| {
95+
cnt += 1;
96+
Saturating(i)
97+
})
98+
.product::<Saturating<u8>>(),
99+
Saturating(0)
100+
);
101+
assert_eq!(cnt, 11); // no short-circuiting
102+
}

0 commit comments

Comments
 (0)