1#[cfg(not(feature = "ferrocene_certified"))]
2use crate::iter;
3#[cfg(not(feature = "ferrocene_certified"))]
4use crate::num::{Saturating, Wrapping};
5
6#[stable(feature = "iter_arith_traits", since = "1.12.0")]
15#[diagnostic::on_unimplemented(
16 message = "a value of type `{Self}` cannot be made by summing an iterator over elements of type `{A}`",
17 label = "value of type `{Self}` cannot be made by summing a `std::iter::Iterator<Item={A}>`"
18)]
19pub trait Sum<A = Self>: Sized {
20 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
23 fn sum<I: Iterator<Item = A>>(iter: I) -> Self;
24}
25
26#[stable(feature = "iter_arith_traits", since = "1.12.0")]
36#[diagnostic::on_unimplemented(
37 message = "a value of type `{Self}` cannot be made by multiplying all elements of type `{A}` from an iterator",
38 label = "value of type `{Self}` cannot be made by multiplying all elements from a `std::iter::Iterator<Item={A}>`"
39)]
40#[cfg(not(feature = "ferrocene_certified"))]
41pub trait Product<A = Self>: Sized {
42 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
45 fn product<I: Iterator<Item = A>>(iter: I) -> Self;
46}
47
48macro_rules! integer_sum_product {
49 (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($(
50 #[$attr]
51 impl Sum for $a {
52 fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
53 iter.fold(
54 $zero,
55 #[rustc_inherit_overflow_checks]
56 |a, b| a + b,
57 )
58 }
59 }
60
61 #[$attr]
62 #[cfg(not(feature = "ferrocene_certified"))]
63 impl Product for $a {
64 fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
65 iter.fold(
66 $one,
67 #[rustc_inherit_overflow_checks]
68 |a, b| a * b,
69 )
70 }
71 }
72
73 #[$attr]
74 impl<'a> Sum<&'a $a> for $a {
75 fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
76 iter.fold(
77 $zero,
78 #[rustc_inherit_overflow_checks]
79 |a, b| a + b,
80 )
81 }
82 }
83
84 #[$attr]
85 #[cfg(not(feature = "ferrocene_certified"))]
86 impl<'a> Product<&'a $a> for $a {
87 fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
88 iter.fold(
89 $one,
90 #[rustc_inherit_overflow_checks]
91 |a, b| a * b,
92 )
93 }
94 }
95 )*);
96 ($($a:ty)*) => (
97 integer_sum_product!(@impls 0, 1,
98 #[stable(feature = "iter_arith_traits", since = "1.12.0")],
99 $($a)*);
100 #[cfg(not(feature = "ferrocene_certified"))]
101 integer_sum_product!(@impls Wrapping(0), Wrapping(1),
102 #[stable(feature = "wrapping_iter_arith", since = "1.14.0")],
103 $(Wrapping<$a>)*);
104 );
105}
106
107#[cfg(not(feature = "ferrocene_certified"))]
108macro_rules! saturating_integer_sum_product {
109 (@impls $zero:expr, $one:expr, $doc:expr, #[$attr:meta], $($a:ty)*) => ($(
110 #[$attr]
111 #[doc = $doc]
112 impl Sum for $a {
113 fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
114 iter.fold(
115 $zero,
116 |a, b| a + b,
117 )
118 }
119 }
120
121 #[$attr]
122 #[doc = $doc]
123 impl Product for $a {
124 fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
125 iter.fold(
126 $one,
127 |a, b| a * b,
128 )
129 }
130 }
131
132 #[$attr]
133 #[doc = $doc]
134 impl<'a> Sum<&'a $a> for $a {
135 fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
136 iter.fold(
137 $zero,
138 |a, b| a + b,
139 )
140 }
141 }
142
143 #[$attr]
144 #[doc = $doc]
145 impl<'a> Product<&'a $a> for $a {
146 fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
147 iter.fold(
148 $one,
149 |a, b| a * b,
150 )
151 }
152 }
153 )*);
154 ($($a:ty)*) => (
155 saturating_integer_sum_product!(@impls Saturating(0), Saturating(1),
156 "The short-circuiting behavior of this implementation is unspecified. If you care about \
157 short-circuiting, use [`Iterator::fold`] directly.",
158 #[stable(feature = "saturating_iter_arith", since = "1.91.0")],
159 $(Saturating<$a>)*);
160 );
161}
162
163macro_rules! float_sum_product {
164 ($($a:ident)*) => ($(
165 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
166 impl Sum for $a {
167 fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
168 iter.fold(
169 -0.0,
170 #[rustc_inherit_overflow_checks]
171 |a, b| a + b,
172 )
173 }
174 }
175
176 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
177 #[cfg(not(feature = "ferrocene_certified"))]
178 impl Product for $a {
179 fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
180 iter.fold(
181 1.0,
182 #[rustc_inherit_overflow_checks]
183 |a, b| a * b,
184 )
185 }
186 }
187
188 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
189 impl<'a> Sum<&'a $a> for $a {
190 fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
191 iter.fold(
192 -0.0,
193 #[rustc_inherit_overflow_checks]
194 |a, b| a + b,
195 )
196 }
197 }
198
199 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
200 #[cfg(not(feature = "ferrocene_certified"))]
201 impl<'a> Product<&'a $a> for $a {
202 fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
203 iter.fold(
204 1.0,
205 #[rustc_inherit_overflow_checks]
206 |a, b| a * b,
207 )
208 }
209 }
210 )*)
211}
212
213integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
214#[cfg(not(feature = "ferrocene_certified"))]
215saturating_integer_sum_product! { u8 u16 u32 u64 u128 usize }
216float_sum_product! { f16 f32 f64 f128 }
217
218#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
219#[cfg(not(feature = "ferrocene_certified"))]
220impl<T, U, E> Sum<Result<U, E>> for Result<T, E>
221where
222 T: Sum<U>,
223{
224 fn sum<I>(iter: I) -> Result<T, E>
243 where
244 I: Iterator<Item = Result<U, E>>,
245 {
246 iter::try_process(iter, |i| i.sum())
247 }
248}
249
250#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
251#[cfg(not(feature = "ferrocene_certified"))]
252impl<T, U, E> Product<Result<U, E>> for Result<T, E>
253where
254 T: Product<U>,
255{
256 fn product<I>(iter: I) -> Result<T, E>
274 where
275 I: Iterator<Item = Result<U, E>>,
276 {
277 iter::try_process(iter, |i| i.product())
278 }
279}
280
281#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
282#[cfg(not(feature = "ferrocene_certified"))]
283impl<T, U> Sum<Option<U>> for Option<T>
284where
285 T: Sum<U>,
286{
287 fn sum<I>(iter: I) -> Option<T>
305 where
306 I: Iterator<Item = Option<U>>,
307 {
308 iter::try_process(iter, |i| i.sum())
309 }
310}
311
312#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
313#[cfg(not(feature = "ferrocene_certified"))]
314impl<T, U> Product<Option<U>> for Option<T>
315where
316 T: Product<U>,
317{
318 fn product<I>(iter: I) -> Option<T>
336 where
337 I: Iterator<Item = Option<U>>,
338 {
339 iter::try_process(iter, |i| i.product())
340 }
341}