use crate::scalar::*;
use core::ops::{Add, Div, Mul, Neg, Rem, Sub};
use num_traits::Zero;
pub trait Vector<T: Scalar, Rhs = Self, Output = Self>:
Add<Rhs, Output = Output>
+ Sub<Rhs, Output = Output>
+ Mul<Rhs, Output = Output>
+ Mul<T, Output = Output>
+ Div<Rhs, Output = Output>
+ Div<T, Output = Output>
+ Neg<Output = Output>
+ Clone
+ Copy
{
fn zero() -> Self;
fn add_vv(l: &Self, r: &Self) -> Self;
fn sub_vv(l: &Self, r: &Self) -> Self;
fn mul_vv(l: &Self, r: &Self) -> Self;
fn div_vv(l: &Self, r: &Self) -> Self;
fn mul_vs(l: &Self, r: T) -> Self;
fn div_vs(l: &Self, r: T) -> Self;
fn rem_vv(l: &Self, r: &Self) -> Self;
fn dot(l: &Self, r: &Self) -> T;
fn min(l: &Self, r: &Self) -> Self;
fn max(l: &Self, r: &Self) -> Self;
}
pub trait FloatVector<T: FloatScalar>: Vector<T> {
fn length(&self) -> T;
fn normalize(&self) -> Self;
fn distance(l: &Self, r: &Self) -> T;
fn length_squared(&self) -> T {
Self::dot(self, self)
}
fn try_normalize(&self, epsilon: T) -> Option<Self> {
let len_sq = self.length_squared();
if len_sq <= epsilon * epsilon {
None
} else {
Some(*self / len_sq.tsqrt())
}
}
fn normalize_or_zero(&self, epsilon: T) -> Self {
self.try_normalize(epsilon).unwrap_or_else(Self::zero)
}
fn normalize_with_inv_len(&self, inv_len: T) -> Self {
*self * inv_len
}
fn try_normalize_with_inv_len(&self, len_sq: T, inv_len: T, epsilon: T) -> Option<Self> {
if len_sq <= epsilon * epsilon {
None
} else {
Some(*self * inv_len)
}
}
}
macro_rules! implVecScalar {
($vecName:ident, $scalar:ident) => {
impl Mul<$vecName<$scalar>> for $scalar {
type Output = $vecName<$scalar>;
fn mul(self, rhs: $vecName<$scalar>) -> Self::Output {
$vecName::mul_vs(&rhs, self)
}
}
};
}
macro_rules! vector_field_doc {
(x) => {
"X component."
};
(y) => {
"Y component."
};
(z) => {
"Z component."
};
(w) => {
"W component."
};
}
macro_rules! implVector {
($(#[$meta:meta])* $vecName:ident, $($field:ident)*) => {
$(#[$meta])*
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
pub struct $vecName<T> { $(#[doc = vector_field_doc!($field)] pub $field: T),* }
impl<T: Scalar> $vecName<T> {
pub fn new($($field:T),*) -> Self { Self { $($field: $field),* } }
}
impl<T> $vecName<T>
where
T: Copy + num_traits::ToPrimitive,
{
pub fn try_cast<U>(&self) -> Option<$vecName<U>>
where
U: Scalar + num_traits::NumCast,
{
Some($vecName {
$($field: num_traits::NumCast::from(self.$field)?),*
})
}
}
impl<T: Scalar> Vector<T> for $vecName<T> {
fn zero() -> Self { Self { $($field: <T as Zero>::zero()),* } }
fn dot (l: &Self, r: &Self) -> T { $(l.$field * r.$field +)* <T as Zero>::zero() }
fn add_vv(l: &Self, r: &Self) -> Self { Self::new($(l.$field + r.$field),*) }
fn sub_vv(l: &Self, r: &Self) -> Self { Self::new($(l.$field - r.$field),*) }
fn mul_vv(l: &Self, r: &Self) -> Self { Self::new($(l.$field * r.$field),*) }
fn div_vv(l: &Self, r: &Self) -> Self { Self::new($(l.$field / r.$field),*) }
fn mul_vs(l: &Self, r: T) -> Self { Self::new($(l.$field * r),*) }
fn div_vs(l: &Self, r: T) -> Self { Self::new($(l.$field / r),*) }
fn rem_vv(l: &Self, r: &Self) -> Self { Self::new($(l.$field % r.$field),*) }
fn min(l: &Self, r: &Self) -> Self { Self::new($(T::min(l.$field, r.$field)),*) }
fn max(l: &Self, r: &Self) -> Self { Self::new($(T::max(l.$field, r.$field)),*) }
}
impl<T> Add for $vecName<T> where T: Scalar {
type Output = $vecName<T>;
fn add(self, rhs: Self) -> Self::Output {
Self { $($field: self.$field + rhs.$field),* }
}
}
impl<T> Sub for $vecName<T> where T: Scalar {
type Output = $vecName<T>;
fn sub(self, rhs: Self) -> Self::Output {
Self { $($field: self.$field - rhs.$field),* }
}
}
impl<T> Mul for $vecName<T> where T: Scalar {
type Output = $vecName<T>;
fn mul(self, rhs: Self) -> Self::Output {
Self { $($field: self.$field * rhs.$field),* }
}
}
impl<T> Mul<T> for $vecName<T> where T:Scalar {
type Output = $vecName<T>;
fn mul(self, rhs: T) -> Self::Output {
Self { $($field: self.$field * rhs),* }
}
}
implVecScalar!($vecName, f32);
implVecScalar!($vecName, f64);
implVecScalar!($vecName, i32);
implVecScalar!($vecName, i64);
impl<T> Div for $vecName<T> where T:Scalar {
type Output = $vecName<T>;
fn div(self, rhs: Self) -> Self::Output {
Self { $($field: self.$field / rhs.$field),* }
}
}
impl<T> Div<T> for $vecName<T> where T:Scalar {
type Output = $vecName<T>;
fn div(self, rhs: T) -> Self::Output {
Self { $($field: self.$field / rhs),* }
}
}
impl<T> Rem for $vecName<T> where T: Scalar {
type Output = $vecName<T>;
fn rem(self, rhs: $vecName<T>) -> Self::Output {
Self { $($field: self.$field % rhs.$field),* }
}
}
impl<T> Rem<T> for $vecName<T> where T:Scalar {
type Output = $vecName<T>;
fn rem(self, rhs: T) -> Self::Output {
Self { $($field: self.$field % rhs),* }
}
}
impl<T: Scalar> Neg for $vecName<T> {
type Output = $vecName<T>;
fn neg(self) -> Self::Output {
Self { $($field: -self.$field),* }
}
}
};
}
macro_rules! implFloatVector {
($vecName:ident) => {
impl<T: FloatScalar> FloatVector<T> for $vecName<T> {
fn length(&self) -> T {
Self::dot(self, self).tsqrt()
}
fn normalize(&self) -> Self {
let len = Self::length(self);
*self / len
}
fn distance(l: &Self, r: &Self) -> T {
Self::length(&(*r - *l))
}
}
};
}
pub trait CrossProduct {
fn cross(l: &Self, r: &Self) -> Self;
}
implVector!(
Vector2,
x y
);
implVector!(
Vector3,
x y z
);
implVector!(
Vector4,
x y z w
);
implFloatVector!(Vector2);
implFloatVector!(Vector3);
implFloatVector!(Vector4);
impl<T> CrossProduct for Vector3<T>
where
T: Scalar,
{
fn cross(l: &Vector3<T>, r: &Vector3<T>) -> Vector3<T> {
Vector3::new(
l.y * r.z - l.z * r.y,
l.z * r.x - l.x * r.z,
l.x * r.y - l.y * r.x,
)
}
}
pub trait Swizzle2<T: Scalar> {
fn xx(&self) -> Vector2<T>;
fn xy(&self) -> Vector2<T>;
fn xz(&self) -> Vector2<T>;
fn yx(&self) -> Vector2<T>;
fn yy(&self) -> Vector2<T>;
fn yz(&self) -> Vector2<T>;
fn zx(&self) -> Vector2<T>;
fn zy(&self) -> Vector2<T>;
fn zz(&self) -> Vector2<T>;
}
macro_rules! swizzle_field {
($s:ident, x) => {
$s.x
};
($s:ident, y) => {
$s.y
};
($s:ident, z) => {
$s.z
};
($s:ident, zero) => {
<T as Zero>::zero()
};
}
macro_rules! impl_swizzle2 {
($vec:ident, $x:tt, $y:tt, $z:tt) => {
impl<T: Scalar> Swizzle2<T> for $vec<T> {
fn xx(&self) -> Vector2<T> {
Vector2::new(swizzle_field!(self, $x), swizzle_field!(self, $x))
}
fn xy(&self) -> Vector2<T> {
Vector2::new(swizzle_field!(self, $x), swizzle_field!(self, $y))
}
fn xz(&self) -> Vector2<T> {
Vector2::new(swizzle_field!(self, $x), swizzle_field!(self, $z))
}
fn yx(&self) -> Vector2<T> {
Vector2::new(swizzle_field!(self, $y), swizzle_field!(self, $x))
}
fn yy(&self) -> Vector2<T> {
Vector2::new(swizzle_field!(self, $y), swizzle_field!(self, $y))
}
fn yz(&self) -> Vector2<T> {
Vector2::new(swizzle_field!(self, $y), swizzle_field!(self, $z))
}
fn zx(&self) -> Vector2<T> {
Vector2::new(swizzle_field!(self, $z), swizzle_field!(self, $x))
}
fn zy(&self) -> Vector2<T> {
Vector2::new(swizzle_field!(self, $z), swizzle_field!(self, $y))
}
fn zz(&self) -> Vector2<T> {
Vector2::new(swizzle_field!(self, $z), swizzle_field!(self, $z))
}
}
};
}
impl_swizzle2!(Vector2, x, y, zero);
impl_swizzle2!(Vector3, x, y, z);
impl_swizzle2!(Vector4, x, y, z);
pub trait Swizzle3<T: Scalar> {
fn xxx(&self) -> Vector3<T>;
fn xxy(&self) -> Vector3<T>;
fn xxz(&self) -> Vector3<T>;
fn xyx(&self) -> Vector3<T>;
fn xyy(&self) -> Vector3<T>;
fn xyz(&self) -> Vector3<T>;
fn xzx(&self) -> Vector3<T>;
fn xzy(&self) -> Vector3<T>;
fn xzz(&self) -> Vector3<T>;
fn yxx(&self) -> Vector3<T>;
fn yxy(&self) -> Vector3<T>;
fn yxz(&self) -> Vector3<T>;
fn yyx(&self) -> Vector3<T>;
fn yyy(&self) -> Vector3<T>;
fn yyz(&self) -> Vector3<T>;
fn yzx(&self) -> Vector3<T>;
fn yzy(&self) -> Vector3<T>;
fn yzz(&self) -> Vector3<T>;
fn zxx(&self) -> Vector3<T>;
fn zxy(&self) -> Vector3<T>;
fn zxz(&self) -> Vector3<T>;
fn zyx(&self) -> Vector3<T>;
fn zyy(&self) -> Vector3<T>;
fn zyz(&self) -> Vector3<T>;
fn zzx(&self) -> Vector3<T>;
fn zzy(&self) -> Vector3<T>;
fn zzz(&self) -> Vector3<T>;
}
macro_rules! impl_swizzle3 {
($vec:ident, $x:tt, $y:tt, $z:tt) => {
impl<T: Scalar> Swizzle3<T> for $vec<T> {
fn xxx(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $x), swizzle_field!(self, $x), swizzle_field!(self, $x))
}
fn xxy(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $x), swizzle_field!(self, $x), swizzle_field!(self, $y))
}
fn xxz(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $x), swizzle_field!(self, $x), swizzle_field!(self, $z))
}
fn xyx(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $x), swizzle_field!(self, $y), swizzle_field!(self, $x))
}
fn xyy(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $x), swizzle_field!(self, $y), swizzle_field!(self, $y))
}
fn xyz(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $x), swizzle_field!(self, $y), swizzle_field!(self, $z))
}
fn xzx(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $x), swizzle_field!(self, $z), swizzle_field!(self, $x))
}
fn xzy(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $x), swizzle_field!(self, $z), swizzle_field!(self, $y))
}
fn xzz(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $x), swizzle_field!(self, $z), swizzle_field!(self, $z))
}
fn yxx(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $y), swizzle_field!(self, $x), swizzle_field!(self, $x))
}
fn yxy(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $y), swizzle_field!(self, $x), swizzle_field!(self, $y))
}
fn yxz(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $y), swizzle_field!(self, $x), swizzle_field!(self, $z))
}
fn yyx(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $y), swizzle_field!(self, $y), swizzle_field!(self, $x))
}
fn yyy(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $y), swizzle_field!(self, $y), swizzle_field!(self, $y))
}
fn yyz(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $y), swizzle_field!(self, $y), swizzle_field!(self, $z))
}
fn yzx(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $y), swizzle_field!(self, $z), swizzle_field!(self, $x))
}
fn yzy(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $y), swizzle_field!(self, $z), swizzle_field!(self, $y))
}
fn yzz(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $y), swizzle_field!(self, $z), swizzle_field!(self, $z))
}
fn zxx(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $z), swizzle_field!(self, $x), swizzle_field!(self, $x))
}
fn zxy(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $z), swizzle_field!(self, $x), swizzle_field!(self, $y))
}
fn zxz(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $z), swizzle_field!(self, $x), swizzle_field!(self, $z))
}
fn zyx(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $z), swizzle_field!(self, $y), swizzle_field!(self, $x))
}
fn zyy(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $z), swizzle_field!(self, $y), swizzle_field!(self, $y))
}
fn zyz(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $z), swizzle_field!(self, $y), swizzle_field!(self, $z))
}
fn zzx(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $z), swizzle_field!(self, $z), swizzle_field!(self, $x))
}
fn zzy(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $z), swizzle_field!(self, $z), swizzle_field!(self, $y))
}
fn zzz(&self) -> Vector3<T> {
Vector3::new(swizzle_field!(self, $z), swizzle_field!(self, $z), swizzle_field!(self, $z))
}
}
};
}
impl_swizzle3!(Vector3, x, y, z);
impl_swizzle3!(Vector4, x, y, z);
#[cfg(test)]
mod tests {
use super::*;
use crate::scalar::{FloatScalar, EPS_F32};
#[test]
pub fn test() {
let f1 = Vector2 { x: 1.0, y: 2.0 };
let f2 = Vector2 { x: 3.0, y: 4.0 };
let out = f1 + f2;
assert_eq!(out.x, 4.0);
assert_eq!(out.y, 6.0);
let f22: Vector2<f32> = 2.0 * f2;
let f23: Vector2<f32> = f2 * 2.0;
assert_eq!(f22.x, 6.0);
assert_eq!(f22.y, 8.0);
assert_eq!(f23.x, f22.x);
assert_eq!(f23.y, f22.y);
}
#[test]
fn test_vector_normalization() {
let v = Vector3::<f32>::new(3.0, 4.0, 0.0);
let nv = v.normalize();
let len = nv.length();
assert!((len - 1.0).abs() < f32::epsilon());
let v_zero = Vector3::<f32>::new(0.0, 0.0, 0.0);
let nv_zero = v_zero.normalize();
assert!(nv_zero.x.is_infinite() || nv_zero.x.is_nan());
let v_unit = Vector3::<f32>::new(1.0, 0.0, 0.0);
let nv_unit = v_unit.normalize();
assert!((nv_unit.x - 1.0).abs() < f32::epsilon());
assert!((nv_unit.y).abs() < f32::epsilon());
assert!((nv_unit.z).abs() < f32::epsilon());
}
#[test]
fn test_vector_try_normalize() {
let v = Vector3::<f32>::new(3.0, 4.0, 0.0);
let nv = v.try_normalize(EPS_F32).expect("should normalize");
assert!((nv.length() - 1.0).abs() < 0.001);
let zero = Vector3::<f32>::zero();
assert!(zero.try_normalize(EPS_F32).is_none());
let zero_norm = zero.normalize_or_zero(EPS_F32);
assert_eq!(zero_norm.x, 0.0);
assert_eq!(zero_norm.y, 0.0);
assert_eq!(zero_norm.z, 0.0);
let len_sq = v.length_squared();
let inv_len = 1.0f32 / len_sq.tsqrt();
let nv_fast = v.normalize_with_inv_len(inv_len);
assert!((nv_fast.length() - 1.0).abs() < 0.001);
let nv_fast_try = v
.try_normalize_with_inv_len(len_sq, inv_len, EPS_F32)
.expect("should normalize");
assert!((nv_fast_try.length() - 1.0).abs() < 0.001);
assert!(zero.try_normalize_with_inv_len(0.0, 0.0, EPS_F32).is_none());
}
#[test]
fn test_vector_length() {
let v2 = Vector2::<f32>::new(3.0, 4.0);
assert!((v2.length() - 5.0).abs() < f32::epsilon());
let v3 = Vector3::<f32>::new(2.0, 3.0, 6.0);
assert!((v3.length() - 7.0).abs() < f32::epsilon());
let v4 = Vector4::<f32>::new(1.0, 2.0, 2.0, 0.0);
assert!((v4.length() - 3.0).abs() < f32::epsilon());
let v_zero = Vector3::<f32>::zero();
assert_eq!(v_zero.length(), 0.0);
}
#[test]
fn test_vector_dot_product() {
let v1 = Vector3::<f32>::new(1.0, 2.0, 3.0);
let v2 = Vector3::<f32>::new(4.0, 5.0, 6.0);
let dot = Vector3::dot(&v1, &v2);
assert_eq!(dot, 32.0);
let v_ortho1 = Vector3::<f32>::new(1.0, 0.0, 0.0);
let v_ortho2 = Vector3::<f32>::new(0.0, 1.0, 0.0);
assert_eq!(Vector3::dot(&v_ortho1, &v_ortho2), 0.0);
let self_dot = Vector3::dot(&v1, &v1);
let len_squared = v1.length() * v1.length();
assert!((self_dot - len_squared).abs() < 0.0001);
}
#[test]
fn test_vector_cross_product() {
let x = Vector3::<f32>::new(1.0, 0.0, 0.0);
let y = Vector3::<f32>::new(0.0, 1.0, 0.0);
let z = Vector3::<f32>::new(0.0, 0.0, 1.0);
let x_cross_y = Vector3::cross(&x, &y);
assert!((x_cross_y.x - z.x).abs() < f32::epsilon());
assert!((x_cross_y.y - z.y).abs() < f32::epsilon());
assert!((x_cross_y.z - z.z).abs() < f32::epsilon());
let y_cross_z = Vector3::cross(&y, &z);
assert!((y_cross_z.x - x.x).abs() < f32::epsilon());
assert!((y_cross_z.y - x.y).abs() < f32::epsilon());
assert!((y_cross_z.z - x.z).abs() < f32::epsilon());
let z_cross_x = Vector3::cross(&z, &x);
assert!((z_cross_x.x - y.x).abs() < f32::epsilon());
assert!((z_cross_x.y - y.y).abs() < f32::epsilon());
assert!((z_cross_x.z - y.z).abs() < f32::epsilon());
let a = Vector3::<f32>::new(1.0, 2.0, 3.0);
let b = Vector3::<f32>::new(4.0, 5.0, 6.0);
let a_cross_b = Vector3::cross(&a, &b);
let b_cross_a = Vector3::cross(&b, &a);
assert!((a_cross_b.x + b_cross_a.x).abs() < f32::epsilon());
assert!((a_cross_b.y + b_cross_a.y).abs() < f32::epsilon());
assert!((a_cross_b.z + b_cross_a.z).abs() < f32::epsilon());
let self_cross = Vector3::cross(&a, &a);
assert!(self_cross.x.abs() < f32::epsilon());
assert!(self_cross.y.abs() < f32::epsilon());
assert!(self_cross.z.abs() < f32::epsilon());
}
#[test]
fn test_vector_distance() {
let v1 = Vector3::<f32>::new(1.0, 2.0, 3.0);
let v2 = Vector3::<f32>::new(4.0, 6.0, 3.0);
let dist = Vector3::distance(&v1, &v2);
assert!((dist - 5.0).abs() < f32::epsilon());
let self_dist = Vector3::distance(&v1, &v1);
assert!(self_dist.abs() < f32::epsilon());
}
#[test]
fn test_vector_min_max() {
let v1 = Vector3::<f32>::new(1.0, 5.0, 3.0);
let v2 = Vector3::<f32>::new(4.0, 2.0, 6.0);
let v_min = Vector3::min(&v1, &v2);
assert_eq!(v_min.x, 1.0);
assert_eq!(v_min.y, 2.0);
assert_eq!(v_min.z, 3.0);
let v_max = Vector3::max(&v1, &v2);
assert_eq!(v_max.x, 4.0);
assert_eq!(v_max.y, 5.0);
assert_eq!(v_max.z, 6.0);
}
#[test]
fn test_vector_arithmetic() {
let v1 = Vector3::<f32>::new(1.0, 2.0, 3.0);
let v2 = Vector3::<f32>::new(4.0, 5.0, 6.0);
let sum = v1 + v2;
assert_eq!(sum.x, 5.0);
assert_eq!(sum.y, 7.0);
assert_eq!(sum.z, 9.0);
let diff = v2 - v1;
assert_eq!(diff.x, 3.0);
assert_eq!(diff.y, 3.0);
assert_eq!(diff.z, 3.0);
let prod = v1 * v2;
assert_eq!(prod.x, 4.0);
assert_eq!(prod.y, 10.0);
assert_eq!(prod.z, 18.0);
let div = v2 / v1;
assert_eq!(div.x, 4.0);
assert_eq!(div.y, 2.5);
assert_eq!(div.z, 2.0);
let scaled = v1 * 2.0;
assert_eq!(scaled.x, 2.0);
assert_eq!(scaled.y, 4.0);
assert_eq!(scaled.z, 6.0);
let divided = v2 / 2.0;
assert_eq!(divided.x, 2.0);
assert_eq!(divided.y, 2.5);
assert_eq!(divided.z, 3.0);
let neg = -v1;
assert_eq!(neg.x, -1.0);
assert_eq!(neg.y, -2.0);
assert_eq!(neg.z, -3.0);
}
#[test]
fn test_swizzle_operations() {
let v2 = Vector2::<f32>::new(1.0, 2.0);
assert_eq!(v2.xx().x, 1.0);
assert_eq!(v2.xx().y, 1.0);
assert_eq!(v2.xy().x, 1.0);
assert_eq!(v2.xy().y, 2.0);
assert_eq!(v2.yx().x, 2.0);
assert_eq!(v2.yx().y, 1.0);
assert_eq!(v2.yy().x, 2.0);
assert_eq!(v2.yy().y, 2.0);
let v2_xz = v2.xz();
assert_eq!(v2_xz.x, 1.0);
assert_eq!(v2_xz.y, 0.0);
let v3 = Vector3::<f32>::new(1.0, 2.0, 3.0);
assert_eq!(v3.xz().x, 1.0);
assert_eq!(v3.xz().y, 3.0);
assert_eq!(v3.zy().x, 3.0);
assert_eq!(v3.zy().y, 2.0);
let v3_swizzle = v3.zyx();
assert_eq!(v3_swizzle.x, 3.0);
assert_eq!(v3_swizzle.y, 2.0);
assert_eq!(v3_swizzle.z, 1.0);
let v4 = Vector4::<f32>::new(1.0, 2.0, 3.0, 4.0);
let v4_xz = v4.xz();
assert_eq!(v4_xz.x, 1.0);
assert_eq!(v4_xz.y, 3.0);
let v4_swizzle = v4.zyx();
assert_eq!(v4_swizzle.x, 3.0);
assert_eq!(v4_swizzle.y, 2.0);
assert_eq!(v4_swizzle.z, 1.0);
}
#[test]
fn test_vector_rem_operation() {
let v1 = Vector3::<i32>::new(10, 15, 20);
let v2 = Vector3::<i32>::new(3, 4, 6);
let rem = v1 % v2;
assert_eq!(rem.x, 1); assert_eq!(rem.y, 3); assert_eq!(rem.z, 2);
let v3 = Vector3::<i32>::new(10, 15, 20);
let rem_scalar = v3 % 7;
assert_eq!(rem_scalar.x, 3); assert_eq!(rem_scalar.y, 1); assert_eq!(rem_scalar.z, 6); }
#[test]
fn test_vector_try_cast() {
let vi = Vector3::<i32>::new(1, 2, 3);
let vf = vi
.try_cast::<f32>()
.expect("integer vector should cast to f32");
assert_eq!(vf.x, 1.0);
assert_eq!(vf.y, 2.0);
assert_eq!(vf.z, 3.0);
}
}