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
48#[cfg(not(feature = "ferrocene_certified"))]
49macro_rules! integer_sum_product {
50 (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($(
51 #[$attr]
52 impl Sum for $a {
53 fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
54 iter.fold(
55 $zero,
56 #[rustc_inherit_overflow_checks]
57 |a, b| a + b,
58 )
59 }
60 }
61
62 #[$attr]
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 impl<'a> Product<&'a $a> for $a {
86 fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
87 iter.fold(
88 $one,
89 #[rustc_inherit_overflow_checks]
90 |a, b| a * b,
91 )
92 }
93 }
94 )*);
95 ($($a:ty)*) => (
96 integer_sum_product!(@impls 0, 1,
97 #[stable(feature = "iter_arith_traits", since = "1.12.0")],
98 $($a)*);
99 integer_sum_product!(@impls Wrapping(0), Wrapping(1),
100 #[stable(feature = "wrapping_iter_arith", since = "1.14.0")],
101 $(Wrapping<$a>)*);
102 );
103}
104
105#[cfg(not(feature = "ferrocene_certified"))]
106macro_rules! saturating_integer_sum_product {
107 (@impls $zero:expr, $one:expr, $doc:expr, #[$attr:meta], $($a:ty)*) => ($(
108 #[$attr]
109 #[doc = $doc]
110 impl Sum for $a {
111 fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
112 iter.fold(
113 $zero,
114 |a, b| a + b,
115 )
116 }
117 }
118
119 #[$attr]
120 #[doc = $doc]
121 impl Product for $a {
122 fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
123 iter.fold(
124 $one,
125 |a, b| a * b,
126 )
127 }
128 }
129
130 #[$attr]
131 #[doc = $doc]
132 impl<'a> Sum<&'a $a> for $a {
133 fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
134 iter.fold(
135 $zero,
136 |a, b| a + b,
137 )
138 }
139 }
140
141 #[$attr]
142 #[doc = $doc]
143 impl<'a> Product<&'a $a> for $a {
144 fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
145 iter.fold(
146 $one,
147 |a, b| a * b,
148 )
149 }
150 }
151 )*);
152 ($($a:ty)*) => (
153 saturating_integer_sum_product!(@impls Saturating(0), Saturating(1),
154 "The short-circuiting behavior of this implementation is unspecified. If you care about \
155 short-circuiting, use [`Iterator::fold`] directly.",
156 #[stable(feature = "saturating_iter_arith", since = "1.91.0")],
157 $(Saturating<$a>)*);
158 );
159}
160
161macro_rules! float_sum_product {
162 ($($a:ident)*) => ($(
163 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
164 impl Sum for $a {
165 fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
166 iter.fold(
167 -0.0,
168 #[rustc_inherit_overflow_checks]
169 |a, b| a + b,
170 )
171 }
172 }
173
174 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
175 #[cfg(not(feature = "ferrocene_certified"))]
176 impl Product for $a {
177 fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
178 iter.fold(
179 1.0,
180 #[rustc_inherit_overflow_checks]
181 |a, b| a * b,
182 )
183 }
184 }
185
186 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
187 impl<'a> Sum<&'a $a> for $a {
188 fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
189 iter.fold(
190 -0.0,
191 #[rustc_inherit_overflow_checks]
192 |a, b| a + b,
193 )
194 }
195 }
196
197 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
198 #[cfg(not(feature = "ferrocene_certified"))]
199 impl<'a> Product<&'a $a> for $a {
200 fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
201 iter.fold(
202 1.0,
203 #[rustc_inherit_overflow_checks]
204 |a, b| a * b,
205 )
206 }
207 }
208 )*)
209}
210
211#[cfg(not(feature = "ferrocene_certified"))]
212integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
213#[cfg(not(feature = "ferrocene_certified"))]
214saturating_integer_sum_product! { u8 u16 u32 u64 u128 usize }
215float_sum_product! { f16 f32 f64 f128 }
216
217#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
218#[cfg(not(feature = "ferrocene_certified"))]
219impl<T, U, E> Sum<Result<U, E>> for Result<T, E>
220where
221 T: Sum<U>,
222{
223 fn sum<I>(iter: I) -> Result<T, E>
242 where
243 I: Iterator<Item = Result<U, E>>,
244 {
245 iter::try_process(iter, |i| i.sum())
246 }
247}
248
249#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
250#[cfg(not(feature = "ferrocene_certified"))]
251impl<T, U, E> Product<Result<U, E>> for Result<T, E>
252where
253 T: Product<U>,
254{
255 fn product<I>(iter: I) -> Result<T, E>
273 where
274 I: Iterator<Item = Result<U, E>>,
275 {
276 iter::try_process(iter, |i| i.product())
277 }
278}
279
280#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
281#[cfg(not(feature = "ferrocene_certified"))]
282impl<T, U> Sum<Option<U>> for Option<T>
283where
284 T: Sum<U>,
285{
286 fn sum<I>(iter: I) -> Option<T>
304 where
305 I: Iterator<Item = Option<U>>,
306 {
307 iter::try_process(iter, |i| i.sum())
308 }
309}
310
311#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
312#[cfg(not(feature = "ferrocene_certified"))]
313impl<T, U> Product<Option<U>> for Option<T>
314where
315 T: Product<U>,
316{
317 fn product<I>(iter: I) -> Option<T>
335 where
336 I: Iterator<Item = Option<U>>,
337 {
338 iter::try_process(iter, |i| i.product())
339 }
340}