primitives/algebra/ops/
dot_product.rs

1use super::wide_ops::MulAccReduce;
2use crate::{izip_eq, utils::IntoExactSizeIterator};
3
4pub trait DotProduct<Lhs = Self, Rhs = Lhs>: Sized {
5    fn dot<I1, I2>(a: I1, b: I2) -> Self
6    where
7        I1: IntoExactSizeIterator<Item = Lhs>,
8        I2: IntoExactSizeIterator<Item = Rhs>;
9}
10
11// TODO: Remove the `DefaultDotProduct` trait, default implementations directly.
12
13/// Provide a default DotProduct implementation for types which implement DefaultDotProduct trait
14pub trait DefaultDotProduct<Lhs = Self, Rhs = Lhs>: MulAccReduce<Lhs, Rhs> {}
15
16// Blanket DotProduct implementation
17impl<T, T1, T2> DotProduct<T1, T2> for T
18where
19    T: DefaultDotProduct<T1, T2>,
20{
21    fn dot<I1, I2>(a: I1, b: I2) -> Self
22    where
23        I1: IntoExactSizeIterator<Item = T1>,
24        I2: IntoExactSizeIterator<Item = T2>,
25    {
26        let tmp = izip_eq!(a, b).fold(
27            <T as MulAccReduce<T1, T2>>::zero_wide(),
28            |mut acc, (ae, be)| {
29                Self::mul_acc(&mut acc, ae, be);
30                acc
31            },
32        );
33
34        Self::reduce_mod_order(tmp)
35    }
36}