array__ops 1.0.3

A selection of useful array operations
Documentation
use core::ops::{AddAssign, Div, Mul};

use crate::private;

use super::{ArrayPartialMagnitude, ArrayMul, ArrayPartialMulDot};

#[const_trait]
pub trait ArrayProj<T, const N: usize>: ArrayPartialMulDot<T, N>
{
    fn proj<Rhs>(self, rhs: [Rhs; N]) -> [<T as Mul<<<T as Mul<Rhs>>::Output as Div<<T as Mul<T>>::Output>>::Output>>::Output; N]
    where
        T: Mul<Rhs, Output: AddAssign + Div<<T as Mul>::Output, Output: Copy>> + Mul<T, Output: AddAssign> + Mul<<<T as Mul<Rhs>>::Output as Div<<T as Mul<T>>::Output>>::Output> + Copy;
    async fn proj_async<Rhs>(self, rhs: [Rhs; N]) -> [<T as Mul<<<T as Mul<Rhs>>::Output as Div<<T as Mul<T>>::Output>>::Output>>::Output; N]
    where
        T: Mul<Rhs, Output: AddAssign + Div<<T as Mul>::Output, Output: Copy>> + Mul<T, Output: AddAssign> + Mul<<<T as Mul<Rhs>>::Output as Div<<T as Mul<T>>::Output>>::Output> + Copy;
}

impl<T, const N: usize> ArrayProj<T, N> for [T; N]
{
    fn proj<Rhs>(self, rhs: [Rhs; N]) -> [<T as Mul<<<T as Mul<Rhs>>::Output as Div<<T as Mul<T>>::Output>>::Output>>::Output; N]
    where
        T: Mul<Rhs, Output: AddAssign + Div<<T as Mul>::Output, Output: Copy>> + Mul<T, Output: AddAssign> + Mul<<<T as Mul<Rhs>>::Output as Div<<T as Mul<T>>::Output>>::Output> + Copy
    {
        if N == 0
        {
            return private::empty()
        }
        let uv = self.try_mul_dot(rhs);
        let uu = self.try_magnitude_squared();
        let a = unsafe {
            uv.unwrap_unchecked()/uu.unwrap_unchecked()
        };
        self.mul_all(a)
    }
    async fn proj_async<Rhs>(self, rhs: [Rhs; N]) -> [<T as Mul<<<T as Mul<Rhs>>::Output as Div<<T as Mul<T>>::Output>>::Output>>::Output; N]
    where
        T: Mul<Rhs, Output: AddAssign + Div<<T as Mul>::Output, Output: Copy>> + Mul<T, Output: AddAssign> + Mul<<<T as Mul<Rhs>>::Output as Div<<T as Mul<T>>::Output>>::Output> + Copy
    {
        if N == 0
        {
            return private::empty()
        }
        let (uv, uu) = core::future::join!(
            self.try_mul_dot_async(rhs),
            self.try_magnitude_squared_async()
        ).await;
        let a = unsafe {
            uv.unwrap_unchecked()/uu.unwrap_unchecked()
        };
        self.mul_all_async(a).await
    }
}