use core::marker::PhantomData;
use crate::{
cast::{self, ArrayCast},
matrix::{matrix_inverse, multiply_3x3, multiply_3x3_and_vec3},
num::{Arithmetics, IsValidDivisor, One, Recip, Zero},
ArrayExt, Mat3,
};
use super::{Convert, ConvertOnce};
pub struct Matrix3<I, O>
where
I: ArrayCast,
{
matrix: Mat3<<I::Array as ArrayExt>::Item>,
transform: PhantomData<fn(I) -> O>,
}
impl<I, O> Convert<I, O> for Matrix3<I, O>
where
Self: ConvertOnce<I, O> + Copy,
I: ArrayCast,
{
#[inline]
fn convert(&self, input: I) -> O {
Self::convert_once(*self, input)
}
}
impl<T, I, O> ConvertOnce<I, O> for Matrix3<I, O>
where
T: Arithmetics,
I: ArrayCast<Array = [T; 3]>,
O: ArrayCast<Array = I::Array>,
{
#[inline]
fn convert_once(self, input: I) -> O {
cast::from_array(multiply_3x3_and_vec3(self.matrix, cast::into_array(input)))
}
}
impl<T, C> Matrix3<C, C>
where
C: ArrayCast<Array = [T; 3]>,
{
#[rustfmt::skip]
#[inline]
pub fn identity() -> Self where T: One + Zero {
Self::from_array([
T::one(), T::zero(), T::zero(),
T::zero(), T::one(), T::zero(),
T::zero(), T::zero(), T::one(),
])
}
#[rustfmt::skip]
#[inline]
pub fn scale(s1: T, s2: T, s3: T) -> Self where T: Zero {
Self::from_array([
s1, T::zero(), T::zero(),
T::zero(), s2, T::zero(),
T::zero(), T::zero(), s3,
])
}
}
impl<T, I, O> Matrix3<I, O>
where
I: ArrayCast<Array = [T; 3]>,
O: ArrayCast<Array = I::Array>,
{
#[inline]
pub fn then<U>(self, next: Matrix3<O, U>) -> Matrix3<I, U>
where
U: ArrayCast<Array = I::Array>,
T: Arithmetics + Clone,
{
Matrix3 {
matrix: multiply_3x3(next.matrix, self.matrix),
transform: PhantomData,
}
}
#[inline]
pub fn invert(self) -> Matrix3<O, I>
where
T: Recip + IsValidDivisor<Mask = bool> + Arithmetics + Clone,
{
Matrix3 {
matrix: matrix_inverse(self.matrix),
transform: PhantomData,
}
}
#[inline]
pub const fn from_array(matrix: Mat3<T>) -> Self {
Self {
matrix,
transform: PhantomData,
}
}
#[inline]
pub fn into_array(self) -> Mat3<T> {
self.matrix
}
}
impl<I, O> Clone for Matrix3<I, O>
where
I: ArrayCast,
<I::Array as ArrayExt>::Item: Clone,
{
#[inline]
fn clone(&self) -> Self {
Self {
matrix: self.matrix.clone(),
transform: self.transform,
}
}
}
impl<I, O> Copy for Matrix3<I, O>
where
I: ArrayCast,
<I::Array as ArrayExt>::Item: Copy,
{
}