#![feature(const_generics)]
#![feature(trivial_bounds)]
#![feature(specialization)]
use std::{
hash::{
Hash,
Hasher,
},
fmt,
mem::{
self,
MaybeUninit,
},
ops::{
Add,
AddAssign,
Sub,
SubAssign,
Deref,
DerefMut,
Div,
DivAssign,
Index,
IndexMut,
Mul,
MulAssign,
Neg,
},
};
#[cfg(feature = "serde")]
use std::marker::PhantomData;
#[cfg(feature = "rand")]
use rand::{
Rng,
distributions::{Distribution, Standard},
};
#[cfg(feature = "serde")]
use serde::{
Serialize,
Serializer,
ser::SerializeTuple,
Deserialize,
Deserializer,
de::{
Error,
SeqAccess,
Visitor,
},
};
pub trait Zero {
fn zero() -> Self;
fn is_zero(&self) -> bool;
}
macro_rules! impl_zero {
(
$type:ty
) => {
impl_zero!{ $type, 0 }
};
(
$type:ty,
$zero:expr
) => {
impl Zero for $type {
fn zero() -> Self {
$zero
}
fn is_zero(&self) -> bool {
*self == $zero
}
}
};
}
impl_zero!{ bool, false }
impl_zero!{ f32, 0.0 }
impl_zero!{ f64, 0.0 }
impl_zero!{ i8 }
impl_zero!{ i16 }
impl_zero!{ i32 }
impl_zero!{ i64 }
impl_zero!{ i128 }
impl_zero!{ isize }
impl_zero!{ u8 }
impl_zero!{ u16 }
impl_zero!{ u32 }
impl_zero!{ u64 }
impl_zero!{ u128 }
impl_zero!{ usize }
pub trait One {
fn one() -> Self;
fn is_one(&self) -> bool;
}
macro_rules! impl_one {
(
$type:ty
) => {
impl_one!{ $type, 1 }
};
(
$type:ty,
$one:expr
) => {
impl One for $type {
fn one() -> Self {
$one
}
fn is_one(&self) -> bool {
*self == $one
}
}
};
}
impl_one!{ bool, true }
impl_one!{ f32, 1.0 }
impl_one!{ f64, 1.0 }
impl_one!{ i8 }
impl_one!{ i16 }
impl_one!{ i32 }
impl_one!{ i64 }
impl_one!{ i128 }
impl_one!{ isize }
impl_one!{ u8 }
impl_one!{ u16 }
impl_one!{ u32 }
impl_one!{ u64 }
impl_one!{ u128 }
impl_one!{ usize }
pub trait Real
where
Self: Sized,
Self: Add<Output = Self>,
Self: Sub<Output = Self>,
Self: Mul<Output = Self>,
Self: Div<Output = Self>,
Self: Neg<Output = Self>,
{
fn sqrt(self) -> Self;
fn mul2(self) -> Self;
fn div2(self) -> Self;
}
impl Real for f32 {
fn sqrt(self) -> Self { self.sqrt() }
fn mul2(self) -> Self { 2.0 * self }
fn div2(self) -> Self { self / 2.0 }
}
impl Real for f64 {
fn sqrt(self) -> Self { self.sqrt() }
fn mul2(self) -> Self { 2.0 * self }
fn div2(self) -> Self { self / 2.0 }
}
#[repr(transparent)]
pub struct Vector<T, const N: usize>([T; N]);
impl<T, const N: usize> From<[T; N]> for Vector<T, {N}> {
fn from(array: [T; N]) -> Self {
Vector::<T, {N}>(array)
}
}
impl<T, const N: usize> From<Matrix<T, {N}, 1>> for Vector<T, {N}> {
fn from(mat: Matrix<T, {N}, 1>) -> Self {
let Matrix([ v ]) = mat;
v
}
}
pub type Vector1<T> = Vector<T, 1>;
pub type Vector2<T> = Vector<T, 2>;
pub type Vector3<T> = Vector<T, 3>;
pub type Vector4<T> = Vector<T, 4>;
pub type Vector5<T> = Vector<T, 5>;
#[deprecated(since = "0.3", note = "use the more powerful vector! macro")]
pub fn vec1<T>(x: T) -> Vector1<T> {
Vector1::<T>::from([ x ])
}
#[deprecated(since = "0.3", note = "use the more powerful vector! macro")]
pub fn vec2<T>(x: T, y: T) -> Vector2<T> {
Vector2::<T>::from([ x, y ])
}
#[deprecated(since = "0.3", note = "use the more powerful vector! macro")]
pub fn vec3<T>(x: T, y: T, z: T) -> Vector3<T> {
Vector3::<T>::from([ x, y, z ])
}
#[deprecated(since = "0.3", note = "use the more powerful vector! macro")]
pub fn vec4<T>(x: T, y: T, z: T, w: T) -> Vector4<T> {
Vector4::<T>::from([ x, y, z, w ])
}
#[inline]
pub fn new_vector<T, const N: usize>(elements: [T; N]) -> Vector<T, {N}> {
Vector(elements)
}
#[macro_export]
macro_rules! vector {
( $($elem:expr),* $(,)? ) => {
$crate::new_vector([
$($elem),*
])
}
}
impl<T, const N: usize> Clone for Vector<T, {N}>
where
T: Clone
{
fn clone(&self) -> Self {
Vector::<T, {N}>(self.0.clone())
}
}
impl<T, const N: usize> Copy for Vector<T, {N}>
where
T: Copy
{}
impl<T, const N: usize> Into<[T; {N}]> for Vector<T, {N}> {
fn into(self) -> [T; {N}] {
self.0
}
}
impl<T, const N: usize> Hash for Vector<T, {N}>
where
T: Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
for i in 0..N {
self.0[i].hash(state);
}
}
}
impl<T, const N: usize> fmt::Debug for Vector<T, {N}>
where
T: fmt::Debug
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match N {
0 => unimplemented!(),
1 => write!(f, "Vector {{ x: {:?} }}", self.0[0]),
2 => write!(f, "Vector {{ x: {:?}, y: {:?} }}", self.0[0], self.0[1]),
3 => write!(f, "Vector {{ x: {:?}, y: {:?}, z: {:?} }}", self.0[0], self.0[1], self.0[2]),
4 => write!(f, "Vector {{ x: {:?}, y: {:?}, z: {:?}, w: {:?} }}", self.0[0], self.0[1], self.0[2], self.0[3]),
_ => write!(f, "Vector {{ x: {:?}, y: {:?}, z: {:?}, w: {:?}, [..]: {:?} }}", self.0[0], self.0[1], self.0[2], self.0[3], &self.0[4..]),
}
}
}
impl<T, const N: usize> Deref for Vector<T, {N}> {
type Target = [T; {N}];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T, const N: usize> DerefMut for Vector<T, {N}> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[cfg(feature = "rand")]
impl<T, const N: usize> Distribution<Vector<T, {N}>> for Standard
where
Standard: Distribution<T>,
{
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Vector<T, {N}> {
let mut rand = MaybeUninit::<Vector<T, {N}>>::uninit();
let randp: *mut T = unsafe { mem::transmute(&mut rand) };
for i in 0..N {
unsafe {
randp.add(i).write(self.sample(rng))
}
}
unsafe { rand.assume_init() }
}
}
#[cfg(feature = "serde")]
struct ArrayVisitor<A> {
marker: PhantomData<A>,
}
#[cfg(feature = "serde")]
impl<A> ArrayVisitor<A> {
fn new() -> Self {
ArrayVisitor {
marker: PhantomData,
}
}
}
#[cfg(feature = "serde")]
impl<'de, T, const N: usize> Visitor<'de> for ArrayVisitor<[T; N]>
where
T: Deserialize<'de>,
{
type Value = [T; N];
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
if N == 0 {
write!(formatter, "an empty array")
} else {
write!(formatter, "an array of length {}", N)
}
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut to = MaybeUninit::<[T; N]>::uninit();
let top: *mut T = unsafe { mem::transmute(&mut to) };
for i in 0..N {
if let Some(element) = seq.next_element()? {
unsafe {
top.add(i).write(element);
}
} else {
return Err(A::Error::invalid_length(i, &self));
}
}
unsafe { Ok(to.assume_init()) }
}
}
#[cfg(feature = "serde")]
impl<T, const N: usize> Serialize for Vector<T, {N}>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_tuple(N)?;
for i in 0..N {
seq.serialize_element(&self.0[i])?;
}
seq.end()
}
}
#[cfg(feature = "serde")]
impl<'de, T, const N: usize> Deserialize<'de> for Vector<T, {N}>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_tuple(N, ArrayVisitor::<[T; {N}]>::new())
.map(|a|Vector(a))
}
}
macro_rules! swizzle {
($a:ident, $x:ident, $y:ident, $z:ident, $w:ident) => {
swizzle!{ $a, $x, $x, $y, $z, $w }
swizzle!{ $a, $y, $x, $y, $z, $w }
swizzle!{ $a, $z, $x, $y, $z, $w }
swizzle!{ $a, $w, $x, $y, $z, $w }
};
($a:ident, $b:ident, $x:ident, $y:ident, $z:ident, $w:ident) => {
paste::item! {
pub fn [< $a $b >](&self) -> Vector<T, 2> {
Vector::<T, 2>::from([
self.$a(),
self.$b(),
])
}
}
swizzle!{ $a, $b, $x, $x, $y, $z, $w }
swizzle!{ $a, $b, $y, $x, $y, $z, $w }
swizzle!{ $a, $b, $z, $x, $y, $z, $w }
swizzle!{ $a, $b, $w, $x, $y, $z, $w }
};
($a:ident, $b:ident, $c:ident, $x:ident, $y:ident, $z:ident, $w:ident) => {
paste::item! {
pub fn [< $a $b $c >](&self) -> Vector<T, 3> {
Vector::<T, 3>::from([
self.$a(),
self.$b(),
self.$c(),
])
}
}
swizzle!{ $a, $b, $c, $x }
swizzle!{ $a, $b, $c, $y }
swizzle!{ $a, $b, $c, $z }
swizzle!{ $a, $b, $c, $w }
};
($a:ident, $b:ident, $c:ident, $d:ident) => {
paste::item! {
pub fn [< $a $b $c $d >](&self) -> Vector<T, 4> {
Vector::<T, 4>::from([
self.$a(),
self.$b(),
self.$c(),
self.$d(),
])
}
}
};
}
impl<T, const N: usize> Vector<T, {N}> {
pub fn map<Out, F>(self, mut f: F) -> Vector<Out, {N}>
where
F: FnMut(T) -> Out,
{
let mut from = MaybeUninit::new(self);
let mut to = MaybeUninit::<Vector<Out, {N}>>::uninit();
let fromp: *mut MaybeUninit<T> = unsafe { mem::transmute(&mut from) };
let top: *mut Out = unsafe { mem::transmute(&mut to) };
for i in 0..N {
unsafe {
top.add(i).write(
f(
fromp
.add(i)
.replace(MaybeUninit::uninit())
.assume_init()
)
);
}
}
unsafe { to.assume_init() }
}
pub fn transpose(self) -> Matrix<T, 1, {N}> {
let mut from = MaybeUninit::new(self);
let mut st = MaybeUninit::<Matrix<T, 1, {N}>>::uninit();
let fromp: *mut MaybeUninit<T> = unsafe { mem::transmute(&mut from) };
let stp: *mut Vector<T, 1> = unsafe { mem::transmute(&mut st) };
for i in 0..N {
unsafe {
stp.add(i).write(
Vector1::<T>::from([
fromp
.add(i)
.replace(MaybeUninit::uninit())
.assume_init()
])
);
}
}
unsafe { st.assume_init() }
}
pub fn trunc(self) -> (TruncatedVector<T, {N}>, T) {
let mut from = MaybeUninit::new(self);
let mut head = MaybeUninit::<TruncatedVector<T, {N}>>::uninit();
let fromp: *mut MaybeUninit<T> = unsafe { mem::transmute(&mut from) };
let headp: *mut T = unsafe { mem::transmute(&mut head) };
for i in 0..N {
unsafe {
headp.add(i).write(
fromp
.add(i)
.replace(MaybeUninit::uninit())
.assume_init()
);
}
}
(
unsafe { head.assume_init() },
unsafe {
fromp
.add(N-1)
.replace(MaybeUninit::uninit())
.assume_init()
}
)
}
}
impl<T, const N: usize> Vector<T, {N}>
where
T: Clone,
{
pub fn first<const M: usize>(&self) -> Vector<T, {M}> {
if M > N {
panic!("attempt to return {} elements from a {}-vector", M, N);
}
let mut head = MaybeUninit::<Vector<T, {M}>>::uninit();
let headp: *mut T = unsafe { mem::transmute(&mut head) };
for i in 0..M {
unsafe {
headp
.add(i)
.write(self[i].clone());
}
}
unsafe { head.assume_init() }
}
pub fn last<const M: usize>(&self) -> Vector<T, {M}> {
if M > N {
panic!("attempt to return {} elements from a {}-vector", M, N);
}
let mut tail = MaybeUninit::<Vector<T, {M}>>::uninit();
let tailp: *mut T = unsafe { mem::transmute(&mut tail) };
for i in 0..M {
unsafe {
tailp
.add(i + N - M)
.write(self[i].clone());
}
}
unsafe { tail.assume_init() }
}
pub fn x(&self) -> T {
self.0[0].clone()
}
pub fn y(&self) -> T {
self.0[1].clone()
}
pub fn z(&self) -> T {
self.0[2].clone()
}
pub fn w(&self) -> T {
self.0[3].clone()
}
pub fn r(&self) -> T {
self.x()
}
pub fn g(&self) -> T {
self.y()
}
pub fn b(&self) -> T {
self.z()
}
pub fn a(&self) -> T {
self.w()
}
swizzle!{x, x, y, z, w}
swizzle!{y, x, y, z, w}
swizzle!{z, x, y, z, w}
swizzle!{w, x, y, z, w}
swizzle!{r, r, g, b, a}
swizzle!{g, r, g, b, a}
swizzle!{b, r, g, b, a}
swizzle!{a, r, g, b, a}
}
pub type TruncatedVector<T, const N: usize> = Vector<T, {N - 1}>;
impl<T, const N: usize> Zero for Vector<T, {N}>
where
T: Zero,
{
fn zero() -> Self {
let mut origin = MaybeUninit::<Vector<T, {N}>>::uninit();
let p: *mut T = unsafe { mem::transmute(&mut origin) };
for i in 0..N {
unsafe {
p.add(i).write(<T as Zero>::zero());
}
}
unsafe { origin.assume_init() }
}
fn is_zero(&self) -> bool {
for i in 0..N {
if !self.0[i].is_zero() {
return false;
}
}
true
}
}
impl<A, B, RHS, const N: usize> PartialEq<RHS> for Vector<A, {N}>
where
RHS: Deref<Target = [B; {N}]>,
A: PartialEq<B>,
{
fn eq(&self, other: &RHS) -> bool {
for (a, b) in self.0.iter().zip(other.deref().iter()) {
if !a.eq(b) {
return false;
}
}
true
}
}
impl<T, const N: usize> Eq for Vector<T, {N}>
where
T: Eq,
{}
impl<A, B, const N: usize> Add<Vector<B, {N}>> for Vector<A, {N}>
where
A: Add<B>,
{
type Output = Vector<<A as Add<B>>::Output, {N}>;
fn add(self, rhs: Vector<B, {N}>) -> Self::Output {
let mut sum = MaybeUninit::<[<A as Add<B>>::Output; {N}]>::uninit();
let mut lhs = MaybeUninit::new(self);
let mut rhs = MaybeUninit::new(rhs);
let sump: *mut <A as Add<B>>::Output = unsafe { mem::transmute(&mut sum) };
let lhsp: *mut MaybeUninit<A> = unsafe { mem::transmute(&mut lhs) };
let rhsp: *mut MaybeUninit<B> = unsafe { mem::transmute(&mut rhs) };
for i in 0..N {
unsafe {
sump.add(i).write(
lhsp.add(i).replace(MaybeUninit::uninit()).assume_init() +
rhsp.add(i).replace(MaybeUninit::uninit()).assume_init()
);
}
}
Vector::<<A as Add<B>>::Output, {N}>(unsafe { sum.assume_init() })
}
}
impl<A, B, const N: usize> AddAssign<Vector<B, {N}>> for Vector<A, {N}>
where
A: AddAssign<B>,
{
fn add_assign(&mut self, rhs: Vector<B, {N}>) {
let mut rhs = MaybeUninit::new(rhs);
let rhsp: *mut MaybeUninit<B> = unsafe { mem::transmute(&mut rhs) };
for i in 0..N {
self.0[i] += unsafe {
rhsp.add(i).replace(MaybeUninit::uninit()).assume_init()
};
}
}
}
impl<A, B, const N: usize> Sub<Vector<B, {N}>> for Vector<A, {N}>
where
A: Sub<B>,
{
type Output = Vector<<A as Sub<B>>::Output, {N}>;
fn sub(self, rhs: Vector<B, {N}>) -> Self::Output {
let mut dif = MaybeUninit::<[<A as Sub<B>>::Output; {N}]>::uninit();
let mut lhs = MaybeUninit::new(self);
let mut rhs = MaybeUninit::new(rhs);
let difp: *mut <A as Sub<B>>::Output = unsafe { mem::transmute(&mut dif) };
let lhsp: *mut MaybeUninit<A> = unsafe { mem::transmute(&mut lhs) };
let rhsp: *mut MaybeUninit<B> = unsafe { mem::transmute(&mut rhs) };
for i in 0..N {
unsafe {
difp.add(i).write(
lhsp.add(i).replace(MaybeUninit::uninit()).assume_init() -
rhsp.add(i).replace(MaybeUninit::uninit()).assume_init()
);
}
}
Vector::<<A as Sub<B>>::Output, {N}>(unsafe { dif.assume_init() })
}
}
impl<A, B, const N: usize> SubAssign<Vector<B, {N}>> for Vector<A, {N}>
where
A: SubAssign<B>,
{
fn sub_assign(&mut self, rhs: Vector<B, {N}>) {
let mut rhs = MaybeUninit::new(rhs);
let rhsp: *mut MaybeUninit<B> = unsafe { mem::transmute(&mut rhs) };
for i in 0..N {
self.0[i] -= unsafe {
rhsp.add(i).replace(MaybeUninit::uninit()).assume_init()
};
}
}
}
impl<T, const N: usize> Neg for Vector<T, {N}>
where
T: Neg,
{
type Output = Vector<<T as Neg>::Output, {N}>;
fn neg(self) -> Self::Output {
let mut from = MaybeUninit::new(self);
let mut neg = MaybeUninit::<[<T as Neg>::Output; {N}]>::uninit();
let fromp: *mut MaybeUninit<T> = unsafe { mem::transmute(&mut from) };
let negp: *mut <T as Neg>::Output = unsafe { mem::transmute(&mut neg) };
for i in 0..N {
unsafe {
negp.add(i).write(
fromp
.add(i)
.replace(MaybeUninit::uninit())
.assume_init()
.neg()
);
}
}
Vector::<<T as Neg>::Output, {N}>(unsafe { neg.assume_init() })
}
}
impl<A, B, const N: usize> Mul<B> for Vector<A, {N}>
where
A: Mul<B>,
B: Clone,
{
type Output = Vector<<A as Mul<B>>::Output, {N}>;
fn mul(self, scalar: B) -> Self::Output {
let mut from = MaybeUninit::new(self);
let mut scaled = MaybeUninit::<[<A as Mul<B>>::Output; {N}]>::uninit();
let fromp: *mut MaybeUninit<A> = unsafe { mem::transmute(&mut from) };
let scaledp: *mut <A as Mul<B>>::Output =
unsafe { mem::transmute(&mut scaled) };
for i in 0..N {
unsafe {
scaledp.add(i).write(
fromp
.add(i)
.replace(MaybeUninit::uninit())
.assume_init() * scalar.clone()
);
}
}
Vector::<<A as Mul<B>>::Output, {N}>(unsafe { scaled.assume_init() })
}
}
impl<A, B, const N: usize> MulAssign<B> for Vector<A, {N}>
where
A: MulAssign<B>,
B: Clone,
{
fn mul_assign(&mut self, scalar: B) {
for i in 0..N {
self.0[i] *= scalar.clone();
}
}
}
impl<A, B, const N: usize> Div<B> for Vector<A, {N}>
where
A: Div<B>,
B: Clone,
{
type Output = Vector<<A as Div<B>>::Output, {N}>;
fn div(self, scalar: B) -> Self::Output {
let mut from = MaybeUninit::new(self);
let mut scaled = MaybeUninit::<[<A as Div<B>>::Output; {N}]>::uninit();
let fromp: *mut MaybeUninit<A> = unsafe { mem::transmute(&mut from) };
let scaledp: *mut <A as Div<B>>::Output =
unsafe { mem::transmute(&mut scaled) };
for i in 0..N {
unsafe {
scaledp.add(i).write(
fromp
.add(i)
.replace(MaybeUninit::uninit())
.assume_init() / scalar.clone()
);
}
}
Vector::<<A as Div<B>>::Output, {N}>(unsafe { scaled.assume_init() })
}
}
impl<A, B, const N: usize> DivAssign<B> for Vector<A, {N}>
where
A: DivAssign<B>,
B: Clone,
{
fn div_assign(&mut self, scalar: B) {
for i in 0..N {
self.0[i] /= scalar.clone();
}
}
}
impl<T> Vector3<T>
where
T: Add<T, Output = T> + Sub<T, Output = T> + Mul<T, Output = T> + Clone,
{
pub fn cross(self, rhs: Vector3<T>) -> Self {
let [x0, y0, z0]: [T; 3] = self.into();
let [x1, y1, z1]: [T; 3] = rhs.into();
Vector3::from([
(y0.clone() * z1.clone()) - (z0.clone() * y1.clone()),
(z0 * x1.clone()) - (x0.clone() * z1),
(x0 * y1) - (y0 * x1)
])
}
}
#[repr(transparent)]
pub struct Point<T, const N: usize>([T; N]);
impl<T, const N: usize> From<[T; N]> for Point<T, {N}> {
fn from(array: [T; N]) -> Self {
Point::<T, {N}>(array)
}
}
pub type Point1<T> = Point<T, 1>;
pub type Point2<T> = Point<T, 2>;
pub type Point3<T> = Point<T, 3>;
pub type Point4<T> = Point<T, 4>;
pub type Point5<T> = Point<T, 5>;
#[inline]
pub fn new_point<T, const N: usize>(elements: [T; N]) -> Point<T, {N}> {
Point(elements)
}
#[macro_export]
macro_rules! point {
( $($elem:expr),* $(,)? ) => {
$crate::new_point([
$($elem),*
])
}
}
impl<T, const N: usize> Clone for Point<T, {N}>
where
T: Clone
{
fn clone(&self) -> Self {
Point::<T, {N}>(self.0.clone())
}
}
impl<T, const N: usize> Copy for Point<T, {N}>
where
T: Copy
{}
impl<T, const N: usize> Into<[T; {N}]> for Point<T, {N}> {
fn into(self) -> [T; {N}] {
self.0
}
}
impl<T, const N: usize> Hash for Point<T, {N}>
where
T: Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
for i in 0..N {
self.0[i].hash(state);
}
}
}
impl<T, const N: usize> fmt::Debug for Point<T, {N}>
where
T: fmt::Debug
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match N {
0 => unimplemented!(),
1 => write!(f, "Point {{ x: {:?} }}", self.0[0]),
2 => write!(f, "Point {{ x: {:?}, y: {:?} }}", self.0[0], self.0[1]),
3 => write!(f, "Point {{ x: {:?}, y: {:?}, z: {:?} }}", self.0[0], self.0[1], self.0[2]),
4 => write!(f, "Point {{ x: {:?}, y: {:?}, z: {:?}, w: {:?} }}", self.0[0], self.0[1], self.0[2], self.0[3]),
_ => write!(f, "Point {{ x: {:?}, y: {:?}, z: {:?}, w: {:?}, [..]: {:?} }}", self.0[0], self.0[1], self.0[2], self.0[3], &self.0[4..]),
}
}
}
impl<T, const N: usize> Deref for Point<T, {N}> {
type Target = [T; {N}];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T, const N: usize> DerefMut for Point<T, {N}> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[cfg(feature = "rand")]
impl<T, const N: usize> Distribution<Point<T, {N}>> for Standard
where
Standard: Distribution<T>,
{
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Point<T, {N}> {
let mut rand = MaybeUninit::<Point<T, {N}>>::uninit();
let randp: *mut T = unsafe { mem::transmute(&mut rand) };
for i in 0..N {
unsafe {
randp.add(i).write(self.sample(rng))
}
}
unsafe { rand.assume_init() }
}
}
#[cfg(feature = "serde")]
impl<T, const N: usize> Serialize for Point<T, {N}>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_tuple(N)?;
for i in 0..N {
seq.serialize_element(&self.0[i])?;
}
seq.end()
}
}
#[cfg(feature = "serde")]
impl<'de, T, const N: usize> Deserialize<'de> for Point<T, {N}>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_tuple(N, ArrayVisitor::<[T; {N}]>::new())
.map(|a|Point(a))
}
}
impl<T, const N: usize> Point<T, {N}> {
pub fn from_vec(vec: Vector<T, {N}>) -> Self {
Point(vec.0)
}
}
impl<A, B, const N: usize> Add<Vector<B, {N}>> for Point<A, {N}>
where
A: Add<B>,
{
type Output = Point<<A as Add<B>>::Output, {N}>;
fn add(self, rhs: Vector<B, {N}>) -> Self::Output {
let lhs = Vector(self.0);
let rhs = Vector(rhs.0);
Point((lhs + rhs).0)
}
}
impl<A, B, const N: usize> Sub<Vector<B, {N}>> for Point<A, {N}>
where
A: Sub<B>,
{
type Output = Point<<A as Sub<B>>::Output, {N}>;
fn sub(self, rhs: Vector<B, {N}>) -> Self::Output {
let lhs = Vector(self.0);
let rhs = Vector(rhs.0);
Point((lhs - rhs).0)
}
}
impl<A, B, const N: usize> Sub<Point<B, {N}>> for Point<A, {N}>
where
A: Sub<B>,
{
type Output = Vector<<A as Sub<B>>::Output, {N}>;
fn sub(self, rhs: Point<B, {N}>) -> Self::Output {
let lhs = Vector(self.0);
let rhs = Vector(rhs.0);
lhs - rhs
}
}
pub trait VectorSpace
where
Self: Sized + Zero,
Self: Add<Self, Output = Self>,
Self: Sub<Self, Output = Self>,
Self: Mul<<Self as VectorSpace>::Scalar, Output = Self>,
Self: Div<<Self as VectorSpace>::Scalar, Output = Self>,
{
type Scalar: Add<Self::Scalar, Output = Self::Scalar> +
Sub<Self::Scalar, Output = Self::Scalar> +
Mul<Self::Scalar, Output = Self::Scalar> +
Div<Self::Scalar, Output = Self::Scalar>;
fn lerp(self, other: Self, amount: Self::Scalar) -> Self;
}
impl<T, const N: usize> VectorSpace for Vector<T, {N}>
where
T: Clone + Zero,
T: Add<T, Output = T>,
T: Sub<T, Output = T>,
T: Mul<T, Output = T>,
T: Div<T, Output = T>,
{
type Scalar = T;
fn lerp(self, other: Self, amount: Self::Scalar) -> Self {
self.clone() + ((other - self) * amount)
}
}
pub trait MetricSpace: Sized {
type Metric;
fn distance2(self, other: Self) -> Self::Metric;
}
pub trait RealMetricSpace: MetricSpace
where
Self::Metric: Real,
{
fn distance(self, other: Self) -> Self::Metric {
self.distance2(other).sqrt()
}
}
impl<T> RealMetricSpace for T
where
T: MetricSpace,
<T as MetricSpace>::Metric: Real
{}
impl<T, const N: usize> MetricSpace for Vector<T, {N}>
where
Self: InnerSpace,
{
type Metric = <Self as VectorSpace>::Scalar;
fn distance2(self, other: Self) -> Self::Metric {
(other - self).magnitude2()
}
}
pub trait InnerSpace: VectorSpace
where
Self: Clone,
Self: MetricSpace<Metric = <Self as VectorSpace>::Scalar>,
{
fn dot(self, other: Self) -> Self::Scalar;
fn magnitude2(self) -> Self::Scalar {
self.clone().dot(self)
}
}
pub trait RealInnerSpace: InnerSpace
where
Self: Clone,
Self: MetricSpace<Metric = <Self as VectorSpace>::Scalar>,
<Self as VectorSpace>::Scalar: Real,
{
fn magnitude(self) -> Self::Scalar {
self.clone().dot(self).sqrt()
}
fn normalize(self) -> Self
where
Self::Scalar: One
{
self.normalize_to(<Self::Scalar as One>::one())
}
fn normalize_to(self, magnitude: Self::Scalar) -> Self {
self.clone() * (magnitude / self.magnitude())
}
fn project_on(self, other: Self) -> Self {
other.clone() * (self.dot(other.clone()) / other.magnitude2())
}
}
impl<T> RealInnerSpace for T
where
T: InnerSpace,
<T as VectorSpace>::Scalar: Real
{}
impl<T, const N: usize> InnerSpace for Vector<T, {N}>
where
T: Clone + Zero,
T: Add<T, Output = T>,
T: Sub<T, Output = T>,
T: Mul<T, Output = T>,
T: Div<T, Output = T>,
T: AddAssign<T>,
Self: Clone,
{
fn dot(self, rhs: Self) -> T {
let mut lhs = MaybeUninit::new(self);
let mut rhs = MaybeUninit::new(rhs);
let mut sum = <T as Zero>::zero();
let lhsp: *mut MaybeUninit<T> = unsafe { mem::transmute(&mut lhs) };
let rhsp: *mut MaybeUninit<T> = unsafe { mem::transmute(&mut rhs) };
for i in 0..N {
sum += unsafe {
lhsp.add(i).replace(MaybeUninit::uninit()).assume_init() *
rhsp.add(i).replace(MaybeUninit::uninit()).assume_init()
};
}
sum
}
}
#[repr(transparent)]
pub struct Matrix<T, const N: usize, const M: usize>([Vector<T, {N}>; {M}]);
pub type Mat1x1<T> = Matrix<T, 1, 1>;
pub type Mat2x2<T> = Matrix<T, 2, 2>;
pub type Mat3x3<T> = Matrix<T, 3, 3>;
pub type Mat4x4<T> = Matrix<T, 4, 4>;
impl<T, const N: usize, const M: usize> From<[Vector<T, {N}>; {M}]> for Matrix<T, {N}, {M}> {
fn from(array: [Vector<T, {N}>; {M}]) -> Self {
Matrix::<T, {N}, {M}>(array)
}
}
impl<T, const N: usize, const M: usize> From<[[T; {N}]; {M}]> for Matrix<T, {N}, {M}> {
fn from(array: [[T; {N}]; {M}]) -> Self {
let mut array = MaybeUninit::<[[T; N]; M]>::new(array);
let mut vec_array: MaybeUninit::<[Vector<T, {N}>; M]> = MaybeUninit::uninit();
let arrayp: *mut MaybeUninit::<[T; N]> =
unsafe { mem::transmute(&mut array) };
let vec_arrayp: *mut Vector<T, {N}> =
unsafe { mem::transmute(&mut vec_array) };
for i in 0..M {
unsafe {
vec_arrayp.add(i).write(
Vector::<T, {N}>(
arrayp.add(i)
.replace(MaybeUninit::uninit())
.assume_init()
)
);
}
}
Matrix::<T, {N}, {M}>(unsafe { vec_array.assume_init() })
}
}
#[deprecated(since = "0.3", note = "use the more powerful matrix! macro")]
pub fn mat1x1<T>(
x00: T,
) -> Mat1x1<T> {
Matrix::<T, 1, 1>([ Vector::<T, 1>([ x00 ]) ])
}
#[deprecated(since = "0.3", note = "use the more powerful matrix! macro")]
pub fn mat2x2<T>(
x00: T, x01: T,
x10: T, x11: T,
) -> Mat2x2<T> {
Matrix::<T, 2, 2>(
[ Vector::<T, 2>([ x00, x10 ]),
Vector::<T, 2>([ x01, x11 ]), ]
)
}
#[deprecated(since = "0.3", note = "use the more powerful matrix! macro")]
pub fn mat3x3<T>(
x00: T, x01: T, x02: T,
x10: T, x11: T, x12: T,
x20: T, x21: T, x22: T,
) -> Mat3x3<T> {
Matrix::<T, 3, 3>(
[ Vector::<T, 3>([ x00, x10, x20, ]),
Vector::<T, 3>([ x01, x11, x21, ]),
Vector::<T, 3>([ x02, x12, x22, ]), ]
)
}
#[deprecated(since = "0.3", note = "use the more powerful matrix! macro")]
pub fn mat4x4<T>(
x00: T, x01: T, x02: T, x03: T,
x10: T, x11: T, x12: T, x13: T,
x20: T, x21: T, x22: T, x23: T,
x30: T, x31: T, x32: T, x33: T,
) -> Mat4x4<T> {
Matrix::<T, 4, 4>(
[ Vector::<T, 4>([ x00, x10, x20, x30 ]),
Vector::<T, 4>([ x01, x11, x21, x31 ]),
Vector::<T, 4>([ x02, x12, x22, x32 ]),
Vector::<T, 4>([ x03, x13, x23, x33 ]) ]
)
}
#[inline]
pub fn new_matrix<T: Clone, const N: usize, const M: usize>(rows: [[T; M]; N]) -> Matrix<T, {N}, {M}> {
Matrix::<T, {M}, {N}>::from(rows).transpose()
}
#[macro_export]
macro_rules! matrix {
( $($rows:expr),* $(,)? ) => {
$crate::new_matrix([
$($rows),*
])
}
}
impl<T, const N: usize, const M: usize> Clone for Matrix<T, {N}, {M}>
where
T: Clone
{
fn clone(&self) -> Self {
Matrix::<T, {N}, {M}>(self.0.clone())
}
}
impl<T, const N: usize, const M: usize> Copy for Matrix<T, {N}, {M}>
where
T: Copy
{}
impl<T, const N: usize, const M: usize> Deref for Matrix<T, {N}, {M}> {
type Target = [Vector<T, {N}>; {M}];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T, const N: usize, const M: usize> DerefMut for Matrix<T, {N}, {M}> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T, const N: usize, const M: usize> Hash for Matrix<T, {N}, {M}>
where
T: Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
for i in 0..M {
self.0[i].hash(state);
}
}
}
#[cfg(feature = "rand")]
impl<T, const N: usize, const M: usize> Distribution<Matrix<T, {N}, {M}>> for Standard
where
Standard: Distribution<Vector<T, {N}>>,
{
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Matrix<T, {N}, {M}> {
let mut rand = MaybeUninit::<[Vector<T, {N}>; {M}]>::uninit();
let randp: *mut Vector<T, {N}> =
unsafe { mem::transmute(&mut rand) };
for i in 0..M {
unsafe { randp.add(i).write(self.sample(rng)); }
}
Matrix::<T, {N}, {M}>(unsafe { rand.assume_init() })
}
}
#[cfg(feature = "serde")]
impl<T, const N: usize, const M: usize> Serialize for Matrix<T, {N}, {M}>
where
Vector<T, {N}>: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_tuple(M)?;
for i in 0..M {
seq.serialize_element(&self.0[i])?;
}
seq.end()
}
}
#[cfg(feature = "serde")]
impl<'de, T, const N: usize, const M: usize> Deserialize<'de> for Matrix<T, {N}, {M}>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_tuple(
N, ArrayVisitor::<[Vector<T, {N}>; {M}]>::new()
).map(|a|Matrix(a))
}
}
impl<T, const N: usize, const M: usize> Zero for Matrix<T, {N}, {M}>
where
T: Zero,
Vector<T, {N}>: Zero,
{
fn zero() -> Self {
let mut zero_mat = MaybeUninit::<[Vector<T, {N}>; {M}]>::uninit();
let matp: *mut Vector<T, {N}> =
unsafe { mem::transmute(&mut zero_mat) };
for i in 0..M {
unsafe { matp.add(i).write(Vector::<T, {N}>::zero()); }
}
Matrix::<T, {N}, {M}>(unsafe { zero_mat.assume_init() })
}
fn is_zero(&self) -> bool {
for i in 0..M {
if !self.0[i].is_zero() {
return false;
}
}
true
}
}
impl<T, const N: usize> One for Matrix<T, {N}, {N}>
where
T: Zero + One + Clone,
Self: PartialEq<Self> + SquareMatrix<T, {N}>,
{
fn one() -> Self {
let mut unit_mat = MaybeUninit::<[Vector<T, {N}>; {N}]>::uninit();
let matp: *mut Vector<T, {N}> =
unsafe { mem::transmute(&mut unit_mat) };
for i in 0..N {
let mut unit_vec = MaybeUninit::<Vector<T, {N}>>::uninit();
let vecp: *mut T = unsafe { mem::transmute(&mut unit_vec) };
for j in 0..i {
unsafe {
vecp.add(j).write(<T as Zero>::zero());
}
}
unsafe { vecp.add(i).write(<T as One>::one()); }
for j in (i+1)..N {
unsafe {
vecp.add(j).write(<T as Zero>::zero());
}
}
unsafe { matp.add(i).write(unit_vec.assume_init()); }
}
Matrix::<T, {N}, {N}>(unsafe { unit_mat.assume_init() })
}
fn is_one(&self) -> bool {
self == &<Self as One>::one()
}
}
impl<T, const N: usize, const M: usize> Index<usize> for Matrix<T, {N}, {M}> {
type Output = Vector<T, {N}>;
fn index(&self, column: usize) -> &Self::Output {
&self.0[column]
}
}
impl<T, const N: usize, const M: usize> IndexMut<usize> for Matrix<T, {N}, {M}> {
fn index_mut(&mut self, column: usize) -> &mut Self::Output {
&mut self.0[column]
}
}
impl<T, const N: usize, const M: usize> Index<(usize, usize)> for Matrix<T, {N}, {M}> {
type Output = T;
fn index(&self, (row, column): (usize, usize)) -> &Self::Output {
&self.0[column][row]
}
}
impl<T, const N: usize, const M: usize> IndexMut<(usize, usize)> for Matrix<T, {N}, {M}> {
fn index_mut(&mut self, (row, column): (usize, usize)) -> &mut Self::Output {
&mut self.0[column][row]
}
}
impl<A, B, RHS, const N: usize, const M: usize> PartialEq<RHS> for Matrix<A, {N}, {M}>
where
RHS: Deref<Target = [Vector<B, {N}>; {M}]>,
A: PartialEq<B>,
{
fn eq(&self, other: &RHS) -> bool {
for (a, b) in self.0.iter().zip(other.deref().iter()) {
if !a.eq(b) {
return false;
}
}
true
}
}
impl<T, const N: usize, const M: usize> fmt::Debug for Matrix<T, {N}, {M}>
where
T: fmt::Debug
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Matrix [ ")?;
for i in 0..N {
write!(f, "[ ")?;
for j in 0..M {
write!(f, "{:?} ", self.0[j].0[i])?;
}
write!(f, "] ")?;
}
write!(f, "]")
}
}
impl<A, B, const N: usize, const M: usize> Add<Matrix<B, {N}, {M}>> for Matrix<A, {N}, {M}>
where
A: Add<B>,
{
type Output = Matrix<<A as Add<B>>::Output, {N}, {M}>;
fn add(self, rhs: Matrix<B, {N}, {M}>) -> Self::Output {
let mut mat =
MaybeUninit::<[Vector<<A as Add<B>>::Output, {N}>; {M}]>::uninit();
let mut lhs = MaybeUninit::new(self);
let mut rhs = MaybeUninit::new(rhs);
let matp: *mut Vector<<A as Add<B>>::Output, {N}> =
unsafe { mem::transmute(&mut mat) };
let lhsp: *mut MaybeUninit<Vector<A, {N}>> =
unsafe { mem::transmute(&mut lhs) };
let rhsp: *mut MaybeUninit<Vector<B, {N}>> =
unsafe { mem::transmute(&mut rhs) };
for i in 0..M {
unsafe {
matp.add(i).write(
lhsp.add(i).replace(MaybeUninit::uninit()).assume_init() +
rhsp.add(i).replace(MaybeUninit::uninit()).assume_init()
);
}
}
Matrix::<<A as Add<B>>::Output, {N}, {M}>(unsafe { mat.assume_init() })
}
}
impl<A, B, const N: usize, const M: usize> AddAssign<Matrix<B, {N}, {M}>> for Matrix<A, {N}, {M}>
where
A: AddAssign<B>,
{
fn add_assign(&mut self, rhs: Matrix<B, {N}, {M}>) {
let mut rhs = MaybeUninit::new(rhs);
let rhsp: *mut MaybeUninit<Vector<B, {N}>> = unsafe { mem::transmute(&mut rhs) };
for i in 0..M {
self.0[i] += unsafe {
rhsp.add(i).replace(MaybeUninit::uninit()).assume_init()
};
}
}
}
impl<A, B, const N: usize, const M: usize> Sub<Matrix<B, {N}, {M}>> for Matrix<A, {N}, {M}>
where
A: Sub<B>,
{
type Output = Matrix<<A as Sub<B>>::Output, {N}, {M}>;
fn sub(self, rhs: Matrix<B, {N}, {M}>) -> Self::Output {
let mut mat =
MaybeUninit::<[Vector<<A as Sub<B>>::Output, {N}>; {M}]>::uninit();
let mut lhs = MaybeUninit::new(self);
let mut rhs = MaybeUninit::new(rhs);
let matp: *mut Vector<<A as Sub<B>>::Output, {N}> =
unsafe { mem::transmute(&mut mat) };
let lhsp: *mut MaybeUninit<Vector<A, {N}>> =
unsafe { mem::transmute(&mut lhs) };
let rhsp: *mut MaybeUninit<Vector<B, {N}>> =
unsafe { mem::transmute(&mut rhs) };
for i in 0..M {
unsafe {
matp.add(i).write(
lhsp.add(i).replace(MaybeUninit::uninit()).assume_init() -
rhsp.add(i).replace(MaybeUninit::uninit()).assume_init()
);
}
}
Matrix::<<A as Sub<B>>::Output, {N}, {M}>(unsafe { mat.assume_init() })
}
}
impl<A, B, const N: usize, const M: usize> SubAssign<Matrix<B, {N}, {M}>> for Matrix<A, {N}, {M}>
where
A: SubAssign<B>,
{
fn sub_assign(&mut self, rhs: Matrix<B, {N}, {M}>) {
let mut rhs = MaybeUninit::new(rhs);
let rhsp: *mut MaybeUninit<Vector<B, {N}>> = unsafe { mem::transmute(&mut rhs) };
for i in 0..M {
self.0[i] -= unsafe {
rhsp.add(i).replace(MaybeUninit::uninit()).assume_init()
};
}
}
}
impl<T, const N: usize, const M: usize> Neg for Matrix<T, {N}, {M}>
where
T: Neg
{
type Output = Matrix<<T as Neg>::Output, {N}, {M}>;
fn neg(self) -> Self::Output {
let mut from = MaybeUninit::new(self);
let mut mat =
MaybeUninit::<[Vector<<T as Neg>::Output, {N}>; {M}]>::uninit();
let fromp: *mut MaybeUninit<Vector<T, {N}>> = unsafe { mem::transmute(&mut from) };
let matp: *mut Vector<<T as Neg>::Output, {N}> =
unsafe { mem::transmute(&mut mat) };
for i in 0..M {
unsafe {
matp.add(i).write(
fromp
.add(i)
.replace(MaybeUninit::uninit())
.assume_init()
.neg()
);
}
}
Matrix::<<T as Neg>::Output, {N}, {M}>(unsafe { mat.assume_init() })
}
}
impl<T, const N: usize, const M: usize, const P: usize> Mul<Matrix<T, {M}, {P}>> for Matrix<T, {N}, {M}>
where
T: Add<T, Output = T> + Mul<T, Output = T> + Clone,
Vector<T, {M}>: InnerSpace,
{
type Output = Matrix<<Vector<T, {M}> as VectorSpace>::Scalar, {N}, {P}>;
fn mul(self, rhs: Matrix<T, {M}, {P}>) -> Self::Output {
let mut mat = MaybeUninit::<[Vector<<Vector<T, {M}> as VectorSpace>::Scalar, {N}>; {P}]>::uninit();
let matp: *mut Vector<<Vector<T, {M}> as VectorSpace>::Scalar, {N}> =
unsafe { mem::transmute(&mut mat) };
for i in 0..P {
let mut column = MaybeUninit::<[<Vector<T, {M}> as VectorSpace>::Scalar; {N}]>::uninit();
let columnp: *mut <Vector<T, {M}> as VectorSpace>::Scalar =
unsafe { mem::transmute(&mut column) };
for j in 0..N {
let mut row = MaybeUninit::<[T; {M}]>::uninit();
let rowp: *mut T = unsafe { mem::transmute(&mut row) };
for k in 0..M {
unsafe {
rowp.add(k).write(self.0[k].0[j].clone());
}
}
let row = Vector::<T, {M}>::from(unsafe { row.assume_init() });
unsafe {
columnp.add(j).write(row.dot(rhs.0[i].clone()));
}
}
let column = Vector::<<Vector<T, {M}> as VectorSpace>::Scalar, {N}>(
unsafe { column.assume_init() }
);
unsafe {
matp.add(i).write(column);
}
}
Matrix::<<Vector<T, {M}> as VectorSpace>::Scalar, {N}, {P}>(
unsafe { mat.assume_init() }
)
}
}
impl<T, const N: usize, const M: usize> Mul<Vector<T, {M}>> for Matrix<T, {N}, {M}>
where
T: Add<T, Output = T> + Mul<T, Output = T> + Clone,
Vector<T, {M}>: InnerSpace,
{
type Output = Vector<<Vector<T, {M}> as VectorSpace>::Scalar, {N}>;
fn mul(self, rhs: Vector<T, {M}>) -> Self::Output {
let mut column = MaybeUninit::<[<Vector<T, {M}> as VectorSpace>::Scalar; {N}]>::uninit();
let columnp: *mut <Vector<T, {M}> as VectorSpace>::Scalar =
unsafe { mem::transmute(&mut column) };
for j in 0..N {
let mut row = MaybeUninit::<[T; {M}]>::uninit();
let rowp: *mut T = unsafe { mem::transmute(&mut row) };
for k in 0..M {
unsafe {
rowp.add(k).write(self.0[k].0[j].clone());
}
}
let row = Vector::<T, {M}>::from(unsafe { row.assume_init() });
unsafe {
columnp.add(j).write(row.dot(rhs.clone()));
}
}
Vector::<<Vector<T, {M}> as VectorSpace>::Scalar, {N}>(
unsafe { column.assume_init() }
)
}
}
impl<T, const N: usize, const M: usize> Mul<T> for Matrix<T, {N}, {M}>
where
T: Mul<T, Output = T> + Clone,
{
type Output = Matrix<T, {N}, {M}>;
fn mul(self, scalar: T) -> Self::Output {
let mut mat = MaybeUninit::<[Vector<T, {N}>; {M}]>::uninit();
let matp: *mut Vector<T, {N}> = unsafe { mem::transmute(&mut mat) };
for i in 0..M {
unsafe {
matp.add(i).write(self.0[i].clone() * scalar.clone());
}
}
Matrix::<T, {N}, {M}>(unsafe { mat.assume_init() })
}
}
impl<T, const N: usize, const M: usize> Matrix<T, {N}, {M}> {
pub fn map<Out, F>(self, mut f: F) -> Matrix<Out, {N}, {M}>
where
F: FnMut(T) -> Out,
{
let mut from = MaybeUninit::new(self);
let mut to = MaybeUninit::<Matrix<Out, {N}, {M}>>::uninit();
let fromp: *mut MaybeUninit<Vector<T, {N}>> = unsafe { mem::transmute(&mut from) };
let top: *mut Vector<Out, {N}> = unsafe { mem::transmute(&mut to) };
for i in 0..M {
unsafe {
let fromp: *mut MaybeUninit<T> = mem::transmute(fromp.add(i));
let top: *mut Out = mem::transmute(top.add(i));
for j in 0..N {
top.add(j).write(
f(
fromp.add(j)
.replace(MaybeUninit::uninit())
.assume_init()
)
);
}
}
}
unsafe { to.assume_init() }
}
pub fn transpose(self) -> Matrix<T, {M}, {N}> {
let mut from = MaybeUninit::new(self);
let mut trans = MaybeUninit::<[Vector<T, {M}>; {N}]>::uninit();
let fromp: *mut Vector<MaybeUninit<T>, {N}> = unsafe { mem::transmute(&mut from) };
let transp: *mut Vector<T, {M}> = unsafe{ mem::transmute(&mut trans) };
for j in 0..N {
let mut row = MaybeUninit::<[T; {M}]>::uninit();
let rowp: *mut T = unsafe { mem::transmute(&mut row) };
for k in 0..M {
unsafe {
let fromp: *mut MaybeUninit<T> = mem::transmute(fromp.add(k));
rowp.add(k).write(
fromp
.add(j)
.replace(MaybeUninit::uninit())
.assume_init()
);
}
}
let row = Vector::<T, {M}>::from(unsafe { row.assume_init() });
unsafe {
transp.add(j).write(row);
}
}
Matrix::<T, {M}, {N}>(unsafe { trans.assume_init() })
}
}
pub trait SquareMatrix<Scalar, const N: usize>: Sized
where
Scalar: Clone,
Self: Add<Self>,
Self: Sub<Self>,
Self: Mul<Self>,
Self: Mul<Vector<Scalar, {N}>, Output = Vector<Scalar, {N}>>,
{
fn determinant(&self) -> Scalar;
fn invert(self) -> Option<Self>;
fn diagonal(&self) -> Vector<Scalar, {N}>;
}
impl<Scalar, const N: usize> SquareMatrix<Scalar, {N}> for Matrix<Scalar, {N}, {N}>
where
Scalar: Clone + One,
Scalar: Add<Scalar, Output = Scalar> + Sub<Scalar, Output = Scalar>,
Scalar: Mul<Scalar, Output = Scalar>,
Self: Add<Self>,
Self: Sub<Self>,
Self: Mul<Self>,
Self: Mul<Vector<Scalar, {N}>, Output = Vector<Scalar, {N}>>,
{
fn determinant(&self) -> Scalar {
match N {
0 => <Scalar as One>::one(),
1 => self[0][0].clone(),
2 => (self[(0, 0)].clone() * self[(1, 1)].clone()
- self[(1, 0)].clone() * self[(0, 1)].clone()),
3 => {
let minor1 =
self[(1, 1)].clone() * self[(2, 2)].clone()
- self[(2, 1)].clone() * self[(1, 2)].clone();
let minor2 =
self[(1, 0)].clone() * self[(2, 2)].clone()
- self[(2, 0)].clone() * self[(1, 2)].clone();
let minor3 =
self[(1, 0)].clone() * self[(2, 1)].clone()
- self[(2, 0)].clone() * self[(1, 1)].clone();
self[(0, 0)].clone() * minor1
- self[(0, 1)].clone() * minor2
+ self[(0, 2)].clone() * minor3
},
_ => unimplemented!(),
}
}
fn invert(self) -> Option<Self> {
unimplemented!()
}
fn diagonal(&self) -> Vector<Scalar, {N}> {
let mut diag = MaybeUninit::<[Scalar; {N}]>::uninit();
let diagp: *mut Scalar = unsafe { mem::transmute(&mut diag) };
for i in 0..N {
unsafe {
diagp.add(i).write(self.0[i].0[i].clone());
}
}
Vector::<Scalar, {N}>(unsafe { diag.assume_init() })
}
}
pub trait Rotation<const DIMS: usize>
where
Self: Sized,
{
type Scalar;
fn rotate_vector(self, v: Vector<Self::Scalar, {DIMS}>) -> Vector<Self::Scalar, {DIMS}>;
fn rotate_point(self, p: Point<Self::Scalar, {DIMS}>) -> Point<Self::Scalar, {DIMS}> {
Point(self.rotate_vector(Vector(p.0)).0)
}
}
pub trait Angle: Real {
fn sin(self) -> Self;
fn cos(self) -> Self;
fn tan(self) -> Self;
fn atan2(self, x: Self) -> Self;
fn sin_cos(self) -> (Self, Self);
}
impl Angle for f32 {
fn sin(self) -> Self { self.sin() }
fn cos(self) -> Self { self.cos() }
fn tan(self) -> Self { self.tan() }
fn atan2(self, x: Self) -> Self { self.atan2(x) }
fn sin_cos(self) -> (Self, Self) { (self.sin(), self.cos()) }
}
impl Angle for f64 {
fn sin(self) -> Self { self.sin() }
fn cos(self) -> Self { self.cos() }
fn tan(self) -> Self { self.tan() }
fn atan2(self, x: Self) -> Self { self.atan2(x) }
fn sin_cos(self) -> (Self, Self) { (self.sin(), self.cos()) }
}
#[repr(C)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Euler<T> {
pub x: T,
pub y: T,
pub z: T,
}
pub struct Orthonormal<T, const DIM: usize>(Matrix<T, {DIM}, {DIM}>);
impl<T> From<T> for Orthonormal<T, 2>
where
T: Angle + Clone,
{
fn from(angle: T) -> Self {
let (s, c) = angle.sin_cos();
Orthonormal(Matrix([vector!(c.clone(), s.clone()), vector!(-s, c)]))
}
}
impl<T> From<Euler<T>> for Orthonormal<T, 3>
where
T: Angle + Copy + Clone,
{
fn from(Euler{ x, y, z }: Euler<T>) -> Self {
let (
(xs, xc),
(ys, yc),
(zs, zc)
) = (
x.sin_cos(),
y.sin_cos(),
z.sin_cos()
);
Orthonormal(Matrix([
vector![ yc * zc, xc * zs + xs * ys * zc, xs * zs - xc * ys * zc ],
vector![ -yc * zs, xc * zc - xs * ys * zs, xs * zc + xc * ys * zs ],
vector![ ys, -xs * yc, xc * yc ],
]))
}
}
#[cfg(feature = "serde")]
impl<T, const DIMS: usize> Serialize for Orthonormal<T, {DIMS}>
where
Matrix<T, {DIMS}, {DIMS}>: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de, T, const DIMS: usize> Deserialize<'de> for Orthonormal<T, {DIMS}>
where
for <'a> Matrix<T, {DIMS}, {DIMS}>: Deserialize<'a>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ok(Orthonormal(Matrix::<T, {DIMS}, {DIMS}>::deserialize(deserializer)?))
}
}
impl<T, const DIMS: usize> Rotation<{DIMS}> for Orthonormal<T, {DIMS}>
where
Matrix<T, {DIMS}, {DIMS}>: Mul<Vector<T, {DIMS}>, Output = Vector<T, {DIMS}>>,
{
type Scalar = T;
fn rotate_vector(self, v: Vector<Self::Scalar, {DIMS}>) -> Vector<Self::Scalar, {DIMS}> {
self.0 * v
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Quaternion<T> {
pub s: T,
pub v: Vector3<T>,
}
impl<T> From<Euler<T>> for Quaternion<T>
where
T: Angle + Clone,
{
fn from(euler: Euler<T>) -> Quaternion<T> {
let Euler { x, y, z } = euler;
let (xs, xc) = x.div2().sin_cos();
let (ys, yc) = y.div2().sin_cos();
let (zs, zc) = z.div2().sin_cos();
Quaternion::new(
-xs.clone() * ys.clone() * zs.clone() + xc.clone() * yc.clone() * zc.clone(),
xs.clone() * yc.clone() * zc.clone() + ys.clone() * zs.clone() * xc.clone(),
-xs.clone() * zs.clone() * yc.clone() + ys.clone() * xc.clone() * zc.clone(),
xs.clone() * ys.clone() * zc.clone() + zs.clone() * xc.clone() * yc.clone(),
)
}
}
impl<T> Quaternion<T> {
pub const fn new(w: T, xi: T, yj: T, zk: T) -> Quaternion<T> {
Quaternion {
s: w,
v: Vector([xi, yj, zk])
}
}
}
impl<T> Quaternion<T>
where
T: Clone,
{
pub fn s(&self) -> T {
self.s.clone()
}
}
impl<T> Mul<T> for Quaternion<T>
where
T: Real + Clone,
{
type Output = Quaternion<T>;
fn mul(self, scalar: T) -> Self {
let Quaternion { s, v: Vector([x, y, z]) } = self;
Quaternion::new(
s * scalar.clone(),
x * scalar.clone(),
y * scalar.clone(),
z * scalar,
)
}
}
impl<T> Div<T> for Quaternion<T>
where
T: Real + Clone,
{
type Output = Quaternion<T>;
fn div(self, scalar: T) -> Self {
let Quaternion { s, v: Vector([x, y, z]) } = self;
Quaternion::new(
s / scalar.clone(),
x / scalar.clone(),
y / scalar.clone(),
z / scalar,
)
}
}
impl<T> MulAssign<T> for Quaternion<T>
where
T: Real + Clone,
{
fn mul_assign(&mut self, scalar: T) {
self.s = self.s() * scalar.clone();
self.v[0] = self.v[0].clone() * scalar.clone();
self.v[1] = self.v[1].clone() * scalar.clone();
self.v[2] = self.v[2].clone() * scalar.clone();
}
}
impl<T> DivAssign<T> for Quaternion<T>
where
T: Real + Clone,
{
fn div_assign(&mut self, scalar: T) {
self.s = self.s() / scalar.clone();
self.v[0] = self.v[0].clone() / scalar.clone();
self.v[1] = self.v[1].clone() / scalar.clone();
self.v[2] = self.v[2].clone() / scalar.clone();
}
}
impl<T> Mul<Quaternion<T>> for Quaternion<T>
where
T: Real + Clone,
{
type Output = Quaternion<T>;
fn mul(self, rhs: Quaternion<T>) -> Self {
Quaternion::new(
self.s() * rhs.s() - self.v.x() * rhs.v.x() - self.v.y() * rhs.v.y() - self.v.z() * rhs.v.z(),
self.s() * rhs.v.x() + self.v.x() * rhs.s() + self.v.y() * rhs.v.z() - self.v.z() * rhs.v.y(),
self.s() * rhs.v.y() + self.v.y() * rhs.s() + self.v.z() * rhs.v.x() - self.v.x() * rhs.v.z(),
self.s() * rhs.v.z() + self.v.z() * rhs.s() + self.v.x() * rhs.v.y() - self.v.y() * rhs.v.x(),
)
}
}
impl<T> Mul<Vector3<T>> for Quaternion<T>
where
T: Real + Clone,
{
type Output = Vector3<T>;
fn mul(self, rhs: Vector3<T>) -> Vector3<T> {
let s = self.s();
self.v.clone()
.cross(self.v.clone().cross(rhs.clone()) + (rhs.clone() * s))
.map(Real::mul2) + rhs
}
}
impl<T> Rotation<3> for Quaternion<T>
where
T: Real + Clone,
{
type Scalar = T;
fn rotate_vector(self, v: Vector<Self::Scalar, 3>) -> Vector<Self::Scalar, 3> {
self * v
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vec_zero() {
let a = Vector3::<u32>::zero();
assert_eq!(a, Vector3::<u32>::from([ 0, 0, 0 ]));
}
#[test]
fn test_vec_index() {
let a = Vector1::<u32>::from([ 0 ]);
assert_eq!(a[0], 0);
let mut b = Vector2::<u32>::from([ 1, 2 ]);
b[1] += 3;
assert_eq!(b[1], 5);
}
#[test]
fn test_vec_eq() {
let a = Vector1::<u32>::from([ 0 ]);
let b = Vector1::<u32>::from([ 1 ]);
let c = Vector1::<u32>::from([ 0 ]);
let d = [ 0u32 ];
assert_ne!(a, b);
assert_eq!(a, c);
assert_eq!(a, &d);
}
#[test]
fn test_vec_addition() {
let a = Vector1::<u32>::from([ 0 ]);
let b = Vector1::<u32>::from([ 1 ]);
let c = Vector1::<u32>::from([ 2 ]);
assert_eq!(a + b, b);
assert_eq!(b + b, c);
let a = Vector2::<u32>::from([ 0, 1 ]);
let b = Vector2::<u32>::from([ 1, 2 ]);
let c = Vector2::<u32>::from([ 1, 3 ]);
let d = Vector2::<u32>::from([ 2, 5 ]);
assert_eq!(a + b, c);
assert_eq!(b + c, d);
let mut c = Vector2::<u32>::from([ 1, 3 ]);
let d = Vector2::<u32>::from([ 2, 5 ]);
c += d;
let e = Vector2::<u32>::from([ 3, 8 ]);
assert_eq!(c, e);
}
#[test]
fn test_vec_subtraction() {
let mut a = Vector1::<u32>::from([ 3 ]);
let b = Vector1::<u32>::from([ 1 ]);
let c = Vector1::<u32>::from([ 2 ]);
assert_eq!(a - c, b);
a -= b;
assert_eq!(a, c);
}
#[test]
fn test_vec_negation() {
let a = Vector4::<i32>::from([ 1, 2, 3, 4 ]);
let b = Vector4::<i32>::from([ -1, -2, -3, -4 ]);
assert_eq!(-a, b);
}
#[test]
fn test_vec_scale() {
let a = Vector4::<f32>::from([ 2.0, 4.0, 2.0, 4.0 ]);
let b = Vector4::<f32>::from([ 4.0, 8.0, 4.0, 8.0 ]);
let c = Vector4::<f32>::from([ 1.0, 2.0, 1.0, 2.0 ]);
assert_eq!(a * 2.0, b);
assert_eq!(a / 2.0, c);
}
#[test]
fn test_vec_cross() {
let a = vector!(1isize, 2isize, 3isize);
let b = vector!(4isize, 5isize, 6isize);
let r = vector!(-3isize, 6isize, -3isize);
assert_eq!(a.cross(b), r);
}
#[test]
fn test_vec_distance() {
let a = Vector1::<f32>::from([ 0.0 ]);
let b = Vector1::<f32>::from([ 1.0 ]);
assert_eq!(a.distance2(b), 1.0);
let a = Vector1::<f32>::from([ 0.0 ]);
let b = Vector1::<f32>::from([ 2.0 ]);
assert_eq!(a.distance2(b), 4.0);
assert_eq!(a.distance(b), 2.0);
let a = Vector2::<f32>::from([ 0.0, 0.0 ]);
let b = Vector2::<f32>::from([ 1.0, 1.0 ]);
assert_eq!(a.distance2(b), 2.0);
}
#[test]
fn test_vec_normalize() {
let a = vector!(5.0);
assert_eq!(a.clone().magnitude(), 5.0);
let a_norm = a.normalize();
assert_eq!(a_norm, vector!(1.0));
}
#[test]
fn test_vec_transpose() {
let v = vector!(1i32, 2, 3, 4);
let m = Matrix::<i32, 1, 4>::from([
vector!(1i32),
vector!(2),
vector!(3),
vector!(4),
]);
assert_eq!(v.transpose(), m);
}
#[test]
fn test_vec_map() {
let int = vector!(1i32, 0, 1, 1, 0, 1, 1, 0, 0, 0);
let boolean = vector!(true, false, true, true, false, true, true, false, false, false);
assert_eq!(
int.map(|i| i != 0),
boolean
);
}
#[test]
fn test_mat_identity() {
let unit = matrix![
[ 1u32, 0, 0, 0 ],
[ 0, 1, 0, 0 ],
[ 0, 0, 1, 0 ],
[ 0, 0, 0, 1 ],
];
assert_eq!(
Matrix::<u32, 4, 4>::one(),
unit
);
}
#[test]
fn test_mat_negation() {
let neg_unit = matrix![
[ -1i32, 0, 0, 0 ],
[ 0, -1, 0, 0 ],
[ 0, 0, -1, 0 ],
[ 0, 0, 0, -1 ],
];
assert_eq!(
-Matrix::<i32, 4, 4>::one(),
neg_unit
);
}
#[test]
fn test_mat_add() {
let a = matrix![ [ matrix![ [ 1u32 ] ] ] ];
let b = matrix![ [ matrix![ [ 10u32 ] ] ] ];
let c = matrix![ [ matrix![ [ 11u32 ] ] ] ];
assert_eq!(a + b, c);
}
#[test]
fn test_mat_scalar_mult() {
let a = Matrix::<f32, 2, 2>::from( [ vector!( 0.0, 1.0 ),
vector!( 0.0, 2.0 ) ] );
let b = Matrix::<f32, 2, 2>::from( [ vector!( 0.0, 2.0 ),
vector!( 0.0, 4.0 ) ] );
assert_eq!(a * 2.0, b);
}
#[test]
fn test_mat_mult() {
let a = Matrix::<f32, 2, 2>::from( [ vector!( 0.0, 0.0 ),
vector!( 1.0, 0.0 ) ] );
let b = Matrix::<f32, 2, 2>::from( [ vector!( 0.0, 1.0 ),
vector!( 0.0, 0.0 ) ] );
assert_eq!(
a * b,
matrix![
[ 1.0, 0.0 ],
[ 0.0, 0.0 ],
]
);
assert_eq!(
b * a,
matrix![
[ 0.0, 0.0 ],
[ 0.0, 1.0 ],
]
);
let a: Matrix::<usize, 1, 1> = matrix![ [ 1 ] ];
let b: Matrix::<usize, 1, 1> = matrix![ [ 2 ] ];
let c: Matrix::<usize, 1, 1> = matrix![ [ 2 ] ];
assert_eq!(a * b, c);
let a = Matrix::<f32, 3, 3>::from( [ vector!( 1.0, 0.0, 0.0 ),
vector!( 0.0, 1.0, 0.0 ),
vector!( 0.0, 0.0, 1.0 ), ] );
let b = a.clone();
let c = a * b;
assert_eq!(
c,
matrix![
[ 1.0, 0.0, 0.0 ],
[ 0.0, 1.0, 0.0 ],
[ 0.0, 0.0, 1.0 ],
]
);
let a: Matrix::<i32, 3, 3> =
matrix![
[ 0, -3, 5 ],
[ 6, 1, -4 ],
[ 2, 3, -2 ],
];
let b: Matrix::<i32, 3, 3> =
matrix![
[ -1, 0, -3 ],
[ 4, 5, 1 ],
[ 2, 6, -2 ]
];
let c: Matrix::<i32, 3, 3> =
matrix![
[ -2, 15, -13 ],
[ -10, -19, -9 ],
[ 6, 3, 1 ]
];
assert_eq!(
a * b,
c
);
}
#[test]
fn test_mat_index() {
let m: Matrix::<i32, 2, 2> =
matrix![
[ 0, 2 ],
[ 1, 3 ],
];
assert_eq!(m[(0, 0)], 0);
assert_eq!(m[0][0], 0);
assert_eq!(m[(1, 0)], 1);
assert_eq!(m[0][1], 1);
assert_eq!(m[(0, 1)], 2);
assert_eq!(m[1][0], 2);
assert_eq!(m[(1, 1)], 3);
assert_eq!(m[1][1], 3);
}
#[test]
fn test_mat_transpose() {
assert_eq!(
Matrix::<i32, 1, 2>::from( [ vector!( 1 ), vector!( 2 ) ] )
.transpose(),
Matrix::<i32, 2, 1>::from( [ vector!( 1, 2 ) ] )
);
assert_eq!(
matrix![
[ 1, 2 ],
[ 3, 4 ],
].transpose(),
matrix![
[ 1, 3 ],
[ 2, 4 ],
]
);
}
#[test]
fn test_square_matrix() {
let a: Matrix::<i32, 3, 3> =
matrix![
[ 5, 0, 0 ],
[ 0, 8, 12 ],
[ 0, 0, 16 ],
];
let diag: Vector::<i32, 3> =
vector!( 5, 8, 16 );
assert_eq!(a.diagonal(), diag);
}
#[test]
fn test_readme_code() {
let a = vector!( 0u32, 1, 2, 3 );
assert_eq!(
a,
Vector::<u32, 4>::from([ 0u32, 1, 2, 3 ])
);
let b = Vector::<f32, 7>::from([ 0.0f32, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, ]);
let c = Vector::<f32, 7>::from([ 1.0f32, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, ]) * 0.5;
assert_eq!(
b + c,
Vector::<f32, 7>::from([ 0.5f32, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5 ])
);
let a = vector!( 1i32, 1);
let b = vector!( 5i32, 5 );
assert_eq!(a.distance2(b), 32);
assert_eq!((b - a).magnitude2(), 32);
let a = vector!( 1.0f32, 1.0 );
let b = vector!( 5.0f32, 5.0 );
const CLOSE: f32 = 5.65685424949;
assert_eq!(a.distance(b), CLOSE);
assert_eq!((b - a).magnitude(), CLOSE);
assert_eq!(
vector!( 0.0f32, 20.0, 0.0 )
.normalize(),
vector!( 0.0f32, 1.0, 0.0 )
);
let _a = Matrix::<f32, 3, 3>::from( [ vector!( 1.0, 0.0, 0.0 ),
vector!( 0.0, 1.0, 0.0 ),
vector!( 0.0, 0.0, 1.0 ), ] );
let _b: Matrix::<i32, 3, 3> =
matrix![
[ 0, -3, 5 ],
[ 6, 1, -4 ],
[ 2, 3, -2 ]
];
assert_eq!(
matrix![
[ 1i32, 0, 0, ],
[ 0, 2, 0 ],
[ 0, 0, 3 ],
].diagonal(),
vector!( 1i32, 2, 3 )
);
assert_eq!(
matrix![
[ 1i32, 0, 0, 0 ],
[ 0, 2, 0, 0 ],
[ 0, 0, 3, 0 ],
[ 0, 0, 0, 4 ]
].diagonal(),
vector!( 1i32, 2, 3, 4 )
);
}
#[test]
fn test_mat_map() {
let int = matrix![
[ 1i32, 0 ],
[ 1, 1 ],
[ 0, 1 ],
[ 1, 0 ],
[ 0, 0 ]
];
let boolean = matrix![
[ true, false ],
[ true, true ],
[ false, true ],
[ true, false ],
[ false, false ]
];
assert_eq!(
int.map(|i| i != 0),
boolean
);
}
#[test]
fn vector_macro_constructor() {
let v: Vector<f32, 0> = vector![];
assert!(v.is_empty());
let v = vector![1];
assert_eq!(1, v[0]);
let v = vector![1, 2, 3, 4, 5, 6, 7, 8, 9, 10,];
for i in 0..10 {
assert_eq!(i + 1, v[i]);
}
}
#[test]
fn matrix_macro_constructor() {
let m: Matrix<f32, 0, 0> = matrix![];
assert!(m.is_empty());
let m = matrix![
[1]
];
assert_eq!(1, m[0][0]);
let m = matrix![
[1, 2],
[3, 4],
[5, 6],
];
assert_eq!(m, Matrix::<u32, 3, 2>::from([
Vector::<u32, 3>::from([1, 3, 5]),
Vector::<u32, 3>::from([2, 4, 6])
]));
}
#[test]
fn test_swizzle() {
let v: Vector<f32, 1> = Vector::<f32, 1>::from([1.0]);
assert_eq!(1.0, v.x());
let v: Vector<f32, 2> = Vector::<f32, 2>::from([1.0, 2.0]);
assert_eq!(1.0, v.x());
assert_eq!(2.0, v.y());
let v: Vector<f32, 3> = Vector::<f32, 3>::from([1.0, 2.0, 3.0]);
assert_eq!(1.0, v.x());
assert_eq!(2.0, v.y());
assert_eq!(3.0, v.z());
let v: Vector<f32, 4> = Vector::<f32, 4>::from([1.0, 2.0, 3.0, 4.0]);
assert_eq!(1.0, v.x());
assert_eq!(2.0, v.y());
assert_eq!(3.0, v.z());
assert_eq!(4.0, v.w());
let v: Vector<f32, 5> = Vector::<f32, 5>::from([1.0, 2.0, 3.0, 4.0, 5.0]);
assert_eq!(1.0, v.x());
assert_eq!(2.0, v.y());
assert_eq!(3.0, v.z());
assert_eq!(4.0, v.w());
}
#[test]
fn test_rotation() {
let rot = Orthonormal::<f32, 3>::from(
Euler {
x: 0.0,
y: 0.0,
z: std::f32::consts::FRAC_PI_2,
}
);
assert_eq!(
rot.rotate_vector(vector![ 1.0f32, 0.0, 0.0 ]).y(),
1.0
);
let v = vector![ 1.0f32, 0.0, 0.0 ];
let q1 = Quaternion::from(
Euler {
x: 0.0,
y: 0.0,
z: std::f32::consts::FRAC_PI_2,
}
);
assert_eq!(
q1.rotate_vector(v).normalize().y(),
1.0
);
}
}