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>;
}
pub trait DefaultDotProduct<Lhs = Self, Rhs = Lhs>: MulAccReduce<Lhs, Rhs> {}
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)
}
}