extensor 0.1.1

the main extensor crate for building arbitrary valent tensors and more.
Documentation
use super::*;

pub trait ProductType
where
    Self: Sized,
{
    type X;
    type Y;

    fn construct(x: Self::X, y: Self::Y) -> Self;

    #[allow(non_snake_case)]
    fn pi_X(&self) -> Self::X;

    #[allow(non_snake_case)]
    fn pi_Y(&self) -> Self::Y;

    #[allow(non_snake_case)]
    fn f<Z>(z: &Z, f_X: impl Fn(&Z) -> Self::X, f_Y: impl Fn(&Z) -> Self::Y) -> Self {
        Self::construct(f_X(z), f_Y(z))
    }
}

#[derive(Copy, Clone)]
pub struct DirectProduct<const M: usize, const N: usize, F> {
    v: V<M, F>,
    w: V<N, F>,
}

impl<const M: usize, const N: usize, F> ProductType for DirectProduct<M, N, F>
where
    F: Copy,
{
    type X = V<M, F>;
    type Y = V<N, F>;

    fn construct(v: Self::X, w: Self::Y) -> Self {
        DirectProduct { v, w }
    }

    fn pi_X(&self) -> Self::X {
        self.v
    }

    fn pi_Y(&self) -> Self::Y {
        self.w
    }
}

impl<const M: usize, const N: usize, F> Add for DirectProduct<M, N, F>
where
    F: Add<Output = F> + Default + Copy,
{
    type Output = Self;
    fn add(self, other: DirectProduct<M, N, F>) -> Self::Output {
        DirectProduct::construct(self.pi_X() + other.pi_X(), self.pi_Y() + other.pi_Y())
    }
}

impl<const M: usize, const N: usize, F> Mul<F> for DirectProduct<M, N, F>
where
    F: Mul<Output = F> + Default + Copy,
{
    type Output = Self;
    fn mul(self, scalar: F) -> Self::Output {
        DirectProduct::construct(self.pi_X() * scalar, self.pi_Y() * scalar)
    }
}