Skip to main content

dashu_cmplx/
iter.rs

1//! Implementation of core::iter traits for [`CBig`].
2//!
3//! `Sum`/`Product` fold with the binary `+`/`*` operators (componentwise perfectly-rounded real
4//! ops on each part). The impls are concrete (`Sum`/`Sum<&CBig>`, `Product`/`Product<&CBig>`)
5//! rather than generic over `Add`/`Mul`, matching the narrowed iter surface used for `FBig`. A
6//! correctly-rounded (exact-accumulating) `Sum` for `CBig` is a possible future refinement.
7
8use crate::cbig::CBig;
9use core::iter::{Product, Sum};
10use dashu_float::round::Round;
11use dashu_int::Word;
12
13impl<R: Round, const B: Word> Sum for CBig<R, B> {
14    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
15        iter.fold(CBig::ZERO, |acc, x| acc + x)
16    }
17}
18
19impl<'a, R: Round, const B: Word> Sum<&'a CBig<R, B>> for CBig<R, B> {
20    fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
21        iter.fold(CBig::ZERO, |acc, x| acc + x)
22    }
23}
24
25impl<R: Round, const B: Word> Product for CBig<R, B> {
26    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
27        iter.fold(CBig::ONE, |acc, x| acc * x)
28    }
29}
30
31impl<'a, R: Round, const B: Word> Product<&'a CBig<R, B>> for CBig<R, B> {
32    fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
33        iter.fold(CBig::ONE, |acc, x| acc * x)
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use crate::cbig::CBig;
40    use dashu_float::round::mode::HalfAway;
41    use dashu_float::FBig;
42
43    type C = CBig<HalfAway, 10>;
44    type F = FBig<HalfAway, 10>;
45
46    #[test]
47    fn sum_owned_and_ref() {
48        let z = C::from_parts(F::from(3), F::from(4)); // 3 + 4i
49        let w = C::from_parts(F::from(1), F::from(2)); // 1 + 2i
50        let expected = C::from_parts(F::from(4), F::from(6));
51
52        let owned: C = [z.clone(), w.clone()].into_iter().sum();
53        assert_eq!(owned, expected);
54
55        let by_ref: C = [z, w].iter().sum();
56        assert_eq!(by_ref, expected);
57    }
58
59    #[test]
60    fn product_owned_and_ref() {
61        // (3+4i)(1+2i) = (3-8) + (6+4)i = -5 + 10i
62        let z = C::from_parts(F::from(3), F::from(4));
63        let w = C::from_parts(F::from(1), F::from(2));
64        let expected = C::from_parts(F::from(-5), F::from(10));
65
66        let owned: C = [z.clone(), w.clone()].into_iter().product();
67        assert_eq!(owned, expected);
68
69        let by_ref: C = [z, w].iter().product();
70        assert_eq!(by_ref, expected);
71    }
72
73    #[test]
74    fn sum_and_product_empty() {
75        let s: C = core::iter::empty::<C>().sum();
76        assert_eq!(s, C::ZERO);
77        let p: C = core::iter::empty::<C>().product();
78        assert_eq!(p, C::ONE);
79    }
80}