// Copyright 2013-2014 The CGMath Developers. For a full listing of the authors, // refer to the Cargo.toml file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use rand::{Rand, Rng}; use num_traits::{Bounded, NumCast}; use std::fmt; use std::iter; use std::mem; use std::ops::*; use structure::*; use angle::Rad; use approx; use num::{BaseFloat, BaseNum}; #[cfg(feature = "simd")] use simd::f32x4 as Simdf32x4; #[cfg(feature = "simd")] use simd::i32x4 as Simdi32x4; #[cfg(feature = "simd")] use simd::u32x4 as Simdu32x4; #[cfg(feature = "mint")] use mint; /// A 1-dimensional vector. /// /// This type is marked as `#[repr(C)]`. #[repr(C)] #[derive(PartialEq, Eq, Copy, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Vector1 { /// The x component of the vector. pub x: S, } /// A 2-dimensional vector. /// /// This type is marked as `#[repr(C)]`. #[repr(C)] #[derive(PartialEq, Eq, Copy, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Vector2 { /// The x component of the vector. pub x: S, /// The y component of the vector. pub y: S, } /// A 3-dimensional vector. /// /// This type is marked as `#[repr(C)]`. #[repr(C)] #[derive(PartialEq, Eq, Copy, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Vector3 { /// The x component of the vector. pub x: S, /// The y component of the vector. pub y: S, /// The z component of the vector. pub z: S, } /// A 4-dimensional vector. /// /// This type is marked as `#[repr(C)]`. #[repr(C)] #[derive(PartialEq, Eq, Copy, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Vector4 { /// The x component of the vector. pub x: S, /// The y component of the vector. pub y: S, /// The z component of the vector. pub z: S, /// The w component of the vector. pub w: S, } // Utility macro for generating associated functions for the vectors macro_rules! impl_vector { ($VectorN:ident { $($field:ident),+ }, $n:expr, $constructor:ident) => { impl $VectorN { /// Construct a new vector, using the provided values. #[inline] pub fn new($($field: S),+) -> $VectorN { $VectorN { $($field: $field),+ } } /// Perform the given operation on each field in the vector, returning a new point /// constructed from the operations. #[inline] pub fn map(self, mut f: F) -> $VectorN where F: FnMut(S) -> U { $VectorN { $($field: f(self.$field)),+ } } } /// The short constructor. #[inline] pub fn $constructor($($field: S),+) -> $VectorN { $VectorN::new($($field),+) } impl $VectorN { /// Component-wise casting to another type. #[inline] pub fn cast(&self) -> Option<$VectorN> { $( let $field = match NumCast::from(self.$field) { Some(field) => field, None => return None }; )+ Some($VectorN { $($field),+ }) } } impl MetricSpace for $VectorN { type Metric = S; #[inline] fn distance2(self, other: Self) -> S { (other - self).magnitude2() } } impl Array for $VectorN { type Element = S; #[inline] fn len() -> usize { $n } #[inline] fn from_value(scalar: S) -> $VectorN { $VectorN { $($field: scalar),+ } } #[inline] fn sum(self) -> S where S: Add { fold_array!(add, { $(self.$field),+ }) } #[inline] fn product(self) -> S where S: Mul { fold_array!(mul, { $(self.$field),+ }) } fn is_finite(&self) -> bool where S: BaseFloat { $(self.$field.is_finite())&&+ } } impl Zero for $VectorN { #[inline] fn zero() -> $VectorN { $VectorN::from_value(S::zero()) } #[inline] fn is_zero(&self) -> bool { *self == $VectorN::zero() } } impl iter::Sum<$VectorN> for $VectorN { #[inline] fn sum>>(iter: I) -> $VectorN { iter.fold($VectorN::zero(), Add::add) } } impl<'a, S: 'a + BaseNum> iter::Sum<&'a $VectorN> for $VectorN { #[inline] fn sum>>(iter: I) -> $VectorN { iter.fold($VectorN::zero(), Add::add) } } impl VectorSpace for $VectorN { type Scalar = S; } impl> Neg for $VectorN { type Output = $VectorN; #[inline] fn neg(self) -> $VectorN { $VectorN::new($(-self.$field),+) } } impl approx::AbsDiffEq for $VectorN { type Epsilon = S::Epsilon; #[inline] fn default_epsilon() -> S::Epsilon { S::default_epsilon() } #[inline] fn abs_diff_eq(&self, other: &Self, epsilon: S::Epsilon) -> bool { $(S::abs_diff_eq(&self.$field, &other.$field, epsilon))&&+ } } impl approx::RelativeEq for $VectorN { #[inline] fn default_max_relative() -> S::Epsilon { S::default_max_relative() } #[inline] fn relative_eq(&self, other: &Self, epsilon: S::Epsilon, max_relative: S::Epsilon) -> bool { $(S::relative_eq(&self.$field, &other.$field, epsilon, max_relative))&&+ } } impl approx::UlpsEq for $VectorN { #[inline] fn default_max_ulps() -> u32 { S::default_max_ulps() } #[inline] fn ulps_eq(&self, other: &Self, epsilon: S::Epsilon, max_ulps: u32) -> bool { $(S::ulps_eq(&self.$field, &other.$field, epsilon, max_ulps))&&+ } } impl Rand for $VectorN { #[inline] fn rand(rng: &mut R) -> $VectorN { $VectorN { $($field: rng.gen()),+ } } } impl Bounded for $VectorN { #[inline] fn min_value() -> $VectorN { $VectorN { $($field: S::min_value()),+ } } #[inline] fn max_value() -> $VectorN { $VectorN { $($field: S::max_value()),+ } } } impl_operator!( Add<$VectorN > for $VectorN { fn add(lhs, rhs) -> $VectorN { $VectorN::new($(lhs.$field + rhs.$field),+) } }); impl_assignment_operator!( AddAssign<$VectorN > for $VectorN { fn add_assign(&mut self, other) { $(self.$field += other.$field);+ } }); impl_operator!( Sub<$VectorN > for $VectorN { fn sub(lhs, rhs) -> $VectorN { $VectorN::new($(lhs.$field - rhs.$field),+) } }); impl_assignment_operator!( SubAssign<$VectorN > for $VectorN { fn sub_assign(&mut self, other) { $(self.$field -= other.$field);+ } }); impl_operator!( Mul for $VectorN { fn mul(vector, scalar) -> $VectorN { $VectorN::new($(vector.$field * scalar),+) } }); impl_assignment_operator!( MulAssign for $VectorN { fn mul_assign(&mut self, scalar) { $(self.$field *= scalar);+ } }); impl_operator!( Div for $VectorN { fn div(vector, scalar) -> $VectorN { $VectorN::new($(vector.$field / scalar),+) } }); impl_assignment_operator!( DivAssign for $VectorN { fn div_assign(&mut self, scalar) { $(self.$field /= scalar);+ } }); impl_operator!( Rem for $VectorN { fn rem(vector, scalar) -> $VectorN { $VectorN::new($(vector.$field % scalar),+) } }); impl_assignment_operator!( RemAssign for $VectorN { fn rem_assign(&mut self, scalar) { $(self.$field %= scalar);+ } }); impl ElementWise for $VectorN { #[inline] fn add_element_wise(self, rhs: $VectorN) -> $VectorN { $VectorN::new($(self.$field + rhs.$field),+) } #[inline] fn sub_element_wise(self, rhs: $VectorN) -> $VectorN { $VectorN::new($(self.$field - rhs.$field),+) } #[inline] fn mul_element_wise(self, rhs: $VectorN) -> $VectorN { $VectorN::new($(self.$field * rhs.$field),+) } #[inline] fn div_element_wise(self, rhs: $VectorN) -> $VectorN { $VectorN::new($(self.$field / rhs.$field),+) } #[inline] fn rem_element_wise(self, rhs: $VectorN) -> $VectorN { $VectorN::new($(self.$field % rhs.$field),+) } #[inline] fn add_assign_element_wise(&mut self, rhs: $VectorN) { $(self.$field += rhs.$field);+ } #[inline] fn sub_assign_element_wise(&mut self, rhs: $VectorN) { $(self.$field -= rhs.$field);+ } #[inline] fn mul_assign_element_wise(&mut self, rhs: $VectorN) { $(self.$field *= rhs.$field);+ } #[inline] fn div_assign_element_wise(&mut self, rhs: $VectorN) { $(self.$field /= rhs.$field);+ } #[inline] fn rem_assign_element_wise(&mut self, rhs: $VectorN) { $(self.$field %= rhs.$field);+ } } impl ElementWise for $VectorN { #[inline] fn add_element_wise(self, rhs: S) -> $VectorN { $VectorN::new($(self.$field + rhs),+) } #[inline] fn sub_element_wise(self, rhs: S) -> $VectorN { $VectorN::new($(self.$field - rhs),+) } #[inline] fn mul_element_wise(self, rhs: S) -> $VectorN { $VectorN::new($(self.$field * rhs),+) } #[inline] fn div_element_wise(self, rhs: S) -> $VectorN { $VectorN::new($(self.$field / rhs),+) } #[inline] fn rem_element_wise(self, rhs: S) -> $VectorN { $VectorN::new($(self.$field % rhs),+) } #[inline] fn add_assign_element_wise(&mut self, rhs: S) { $(self.$field += rhs);+ } #[inline] fn sub_assign_element_wise(&mut self, rhs: S) { $(self.$field -= rhs);+ } #[inline] fn mul_assign_element_wise(&mut self, rhs: S) { $(self.$field *= rhs);+ } #[inline] fn div_assign_element_wise(&mut self, rhs: S) { $(self.$field /= rhs);+ } #[inline] fn rem_assign_element_wise(&mut self, rhs: S) { $(self.$field %= rhs);+ } } impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_index_operators!($VectorN, $n, S, usize); impl_index_operators!($VectorN, $n, [S], Range); impl_index_operators!($VectorN, $n, [S], RangeTo); impl_index_operators!($VectorN, $n, [S], RangeFrom); impl_index_operators!($VectorN, $n, [S], RangeFull); } } // Utility macro for generating associated functions for the vectors // mainly duplication #[cfg(feature = "simd")] macro_rules! impl_vector_default { ($VectorN:ident { $($field:ident),+ }, $n:expr, $constructor:ident) => { impl $VectorN { /// Construct a new vector, using the provided values. #[inline] pub fn new($($field: S),+) -> $VectorN { $VectorN { $($field: $field),+ } } } /// The short constructor. #[inline] pub fn $constructor($($field: S),+) -> $VectorN { $VectorN::new($($field),+) } impl $VectorN { /// True if all entries in the vector are finite pub fn is_finite(&self) -> bool { $(self.$field.is_finite())&&+ } } impl $VectorN { /// Component-wise casting to another type. #[inline] pub fn cast(&self) -> Option<$VectorN> { $( let $field = match NumCast::from(self.$field) { Some(field) => field, None => return None }; )+ Some($VectorN { $($field),+ }) } } impl MetricSpace for $VectorN { type Metric = S; #[inline] fn distance2(self, other: Self) -> S { (other - self).magnitude2() } } impl Array for $VectorN { type Element = S; #[inline] fn len() -> usize { $n } #[inline] fn from_value(scalar: S) -> $VectorN { $VectorN { $($field: scalar),+ } } #[inline] fn sum(self) -> S where S: Add { fold_array!(add, { $(self.$field),+ }) } #[inline] fn product(self) -> S where S: Mul { fold_array!(mul, { $(self.$field),+ }) } fn is_finite(&self) -> bool where S: BaseFloat { $(self.$field.is_finite())&&+ } } impl Zero for $VectorN { #[inline] fn zero() -> $VectorN { $VectorN::from_value(S::zero()) } #[inline] fn is_zero(&self) -> bool { *self == $VectorN::zero() } } impl iter::Sum for $VectorN { #[inline] fn sum>(iter: I) -> Self { iter.fold(Self::zero(), Add::add) } } impl<'a, S: 'a + BaseNum> iter::Sum<&'a Self> for $VectorN { #[inline] fn sum>(iter: I) -> Self { iter.fold(Self::zero(), Add::add) } } impl VectorSpace for $VectorN { type Scalar = S; } impl> Neg for $VectorN { type Output = $VectorN; #[inline] default fn neg(self) -> $VectorN { $VectorN::new($(-self.$field),+) } } impl approx::AbsDiffEq for $VectorN { type Epsilon = S::Epsilon; #[inline] fn default_epsilon() -> S::Epsilon { S::default_epsilon() } #[inline] fn abs_diff_eq(&self, other: &Self, epsilon: S::Epsilon) -> bool { $(S::abs_diff_eq(&self.$field, &other.$field, epsilon))&&+ } } impl approx::RelativeEq for $VectorN { #[inline] fn default_max_relative() -> S::Epsilon { S::default_max_relative() } #[inline] fn relative_eq(&self, other: &Self, epsilon: S::Epsilon, max_relative: S::Epsilon) -> bool { $(S::relative_eq(&self.$field, &other.$field, epsilon, max_relative))&&+ } } impl approx::UlpsEq for $VectorN { #[inline] fn default_max_ulps() -> u32 { S::default_max_ulps() } #[inline] fn ulps_eq(&self, other: &Self, epsilon: S::Epsilon, max_ulps: u32) -> bool { $(S::ulps_eq(&self.$field, &other.$field, epsilon, max_ulps))&&+ } } impl Rand for $VectorN { #[inline] fn rand(rng: &mut R) -> $VectorN { $VectorN { $($field: rng.gen()),+ } } } impl_operator_default!( Add<$VectorN > for $VectorN { fn add(lhs, rhs) -> $VectorN { $VectorN::new($(lhs.$field + rhs.$field),+) } }); impl_assignment_operator_default!( AddAssign<$VectorN > for $VectorN { fn add_assign(&mut self, other) { $(self.$field += other.$field);+ } }); impl_operator_default!( Sub<$VectorN > for $VectorN { fn sub(lhs, rhs) -> $VectorN { $VectorN::new($(lhs.$field - rhs.$field),+) } }); impl_assignment_operator_default!( SubAssign<$VectorN > for $VectorN { fn sub_assign(&mut self, other) { $(self.$field -= other.$field);+ } }); impl_operator_default!( Mul for $VectorN { fn mul(vector, scalar) -> $VectorN { $VectorN::new($(vector.$field * scalar),+) } }); impl_assignment_operator_default!( MulAssign for $VectorN { fn mul_assign(&mut self, scalar) { $(self.$field *= scalar);+ } }); impl_operator_default!( Div for $VectorN { fn div(vector, scalar) -> $VectorN { $VectorN::new($(vector.$field / scalar),+) } }); impl_assignment_operator_default!( DivAssign for $VectorN { fn div_assign(&mut self, scalar) { $(self.$field /= scalar);+ } }); impl_operator!( Rem for $VectorN { fn rem(vector, scalar) -> $VectorN { $VectorN::new($(vector.$field % scalar),+) } }); impl_assignment_operator!( RemAssign for $VectorN { fn rem_assign(&mut self, scalar) { $(self.$field %= scalar);+ } }); impl ElementWise for $VectorN { #[inline] default fn add_element_wise(self, rhs: $VectorN) -> $VectorN { $VectorN::new($(self.$field + rhs.$field),+) } #[inline] default fn sub_element_wise(self, rhs: $VectorN) -> $VectorN { $VectorN::new($(self.$field - rhs.$field),+) } #[inline] default fn mul_element_wise(self, rhs: $VectorN) -> $VectorN { $VectorN::new($(self.$field * rhs.$field),+) } #[inline] default fn div_element_wise(self, rhs: $VectorN) -> $VectorN { $VectorN::new($(self.$field / rhs.$field),+) } #[inline] fn rem_element_wise(self, rhs: $VectorN) -> $VectorN { $VectorN::new($(self.$field % rhs.$field),+) } #[inline] default fn add_assign_element_wise(&mut self, rhs: $VectorN) { $(self.$field += rhs.$field);+ } #[inline] default fn sub_assign_element_wise(&mut self, rhs: $VectorN) { $(self.$field -= rhs.$field);+ } #[inline] default fn mul_assign_element_wise(&mut self, rhs: $VectorN) { $(self.$field *= rhs.$field);+ } #[inline] default fn div_assign_element_wise(&mut self, rhs: $VectorN) { $(self.$field /= rhs.$field);+ } #[inline] fn rem_assign_element_wise(&mut self, rhs: $VectorN) { $(self.$field %= rhs.$field);+ } } impl ElementWise for $VectorN { #[inline] default fn add_element_wise(self, rhs: S) -> $VectorN { $VectorN::new($(self.$field + rhs),+) } #[inline] default fn sub_element_wise(self, rhs: S) -> $VectorN { $VectorN::new($(self.$field - rhs),+) } #[inline] default fn mul_element_wise(self, rhs: S) -> $VectorN { $VectorN::new($(self.$field * rhs),+) } #[inline] default fn div_element_wise(self, rhs: S) -> $VectorN { $VectorN::new($(self.$field / rhs),+) } #[inline] fn rem_element_wise(self, rhs: S) -> $VectorN { $VectorN::new($(self.$field % rhs),+) } #[inline] default fn add_assign_element_wise(&mut self, rhs: S) { $(self.$field += rhs);+ } #[inline] default fn sub_assign_element_wise(&mut self, rhs: S) { $(self.$field -= rhs);+ } #[inline] default fn mul_assign_element_wise(&mut self, rhs: S) { $(self.$field *= rhs);+ } #[inline] default fn div_assign_element_wise(&mut self, rhs: S) { $(self.$field /= rhs);+ } #[inline] fn rem_assign_element_wise(&mut self, rhs: S) { $(self.$field %= rhs);+ } } impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops_default!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops_default!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_scalar_ops_default!($VectorN { $($field),+ }); impl_scalar_ops!($VectorN { $($field),+ }); impl_index_operators!($VectorN, $n, S, usize); impl_index_operators!($VectorN, $n, [S], Range); impl_index_operators!($VectorN, $n, [S], RangeTo); impl_index_operators!($VectorN, $n, [S], RangeFrom); impl_index_operators!($VectorN, $n, [S], RangeFull); } } macro_rules! impl_scalar_ops { ($VectorN:ident<$S:ident> { $($field:ident),+ }) => { impl_operator!(Mul<$VectorN<$S>> for $S { fn mul(scalar, vector) -> $VectorN<$S> { $VectorN::new($(scalar * vector.$field),+) } }); impl_operator!(Div<$VectorN<$S>> for $S { fn div(scalar, vector) -> $VectorN<$S> { $VectorN::new($(scalar / vector.$field),+) } }); impl_operator!(Rem<$VectorN<$S>> for $S { fn rem(scalar, vector) -> $VectorN<$S> { $VectorN::new($(scalar % vector.$field),+) } }); }; } #[cfg(feature = "simd")] macro_rules! impl_scalar_ops_default { ($VectorN:ident<$S:ident> { $($field:ident),+ }) => { impl_operator_default!(Mul<$VectorN<$S>> for $S { fn mul(scalar, vector) -> $VectorN<$S> { $VectorN::new($(scalar * vector.$field),+) } }); impl_operator_default!(Div<$VectorN<$S>> for $S { fn div(scalar, vector) -> $VectorN<$S> { $VectorN::new($(scalar / vector.$field),+) } }); impl_operator_default!(Rem<$VectorN<$S>> for $S { fn rem(scalar, vector) -> $VectorN<$S> { $VectorN::new($(scalar % vector.$field),+) } }); }; } impl_vector!(Vector1 { x }, 1, vec1); impl_vector!(Vector2 { x, y }, 2, vec2); impl_vector!(Vector3 { x, y, z }, 3, vec3); #[cfg(not(feature = "simd"))] impl_vector!(Vector4 { x, y, z, w }, 4, vec4); #[cfg(feature = "simd")] impl_vector_default!(Vector4 { x, y, z, w }, 4, vec4); impl_fixed_array_conversions!(Vector1 { x: 0 }, 1); impl_fixed_array_conversions!(Vector2 { x: 0, y: 1 }, 2); impl_fixed_array_conversions!(Vector3 { x: 0, y: 1, z: 2 }, 3); impl_fixed_array_conversions!(Vector4 { x: 0, y: 1, z: 2, w: 3 }, 4); impl_tuple_conversions!(Vector1 { x }, (S,)); impl_tuple_conversions!(Vector2 { x, y }, (S, S)); impl_tuple_conversions!(Vector3 { x, y, z }, (S, S, S)); impl_tuple_conversions!(Vector4 { x, y, z, w }, (S, S, S, S)); impl Vector1 { /// A unit vector in the `x` direction. #[inline] pub fn unit_x() -> Vector1 { Vector1::new(S::one()) } impl_swizzle_functions!(Vector1, Vector2, Vector3, Vector4, S, x); } impl Vector2 { /// A unit vector in the `x` direction. #[inline] pub fn unit_x() -> Vector2 { Vector2::new(S::one(), S::zero()) } /// A unit vector in the `y` direction. #[inline] pub fn unit_y() -> Vector2 { Vector2::new(S::zero(), S::one()) } /// The perpendicular dot product of the vector and `other`. #[inline] pub fn perp_dot(self, other: Vector2) -> S { (self.x * other.y) - (self.y * other.x) } /// Create a `Vector3`, using the `x` and `y` values from this vector, and the /// provided `z`. #[inline] pub fn extend(self, z: S) -> Vector3 { Vector3::new(self.x, self.y, z) } impl_swizzle_functions!(Vector1, Vector2, Vector3, Vector4, S, xy); } impl Vector3 { /// A unit vector in the `x` direction. #[inline] pub fn unit_x() -> Vector3 { Vector3::new(S::one(), S::zero(), S::zero()) } /// A unit vector in the `y` direction. #[inline] pub fn unit_y() -> Vector3 { Vector3::new(S::zero(), S::one(), S::zero()) } /// A unit vector in the `z` direction. #[inline] pub fn unit_z() -> Vector3 { Vector3::new(S::zero(), S::zero(), S::one()) } /// Returns the cross product of the vector and `other`. #[inline] pub fn cross(self, other: Vector3) -> Vector3 { Vector3::new( (self.y * other.z) - (self.z * other.y), (self.z * other.x) - (self.x * other.z), (self.x * other.y) - (self.y * other.x), ) } /// Create a `Vector4`, using the `x`, `y` and `z` values from this vector, and the /// provided `w`. #[inline] pub fn extend(self, w: S) -> Vector4 { Vector4::new(self.x, self.y, self.z, w) } /// Create a `Vector2`, dropping the `z` value. #[inline] pub fn truncate(self) -> Vector2 { Vector2::new(self.x, self.y) } impl_swizzle_functions!(Vector1, Vector2, Vector3, Vector4, S, xyz); } impl Vector4 { /// A unit vector in the `x` direction. #[inline] pub fn unit_x() -> Vector4 { Vector4::new(S::one(), S::zero(), S::zero(), S::zero()) } /// A unit vector in the `y` direction. #[inline] pub fn unit_y() -> Vector4 { Vector4::new(S::zero(), S::one(), S::zero(), S::zero()) } /// A unit vector in the `z` direction. #[inline] pub fn unit_z() -> Vector4 { Vector4::new(S::zero(), S::zero(), S::one(), S::zero()) } /// A unit vector in the `w` direction. #[inline] pub fn unit_w() -> Vector4 { Vector4::new(S::zero(), S::zero(), S::zero(), S::one()) } /// Create a `Vector3`, dropping the `w` value. #[inline] pub fn truncate(self) -> Vector3 { Vector3::new(self.x, self.y, self.z) } /// Create a `Vector3`, dropping the nth element. #[inline] pub fn truncate_n(&self, n: isize) -> Vector3 { match n { 0 => Vector3::new(self.y, self.z, self.w), 1 => Vector3::new(self.x, self.z, self.w), 2 => Vector3::new(self.x, self.y, self.w), 3 => Vector3::new(self.x, self.y, self.z), _ => panic!("{:?} is out of range", n), } } impl_swizzle_functions!(Vector1, Vector2, Vector3, Vector4, S, xyzw); } /// Dot product of two vectors. #[inline] pub fn dot(a: V, b: V) -> V::Scalar where V::Scalar: BaseFloat, { V::dot(a, b) } impl InnerSpace for Vector1 { #[inline] fn dot(self, other: Vector1) -> S { Vector1::mul_element_wise(self, other).sum() } } impl InnerSpace for Vector2 { #[inline] fn dot(self, other: Vector2) -> S { Vector2::mul_element_wise(self, other).sum() } #[inline] fn angle(self, other: Vector2) -> Rad { Rad::atan2(Self::perp_dot(self, other), Self::dot(self, other)) } } impl InnerSpace for Vector3 { #[inline] fn dot(self, other: Vector3) -> S { Vector3::mul_element_wise(self, other).sum() } #[inline] fn angle(self, other: Vector3) -> Rad { Rad::atan2(self.cross(other).magnitude(), Self::dot(self, other)) } } impl InnerSpace for Vector4 { #[inline] fn dot(self, other: Vector4) -> S { Vector4::mul_element_wise(self, other).sum() } } impl fmt::Debug for Vector1 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "Vector1 ")); <[S; 1] as fmt::Debug>::fmt(self.as_ref(), f) } } impl fmt::Debug for Vector2 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "Vector2 ")); <[S; 2] as fmt::Debug>::fmt(self.as_ref(), f) } } impl fmt::Debug for Vector3 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "Vector3 ")); <[S; 3] as fmt::Debug>::fmt(self.as_ref(), f) } } impl fmt::Debug for Vector4 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "Vector4 ")); <[S; 4] as fmt::Debug>::fmt(self.as_ref(), f) } } #[cfg(feature = "simd")] impl From for Vector4 { #[inline] fn from(f: Simdf32x4) -> Self { unsafe { let mut ret: Self = mem::uninitialized(); { let ret_mut: &mut [f32; 4] = ret.as_mut(); f.store(ret_mut.as_mut(), 0 as usize); } ret } } } #[cfg(feature = "simd")] impl Vector4 { /// Compute and return the square root of each element. #[inline] pub fn sqrt_element_wide(self) -> Self { let s: Simdf32x4 = self.into(); s.sqrt().into() } /// Compute and return the reciprocal of the square root of each element. #[inline] pub fn rsqrt_element_wide(self) -> Self { let s: Simdf32x4 = self.into(); s.approx_rsqrt().into() } /// Compute and return the reciprocal of each element. #[inline] pub fn recip_element_wide(self) -> Self { let s: Simdf32x4 = self.into(); s.approx_reciprocal().into() } } #[cfg(feature = "simd")] impl Into for Vector4 { #[inline] fn into(self) -> Simdf32x4 { let self_ref: &[f32; 4] = self.as_ref(); Simdf32x4::load(self_ref.as_ref(), 0 as usize) } } #[cfg(feature = "simd")] impl_operator_simd!{ [Simdf32x4]; Add> for Vector4 { fn add(lhs, rhs) -> Vector4 { (lhs + rhs).into() } } } #[cfg(feature = "simd")] impl_operator_simd!{ [Simdf32x4]; Sub> for Vector4 { fn sub(lhs, rhs) -> Vector4 { (lhs - rhs).into() } } } #[cfg(feature = "simd")] impl_operator_simd!{@rs [Simdf32x4]; Mul for Vector4 { fn mul(lhs, rhs) -> Vector4 { (lhs * rhs).into() } } } #[cfg(feature = "simd")] impl_operator_simd!{@rs [Simdf32x4]; Div for Vector4 { fn div(lhs, rhs) -> Vector4 { (lhs / rhs).into() } } } #[cfg(feature = "simd")] impl_operator_simd!{ [Simdf32x4]; Neg for Vector4 { fn neg(lhs) -> Vector4 { (-lhs).into() } } } #[cfg(feature = "simd")] impl AddAssign for Vector4 { #[inline] fn add_assign(&mut self, rhs: Self) { let s: Simdf32x4 = (*self).into(); let rhs: Simdf32x4 = rhs.into(); *self = (s + rhs).into(); } } #[cfg(feature = "simd")] impl SubAssign for Vector4 { #[inline] fn sub_assign(&mut self, rhs: Self) { let s: Simdf32x4 = (*self).into(); let rhs: Simdf32x4 = rhs.into(); *self = (s - rhs).into(); } } #[cfg(feature = "simd")] impl MulAssign for Vector4 { fn mul_assign(&mut self, other: f32) { let s: Simdf32x4 = (*self).into(); let other = Simdf32x4::splat(other); *self = (s * other).into(); } } #[cfg(feature = "simd")] impl DivAssign for Vector4 { fn div_assign(&mut self, other: f32) { let s: Simdf32x4 = (*self).into(); let other = Simdf32x4::splat(other); *self = (s / other).into(); } } #[cfg(feature = "simd")] impl ElementWise for Vector4 { #[inline] fn add_element_wise(self, rhs: Vector4) -> Vector4 { self + rhs } #[inline] fn sub_element_wise(self, rhs: Vector4) -> Vector4 { self - rhs } #[inline] fn mul_element_wise(self, rhs: Vector4) -> Vector4 { let s: Simdf32x4 = self.into(); let rhs: Simdf32x4 = rhs.into(); (s * rhs).into() } #[inline] fn div_element_wise(self, rhs: Vector4) -> Vector4 { let s: Simdf32x4 = self.into(); let rhs: Simdf32x4 = rhs.into(); (s / rhs).into() } #[inline] fn add_assign_element_wise(&mut self, rhs: Vector4) { (*self) += rhs; } #[inline] fn sub_assign_element_wise(&mut self, rhs: Vector4) { (*self) -= rhs; } #[inline] fn mul_assign_element_wise(&mut self, rhs: Vector4) { let s: Simdf32x4 = (*self).into(); let rhs: Simdf32x4 = rhs.into(); *self = (s * rhs).into(); } #[inline] fn div_assign_element_wise(&mut self, rhs: Vector4) { let s: Simdf32x4 = (*self).into(); let rhs: Simdf32x4 = rhs.into(); *self = (s * rhs).into(); } } #[cfg(feature = "simd")] impl ElementWise for Vector4 { #[inline] fn add_element_wise(self, rhs: f32) -> Vector4 { let s: Simdf32x4 = self.into(); let rhs = Simdf32x4::splat(rhs); (s + rhs).into() } #[inline] fn sub_element_wise(self, rhs: f32) -> Vector4 { let s: Simdf32x4 = self.into(); let rhs = Simdf32x4::splat(rhs); (s - rhs).into() } #[inline] fn mul_element_wise(self, rhs: f32) -> Vector4 { self * rhs } #[inline] fn div_element_wise(self, rhs: f32) -> Vector4 { self / rhs } #[inline] fn add_assign_element_wise(&mut self, rhs: f32) { let s: Simdf32x4 = (*self).into(); let rhs = Simdf32x4::splat(rhs); *self = (s + rhs).into(); } #[inline] fn sub_assign_element_wise(&mut self, rhs: f32) { let s: Simdf32x4 = (*self).into(); let rhs = Simdf32x4::splat(rhs); *self = (s - rhs).into(); } #[inline] fn mul_assign_element_wise(&mut self, rhs: f32) { (*self) *= rhs; } #[inline] fn div_assign_element_wise(&mut self, rhs: f32) { (*self) /= rhs; } } #[cfg(feature = "simd")] impl From for Vector4 { #[inline] fn from(f: Simdi32x4) -> Self { unsafe { let mut ret: Self = mem::uninitialized(); { let ret_mut: &mut [i32; 4] = ret.as_mut(); f.store(ret_mut.as_mut(), 0 as usize); } ret } } } #[cfg(feature = "simd")] impl Into for Vector4 { #[inline] fn into(self) -> Simdi32x4 { let self_ref: &[i32; 4] = self.as_ref(); Simdi32x4::load(self_ref.as_ref(), 0 as usize) } } #[cfg(feature = "simd")] impl_operator_simd!{ [Simdi32x4]; Add> for Vector4 { fn add(lhs, rhs) -> Vector4 { (lhs + rhs).into() } } } #[cfg(feature = "simd")] impl_operator_simd!{ [Simdi32x4]; Sub> for Vector4 { fn sub(lhs, rhs) -> Vector4 { (lhs - rhs).into() } } } #[cfg(feature = "simd")] impl_operator_simd!{@rs [Simdi32x4]; Mul for Vector4 { fn mul(lhs, rhs) -> Vector4 { (lhs * rhs).into() } } } #[cfg(feature = "simd")] impl_operator_simd!{ [Simdi32x4]; Neg for Vector4 { fn neg(lhs) -> Vector4 { (-lhs).into() } } } #[cfg(feature = "simd")] impl AddAssign for Vector4 { #[inline] fn add_assign(&mut self, rhs: Self) { let s: Simdi32x4 = (*self).into(); let rhs: Simdi32x4 = rhs.into(); *self = (s + rhs).into(); } } #[cfg(feature = "simd")] impl SubAssign for Vector4 { #[inline] fn sub_assign(&mut self, rhs: Self) { let s: Simdi32x4 = (*self).into(); let rhs: Simdi32x4 = rhs.into(); *self = (s - rhs).into(); } } #[cfg(feature = "simd")] impl MulAssign for Vector4 { fn mul_assign(&mut self, other: i32) { let s: Simdi32x4 = (*self).into(); let other = Simdi32x4::splat(other); *self = (s * other).into(); } } #[cfg(feature = "simd")] impl From for Vector4 { #[inline] fn from(f: Simdu32x4) -> Self { unsafe { let mut ret: Self = mem::uninitialized(); { let ret_mut: &mut [u32; 4] = ret.as_mut(); f.store(ret_mut.as_mut(), 0 as usize); } ret } } } #[cfg(feature = "simd")] impl Into for Vector4 { #[inline] fn into(self) -> Simdu32x4 { let self_ref: &[u32; 4] = self.as_ref(); Simdu32x4::load(self_ref.as_ref(), 0 as usize) } } #[cfg(feature = "simd")] impl_operator_simd!{ [Simdu32x4]; Add> for Vector4 { fn add(lhs, rhs) -> Vector4 { (lhs + rhs).into() } } } #[cfg(feature = "simd")] impl_operator_simd!{ [Simdu32x4]; Sub> for Vector4 { fn sub(lhs, rhs) -> Vector4 { (lhs - rhs).into() } } } #[cfg(feature = "simd")] impl_operator_simd!{@rs [Simdu32x4]; Mul for Vector4 { fn mul(lhs, rhs) -> Vector4 { (lhs * rhs).into() } } } #[cfg(feature = "simd")] impl AddAssign for Vector4 { #[inline] fn add_assign(&mut self, rhs: Self) { let s: Simdu32x4 = (*self).into(); let rhs: Simdu32x4 = rhs.into(); *self = (s + rhs).into(); } } #[cfg(feature = "simd")] impl SubAssign for Vector4 { #[inline] fn sub_assign(&mut self, rhs: Self) { let s: Simdu32x4 = (*self).into(); let rhs: Simdu32x4 = rhs.into(); *self = (s - rhs).into(); } } #[cfg(feature = "simd")] impl MulAssign for Vector4 { fn mul_assign(&mut self, other: u32) { let s: Simdu32x4 = (*self).into(); let other = Simdu32x4::splat(other); *self = (s * other).into(); } } #[cfg(feature = "mint")] impl_mint_conversions!(Vector2 { x, y }, Vector2); #[cfg(feature = "mint")] impl_mint_conversions!(Vector3 { x, y, z }, Vector3); #[cfg(feature = "mint")] impl_mint_conversions!(Vector4 { x, y, z, w }, Vector4); #[cfg(test)] mod tests { mod vector2 { use vector::*; const VECTOR2: Vector2 = Vector2 { x: 1, y: 2 }; #[test] fn test_index() { assert_eq!(VECTOR2[0], VECTOR2.x); assert_eq!(VECTOR2[1], VECTOR2.y); } #[test] fn test_index_mut() { let mut v = VECTOR2; *&mut v[0] = 0; assert_eq!(v, [0, 2].into()); } #[test] #[should_panic] fn test_index_out_of_bounds() { VECTOR2[2]; } #[test] fn test_index_range() { assert_eq!(&VECTOR2[..0], &[]); assert_eq!(&VECTOR2[..1], &[1]); assert_eq!(VECTOR2[..0].len(), 0); assert_eq!(VECTOR2[..1].len(), 1); assert_eq!(&VECTOR2[2..], &[]); assert_eq!(&VECTOR2[1..], &[2]); assert_eq!(VECTOR2[2..].len(), 0); assert_eq!(VECTOR2[1..].len(), 1); assert_eq!(&VECTOR2[..], &[1, 2]); assert_eq!(VECTOR2[..].len(), 2); } #[test] fn test_into() { let v = VECTOR2; { let v: [i32; 2] = v.into(); assert_eq!(v, [1, 2]); } { let v: (i32, i32) = v.into(); assert_eq!(v, (1, 2)); } } #[test] fn test_as_ref() { let v = VECTOR2; { let v: &[i32; 2] = v.as_ref(); assert_eq!(v, &[1, 2]); } { let v: &(i32, i32) = v.as_ref(); assert_eq!(v, &(1, 2)); } } #[test] fn test_as_mut() { let mut v = VECTOR2; { let v: &mut [i32; 2] = v.as_mut(); assert_eq!(v, &mut [1, 2]); } { let v: &mut (i32, i32) = v.as_mut(); assert_eq!(v, &mut (1, 2)); } } #[test] fn test_from() { assert_eq!(Vector2::from([1, 2]), VECTOR2); { let v = &[1, 2]; let v: &Vector2<_> = From::from(v); assert_eq!(v, &VECTOR2); } { let v = &mut [1, 2]; let v: &mut Vector2<_> = From::from(v); assert_eq!(v, &VECTOR2); } assert_eq!(Vector2::from((1, 2)), VECTOR2); { let v = &(1, 2); let v: &Vector2<_> = From::from(v); assert_eq!(v, &VECTOR2); } { let v = &mut (1, 2); let v: &mut Vector2<_> = From::from(v); assert_eq!(v, &VECTOR2); } } #[test] fn test_is_finite() { use num_traits::Float; assert!(!Vector2::from([Float::nan(), 1.0]).is_finite()); assert!(!Vector2::from([1.0, Float::infinity()]).is_finite()); assert!(Vector2::from([-1.0, 1.0]).is_finite()); } } mod vector3 { use vector::*; const VECTOR3: Vector3 = Vector3 { x: 1, y: 2, z: 3 }; #[test] fn test_index() { assert_eq!(VECTOR3[0], VECTOR3.x); assert_eq!(VECTOR3[1], VECTOR3.y); assert_eq!(VECTOR3[2], VECTOR3.z); } #[test] fn test_index_mut() { let mut v = VECTOR3; *&mut v[1] = 0; assert_eq!(v, [1, 0, 3].into()); } #[test] #[should_panic] fn test_index_out_of_bounds() { VECTOR3[3]; } #[test] fn test_index_range() { assert_eq!(&VECTOR3[..1], &[1]); assert_eq!(&VECTOR3[..2], &[1, 2]); assert_eq!(VECTOR3[..1].len(), 1); assert_eq!(VECTOR3[..2].len(), 2); assert_eq!(&VECTOR3[2..], &[3]); assert_eq!(&VECTOR3[1..], &[2, 3]); assert_eq!(VECTOR3[2..].len(), 1); assert_eq!(VECTOR3[1..].len(), 2); assert_eq!(&VECTOR3[..], &[1, 2, 3]); assert_eq!(VECTOR3[..].len(), 3); } #[test] fn test_into() { let v = VECTOR3; { let v: [i32; 3] = v.into(); assert_eq!(v, [1, 2, 3]); } { let v: (i32, i32, i32) = v.into(); assert_eq!(v, (1, 2, 3)); } } #[test] fn test_as_ref() { let v = VECTOR3; { let v: &[i32; 3] = v.as_ref(); assert_eq!(v, &[1, 2, 3]); } { let v: &(i32, i32, i32) = v.as_ref(); assert_eq!(v, &(1, 2, 3)); } } #[test] fn test_as_mut() { let mut v = VECTOR3; { let v: &mut [i32; 3] = v.as_mut(); assert_eq!(v, &mut [1, 2, 3]); } { let v: &mut (i32, i32, i32) = v.as_mut(); assert_eq!(v, &mut (1, 2, 3)); } } #[test] fn test_from() { assert_eq!(Vector3::from([1, 2, 3]), VECTOR3); { let v = &[1, 2, 3]; let v: &Vector3<_> = From::from(v); assert_eq!(v, &VECTOR3); } { let v = &mut [1, 2, 3]; let v: &mut Vector3<_> = From::from(v); assert_eq!(v, &VECTOR3); } assert_eq!(Vector3::from((1, 2, 3)), VECTOR3); { let v = &(1, 2, 3); let v: &Vector3<_> = From::from(v); assert_eq!(v, &VECTOR3); } { let v = &mut (1, 2, 3); let v: &mut Vector3<_> = From::from(v); assert_eq!(v, &VECTOR3); } } #[test] fn test_is_finite() { use num_traits::Float; assert!(!Vector3::from([Float::nan(), 1.0, 1.0]).is_finite()); assert!(!Vector3::from([1.0, 1.0, Float::infinity()]).is_finite()); assert!(Vector3::from([-1.0, 1.0, 1.0]).is_finite()); } } mod vector4 { use vector::*; const VECTOR4: Vector4 = Vector4 { x: 1, y: 2, z: 3, w: 4, }; #[test] fn test_index() { assert_eq!(VECTOR4[0], VECTOR4.x); assert_eq!(VECTOR4[1], VECTOR4.y); assert_eq!(VECTOR4[2], VECTOR4.z); assert_eq!(VECTOR4[3], VECTOR4.w); } #[test] fn test_index_mut() { let mut v = VECTOR4; *&mut v[2] = 0; assert_eq!(v, [1, 2, 0, 4].into()); } #[test] #[should_panic] fn test_index_out_of_bounds() { VECTOR4[4]; } #[test] fn test_index_range() { assert_eq!(&VECTOR4[..2], &[1, 2]); assert_eq!(&VECTOR4[..3], &[1, 2, 3]); assert_eq!(VECTOR4[..2].len(), 2); assert_eq!(VECTOR4[..3].len(), 3); assert_eq!(&VECTOR4[2..], &[3, 4]); assert_eq!(&VECTOR4[1..], &[2, 3, 4]); assert_eq!(VECTOR4[2..].len(), 2); assert_eq!(VECTOR4[1..].len(), 3); assert_eq!(&VECTOR4[..], &[1, 2, 3, 4]); assert_eq!(VECTOR4[..].len(), 4); } #[test] fn test_into() { let v = VECTOR4; { let v: [i32; 4] = v.into(); assert_eq!(v, [1, 2, 3, 4]); } { let v: (i32, i32, i32, i32) = v.into(); assert_eq!(v, (1, 2, 3, 4)); } } #[test] fn test_as_ref() { let v = VECTOR4; { let v: &[i32; 4] = v.as_ref(); assert_eq!(v, &[1, 2, 3, 4]); } { let v: &(i32, i32, i32, i32) = v.as_ref(); assert_eq!(v, &(1, 2, 3, 4)); } } #[test] fn test_as_mut() { let mut v = VECTOR4; { let v: &mut [i32; 4] = v.as_mut(); assert_eq!(v, &mut [1, 2, 3, 4]); } { let v: &mut (i32, i32, i32, i32) = v.as_mut(); assert_eq!(v, &mut (1, 2, 3, 4)); } } #[test] fn test_from() { assert_eq!(Vector4::from([1, 2, 3, 4]), VECTOR4); { let v = &[1, 2, 3, 4]; let v: &Vector4<_> = From::from(v); assert_eq!(v, &VECTOR4); } { let v = &mut [1, 2, 3, 4]; let v: &mut Vector4<_> = From::from(v); assert_eq!(v, &VECTOR4); } assert_eq!(Vector4::from((1, 2, 3, 4)), VECTOR4); { let v = &(1, 2, 3, 4); let v: &Vector4<_> = From::from(v); assert_eq!(v, &VECTOR4); } { let v = &mut (1, 2, 3, 4); let v: &mut Vector4<_> = From::from(v); assert_eq!(v, &VECTOR4); } } #[test] fn test_is_finite() { use num_traits::Float; assert!(!Vector4::from([0.0, Float::nan(), 1.0, 1.0]).is_finite()); assert!(!Vector4::from([1.0, 1.0, Float::neg_infinity(), 0.0]).is_finite()); assert!(Vector4::from([-1.0, 0.0, 1.0, 1.0]).is_finite()); } } }