use num_traits::float::Float;
use std::ops::{Add, AddAssign, Div, DivAssign, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign};
#[rustfmt::skip]
pub trait ScalarOps<V>:
Copy
+ Add<V, Output = V>
+ Sub<V, Output = V>
+ Mul<V, Output = V>
+ Div<V, Output = V>
{}
#[rustfmt::skip]
pub trait VecOps<S>:
Copy
+ Default
+ Add<Self, Output = Self> + AddAssign<Self>
+ Sub<Self, Output = Self> + SubAssign<Self>
+ Mul<Self, Output = Self> + MulAssign<Self>
+ Div<Self, Output = Self> + DivAssign<Self>
+ Add<S, Output = Self> + AddAssign<Self>
+ Sub<S, Output = Self> + SubAssign<Self>
+ Mul<S, Output = Self> + MulAssign<S>
+ Div<S, Output = Self> + DivAssign<S>
+ Neg<Output = Self>
+ IndexMut<usize, Output = S>
+ PartialEq<Self>
{}
#[rustfmt::skip]
pub trait MatOps<S, V>:
Copy
+ Default
+ Add<Self, Output = Self> + AddAssign<Self>
+ Sub<Self, Output = Self> + SubAssign<Self>
+ Mul<V, Output = V>
+ Mul<Self, Output = Self> + MulAssign<Self>
+ Neg<Output = Self>
+ IndexMut<usize, Output = V>
+ PartialEq<Self>
{}
pub trait Vec2<S>
where
Self: VecOps<S>,
S: Float + ScalarOps<Self>,
{
fn new(x: S, y: S) -> Self;
fn as_array(&self) -> &[S; 2];
fn as_mut_array(&mut self) -> &mut [S; 2];
fn add_componentwise(&self, rhs: Self) -> Self;
fn sub_componentwise(&self, rhs: Self) -> Self;
fn mul_componentwise(&self, rhs: Self) -> Self;
fn div_componentwise(&self, rhs: Self) -> Self;
fn min_componentwise(&self, rhs: Self) -> Self;
fn max_componentwise(&self, rhs: Self) -> Self;
fn floor(&self) -> Self;
fn min_reduce(&self) -> S;
fn max_reduce(&self) -> S;
fn eq_reduce(&self, rhs: Self) -> bool;
fn dot(&self, rhs: Self) -> S;
fn splat(value: S) -> Self {
Self::new(value, value)
}
fn norm(&self) -> S {
self.dot(*self).sqrt()
}
fn normalize(&self) -> Self {
self.div(Self::splat(self.norm()))
}
}
pub trait Vec4<S>
where
Self: VecOps<S>,
S: Float,
{
fn new(x: S, y: S, y: S, z: S) -> Self;
fn as_array(&self) -> &[S; 4];
fn as_mut_array(&mut self) -> &mut [S; 4];
fn add_componentwise(&self, rhs: Self) -> Self;
fn sub_componentwise(&self, rhs: Self) -> Self;
fn mul_componentwise(&self, rhs: Self) -> Self;
fn div_componentwise(&self, rhs: Self) -> Self;
fn min_componentwise(&self, rhs: Self) -> Self;
fn max_componentwise(&self, rhs: Self) -> Self;
fn floor(&self) -> Self;
fn min_reduce(&self) -> S;
fn max_reduce(&self) -> S;
fn eq_reduce(&self, rhs: Self) -> bool;
fn dot(&self, rhs: Self) -> S;
fn cross(&self, rhs: Self) -> Self;
fn splat(value: S) -> Self {
Self::new(value, value, value, value)
}
fn norm(&self) -> S {
self.dot(*self).sqrt()
}
fn normalize(&self) -> Self {
self.div(Self::splat(self.norm()))
}
fn point(x: S, y: S, z: S) -> Self {
Self::new(x, y, z, S::one())
}
fn direction(x: S, y: S, z: S) -> Self {
Self::new(x, y, z, S::zero())
}
}
pub trait Mat4<S, V>
where
Self: MatOps<S, V>,
S: Float,
V: Vec4<S>,
{
fn from_columns(x: V, y: V, z: V, w: V) -> Self;
fn as_array(&self) -> &[V; 4];
fn as_mut_array(&mut self) -> &mut [V; 4];
fn mul_vector(&self, rhs: V) -> V;
fn transpose(&self) -> Self;
fn splat(value: S) -> Self {
Self::from_columns(
V::splat(value),
V::splat(value),
V::splat(value),
V::splat(value),
)
}
fn from_rows(r0: [S; 4], r1: [S; 4], r2: [S; 4], r3: [S; 4]) -> Self {
Self::from_columns(
V::new(r0[0], r1[0], r2[0], r3[0]),
V::new(r0[1], r1[1], r2[1], r3[1]),
V::new(r0[2], r1[2], r2[2], r3[2]),
V::new(r0[3], r1[3], r2[3], r3[3]),
)
}
fn identity() -> Self {
Self::from_columns(
V::new(S::one(), S::zero(), S::zero(), S::zero()),
V::new(S::zero(), S::one(), S::zero(), S::zero()),
V::new(S::zero(), S::zero(), S::one(), S::zero()),
V::new(S::zero(), S::zero(), S::zero(), S::one()),
)
}
fn add_componentwise(&self, rhs: Self) -> Self {
Self::from_columns(
self[0] + rhs[0],
self[1] + rhs[1],
self[2] + rhs[2],
self[3] + rhs[3],
)
}
fn sub_componentwise(&self, rhs: Self) -> Self {
Self::from_columns(
self[0] - rhs[0],
self[1] - rhs[1],
self[2] - rhs[2],
self[3] - rhs[3],
)
}
fn mul_matrix(&self, rhs: Self) -> Self {
Self::from_columns(
self.mul_vector(rhs[0]),
self.mul_vector(rhs[1]),
self.mul_vector(rhs[2]),
self.mul_vector(rhs[3]),
)
}
fn inverse_se3(&self) -> Self {
let mut m = *self;
let p = m[3];
m[3] = V::new(S::zero(), S::zero(), S::zero(), S::one());
m = m.transpose(); m[3] = -m.mul_vector(p); m[3][3] = S::one();
m
}
}