use super::HeaplessBigInt;
use crate::MachineWord;
use const_num_traits::{CarryingMul, One, Personality, Zero};
impl<T, const CAP: usize, P: Personality> core::iter::Sum for HeaplessBigInt<T, CAP, P>
where
T: MachineWord,
{
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.fold(<Self as Zero>::zero(), |acc, x| acc + x)
}
}
impl<'a, T, const CAP: usize, P: Personality> core::iter::Sum<&'a Self>
for HeaplessBigInt<T, CAP, P>
where
T: MachineWord,
{
fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
iter.fold(<Self as Zero>::zero(), |acc, x| acc + *x)
}
}
impl<T, const CAP: usize, P: Personality> core::iter::Product for HeaplessBigInt<T, CAP, P>
where
T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
{
fn product<I: Iterator<Item = Self>>(mut iter: I) -> Self {
match iter.next() {
None => <Self as One>::one(),
Some(first) => iter.fold(first, |acc, x| acc * x),
}
}
}
impl<'a, T, const CAP: usize, P: Personality> core::iter::Product<&'a Self>
for HeaplessBigInt<T, CAP, P>
where
T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
{
fn product<I: Iterator<Item = &'a Self>>(mut iter: I) -> Self {
match iter.next() {
None => <Self as One>::one(),
Some(first) => iter.fold(*first, |acc, x| acc * *x),
}
}
}
#[cfg(test)]
mod tests {
use super::HeaplessBigInt;
type H = HeaplessBigInt<u8, 8>;
#[test]
fn sum_product() {
let vals = [H::from(1u8), H::from(2u8), H::from(3u8), H::from(4u8)];
assert_eq!(vals.iter().copied().sum::<H>(), H::from(10u8));
assert_eq!(vals.iter().sum::<H>(), H::from(10u8));
assert_eq!(vals.iter().copied().product::<H>(), H::from(24u8));
assert_eq!(vals.iter().product::<H>(), H::from(24u8));
}
#[test]
fn empty_iter_is_identity() {
let empty: [H; 0] = [];
assert_eq!(empty.iter().copied().sum::<H>(), H::from(0u8));
assert_eq!(empty.iter().copied().product::<H>(), H::from(1u8));
}
#[test]
fn product_preserves_operand_width_not_identity() {
let zeros = [H::new_zero_with_len(0)];
let p = zeros.iter().copied().product::<H>();
assert!(<H as const_num_traits::Zero>::is_zero(&p));
assert_eq!(p.len(), 0);
let mixed = [H::from(2u8), H::from(3u8).widened(8)];
assert_eq!(mixed.iter().copied().product::<H>().len(), 8);
}
}