use core::ops::{MulAssign, Sub};
use array_trait::Array;
use slice_ops::AsSlice;
use crate::form::ArrayForm;
#[const_trait]
pub trait ArrayMulCross<T, const N: usize>: Array + AsSlice<Item = T>
{
fn mul_cross<Rhs>(&self, rhs: [&Rhs; N - 2]) -> [<T as Sub>::Output; N]
where
T: MulAssign<Rhs::Elem> + Sub + Copy,
Rhs: ArrayForm<N, Elem: Copy>;
async fn mul_cross_async<Rhs>(&self, rhs: [&Rhs; N - 2]) -> [<T as Sub>::Output; N]
where
T: MulAssign<Rhs::Elem> + Sub + Copy,
Rhs: ArrayForm<N, Elem: Copy>;
}
impl<T, const N: usize> ArrayMulCross<T, N> for [T; N]
{
fn mul_cross<Rhs>(&self, rhs: [&Rhs; N - 2]) -> [<T as Sub>::Output; N]
where
T: MulAssign<Rhs::Elem> + Sub + Copy,
Rhs: ArrayForm<N, Elem: Copy>
{
crate::from_fn(|i| {
let mut m_p = self[(i + 1) % N];
let mut m_m = self[(i + (N - 1)) % N];
let mut n = 2;
while n < N
{
m_p *= rhs[n - 2].copy_elem((i + n) % N);
m_m *= rhs[n - 2].copy_elem((i + (N - n)) % N);
n += 1;
}
m_p - m_m
})
}
async fn mul_cross_async<Rhs>(&self, rhs: [&Rhs; N - 2]) -> [<T as Sub>::Output; N]
where
T: MulAssign<Rhs::Elem> + Sub + Copy,
Rhs: ArrayForm<N, Elem: Copy>
{
crate::from_fn_async(async |i| {
let mut m_p = self[(i + 1) % N];
let mut m_m = self[(i + (N - 1)) % N];
let mut n = 2;
while n < N
{
m_p *= rhs[n - 2].copy_elem((i + n) % N);
m_m *= rhs[n - 2].copy_elem((i + (N - n)) % N);
n += 1;
}
m_p - m_m
}).await
}
}