arcium-primitives 0.4.5

Arcium primitives
Documentation
use super::wide_ops::MulAccReduce;
use crate::{izip_eq, utils::IntoExactSizeIterator};

pub trait DotProduct<Lhs = Self, Rhs = Lhs>: Sized {
    fn dot<I1, I2>(a: I1, b: I2) -> Self
    where
        I1: IntoExactSizeIterator<Item = Lhs>,
        I2: IntoExactSizeIterator<Item = Rhs>;
}

// TODO: Remove the `DefaultDotProduct` trait, default implementations directly.

/// Provide a default DotProduct implementation for types which implement DefaultDotProduct trait
pub trait DefaultDotProduct<Lhs = Self, Rhs = Lhs>: MulAccReduce<Lhs, Rhs> {}

// Blanket DotProduct implementation
impl<T, T1, T2> DotProduct<T1, T2> for T
where
    T: DefaultDotProduct<T1, T2>,
{
    fn dot<I1, I2>(a: I1, b: I2) -> Self
    where
        I1: IntoExactSizeIterator<Item = T1>,
        I2: IntoExactSizeIterator<Item = T2>,
    {
        let tmp = izip_eq!(a, b).fold(
            <T as MulAccReduce<T1, T2>>::zero_wide(),
            |mut acc, (ae, be)| {
                Self::mul_acc(&mut acc, ae, be);
                acc
            },
        );

        Self::reduce_mod_order(tmp)
    }
}