Run rustfmt on most files

This commit is contained in:
Brendan Zabarauskas 2018-01-03 13:01:02 +11:00
parent 68b9052be1
commit 574dd3b972
23 changed files with 1403 additions and 667 deletions

View file

@ -15,16 +15,17 @@
#![feature(test)]
extern crate cgmath;
extern crate rand;
extern crate test;
extern crate cgmath;
use rand::{IsaacRng, Rng};
use test::Bencher;
use cgmath::*;
#[path="common/macros.rs"]
#[macro_use] mod macros;
#[path = "common/macros.rs"]
#[macro_use]
mod macros;
fn bench_from_axis_angle<T: Rotation3<f32>>(bh: &mut Bencher) {
const LEN: usize = 1 << 13;
@ -39,7 +40,8 @@ fn bench_from_axis_angle<T: Rotation3<f32>>(bh: &mut Bencher) {
i = (i + 1) & (LEN - 1);
unsafe {
let res: T = Rotation3::from_axis_angle(*axis.get_unchecked(i), *angle.get_unchecked(i));
let res: T =
Rotation3::from_axis_angle(*axis.get_unchecked(i), *angle.get_unchecked(i));
test::black_box(res)
}
})
@ -55,7 +57,19 @@ fn _bench_rot3_from_axisangle(bh: &mut Bencher) {
bench_from_axis_angle::<Basis3<f32>>(bh)
}
bench_construction!(_bench_rot2_from_axisangle, Basis2<f32>, Basis2::from_angle [ angle: Rad<f32> ]);
bench_construction!(
_bench_rot2_from_axisangle,
Basis2<f32>,
Basis2::from_angle[angle: Rad<f32>]
);
bench_construction!(_bench_quat_from_euler_angles, Quaternion<f32>, Quaternion::from [src: Euler<Rad<f32>>]);
bench_construction!(_bench_rot3_from_euler_angles, Basis3<f32>, Basis3::from [src: Euler<Rad<f32>>]);
bench_construction!(
_bench_quat_from_euler_angles,
Quaternion<f32>,
Quaternion::from[src: Euler<Rad<f32>>]
);
bench_construction!(
_bench_rot3_from_euler_angles,
Basis3<f32>,
Basis3::from[src: Euler<Rad<f32>>]
);

View file

@ -15,9 +15,9 @@
#![feature(test)]
extern crate cgmath;
extern crate rand;
extern crate test;
extern crate cgmath;
use rand::{IsaacRng, Rng};
use std::ops::*;
@ -25,8 +25,9 @@ use test::Bencher;
use cgmath::*;
#[path="common/macros.rs"]
#[macro_use] mod macros;
#[path = "common/macros.rs"]
#[macro_use]
mod macros;
bench_binop!(_bench_matrix2_mul_m, Matrix2<f32>, Matrix2<f32>, mul);
bench_binop!(_bench_matrix3_mul_m, Matrix3<f32>, Matrix3<f32>, mul);

View file

@ -15,9 +15,9 @@
#![feature(test)]
extern crate cgmath;
extern crate rand;
extern crate test;
extern crate cgmath;
use rand::{IsaacRng, Rng};
use std::ops::*;
@ -25,8 +25,9 @@ use test::Bencher;
use cgmath::*;
#[path="common/macros.rs"]
#[macro_use] mod macros;
#[path = "common/macros.rs"]
#[macro_use]
mod macros;
bench_binop!(_bench_quat_add_q, Quaternion<f32>, Quaternion<f32>, add);
bench_binop!(_bench_quat_sub_q, Quaternion<f32>, Quaternion<f32>, sub);

View file

@ -15,9 +15,9 @@
#![feature(test)]
extern crate cgmath;
extern crate rand;
extern crate test;
extern crate cgmath;
use rand::{IsaacRng, Rng};
use std::ops::*;
@ -25,8 +25,9 @@ use test::Bencher;
use cgmath::*;
#[path="common/macros.rs"]
#[macro_use] mod macros;
#[path = "common/macros.rs"]
#[macro_use]
mod macros;
bench_binop!(_bench_vector2_add_v, Vector2<f32>, Vector2<f32>, add);
bench_binop!(_bench_vector3_add_v, Vector3<f32>, Vector3<f32>, add);

View file

@ -45,14 +45,20 @@ pub struct Rad<S>(pub S);
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Deg<S>(pub S);
impl<S> From<Rad<S>> for Deg<S> where S: BaseFloat {
impl<S> From<Rad<S>> for Deg<S>
where
S: BaseFloat,
{
#[inline]
fn from(rad: Rad<S>) -> Deg<S> {
Deg(rad.0 * cast(180.0 / f64::consts::PI).unwrap())
}
}
impl<S> From<Deg<S>> for Rad<S> where S: BaseFloat {
impl<S> From<Deg<S>> for Rad<S>
where
S: BaseFloat,
{
#[inline]
fn from(deg: Deg<S>) -> Rad<S> {
Rad(deg.0 * cast(f64::consts::PI / 180.0).unwrap())

View file

@ -75,8 +75,7 @@ use num::BaseFloat;
/// [gimbal lock]: https://en.wikipedia.org/wiki/Gimbal_lock#Gimbal_lock_in_applied_mathematics
/// [convert]: #defining-rotations-using-euler-angles
#[repr(C)]
#[derive(Copy, Clone, Debug)]
#[derive(PartialEq, Eq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Euler<A: Angle> {
/// The angle to apply around the _x_ axis. Also known at the _pitch_.
@ -162,23 +161,27 @@ impl<A: Angle> ApproxEq for Euler<A> {
#[inline]
fn relative_eq(&self, other: &Self, epsilon: A::Epsilon, max_relative: A::Epsilon) -> bool {
A::relative_eq(&self.x, &other.x, epsilon, max_relative) &&
A::relative_eq(&self.y, &other.y, epsilon, max_relative) &&
A::relative_eq(&self.z, &other.z, epsilon, max_relative)
A::relative_eq(&self.x, &other.x, epsilon, max_relative)
&& A::relative_eq(&self.y, &other.y, epsilon, max_relative)
&& A::relative_eq(&self.z, &other.z, epsilon, max_relative)
}
#[inline]
fn ulps_eq(&self, other: &Self, epsilon: A::Epsilon, max_ulps: u32) -> bool {
A::ulps_eq(&self.x, &other.x, epsilon, max_ulps) &&
A::ulps_eq(&self.y, &other.y, epsilon, max_ulps) &&
A::ulps_eq(&self.z, &other.z, epsilon, max_ulps)
A::ulps_eq(&self.x, &other.x, epsilon, max_ulps)
&& A::ulps_eq(&self.y, &other.y, epsilon, max_ulps)
&& A::ulps_eq(&self.z, &other.z, epsilon, max_ulps)
}
}
impl<A: Angle + Rand> Rand for Euler<A> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Euler<A> {
Euler { x: rng.gen(), y: rng.gen(), z: rng.gen() }
Euler {
x: rng.gen(),
y: rng.gen(),
z: rng.gen(),
}
}
}

View file

@ -58,8 +58,8 @@ extern crate approx;
#[cfg(feature = "mint")]
pub extern crate mint;
pub extern crate num_traits;
extern crate rand;
pub extern crate num_traits;
#[cfg(feature = "serde")]
#[macro_use]
@ -76,7 +76,7 @@ pub use structure::*;
pub use matrix::{Matrix2, Matrix3, Matrix4};
pub use quaternion::Quaternion;
pub use vector::{Vector1, Vector2, Vector3, Vector4, dot, vec1, vec2, vec3, vec4};
pub use vector::{dot, Vector1, Vector2, Vector3, Vector4, vec1, vec2, vec3, vec4};
pub use angle::{Deg, Rad};
pub use euler::Euler;

File diff suppressed because it is too large Load diff

View file

@ -21,11 +21,41 @@ use std::ops::*;
use num_traits::{Float, Num, NumCast};
/// Base numeric types with partial ordering
pub trait BaseNum: Copy + Clone + fmt::Debug + Num + NumCast + PartialOrd + AddAssign + SubAssign + MulAssign + DivAssign + RemAssign {}
pub trait BaseNum
: Copy
+ Clone
+ fmt::Debug
+ Num
+ NumCast
+ PartialOrd
+ AddAssign
+ SubAssign
+ MulAssign
+ DivAssign
+ RemAssign {
}
impl<T> BaseNum for T where T: Copy + Clone + fmt::Debug + Num + NumCast + PartialOrd + AddAssign + SubAssign + MulAssign + DivAssign + RemAssign {}
impl<T> BaseNum for T
where
T: Copy
+ Clone
+ fmt::Debug
+ Num
+ NumCast
+ PartialOrd
+ AddAssign
+ SubAssign
+ MulAssign
+ DivAssign
+ RemAssign,
{
}
/// Base floating point types
pub trait BaseFloat: BaseNum + Float + ApproxEq<Epsilon = Self> {}
impl<T> BaseFloat for T where T: BaseNum + Float + ApproxEq<Epsilon = Self> {}
impl<T> BaseFloat for T
where
T: BaseNum + Float + ApproxEq<Epsilon = Self>,
{
}

View file

@ -17,7 +17,7 @@
//! distinguishes them from vectors, which have a length and direction, but do
//! not have a fixed position.
use num_traits::{NumCast, Bounded};
use num_traits::{Bounded, NumCast};
use std::fmt;
use std::mem;
use std::ops::*;
@ -25,7 +25,7 @@ use std::ops::*;
use structure::*;
use approx::ApproxEq;
use num::{BaseNum, BaseFloat};
use num::{BaseFloat, BaseNum};
use vector::{Vector1, Vector2, Vector3, Vector4};
#[cfg(feature = "mint")]
@ -95,7 +95,7 @@ impl<S: BaseNum> Point3<S> {
#[inline]
pub fn from_homogeneous(v: Vector4<S>) -> Point3<S> {
let e = v.truncate() * (S::one() / v.w);
Point3::new(e.x, e.y, e.z) //FIXME
Point3::new(e.x, e.y, e.z) //FIXME
}
#[inline]

View file

@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use num_traits::{Zero};
use num_traits::Zero;
use num_traits::cast;
use structure::Angle;
@ -26,12 +26,17 @@ use num::BaseFloat;
///
/// This is the equivalent to the [gluPerspective]
/// (http://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml) function.
pub fn perspective<S: BaseFloat, A: Into<Rad<S>>>(fovy: A, aspect: S, near: S, far: S) -> Matrix4<S> {
pub fn perspective<S: BaseFloat, A: Into<Rad<S>>>(
fovy: A,
aspect: S,
near: S,
far: S,
) -> Matrix4<S> {
PerspectiveFov {
fovy: fovy.into(),
fovy: fovy.into(),
aspect: aspect,
near: near,
far: far,
near: near,
far: far,
}.into()
}
@ -41,12 +46,12 @@ pub fn perspective<S: BaseFloat, A: Into<Rad<S>>>(fovy: A, aspect: S, near: S, f
/// (http://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml) function.
pub fn frustum<S: BaseFloat>(left: S, right: S, bottom: S, top: S, near: S, far: S) -> Matrix4<S> {
Perspective {
left: left,
right: right,
left: left,
right: right,
bottom: bottom,
top: top,
near: near,
far: far,
top: top,
near: near,
far: far,
}.into()
}
@ -56,12 +61,12 @@ pub fn frustum<S: BaseFloat>(left: S, right: S, bottom: S, top: S, near: S, far:
/// (http://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml) function.
pub fn ortho<S: BaseFloat>(left: S, right: S, bottom: S, top: S, near: S, far: S) -> Matrix4<S> {
Ortho {
left: left,
right: right,
left: left,
right: right,
bottom: bottom,
top: top,
near: near,
far: far,
top: top,
near: near,
far: far,
}.into()
}
@ -70,10 +75,10 @@ pub fn ortho<S: BaseFloat>(left: S, right: S, bottom: S, top: S, near: S, far: S
#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct PerspectiveFov<S> {
pub fovy: Rad<S>,
pub fovy: Rad<S>,
pub aspect: S,
pub near: S,
pub far: S,
pub near: S,
pub far: S,
}
impl<S: BaseFloat> PerspectiveFov<S> {
@ -84,24 +89,49 @@ impl<S: BaseFloat> PerspectiveFov<S> {
let xmax = ymax * self.aspect;
Perspective {
left: -xmax,
right: xmax,
left: -xmax,
right: xmax,
bottom: -ymax,
top: ymax,
near: self.near.clone(),
far: self.far.clone(),
top: ymax,
near: self.near.clone(),
far: self.far.clone(),
}
}
}
impl<S: BaseFloat> From<PerspectiveFov<S>> for Matrix4<S> {
fn from(persp: PerspectiveFov<S>) -> Matrix4<S> {
assert!(persp.fovy > Rad::zero(), "The vertical field of view cannot be below zero, found: {:?}", persp.fovy);
assert!(persp.fovy < Rad::turn_div_2(), "The vertical field of view cannot be greater than a half turn, found: {:?}", persp.fovy);
assert!(persp.aspect > S::zero(), "The aspect ratio cannot be below zero, found: {:?}", persp.aspect);
assert!(persp.near > S::zero(), "The near plane distance cannot be below zero, found: {:?}", persp.near);
assert!(persp.far > S::zero(), "The far plane distance cannot be below zero, found: {:?}", persp.far);
assert!(persp.far > persp.near, "The far plane cannot be closer than the near plane, found: far: {:?}, near: {:?}", persp.far, persp.near);
assert!(
persp.fovy > Rad::zero(),
"The vertical field of view cannot be below zero, found: {:?}",
persp.fovy
);
assert!(
persp.fovy < Rad::turn_div_2(),
"The vertical field of view cannot be greater than a half turn, found: {:?}",
persp.fovy
);
assert!(
persp.aspect > S::zero(),
"The aspect ratio cannot be below zero, found: {:?}",
persp.aspect
);
assert!(
persp.near > S::zero(),
"The near plane distance cannot be below zero, found: {:?}",
persp.near
);
assert!(
persp.far > S::zero(),
"The far plane distance cannot be below zero, found: {:?}",
persp.far
);
assert!(
persp.far > persp.near,
"The far plane cannot be closer than the near plane, found: far: {:?}, near: {:?}",
persp.far,
persp.near
);
let two: S = cast(2).unwrap();
let f = Rad::cot(persp.fovy / two);
@ -126,10 +156,13 @@ impl<S: BaseFloat> From<PerspectiveFov<S>> for Matrix4<S> {
let c3r2 = (two * persp.far * persp.near) / (persp.near - persp.far);
let c3r3 = S::zero();
Matrix4::new(c0r0, c0r1, c0r2, c0r3,
c1r0, c1r1, c1r2, c1r3,
c2r0, c2r1, c2r2, c2r3,
c3r0, c3r1, c3r2, c3r3)
#[cfg_attr(rustfmt, rustfmt_skip)]
Matrix4::new(
c0r0, c0r1, c0r2, c0r3,
c1r0, c1r1, c1r2, c1r3,
c2r0, c2r1, c2r2, c2r3,
c3r0, c3r1, c3r2, c3r3,
)
}
}
@ -137,19 +170,34 @@ impl<S: BaseFloat> From<PerspectiveFov<S>> for Matrix4<S> {
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Perspective<S> {
pub left: S,
pub right: S,
pub left: S,
pub right: S,
pub bottom: S,
pub top: S,
pub near: S,
pub far: S,
pub top: S,
pub near: S,
pub far: S,
}
impl<S: BaseFloat> From<Perspective<S>> for Matrix4<S> {
fn from(persp: Perspective<S>) -> Matrix4<S> {
assert!(persp.left <= persp.right, "`left` cannot be greater than `right`, found: left: {:?} right: {:?}", persp.left, persp.right);
assert!(persp.bottom <= persp.top, "`bottom` cannot be greater than `top`, found: bottom: {:?} top: {:?}", persp.bottom, persp.top);
assert!(persp.near <= persp.far, "`near` cannot be greater than `far`, found: near: {:?} far: {:?}", persp.near, persp.far);
assert!(
persp.left <= persp.right,
"`left` cannot be greater than `right`, found: left: {:?} right: {:?}",
persp.left,
persp.right
);
assert!(
persp.bottom <= persp.top,
"`bottom` cannot be greater than `top`, found: bottom: {:?} top: {:?}",
persp.bottom,
persp.top
);
assert!(
persp.near <= persp.far,
"`near` cannot be greater than `far`, found: near: {:?} far: {:?}",
persp.near,
persp.far
);
let two: S = cast(2i8).unwrap();
@ -173,10 +221,13 @@ impl<S: BaseFloat> From<Perspective<S>> for Matrix4<S> {
let c3r2 = -(two * persp.far * persp.near) / (persp.far - persp.near);
let c3r3 = S::zero();
Matrix4::new(c0r0, c0r1, c0r2, c0r3,
c1r0, c1r1, c1r2, c1r3,
c2r0, c2r1, c2r2, c2r3,
c3r0, c3r1, c3r2, c3r3)
#[cfg_attr(rustfmt, rustfmt_skip)]
Matrix4::new(
c0r0, c0r1, c0r2, c0r3,
c1r0, c1r1, c1r2, c1r3,
c2r0, c2r1, c2r2, c2r3,
c3r0, c3r1, c3r2, c3r3,
)
}
}
@ -184,12 +235,12 @@ impl<S: BaseFloat> From<Perspective<S>> for Matrix4<S> {
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Ortho<S> {
pub left: S,
pub right: S,
pub left: S,
pub right: S,
pub bottom: S,
pub top: S,
pub near: S,
pub far: S,
pub top: S,
pub near: S,
pub far: S,
}
impl<S: BaseFloat> From<Ortho<S>> for Matrix4<S> {
@ -216,9 +267,12 @@ impl<S: BaseFloat> From<Ortho<S>> for Matrix4<S> {
let c3r2 = -(ortho.far + ortho.near) / (ortho.far - ortho.near);
let c3r3 = S::one();
Matrix4::new(c0r0, c0r1, c0r2, c0r3,
c1r0, c1r1, c1r2, c1r3,
c2r0, c2r1, c2r2, c2r3,
c3r0, c3r1, c3r2, c3r3)
#[cfg_attr(rustfmt, rustfmt_skip)]
Matrix4::new(
c0r0, c0r1, c0r2, c0r3,
c1r0, c1r1, c1r2, c1r3,
c2r0, c2r1, c2r2, c2r3,
c3r0, c3r1, c3r2, c3r3,
)
}
}

View file

@ -18,7 +18,7 @@ use std::mem;
use std::ops::*;
use rand::{Rand, Rng};
use num_traits::{NumCast, cast};
use num_traits::{cast, NumCast};
use structure::*;
@ -28,7 +28,7 @@ use euler::Euler;
use matrix::{Matrix3, Matrix4};
use num::BaseFloat;
use point::Point3;
use rotation::{Rotation, Rotation3, Basis3};
use rotation::{Basis3, Rotation, Rotation3};
use vector::Vector3;
#[cfg(feature = "simd")]
@ -97,8 +97,11 @@ impl<S: BaseFloat> Quaternion<S> {
/// (http://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another)
/// - [Ogre implementation for normalized vectors]
/// (https://bitbucket.org/sinbad/ogre/src/9db75e3ba05c/OgreMain/include/OgreVector3.h?fileviewer=file-view-default#cl-651)
pub fn from_arc(src: Vector3<S>, dst: Vector3<S>, fallback: Option<Vector3<S>>)
-> Quaternion<S> {
pub fn from_arc(
src: Vector3<S>,
dst: Vector3<S>,
fallback: Option<Vector3<S>>,
) -> Quaternion<S> {
let mag_avg = (src.magnitude2() * dst.magnitude2()).sqrt();
let dot = src.dot(dst);
if ulps_eq!(dot, &mag_avg) {
@ -193,28 +196,28 @@ impl<S: BaseFloat> One for Quaternion<S> {
impl<S: BaseFloat> iter::Sum<Quaternion<S>> for Quaternion<S> {
#[inline]
fn sum<I: Iterator<Item=Quaternion<S>>>(iter: I) -> Quaternion<S> {
fn sum<I: Iterator<Item = Quaternion<S>>>(iter: I) -> Quaternion<S> {
iter.fold(Quaternion::<S>::zero(), Add::add)
}
}
impl<'a, S: 'a + BaseFloat> iter::Sum<&'a Quaternion<S>> for Quaternion<S> {
#[inline]
fn sum<I: Iterator<Item=&'a Quaternion<S>>>(iter: I) -> Quaternion<S> {
fn sum<I: Iterator<Item = &'a Quaternion<S>>>(iter: I) -> Quaternion<S> {
iter.fold(Quaternion::<S>::zero(), Add::add)
}
}
impl<S: BaseFloat> iter::Product<Quaternion<S>> for Quaternion<S> {
#[inline]
fn product<I: Iterator<Item=Quaternion<S>>>(iter: I) -> Quaternion<S> {
fn product<I: Iterator<Item = Quaternion<S>>>(iter: I) -> Quaternion<S> {
iter.fold(Quaternion::<S>::one(), Mul::mul)
}
}
impl<'a, S: 'a + BaseFloat> iter::Product<&'a Quaternion<S>> for Quaternion<S> {
#[inline]
fn product<I: Iterator<Item=&'a Quaternion<S>>>(iter: I) -> Quaternion<S> {
fn product<I: Iterator<Item = &'a Quaternion<S>>>(iter: I) -> Quaternion<S> {
iter.fold(Quaternion::<S>::one(), Mul::mul)
}
}
@ -237,11 +240,11 @@ impl<S: NumCast + Copy> Quaternion<S> {
pub fn cast<T: BaseFloat>(&self) -> Option<Quaternion<T>> {
let s = match NumCast::from(self.s) {
Some(s) => s,
None => return None
None => return None,
};
let v = match self.v.cast() {
Some(v) => v,
None => return None
None => return None,
};
Some(Quaternion::from_sv(s, v))
}
@ -274,7 +277,8 @@ impl InnerSpace for Quaternion<f32> {
}
}
impl<A> From<Euler<A>> for Quaternion<A::Unitless> where
impl<A> From<Euler<A>> for Quaternion<A::Unitless>
where
A: Angle + Into<Rad<<A as Angle>::Unitless>>,
{
fn from(src: Euler<A>) -> Quaternion<A::Unitless> {
@ -288,10 +292,12 @@ impl<A> From<Euler<A>> for Quaternion<A::Unitless> where
let (s_y, c_y) = Rad::sin_cos(src.y.into() * half);
let (s_z, c_z) = Rad::sin_cos(src.z.into() * half);
Quaternion::new(-s_x * s_y * s_z + c_x * c_y * c_z,
s_x * c_y * c_z + s_y * s_z * c_x,
-s_x * s_z * c_y + s_y * c_x * c_z,
s_x * s_y * c_z + s_z * c_x * c_y)
Quaternion::new(
-s_x * s_y * s_z + c_x * c_y * c_z,
s_x * c_y * c_z + s_y * s_z * c_x,
-s_x * s_z * c_y + s_y * c_x * c_z,
s_x * s_y * c_z + s_z * c_x * c_y,
)
}
}
@ -510,20 +516,24 @@ impl SubAssign for Quaternion<f32> {
#[cfg(not(feature = "simd"))]
impl_operator!(<S: BaseFloat> Mul<Quaternion<S> > for Quaternion<S> {
fn mul(lhs, rhs) -> Quaternion<S> {
Quaternion::new(lhs.s * rhs.s - lhs.v.x * rhs.v.x - lhs.v.y * rhs.v.y - lhs.v.z * rhs.v.z,
lhs.s * rhs.v.x + lhs.v.x * rhs.s + lhs.v.y * rhs.v.z - lhs.v.z * rhs.v.y,
lhs.s * rhs.v.y + lhs.v.y * rhs.s + lhs.v.z * rhs.v.x - lhs.v.x * rhs.v.z,
lhs.s * rhs.v.z + lhs.v.z * rhs.s + lhs.v.x * rhs.v.y - lhs.v.y * rhs.v.x)
Quaternion::new(
lhs.s * rhs.s - lhs.v.x * rhs.v.x - lhs.v.y * rhs.v.y - lhs.v.z * rhs.v.z,
lhs.s * rhs.v.x + lhs.v.x * rhs.s + lhs.v.y * rhs.v.z - lhs.v.z * rhs.v.y,
lhs.s * rhs.v.y + lhs.v.y * rhs.s + lhs.v.z * rhs.v.x - lhs.v.x * rhs.v.z,
lhs.s * rhs.v.z + lhs.v.z * rhs.s + lhs.v.x * rhs.v.y - lhs.v.y * rhs.v.x,
)
}
});
#[cfg(feature = "simd")]
impl_operator_default!(<S: BaseFloat> Mul<Quaternion<S> > for Quaternion<S> {
fn mul(lhs, rhs) -> Quaternion<S> {
Quaternion::new(lhs.s * rhs.s - lhs.v.x * rhs.v.x - lhs.v.y * rhs.v.y - lhs.v.z * rhs.v.z,
lhs.s * rhs.v.x + lhs.v.x * rhs.s + lhs.v.y * rhs.v.z - lhs.v.z * rhs.v.y,
lhs.s * rhs.v.y + lhs.v.y * rhs.s + lhs.v.z * rhs.v.x - lhs.v.x * rhs.v.z,
lhs.s * rhs.v.z + lhs.v.z * rhs.s + lhs.v.x * rhs.v.y - lhs.v.y * rhs.v.x)
Quaternion::new(
lhs.s * rhs.s - lhs.v.x * rhs.v.x - lhs.v.y * rhs.v.y - lhs.v.z * rhs.v.z,
lhs.s * rhs.v.x + lhs.v.x * rhs.s + lhs.v.y * rhs.v.z - lhs.v.z * rhs.v.y,
lhs.s * rhs.v.y + lhs.v.y * rhs.s + lhs.v.z * rhs.v.x - lhs.v.x * rhs.v.z,
lhs.s * rhs.v.z + lhs.v.z * rhs.s + lhs.v.x * rhs.v.y - lhs.v.y * rhs.v.x,
)
}
});
@ -593,14 +603,14 @@ impl<S: BaseFloat> ApproxEq for Quaternion<S> {
#[inline]
fn relative_eq(&self, other: &Self, epsilon: S::Epsilon, max_relative: S::Epsilon) -> bool {
S::relative_eq(&self.s, &other.s, epsilon, max_relative) &&
Vector3::relative_eq(&self.v, &other.v, epsilon, max_relative)
S::relative_eq(&self.s, &other.s, epsilon, max_relative)
&& Vector3::relative_eq(&self.v, &other.v, epsilon, max_relative)
}
#[inline]
fn ulps_eq(&self, other: &Self, epsilon: S::Epsilon, max_ulps: u32) -> bool {
S::ulps_eq(&self.s, &other.s, epsilon, max_ulps) &&
Vector3::ulps_eq(&self.v, &other.v, epsilon, max_ulps)
S::ulps_eq(&self.s, &other.s, epsilon, max_ulps)
&& Vector3::ulps_eq(&self.v, &other.v, epsilon, max_ulps)
}
}
@ -623,9 +633,12 @@ impl<S: BaseFloat> From<Quaternion<S>> for Matrix3<S> {
let sz2 = z2 * quat.s;
let sx2 = x2 * quat.s;
Matrix3::new(S::one() - yy2 - zz2, xy2 + sz2, xz2 - sy2,
xy2 - sz2, S::one() - xx2 - zz2, yz2 + sx2,
xz2 + sy2, yz2 - sx2, S::one() - xx2 - yy2)
#[cfg_attr(rustfmt, rustfmt_skip)]
Matrix3::new(
S::one() - yy2 - zz2, xy2 + sz2, xz2 - sy2,
xy2 - sz2, S::one() - xx2 - zz2, yz2 + sx2,
xz2 + sy2, yz2 - sx2, S::one() - xx2 - yy2,
)
}
}
@ -648,10 +661,13 @@ impl<S: BaseFloat> From<Quaternion<S>> for Matrix4<S> {
let sz2 = z2 * quat.s;
let sx2 = x2 * quat.s;
Matrix4::new(S::one() - yy2 - zz2, xy2 + sz2, xz2 - sy2, S::zero(),
xy2 - sz2, S::one() - xx2 - zz2, yz2 + sx2, S::zero(),
xz2 + sy2, yz2 - sx2, S::one() - xx2 - yy2, S::zero(),
S::zero(), S::zero(), S::zero(), S::one())
#[cfg_attr(rustfmt, rustfmt_skip)]
Matrix4::new(
S::one() - yy2 - zz2, xy2 + sz2, xz2 - sy2, S::zero(),
xy2 - sz2, S::one() - xx2 - zz2, yz2 + sx2, S::zero(),
xz2 + sy2, yz2 - sx2, S::one() - xx2 - yy2, S::zero(),
S::zero(), S::zero(), S::zero(), S::one(),
)
}
}
@ -659,7 +675,9 @@ impl<S: BaseFloat> From<Quaternion<S>> for Matrix4<S> {
impl<S: BaseFloat> From<Quaternion<S>> for Basis3<S> {
#[inline]
fn from(quat: Quaternion<S>) -> Basis3<S> { Basis3::from_quaternion(&quat) }
fn from(quat: Quaternion<S>) -> Basis3<S> {
Basis3::from_quaternion(&quat)
}
}
impl<S: BaseFloat> Rotation<Point3<S>> for Quaternion<S> {
@ -695,10 +713,14 @@ impl<S: BaseFloat> Rotation<Point3<S>> for Quaternion<S> {
}
#[inline]
fn rotate_vector(&self, vec: Vector3<S>) -> Vector3<S> { self * vec }
fn rotate_vector(&self, vec: Vector3<S>) -> Vector3<S> {
self * vec
}
#[inline]
fn invert(&self) -> Quaternion<S> { self.conjugate() / self.magnitude2() }
fn invert(&self) -> Quaternion<S> {
self.conjugate() / self.magnitude2()
}
}
impl<S: BaseFloat> Rotation3<S> for Quaternion<S> {
@ -712,7 +734,9 @@ impl<S: BaseFloat> Rotation3<S> for Quaternion<S> {
impl<S: BaseFloat> Into<[S; 4]> for Quaternion<S> {
#[inline]
fn into(self) -> [S; 4] {
match self.into() { (w, xi, yj, zk) => [w, xi, yj, zk] }
match self.into() {
(w, xi, yj, zk) => [w, xi, yj, zk],
}
}
}
@ -754,7 +778,12 @@ impl<'a, S: BaseFloat> From<&'a mut [S; 4]> for &'a mut Quaternion<S> {
impl<S: BaseFloat> Into<(S, S, S, S)> for Quaternion<S> {
#[inline]
fn into(self) -> (S, S, S, S) {
match self { Quaternion { s, v: Vector3 { x, y, z } } => (s, x, y, z) }
match self {
Quaternion {
s,
v: Vector3 { x, y, z },
} => (s, x, y, z),
}
}
}
@ -775,7 +804,9 @@ impl<S: BaseFloat> AsMut<(S, S, S, S)> for Quaternion<S> {
impl<S: BaseFloat> From<(S, S, S, S)> for Quaternion<S> {
#[inline]
fn from(v: (S, S, S, S)) -> Quaternion<S> {
match v { (w, xi, yj, zk) => Quaternion::new(w, xi, yj, zk) }
match v {
(w, xi, yj, zk) => Quaternion::new(w, xi, yj, zk),
}
}
}
@ -822,7 +853,7 @@ index_operators!(S, [S], RangeFull);
impl<S: BaseFloat + Rand> Rand for Quaternion<S> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Quaternion<S> {
Quaternion::from_sv(rng.gen(), rng.gen())
Quaternion::from_sv(rng.gen(), rng.gen())
}
}
@ -846,7 +877,6 @@ impl<S: Clone> Into<mint::Quaternion<S>> for Quaternion<S> {
}
}
#[cfg(test)]
mod tests {
use quaternion::*;
@ -854,7 +884,11 @@ mod tests {
const QUATERNION: Quaternion<f32> = Quaternion {
s: 1.0,
v: Vector3 { x: 2.0, y: 3.0, z: 4.0 },
v: Vector3 {
x: 2.0,
y: 3.0,
z: 4.0,
},
};
#[test]
@ -887,11 +921,11 @@ mod tests {
fn test_as_mut() {
let mut v = QUATERNION;
{
let v: &mut[f32; 4] = v.as_mut();
let v: &mut [f32; 4] = v.as_mut();
assert_eq!(v, &mut [1.0, 2.0, 3.0, 4.0]);
}
{
let v: &mut(f32, f32, f32, f32) = v.as_mut();
let v: &mut (f32, f32, f32, f32) = v.as_mut();
assert_eq!(v, &mut (1.0, 2.0, 3.0, 4.0));
}
}

View file

@ -30,7 +30,8 @@ use vector::{Vector2, Vector3};
/// A trait for a generic rotation. A rotation is a transformation that
/// creates a circular motion, and preserves at least one point in the space.
pub trait Rotation<P: EuclideanSpace>: Sized + Copy + One where
pub trait Rotation<P: EuclideanSpace>: Sized + Copy + One
where
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
Self: ApproxEq<Epsilon = P::Scalar>,
P::Scalar: BaseFloat,
@ -59,20 +60,17 @@ pub trait Rotation<P: EuclideanSpace>: Sized + Copy + One where
}
/// A two-dimensional rotation.
pub trait Rotation2<S: BaseFloat>: Rotation<Point2<S>>
+ Into<Matrix2<S>>
+ Into<Basis2<S>> {
pub trait Rotation2<S: BaseFloat>
: Rotation<Point2<S>> + Into<Matrix2<S>> + Into<Basis2<S>> {
/// Create a rotation by a given angle. Thus is a redundant case of both
/// from_axis_angle() and from_euler() for 2D space.
fn from_angle<A: Into<Rad<S>>>(theta: A) -> Self;
}
/// A three-dimensional rotation.
pub trait Rotation3<S: BaseFloat>: Rotation<Point3<S>>
+ Into<Matrix3<S>>
+ Into<Basis3<S>>
+ Into<Quaternion<S>>
+ From<Euler<Rad<S>>> {
pub trait Rotation3<S: BaseFloat>
: Rotation<Point3<S>> + Into<Matrix3<S>> + Into<Basis3<S>> + Into<Quaternion<S>> + From<Euler<Rad<S>>>
{
/// Create a rotation using an angle around a given axis.
///
/// The specified axis **must be normalized**, or it represents an invalid rotation.
@ -97,7 +95,6 @@ pub trait Rotation3<S: BaseFloat>: Rotation<Point3<S>>
}
}
/// A two-dimensional rotation matrix.
///
/// The matrix is guaranteed to be orthogonal, so some operations can be
@ -144,7 +141,7 @@ pub trait Rotation3<S: BaseFloat>: Rotation<Point3<S>>
#[derive(PartialEq, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Basis2<S> {
mat: Matrix2<S>
mat: Matrix2<S>,
}
impl<S: BaseFloat> AsRef<Matrix2<S>> for Basis2<S> {
@ -156,19 +153,21 @@ impl<S: BaseFloat> AsRef<Matrix2<S>> for Basis2<S> {
impl<S: BaseFloat> From<Basis2<S>> for Matrix2<S> {
#[inline]
fn from(b: Basis2<S>) -> Matrix2<S> { b.mat }
fn from(b: Basis2<S>) -> Matrix2<S> {
b.mat
}
}
impl<S: BaseFloat> iter::Product<Basis2<S>> for Basis2<S> {
#[inline]
fn product<I: Iterator<Item=Basis2<S>>>(iter: I) -> Basis2<S> {
fn product<I: Iterator<Item = Basis2<S>>>(iter: I) -> Basis2<S> {
iter.fold(Basis2::one(), Mul::mul)
}
}
impl<'a, S: 'a + BaseFloat> iter::Product<&'a Basis2<S>> for Basis2<S> {
#[inline]
fn product<I: Iterator<Item=&'a Basis2<S>>>(iter: I) -> Basis2<S> {
fn product<I: Iterator<Item = &'a Basis2<S>>>(iter: I) -> Basis2<S> {
iter.fold(Basis2::one(), Mul::mul)
}
}
@ -176,26 +175,38 @@ impl<'a, S: 'a + BaseFloat> iter::Product<&'a Basis2<S>> for Basis2<S> {
impl<S: BaseFloat> Rotation<Point2<S>> for Basis2<S> {
#[inline]
fn look_at(dir: Vector2<S>, up: Vector2<S>) -> Basis2<S> {
Basis2 { mat: Matrix2::look_at(dir, up) }
Basis2 {
mat: Matrix2::look_at(dir, up),
}
}
#[inline]
fn between_vectors(a: Vector2<S>, b: Vector2<S>) -> Basis2<S> {
Rotation2::from_angle(Rad::acos(a.dot(b)) )
Rotation2::from_angle(Rad::acos(a.dot(b)))
}
#[inline]
fn rotate_vector(&self, vec: Vector2<S>) -> Vector2<S> { self.mat * vec }
fn rotate_vector(&self, vec: Vector2<S>) -> Vector2<S> {
self.mat * vec
}
// TODO: we know the matrix is orthogonal, so this could be re-written
// to be faster
#[inline]
fn invert(&self) -> Basis2<S> { Basis2 { mat: self.mat.invert().unwrap() } }
fn invert(&self) -> Basis2<S> {
Basis2 {
mat: self.mat.invert().unwrap(),
}
}
}
impl<S: BaseFloat> One for Basis2<S> {
#[inline]
fn one() -> Basis2<S> { Basis2 { mat: Matrix2::one() } }
fn one() -> Basis2<S> {
Basis2 {
mat: Matrix2::one(),
}
}
}
impl_operator!(<S: BaseFloat> Mul<Basis2<S> > for Basis2<S> {
@ -232,7 +243,11 @@ impl<S: BaseFloat> ApproxEq for Basis2<S> {
}
impl<S: BaseFloat> Rotation2<S> for Basis2<S> {
fn from_angle<A: Into<Rad<S>>>(theta: A) -> Basis2<S> { Basis2 { mat: Matrix2::from_angle(theta) } }
fn from_angle<A: Into<Rad<S>>>(theta: A) -> Basis2<S> {
Basis2 {
mat: Matrix2::from_angle(theta),
}
}
}
impl<S: fmt::Debug> fmt::Debug for Basis2<S> {
@ -251,14 +266,16 @@ impl<S: fmt::Debug> fmt::Debug for Basis2<S> {
#[derive(PartialEq, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Basis3<S> {
mat: Matrix3<S>
mat: Matrix3<S>,
}
impl<S: BaseFloat> Basis3<S> {
/// Create a new rotation matrix from a quaternion.
#[inline]
pub fn from_quaternion(quaternion: &Quaternion<S>) -> Basis3<S> {
Basis3 { mat: quaternion.clone().into() }
Basis3 {
mat: quaternion.clone().into(),
}
}
}
@ -271,24 +288,28 @@ impl<S> AsRef<Matrix3<S>> for Basis3<S> {
impl<S: BaseFloat> From<Basis3<S>> for Matrix3<S> {
#[inline]
fn from(b: Basis3<S>) -> Matrix3<S> { b.mat }
fn from(b: Basis3<S>) -> Matrix3<S> {
b.mat
}
}
impl<S: BaseFloat> From<Basis3<S>> for Quaternion<S> {
#[inline]
fn from(b: Basis3<S>) -> Quaternion<S> { b.mat.into() }
fn from(b: Basis3<S>) -> Quaternion<S> {
b.mat.into()
}
}
impl<S: BaseFloat> iter::Product<Basis3<S>> for Basis3<S> {
#[inline]
fn product<I: Iterator<Item=Basis3<S>>>(iter: I) -> Basis3<S> {
fn product<I: Iterator<Item = Basis3<S>>>(iter: I) -> Basis3<S> {
iter.fold(Basis3::one(), Mul::mul)
}
}
impl<'a, S: 'a + BaseFloat> iter::Product<&'a Basis3<S>> for Basis3<S> {
#[inline]
fn product<I: Iterator<Item=&'a Basis3<S>>>(iter: I) -> Basis3<S> {
fn product<I: Iterator<Item = &'a Basis3<S>>>(iter: I) -> Basis3<S> {
iter.fold(Basis3::one(), Mul::mul)
}
}
@ -296,7 +317,9 @@ impl<'a, S: 'a + BaseFloat> iter::Product<&'a Basis3<S>> for Basis3<S> {
impl<S: BaseFloat> Rotation<Point3<S>> for Basis3<S> {
#[inline]
fn look_at(dir: Vector3<S>, up: Vector3<S>) -> Basis3<S> {
Basis3 { mat: Matrix3::look_at(dir, up) }
Basis3 {
mat: Matrix3::look_at(dir, up),
}
}
#[inline]
@ -306,17 +329,27 @@ impl<S: BaseFloat> Rotation<Point3<S>> for Basis3<S> {
}
#[inline]
fn rotate_vector(&self, vec: Vector3<S>) -> Vector3<S> { self.mat * vec }
fn rotate_vector(&self, vec: Vector3<S>) -> Vector3<S> {
self.mat * vec
}
// TODO: we know the matrix is orthogonal, so this could be re-written
// to be faster
#[inline]
fn invert(&self) -> Basis3<S> { Basis3 { mat: self.mat.invert().unwrap() } }
fn invert(&self) -> Basis3<S> {
Basis3 {
mat: self.mat.invert().unwrap(),
}
}
}
impl<S: BaseFloat> One for Basis3<S> {
#[inline]
fn one() -> Basis3<S> { Basis3 { mat: Matrix3::one() } }
fn one() -> Basis3<S> {
Basis3 {
mat: Matrix3::one(),
}
}
}
impl_operator!(<S: BaseFloat> Mul<Basis3<S> > for Basis3<S> {
@ -354,23 +387,32 @@ impl<S: BaseFloat> ApproxEq for Basis3<S> {
impl<S: BaseFloat> Rotation3<S> for Basis3<S> {
fn from_axis_angle<A: Into<Rad<S>>>(axis: Vector3<S>, angle: A) -> Basis3<S> {
Basis3 { mat: Matrix3::from_axis_angle(axis, angle) }
Basis3 {
mat: Matrix3::from_axis_angle(axis, angle),
}
}
fn from_angle_x<A: Into<Rad<S>>>(theta: A) -> Basis3<S> {
Basis3 { mat: Matrix3::from_angle_x(theta) }
Basis3 {
mat: Matrix3::from_angle_x(theta),
}
}
fn from_angle_y<A: Into<Rad<S>>>(theta: A) -> Basis3<S> {
Basis3 { mat: Matrix3::from_angle_y(theta) }
Basis3 {
mat: Matrix3::from_angle_y(theta),
}
}
fn from_angle_z<A: Into<Rad<S>>>(theta: A) -> Basis3<S> {
Basis3 { mat: Matrix3::from_angle_z(theta) }
Basis3 {
mat: Matrix3::from_angle_z(theta),
}
}
}
impl<A: Angle> From<Euler<A>> for Basis3<A::Unitless> where
impl<A: Angle> From<Euler<A>> for Basis3<A::Unitless>
where
A: Into<Rad<<A as Angle>::Unitless>>,
{
/// Create a three-dimensional rotation matrix from a set of euler angles.

View file

@ -23,12 +23,13 @@ use std::ops::*;
use approx::ApproxEq;
use angle::Rad;
use num::{BaseNum, BaseFloat};
use num::{BaseFloat, BaseNum};
pub use num_traits::{One, Zero, Bounded};
pub use num_traits::{Bounded, One, Zero};
/// An array containing elements of type `Element`
pub trait Array where
pub trait Array
where
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
Self: Index<usize, Output = <Self as Array>::Element>,
Self: IndexMut<usize, Output = <Self as Array>::Element>,
@ -78,10 +79,14 @@ pub trait Array where
}
/// The sum of the elements of the array.
fn sum(self) -> Self::Element where Self::Element: Add<Output = <Self as Array>::Element>;
fn sum(self) -> Self::Element
where
Self::Element: Add<Output = <Self as Array>::Element>;
/// The product of the elements of the array.
fn product(self) -> Self::Element where Self::Element: Mul<Output = <Self as Array>::Element>;
fn product(self) -> Self::Element
where
Self::Element: Mul<Output = <Self as Array>::Element>;
}
/// Element-wise arithmetic operations. These are supplied for pragmatic
@ -156,7 +161,8 @@ pub trait ElementWise<Rhs = Self> {
/// let upscaled_translation = translation * scale_factor;
/// let downscaled_translation = translation / scale_factor;
/// ```
pub trait VectorSpace: Copy + Clone where
pub trait VectorSpace: Copy + Clone
where
Self: Zero,
Self: Add<Self, Output = Self>,
@ -199,7 +205,8 @@ pub trait MetricSpace: Sized {
/// finding the magnitude of a vector or normalizing it.
///
/// Examples include vectors and quaternions.
pub trait InnerSpace: VectorSpace where
pub trait InnerSpace: VectorSpace
where
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
<Self as VectorSpace>::Scalar: BaseFloat,
Self: MetricSpace<Metric = <Self as VectorSpace>::Scalar>,
@ -310,7 +317,8 @@ pub trait InnerSpace: VectorSpace where
/// - [CGAL 4.7 - 2D and 3D Linear Geometry Kernel: 3.1 Points and Vectors](http://doc.cgal.org/latest/Kernel_23/index.html#Kernel_23PointsandVectors)
/// - [What is the difference between a point and a vector](http://math.stackexchange.com/q/645827)
///
pub trait EuclideanSpace: Copy + Clone where
pub trait EuclideanSpace: Copy + Clone
where
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
Self: Array<Element = <Self as EuclideanSpace>::Scalar>,
@ -378,10 +386,9 @@ pub trait EuclideanSpace: Copy + Clone where
/// ```
#[inline]
fn centroid(points: &[Self]) -> Self {
let total_displacement =
points.iter().fold(Self::Diff::zero(), |acc, p| {
acc + p.to_vec()
});
let total_displacement = points
.iter()
.fold(Self::Diff::zero(), |acc, p| acc + p.to_vec());
Self::from_vec(total_displacement / cast(points.len()).unwrap())
}
@ -411,7 +418,8 @@ pub trait EuclideanSpace: Copy + Clone where
/// trait. This is due to the complexities of implementing these operators with
/// Rust's current type system. For the multiplication of square matrices,
/// see `SquareMatrix`.
pub trait Matrix: VectorSpace where
pub trait Matrix: VectorSpace
where
Self::Scalar: BaseFloat,
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
@ -463,7 +471,8 @@ pub trait Matrix: VectorSpace where
}
/// A column-major major matrix where the rows and column vectors are of the same dimensions.
pub trait SquareMatrix where
pub trait SquareMatrix
where
Self::Scalar: BaseFloat,
Self: One,
@ -514,7 +523,9 @@ pub trait SquareMatrix where
/// Return the trace of this matrix. That is, the sum of the diagonal.
#[inline]
fn trace(&self) -> Self::Scalar { self.diagonal().sum() }
fn trace(&self) -> Self::Scalar {
self.diagonal().sum()
}
/// Invert this matrix, returning a new matrix. `m.mul_m(m.invert())` is
/// the identity matrix. Returns `None` if this matrix is not invertible
@ -523,12 +534,16 @@ pub trait SquareMatrix where
/// Test if this matrix is invertible.
#[inline]
fn is_invertible(&self) -> bool { ulps_ne!(self.determinant(), &Self::Scalar::zero()) }
fn is_invertible(&self) -> bool {
ulps_ne!(self.determinant(), &Self::Scalar::zero())
}
/// Test if this matrix is the identity matrix. That is, it is diagonal
/// and every element in the diagonal is one.
#[inline]
fn is_identity(&self) -> bool { ulps_eq!(self, &Self::identity()) }
fn is_identity(&self) -> bool {
ulps_eq!(self, &Self::identity())
}
/// Test if this is a diagonal matrix. That is, every element outside of
/// the diagonal is 0.
@ -545,7 +560,8 @@ pub trait SquareMatrix where
/// clear when semantic violations have occured - for example, adding degrees to
/// radians, or adding a number to an angle.
///
pub trait Angle where
pub trait Angle
where
Self: Copy + Clone,
Self: PartialEq + cmp::PartialOrd,
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
@ -569,7 +585,11 @@ pub trait Angle where
#[inline]
fn normalize(self) -> Self {
let rem = self % Self::full_turn();
if rem < Self::zero() { rem + Self::full_turn() } else { rem }
if rem < Self::zero() {
rem + Self::full_turn()
} else {
rem
}
}
/// Return the angle rotated by half a turn.

View file

@ -39,7 +39,8 @@ pub trait Transform<P: EuclideanSpace>: Sized {
/// Inverse transform a vector using this transform
fn inverse_transform_vector(&self, vec: P::Diff) -> Option<P::Diff> {
self.inverse_transform().and_then(|inverse| Some(inverse.transform_vector(vec)))
self.inverse_transform()
.and_then(|inverse| Some(inverse.transform_vector(vec)))
}
/// Transform a point using this transform.
@ -69,9 +70,10 @@ pub struct Decomposed<V: VectorSpace, R> {
}
impl<P: EuclideanSpace, R: Rotation<P>> Transform<P> for Decomposed<P::Diff, R>
where P::Scalar: BaseFloat,
// FIXME: Investigate why this is needed!
P::Diff: VectorSpace
where
P::Scalar: BaseFloat,
// FIXME: Investigate why this is needed!
P::Diff: VectorSpace,
{
#[inline]
fn one() -> Decomposed<P::Diff, R> {
@ -128,10 +130,10 @@ impl<P: EuclideanSpace, R: Rotation<P>> Transform<P> for Decomposed<P::Diff, R>
let r = self.rot.invert();
let d = r.rotate_vector(self.disp.clone()) * -s;
Some(Decomposed {
scale: s,
rot: r,
disp: d,
})
scale: s,
rot: r,
disp: d,
})
}
}
}
@ -162,9 +164,10 @@ impl<S: BaseFloat, R: Rotation2<S>> Transform2<S> for Decomposed<Vector2<S>, R>
impl<S: BaseFloat, R: Rotation3<S>> Transform3<S> for Decomposed<Vector3<S>, R> {}
impl<S: VectorSpace, R, E: BaseFloat> ApproxEq for Decomposed<S, R>
where S: ApproxEq<Epsilon = E>,
S::Scalar: ApproxEq<Epsilon = E>,
R: ApproxEq<Epsilon = E>
where
S: ApproxEq<Epsilon = E>,
S::Scalar: ApproxEq<Epsilon = E>,
R: ApproxEq<Epsilon = E>,
{
type Epsilon = E;
@ -185,16 +188,16 @@ impl<S: VectorSpace, R, E: BaseFloat> ApproxEq for Decomposed<S, R>
#[inline]
fn relative_eq(&self, other: &Self, epsilon: E, max_relative: E) -> bool {
S::Scalar::relative_eq(&self.scale, &other.scale, epsilon, max_relative) &&
R::relative_eq(&self.rot, &other.rot, epsilon, max_relative) &&
S::relative_eq(&self.disp, &other.disp, epsilon, max_relative)
S::Scalar::relative_eq(&self.scale, &other.scale, epsilon, max_relative)
&& R::relative_eq(&self.rot, &other.rot, epsilon, max_relative)
&& S::relative_eq(&self.disp, &other.disp, epsilon, max_relative)
}
#[inline]
fn ulps_eq(&self, other: &Self, epsilon: E, max_ulps: u32) -> bool {
S::Scalar::ulps_eq(&self.scale, &other.scale, epsilon, max_ulps) &&
R::ulps_eq(&self.rot, &other.rot, epsilon, max_ulps) &&
S::ulps_eq(&self.disp, &other.disp, epsilon, max_ulps)
S::Scalar::ulps_eq(&self.scale, &other.scale, epsilon, max_ulps)
&& R::ulps_eq(&self.rot, &other.rot, epsilon, max_ulps)
&& S::ulps_eq(&self.disp, &other.disp, epsilon, max_ulps)
}
}
@ -207,12 +210,14 @@ mod serde_ser {
use serde::ser::SerializeStruct;
impl<V, R> Serialize for Decomposed<V, R>
where V: Serialize + VectorSpace,
V::Scalar: Serialize,
R: Serialize
where
V: Serialize + VectorSpace,
V::Scalar: Serialize,
R: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: serde::Serializer
where
S: serde::Serializer,
{
let mut struc = serializer.serialize_struct("Decomposed", 3)?;
struc.serialize_field("scale", &self.scale)?;
@ -240,7 +245,8 @@ mod serde_de {
impl<'a> Deserialize<'a> for DecomposedField {
fn deserialize<D>(deserializer: D) -> Result<DecomposedField, D::Error>
where D: serde::Deserializer<'a>
where
D: serde::Deserializer<'a>,
{
struct DecomposedFieldVisitor;
@ -252,7 +258,8 @@ mod serde_de {
}
fn visit_str<E>(self, value: &str) -> Result<DecomposedField, E>
where E: serde::de::Error
where
E: serde::de::Error,
{
match value {
"scale" => Ok(DecomposedField::Scale),
@ -268,12 +275,14 @@ mod serde_de {
}
impl<'a, S: VectorSpace, R> Deserialize<'a> for Decomposed<S, R>
where S: Deserialize<'a>,
S::Scalar: Deserialize<'a>,
R: Deserialize<'a>
where
S: Deserialize<'a>,
S::Scalar: Deserialize<'a>,
R: Deserialize<'a>,
{
fn deserialize<D>(deserializer: D) -> Result<Decomposed<S, R>, D::Error>
where D: serde::de::Deserializer<'a>
where
D: serde::de::Deserializer<'a>,
{
const FIELDS: &'static [&'static str] = &["scale", "rot", "disp"];
deserializer.deserialize_struct("Decomposed", FIELDS, DecomposedVisitor(PhantomData))
@ -283,9 +292,10 @@ mod serde_de {
struct DecomposedVisitor<S: VectorSpace, R>(PhantomData<(S, R)>);
impl<'a, S: VectorSpace, R> serde::de::Visitor<'a> for DecomposedVisitor<S, R>
where S: Deserialize<'a>,
S::Scalar: Deserialize<'a>,
R: Deserialize<'a>
where
S: Deserialize<'a>,
S::Scalar: Deserialize<'a>,
R: Deserialize<'a>,
{
type Value = Decomposed<S, R>;
@ -294,7 +304,8 @@ mod serde_de {
}
fn visit_map<V>(self, mut visitor: V) -> Result<Decomposed<S, R>, V::Error>
where V: serde::de::MapAccess<'a>
where
V: serde::de::MapAccess<'a>,
{
let mut scale = None;
let mut rot = None;
@ -330,10 +341,10 @@ mod serde_de {
};
Ok(Decomposed {
scale: scale,
rot: rot,
disp: disp,
})
scale: scale,
rot: rot,
disp: disp,
})
}
}
}

View file

@ -14,7 +14,7 @@
// limitations under the License.
use rand::{Rand, Rng};
use num_traits::{NumCast, Bounded};
use num_traits::{Bounded, NumCast};
use std::fmt;
use std::iter;
use std::mem;
@ -24,7 +24,7 @@ use structure::*;
use angle::Rad;
use approx::ApproxEq;
use num::{BaseNum, BaseFloat};
use num::{BaseFloat, BaseNum};
#[cfg(feature = "simd")]
use simd::f32x4 as Simdf32x4;
@ -660,9 +660,11 @@ impl<S: BaseNum> Vector3<S> {
/// Returns the cross product of the vector and `other`.
#[inline]
pub fn cross(self, other: Vector3<S>) -> Vector3<S> {
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))
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
@ -730,7 +732,8 @@ impl<S: BaseNum> Vector4<S> {
/// Dot product of two vectors.
#[inline]
pub fn dot<V: InnerSpace>(a: V, b: V) -> V::Scalar
where V::Scalar: BaseFloat
where
V::Scalar: BaseFloat,
{
V::dot(a, b)
}
@ -840,8 +843,6 @@ impl Vector4<f32> {
}
}
#[cfg(feature = "simd")]
impl Into<Simdf32x4> for Vector4<f32> {
#[inline]
@ -887,8 +888,6 @@ impl_operator_simd!{@rs
}
}
#[cfg(feature = "simd")]
impl_operator_simd!{
[Simdf32x4]; Neg for Vector4<f32> {
@ -938,27 +937,46 @@ impl DivAssign<f32> for Vector4<f32> {
#[cfg(feature = "simd")]
impl ElementWise for Vector4<f32> {
#[inline] fn add_element_wise(self, rhs: Vector4<f32>) -> Vector4<f32> { self + rhs }
#[inline] fn sub_element_wise(self, rhs: Vector4<f32>) -> Vector4<f32> { self - rhs }
#[inline] fn mul_element_wise(self, rhs: Vector4<f32>) -> Vector4<f32> {
#[inline]
fn add_element_wise(self, rhs: Vector4<f32>) -> Vector4<f32> {
self + rhs
}
#[inline]
fn sub_element_wise(self, rhs: Vector4<f32>) -> Vector4<f32> {
self - rhs
}
#[inline]
fn mul_element_wise(self, rhs: Vector4<f32>) -> Vector4<f32> {
let s: Simdf32x4 = self.into();
let rhs: Simdf32x4 = rhs.into();
(s * rhs).into()
}
#[inline] fn div_element_wise(self, rhs: Vector4<f32>) -> Vector4<f32> {
#[inline]
fn div_element_wise(self, rhs: Vector4<f32>) -> Vector4<f32> {
let s: Simdf32x4 = self.into();
let rhs: Simdf32x4 = rhs.into();
(s / rhs).into()
}
#[inline] fn add_assign_element_wise(&mut self, rhs: Vector4<f32>) { (*self) += rhs; }
#[inline] fn sub_assign_element_wise(&mut self, rhs: Vector4<f32>) { (*self) -= rhs; }
#[inline] fn mul_assign_element_wise(&mut self, rhs: Vector4<f32>) {
#[inline]
fn add_assign_element_wise(&mut self, rhs: Vector4<f32>) {
(*self) += rhs;
}
#[inline]
fn sub_assign_element_wise(&mut self, rhs: Vector4<f32>) {
(*self) -= rhs;
}
#[inline]
fn mul_assign_element_wise(&mut self, rhs: Vector4<f32>) {
let s: Simdf32x4 = (*self).into();
let rhs: Simdf32x4 = rhs.into();
*self = (s * rhs).into();
}
#[inline] fn div_assign_element_wise(&mut self, rhs: Vector4<f32>) {
#[inline]
fn div_assign_element_wise(&mut self, rhs: Vector4<f32>) {
let s: Simdf32x4 = (*self).into();
let rhs: Simdf32x4 = rhs.into();
*self = (s * rhs).into();
@ -967,31 +985,53 @@ impl ElementWise for Vector4<f32> {
#[cfg(feature = "simd")]
impl ElementWise<f32> for Vector4<f32> {
#[inline] fn add_element_wise(self, rhs: f32) -> Vector4<f32> {
#[inline]
fn add_element_wise(self, rhs: f32) -> Vector4<f32> {
let s: Simdf32x4 = self.into();
let rhs = Simdf32x4::splat(rhs);
(s + rhs).into()
}
#[inline] fn sub_element_wise(self, rhs: f32) -> Vector4<f32> {
#[inline]
fn sub_element_wise(self, rhs: f32) -> Vector4<f32> {
let s: Simdf32x4 = self.into();
let rhs = Simdf32x4::splat(rhs);
(s - rhs).into()
}
#[inline] fn mul_element_wise(self, rhs: f32) -> Vector4<f32> { self * rhs }
#[inline] fn div_element_wise(self, rhs: f32) -> Vector4<f32> { self / rhs }
#[inline] fn add_assign_element_wise(&mut self, rhs: f32) {
#[inline]
fn mul_element_wise(self, rhs: f32) -> Vector4<f32> {
self * rhs
}
#[inline]
fn div_element_wise(self, rhs: f32) -> Vector4<f32> {
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) {
#[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; }
#[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")]
@ -1170,7 +1210,6 @@ 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 {

View file

@ -17,7 +17,7 @@
extern crate approx;
extern crate cgmath;
use cgmath::{Rad, Deg};
use cgmath::{Deg, Rad};
#[test]
fn test_conv() {
@ -43,8 +43,14 @@ mod rad {
#[test]
fn test_iter_sum() {
assert_eq!(Rad(2.0) + Rad(3.0) + Rad(4.0), [Rad(2.0), Rad(3.0), Rad(4.0)].iter().sum());
assert_eq!(Rad(2.0) + Rad(3.0) + Rad(4.0), [Rad(2.0), Rad(3.0), Rad(4.0)].iter().cloned().sum());
assert_eq!(
Rad(2.0) + Rad(3.0) + Rad(4.0),
[Rad(2.0), Rad(3.0), Rad(4.0)].iter().sum()
);
assert_eq!(
Rad(2.0) + Rad(3.0) + Rad(4.0),
[Rad(2.0), Rad(3.0), Rad(4.0)].iter().cloned().sum()
);
}
}
@ -53,7 +59,13 @@ mod deg {
#[test]
fn test_iter_sum() {
assert_eq!(Deg(2.0) + Deg(3.0) + Deg(4.0), [Deg(2.0), Deg(3.0), Deg(4.0)].iter().sum());
assert_eq!(Deg(2.0) + Deg(3.0) + Deg(4.0), [Deg(2.0), Deg(3.0), Deg(4.0)].iter().cloned().sum());
assert_eq!(
Deg(2.0) + Deg(3.0) + Deg(4.0),
[Deg(2.0), Deg(3.0), Deg(4.0)].iter().sum()
);
assert_eq!(
Deg(2.0) + Deg(3.0) + Deg(4.0),
[Deg(2.0), Deg(3.0), Deg(4.0)].iter().cloned().sum()
);
}
}

View file

@ -53,7 +53,7 @@ macro_rules! impl_test_rem {
#[test]
fn test_homogeneous() {
let p = Point3::new(1.0f64, 2.0f64, 3.0f64);
let p = Point3::new(1.0f64, 2.0f64, 3.0f64);
assert_ulps_eq!(&p, &Point3::from_homogeneous(p.to_homogeneous()));
}
@ -78,6 +78,12 @@ fn test_rem() {
#[test]
fn test_cast() {
assert_ulps_eq!(Point1::new(0.9f64).cast().unwrap(), Point1::new(0.9f32));
assert_ulps_eq!(Point2::new(0.9f64, 1.5).cast().unwrap(), Point2::new(0.9f32, 1.5));
assert_ulps_eq!(Point3::new(1.0f64, 2.4, -3.13).cast().unwrap(), Point3::new(1.0f32, 2.4, -3.13));
assert_ulps_eq!(
Point2::new(0.9f64, 1.5).cast().unwrap(),
Point2::new(0.9f32, 1.5)
);
assert_ulps_eq!(
Point3::new(1.0f64, 2.4, -3.13).cast().unwrap(),
Point3::new(1.0f32, 2.4, -3.13)
);
}

View file

@ -15,7 +15,7 @@
extern crate cgmath;
use cgmath::{Vector4, ortho, Matrix4};
use cgmath::{ortho, Matrix4, Vector4};
#[test]
fn test_ortho_scale() {
@ -36,7 +36,6 @@ fn test_ortho_scale() {
assert_eq!(orig, Vector4::new(0f32, 0., 0., 1.));
assert_eq!(far, Vector4::new(1f32, 1., -1., 1.));
let o: Matrix4<f32> = ortho(-2., 2., -2., 2., -2., 2.);
let near = o * vec_near;
let orig = o * vec_orig;

View file

@ -44,19 +44,45 @@ mod operators {
#[test]
fn test_mul() {
impl_test_mul!(2.0f32, Quaternion::from(Euler { x: Rad(1f32), y: Rad(1f32), z: Rad(1f32) }));
impl_test_mul!(
2.0f32,
Quaternion::from(Euler {
x: Rad(1f32),
y: Rad(1f32),
z: Rad(1f32),
})
);
}
#[test]
fn test_div() {
impl_test_div!(2.0f32, Quaternion::from(Euler { x: Rad(1f32), y: Rad(1f32), z: Rad(1f32) }));
impl_test_div!(
2.0f32,
Quaternion::from(Euler {
x: Rad(1f32),
y: Rad(1f32),
z: Rad(1f32),
})
);
}
#[test]
fn test_iter_sum() {
let q1 = Quaternion::from(Euler { x: Rad(2f32), y: Rad(1f32), z: Rad(1f32) });
let q2 = Quaternion::from(Euler { x: Rad(1f32), y: Rad(2f32), z: Rad(1f32) });
let q3 = Quaternion::from(Euler { x: Rad(1f32), y: Rad(1f32), z: Rad(2f32) });
let q1 = Quaternion::from(Euler {
x: Rad(2f32),
y: Rad(1f32),
z: Rad(1f32),
});
let q2 = Quaternion::from(Euler {
x: Rad(1f32),
y: Rad(2f32),
z: Rad(1f32),
});
let q3 = Quaternion::from(Euler {
x: Rad(1f32),
y: Rad(1f32),
z: Rad(2f32),
});
assert_eq!(q1 + q2 + q3, [q1, q2, q3].iter().sum());
assert_eq!(q1 + q2 + q3, [q1, q2, q3].iter().cloned().sum());
@ -64,9 +90,21 @@ mod operators {
#[test]
fn test_iter_product() {
let q1 = Quaternion::from(Euler { x: Rad(2f32), y: Rad(1f32), z: Rad(1f32) });
let q2 = Quaternion::from(Euler { x: Rad(1f32), y: Rad(2f32), z: Rad(1f32) });
let q3 = Quaternion::from(Euler { x: Rad(1f32), y: Rad(1f32), z: Rad(2f32) });
let q1 = Quaternion::from(Euler {
x: Rad(2f32),
y: Rad(1f32),
z: Rad(1f32),
});
let q2 = Quaternion::from(Euler {
x: Rad(1f32),
y: Rad(2f32),
z: Rad(1f32),
});
let q3 = Quaternion::from(Euler {
x: Rad(1f32),
y: Rad(1f32),
z: Rad(2f32),
});
assert_eq!(q1 * q2 * q3, [q1, q2, q3].iter().product());
assert_eq!(q1 * q2 * q3, [q1, q2, q3].iter().cloned().product());
@ -79,22 +117,103 @@ mod to_from_euler {
use cgmath::*;
fn check_euler(rotation: Euler<Rad<f32>>) {
assert_relative_eq!(Euler::from(Quaternion::from(rotation)), rotation, epsilon = 0.001);
assert_relative_eq!(
Euler::from(Quaternion::from(rotation)),
rotation,
epsilon = 0.001
);
}
const HPI: f32 = f32::consts::FRAC_PI_2;
#[test] fn test_zero() { check_euler(Euler { x: Rad( 0f32), y: Rad( 0f32), z: Rad( 0f32) }); }
#[test] fn test_yaw_pos_1() { check_euler(Euler { x: Rad( 0f32), y: Rad( 1f32), z: Rad( 0f32) }); }
#[test] fn test_yaw_neg_1() { check_euler(Euler { x: Rad( 0f32), y: Rad(-1f32), z: Rad( 0f32) }); }
#[test] fn test_pitch_pos_1() { check_euler(Euler { x: Rad( 1f32), y: Rad( 0f32), z: Rad( 0f32) }); }
#[test] fn test_pitch_neg_1() { check_euler(Euler { x: Rad(-1f32), y: Rad( 0f32), z: Rad( 0f32) }); }
#[test] fn test_roll_pos_1() { check_euler(Euler { x: Rad( 0f32), y: Rad( 0f32), z: Rad( 1f32) }); }
#[test] fn test_roll_neg_1() { check_euler(Euler { x: Rad( 0f32), y: Rad( 0f32), z: Rad(-1f32) }); }
#[test] fn test_pitch_yaw_roll_pos_1() { check_euler(Euler { x: Rad( 1f32), y: Rad( 1f32), z: Rad( 1f32) }); }
#[test] fn test_pitch_yaw_roll_neg_1() { check_euler(Euler { x: Rad(-1f32), y: Rad(-1f32), z: Rad(-1f32) }); }
#[test] fn test_pitch_yaw_roll_pos_hp() { check_euler(Euler { x: Rad( 0f32), y: Rad( HPI), z: Rad( 1f32) }); }
#[test] fn test_pitch_yaw_roll_neg_hp() { check_euler(Euler { x: Rad( 0f32), y: Rad( -HPI), z: Rad( 1f32) }); }
#[test]
fn test_zero() {
check_euler(Euler {
x: Rad(0f32),
y: Rad(0f32),
z: Rad(0f32),
});
}
#[test]
fn test_yaw_pos_1() {
check_euler(Euler {
x: Rad(0f32),
y: Rad(1f32),
z: Rad(0f32),
});
}
#[test]
fn test_yaw_neg_1() {
check_euler(Euler {
x: Rad(0f32),
y: Rad(-1f32),
z: Rad(0f32),
});
}
#[test]
fn test_pitch_pos_1() {
check_euler(Euler {
x: Rad(1f32),
y: Rad(0f32),
z: Rad(0f32),
});
}
#[test]
fn test_pitch_neg_1() {
check_euler(Euler {
x: Rad(-1f32),
y: Rad(0f32),
z: Rad(0f32),
});
}
#[test]
fn test_roll_pos_1() {
check_euler(Euler {
x: Rad(0f32),
y: Rad(0f32),
z: Rad(1f32),
});
}
#[test]
fn test_roll_neg_1() {
check_euler(Euler {
x: Rad(0f32),
y: Rad(0f32),
z: Rad(-1f32),
});
}
#[test]
fn test_pitch_yaw_roll_pos_1() {
check_euler(Euler {
x: Rad(1f32),
y: Rad(1f32),
z: Rad(1f32),
});
}
#[test]
fn test_pitch_yaw_roll_neg_1() {
check_euler(Euler {
x: Rad(-1f32),
y: Rad(-1f32),
z: Rad(-1f32),
});
}
#[test]
fn test_pitch_yaw_roll_pos_hp() {
check_euler(Euler {
x: Rad(0f32),
y: Rad(HPI),
z: Rad(1f32),
});
}
#[test]
fn test_pitch_yaw_roll_neg_hp() {
check_euler(Euler {
x: Rad(0f32),
y: Rad(-HPI),
z: Rad(1f32),
});
}
}
mod from {
@ -206,7 +325,6 @@ mod rotate_from_euler {
assert_ulps_eq!(vec3(0.0, -1.0, 0.0), rot * vec);
}
// tests that the Y rotation is done after the X
#[test]
fn test_x_then_y() {
@ -258,7 +376,10 @@ mod rotate_from_axis_angle {
let vec = vec3(0.0, 0.0, 1.0);
let rot = Quaternion::from_axis_angle(vec3(1.0, 1.0, 0.0).normalize(), Deg(90.0));
assert_ulps_eq!(vec3(2.0f32.sqrt() / 2.0, -2.0f32.sqrt() / 2.0, 0.0), rot * vec);
assert_ulps_eq!(
vec3(2.0f32.sqrt() / 2.0, -2.0f32.sqrt() / 2.0, 0.0),
rot * vec
);
}
#[test]
@ -266,7 +387,10 @@ mod rotate_from_axis_angle {
let vec = vec3(1.0, 0.0, 0.0);
let rot = Quaternion::from_axis_angle(vec3(0.0, 1.0, 1.0).normalize(), Deg(-90.0));
assert_ulps_eq!(vec3(0.0, -2.0f32.sqrt() / 2.0, 2.0f32.sqrt() / 2.0), rot * vec);
assert_ulps_eq!(
vec3(0.0, -2.0f32.sqrt() / 2.0, 2.0f32.sqrt() / 2.0),
rot * vec
);
}
#[test]
@ -274,7 +398,10 @@ mod rotate_from_axis_angle {
let vec = vec3(0.0, 1.0, 0.0);
let rot = Quaternion::from_axis_angle(vec3(1.0, 0.0, 1.0).normalize(), Deg(90.0));
assert_ulps_eq!(vec3(-2.0f32.sqrt() / 2.0, 0.0, 2.0f32.sqrt() / 2.0), rot * vec);
assert_ulps_eq!(
vec3(-2.0f32.sqrt() / 2.0, 0.0, 2.0f32.sqrt() / 2.0),
rot * vec
);
}
}
@ -337,7 +464,9 @@ mod cast {
#[test]
fn test_cast() {
assert_ulps_eq!(Quaternion::new(0.9f64, 1.5, 2.4, 7.6).cast().unwrap(),
Quaternion::new(0.9f32, 1.5, 2.4, 7.6));
assert_ulps_eq!(
Quaternion::new(0.9f64, 1.5, 2.4, 7.6).cast().unwrap(),
Quaternion::new(0.9f32, 1.5, 2.4, 7.6)
);
}
}

View file

@ -30,7 +30,8 @@ fn test_invert() {
rot: Quaternion::new(0.5f64, 0.5, 0.5, 0.5),
disp: Vector3::new(6.0f64, -7.0, 8.0),
};
let ti = t.inverse_transform().expect("Expected successful inversion");
let ti = t.inverse_transform()
.expect("Expected successful inversion");
let vt = t.transform_vector(v);
assert_ulps_eq!(&v, &ti.transform_vector(vt));
}
@ -43,7 +44,8 @@ fn test_inverse_vector() {
rot: Quaternion::new(0.5f64, 0.5, 0.5, 0.5),
disp: Vector3::new(6.0f64, -7.0, 8.0),
};
let vt = t.inverse_transform_vector(v).expect("Expected successful inversion");
let vt = t.inverse_transform_vector(v)
.expect("Expected successful inversion");
assert_ulps_eq!(v, t.transform_vector(vt));
}
@ -68,7 +70,8 @@ fn test_serialize() {
};
let serialized = serde_json::to_string(&t).unwrap();
let deserialized: Decomposed<Vector3<f64>, Quaternion<f64>> = serde_json::from_str(&serialized).unwrap();
let deserialized: Decomposed<Vector3<f64>, Quaternion<f64>> =
serde_json::from_str(&serialized).unwrap();
assert_ulps_eq!(&t, &deserialized);
}

View file

@ -25,14 +25,26 @@ use std::iter;
fn test_constructor() {
assert_eq!(vec2(1f32, 2f32), Vector2::new(1f32, 2f32));
assert_eq!(vec3(1f64, 2f64, 3f64), Vector3::new(1f64, 2f64, 3f64));
assert_eq!(vec4(1isize, 2isize, 3isize, 4isize), Vector4::new(1isize, 2isize, 3isize, 4isize));
assert_eq!(
vec4(1isize, 2isize, 3isize, 4isize),
Vector4::new(1isize, 2isize, 3isize, 4isize)
);
}
#[test]
fn test_from_value() {
assert_eq!(Vector2::from_value(102isize), Vector2::new(102isize, 102isize));
assert_eq!(Vector3::from_value(22isize), Vector3::new(22isize, 22isize, 22isize));
assert_eq!(Vector4::from_value(76.5f64), Vector4::new(76.5f64, 76.5f64, 76.5f64, 76.5f64));
assert_eq!(
Vector2::from_value(102isize),
Vector2::new(102isize, 102isize)
);
assert_eq!(
Vector3::from_value(22isize),
Vector3::new(22isize, 22isize, 22isize)
);
assert_eq!(
Vector4::from_value(76.5f64),
Vector4::new(76.5f64, 76.5f64, 76.5f64, 76.5f64)
);
}
macro_rules! impl_test_add {
@ -132,8 +144,14 @@ fn test_rem() {
#[test]
fn test_dot() {
assert_eq!(Vector2::new(1.0, 2.0).dot(Vector2::new(3.0, 4.0)), 11.0);
assert_eq!(Vector3::new(1.0, 2.0, 3.0).dot(Vector3::new(4.0, 5.0, 6.0)), 32.0);
assert_eq!(Vector4::new(1.0, 2.0, 3.0, 4.0).dot(Vector4::new(5.0, 6.0, 7.0, 8.0)), 70.0);
assert_eq!(
Vector3::new(1.0, 2.0, 3.0).dot(Vector3::new(4.0, 5.0, 6.0)),
32.0
);
assert_eq!(
Vector4::new(1.0, 2.0, 3.0, 4.0).dot(Vector4::new(5.0, 6.0, 7.0, 8.0)),
70.0
);
}
#[test]
@ -149,7 +167,12 @@ fn test_sum() {
#[test]
fn test_iter_sum() {
impl_test_iter_sum!(Vector4 { x, y, z, w }, f32, 2.0f32, vec4(2.0f32, 4.0, 6.0, 8.0));
impl_test_iter_sum!(
Vector4 { x, y, z, w },
f32,
2.0f32,
vec4(2.0f32, 4.0, 6.0, 8.0)
);
impl_test_iter_sum!(Vector3 { x, y, z }, f32, 2.0f32, vec3(2.0f32, 4.0, 6.0));
impl_test_iter_sum!(Vector2 { x, y }, f32, 2.0f32, vec2(2.0f32, 4.0));
@ -162,11 +185,17 @@ fn test_iter_sum() {
fn test_product() {
assert_eq!(Vector2::new(1isize, 2isize).product(), 2isize);
assert_eq!(Vector3::new(1isize, 2isize, 3isize).product(), 6isize);
assert_eq!(Vector4::new(1isize, 2isize, 3isize, 4isize).product(), 24isize);
assert_eq!(
Vector4::new(1isize, 2isize, 3isize, 4isize).product(),
24isize
);
assert_eq!(Vector2::new(3.0f64, 4.0f64).product(), 12.0f64);
assert_eq!(Vector3::new(4.0f64, 5.0f64, 6.0f64).product(), 120.0f64);
assert_eq!(Vector4::new(5.0f64, 6.0f64, 7.0f64, 8.0f64).product(), 1680.0f64);
assert_eq!(
Vector4::new(5.0f64, 6.0f64, 7.0f64, 8.0f64).product(),
1680.0f64
);
}
#[test]
@ -180,8 +209,17 @@ fn test_cross() {
#[test]
fn test_is_perpendicular() {
assert!(Vector2::new(1.0f64, 0.0f64).is_perpendicular(Vector2::new(0.0f64, 1.0f64)));
assert!(Vector3::new(0.0f64, 1.0f64, 0.0f64).is_perpendicular(Vector3::new(0.0f64, 0.0f64, 1.0f64)));
assert!(Vector4::new(1.0f64, 0.0f64, 0.0f64, 0.0f64).is_perpendicular(Vector4::new(0.0f64, 0.0f64, 0.0f64, 1.0f64)));
assert!(
Vector3::new(0.0f64, 1.0f64, 0.0f64).is_perpendicular(Vector3::new(0.0f64, 0.0f64, 1.0f64))
);
assert!(
Vector4::new(1.0f64, 0.0f64, 0.0f64, 0.0f64).is_perpendicular(Vector4::new(
0.0f64,
0.0f64,
0.0f64,
1.0f64
))
);
}
#[cfg(test)]
@ -189,7 +227,7 @@ mod test_magnitude {
use cgmath::*;
#[test]
fn test_vector2(){
fn test_vector2() {
let (a, a_res) = (Vector2::new(3.0f64, 4.0f64), 5.0f64); // (3, 4, 5) Pythagorean triple
let (b, b_res) = (Vector2::new(5.0f64, 12.0f64), 13.0f64); // (5, 12, 13) Pythagorean triple
@ -201,7 +239,7 @@ mod test_magnitude {
}
#[test]
fn test_vector3(){
fn test_vector3() {
let (a, a_res) = (Vector3::new(2.0f64, 3.0f64, 6.0f64), 7.0f64); // (2, 3, 6, 7) Pythagorean quadruple
let (b, b_res) = (Vector3::new(1.0f64, 4.0f64, 8.0f64), 9.0f64); // (1, 4, 8, 9) Pythagorean quadruple
@ -213,7 +251,7 @@ mod test_magnitude {
}
#[test]
fn test_vector4(){
fn test_vector4() {
let (a, a_res) = (Vector4::new(1.0f64, 2.0f64, 4.0f64, 10.0f64), 11.0f64); // (1, 2, 4, 10, 11) Pythagorean quintuple
let (b, b_res) = (Vector4::new(1.0f64, 2.0f64, 8.0f64, 10.0f64), 13.0f64); // (1, 2, 8, 10, 13) Pythagorean quintuple
@ -227,37 +265,106 @@ mod test_magnitude {
#[test]
fn test_angle() {
assert_ulps_eq!(Vector2::new(1.0f64, 0.0f64).angle(Vector2::new(0.0f64, 1.0f64)), &Rad(f64::consts::FRAC_PI_2));
assert_ulps_eq!(Vector2::new(10.0f64, 0.0f64).angle(Vector2::new(0.0f64, 5.0f64)), &Rad(f64::consts::FRAC_PI_2));
assert_ulps_eq!(Vector2::new(-1.0f64, 0.0f64).angle(Vector2::new(0.0f64, 1.0f64)), &-Rad(f64::consts::FRAC_PI_2));
assert_ulps_eq!(
Vector2::new(1.0f64, 0.0f64).angle(Vector2::new(0.0f64, 1.0f64)),
&Rad(f64::consts::FRAC_PI_2)
);
assert_ulps_eq!(
Vector2::new(10.0f64, 0.0f64).angle(Vector2::new(0.0f64, 5.0f64)),
&Rad(f64::consts::FRAC_PI_2)
);
assert_ulps_eq!(
Vector2::new(-1.0f64, 0.0f64).angle(Vector2::new(0.0f64, 1.0f64)),
&-Rad(f64::consts::FRAC_PI_2)
);
assert_ulps_eq!(Vector3::new(1.0f64, 0.0f64, 1.0f64).angle(Vector3::new(1.0f64, 1.0f64, 0.0f64)), &Rad(f64::consts::FRAC_PI_3));
assert_ulps_eq!(Vector3::new(10.0f64, 0.0f64, 10.0f64).angle(Vector3::new(5.0f64, 5.0f64, 0.0f64)), &Rad(f64::consts::FRAC_PI_3));
assert_ulps_eq!(Vector3::new(-1.0f64, 0.0f64, -1.0f64).angle(Vector3::new(1.0f64, -1.0f64, 0.0f64)), &Rad(2.0f64 * f64::consts::FRAC_PI_3));
assert_ulps_eq!(
Vector3::new(1.0f64, 0.0f64, 1.0f64).angle(Vector3::new(1.0f64, 1.0f64, 0.0f64)),
&Rad(f64::consts::FRAC_PI_3)
);
assert_ulps_eq!(
Vector3::new(10.0f64, 0.0f64, 10.0f64).angle(Vector3::new(5.0f64, 5.0f64, 0.0f64)),
&Rad(f64::consts::FRAC_PI_3)
);
assert_ulps_eq!(
Vector3::new(-1.0f64, 0.0f64, -1.0f64).angle(Vector3::new(1.0f64, -1.0f64, 0.0f64)),
&Rad(2.0f64 * f64::consts::FRAC_PI_3)
);
assert_ulps_eq!(Vector4::new(1.0f64, 0.0f64, 1.0f64, 0.0f64).angle(Vector4::new(0.0f64, 1.0f64, 0.0f64, 1.0f64)), &Rad(f64::consts::FRAC_PI_2));
assert_ulps_eq!(Vector4::new(10.0f64, 0.0f64, 10.0f64, 0.0f64).angle(Vector4::new(0.0f64, 5.0f64, 0.0f64, 5.0f64)), &Rad(f64::consts::FRAC_PI_2));
assert_ulps_eq!(Vector4::new(-1.0f64, 0.0f64, -1.0f64, 0.0f64).angle(Vector4::new(0.0f64, 1.0f64, 0.0f64, 1.0f64)), &Rad(f64::consts::FRAC_PI_2));
assert_ulps_eq!(
Vector4::new(1.0f64, 0.0f64, 1.0f64, 0.0f64).angle(Vector4::new(
0.0f64,
1.0f64,
0.0f64,
1.0f64
)),
&Rad(f64::consts::FRAC_PI_2)
);
assert_ulps_eq!(
Vector4::new(10.0f64, 0.0f64, 10.0f64, 0.0f64).angle(Vector4::new(
0.0f64,
5.0f64,
0.0f64,
5.0f64
)),
&Rad(f64::consts::FRAC_PI_2)
);
assert_ulps_eq!(
Vector4::new(-1.0f64, 0.0f64, -1.0f64, 0.0f64).angle(Vector4::new(
0.0f64,
1.0f64,
0.0f64,
1.0f64
)),
&Rad(f64::consts::FRAC_PI_2)
);
}
#[test]
fn test_normalize() {
// TODO: test normalize_to, normalize_sel.0, and normalize_self_to
assert_ulps_eq!(Vector2::new(3.0f64, 4.0f64).normalize(), &Vector2::new(3.0/5.0, 4.0/5.0));
assert_ulps_eq!(Vector3::new(2.0f64, 3.0f64, 6.0f64).normalize(), &Vector3::new(2.0/7.0, 3.0/7.0, 6.0/7.0));
assert_ulps_eq!(Vector4::new(1.0f64, 2.0f64, 4.0f64, 10.0f64).normalize(), &Vector4::new(1.0/11.0, 2.0/11.0, 4.0/11.0, 10.0/11.0));
assert_ulps_eq!(
Vector2::new(3.0f64, 4.0f64).normalize(),
&Vector2::new(3.0 / 5.0, 4.0 / 5.0)
);
assert_ulps_eq!(
Vector3::new(2.0f64, 3.0f64, 6.0f64).normalize(),
&Vector3::new(2.0 / 7.0, 3.0 / 7.0, 6.0 / 7.0)
);
assert_ulps_eq!(
Vector4::new(1.0f64, 2.0f64, 4.0f64, 10.0f64).normalize(),
&Vector4::new(1.0 / 11.0, 2.0 / 11.0, 4.0 / 11.0, 10.0 / 11.0)
);
}
#[test]
fn test_project_on() {
assert_ulps_eq!(Vector2::new(-1.0f64, 5.0).project_on(Vector2::new(2.0, 4.0)), &Vector2::new(9.0/5.0, 18.0/5.0));
assert_ulps_eq!(Vector3::new(5.0f64, 6.0, 7.0).project_on(Vector3::new(1.0, 1.0, 1.0)), &Vector3::new(6.0, 6.0, 6.0));
assert_ulps_eq!(Vector4::new(0.0f64, -5.0, 5.0, 5.0).project_on(Vector4::new(0.0, 1.0, 0.0, 0.5)), &Vector4::new(0.0, -2.0, 0.0, -1.0));
assert_ulps_eq!(
Vector2::new(-1.0f64, 5.0).project_on(Vector2::new(2.0, 4.0)),
&Vector2::new(9.0 / 5.0, 18.0 / 5.0)
);
assert_ulps_eq!(
Vector3::new(5.0f64, 6.0, 7.0).project_on(Vector3::new(1.0, 1.0, 1.0)),
&Vector3::new(6.0, 6.0, 6.0)
);
assert_ulps_eq!(
Vector4::new(0.0f64, -5.0, 5.0, 5.0).project_on(Vector4::new(0.0, 1.0, 0.0, 0.5)),
&Vector4::new(0.0, -2.0, 0.0, -1.0)
);
}
#[test]
fn test_cast() {
assert_ulps_eq!(Vector2::new(0.9f64, 1.5).cast().unwrap(), Vector2::new(0.9f32, 1.5));
assert_ulps_eq!(Vector3::new(1.0f64, 2.4, -3.13).cast().unwrap(), Vector3::new(1.0f32, 2.4, -3.13));
assert_ulps_eq!(Vector4::new(13.5f64, -4.6, -8.3, 2.41).cast().unwrap(), Vector4::new(13.5f32, -4.6, -8.3, 2.41));
assert_ulps_eq!(
Vector2::new(0.9f64, 1.5).cast().unwrap(),
Vector2::new(0.9f32, 1.5)
);
assert_ulps_eq!(
Vector3::new(1.0f64, 2.4, -3.13).cast().unwrap(),
Vector3::new(1.0f32, 2.4, -3.13)
);
assert_ulps_eq!(
Vector4::new(13.5f64, -4.6, -8.3, 2.41).cast().unwrap(),
Vector4::new(13.5f32, -4.6, -8.3, 2.41)
);
}

View file

@ -22,12 +22,18 @@ use std::f32;
#[test]
fn test_constructor() {
assert_eq!(vec4(1f32, 2f32, 3f32, 4f32), Vector4::new(1f32, 2f32, 3f32, 4f32));
assert_eq!(
vec4(1f32, 2f32, 3f32, 4f32),
Vector4::new(1f32, 2f32, 3f32, 4f32)
);
}
#[test]
fn test_from_value() {
assert_eq!(Vector4::from_value(76.5f32), Vector4::new(76.5f32, 76.5f32, 76.5f32, 76.5f32));
assert_eq!(
Vector4::from_value(76.5f32),
Vector4::new(76.5f32, 76.5f32, 76.5f32, 76.5f32)
);
}
macro_rules! impl_test_add {
@ -84,32 +90,60 @@ macro_rules! impl_test_rem {
#[test]
fn test_add() {
impl_test_add!(Vector4 { x, y, z, w }, 2.0f32, vec4(2.0f32, 4.0f32, 6.0f32, 8.0f32));
impl_test_add!(
Vector4 { x, y, z, w },
2.0f32,
vec4(2.0f32, 4.0f32, 6.0f32, 8.0f32)
);
}
#[test]
fn test_sub() {
impl_test_sub!(Vector4 { x, y, z, w }, 2.0f32, vec4(2.0f32, 4.0f32, 6.0f32, 8.0f32));
impl_test_sub!(
Vector4 { x, y, z, w },
2.0f32,
vec4(2.0f32, 4.0f32, 6.0f32, 8.0f32)
);
}
#[test]
fn test_mul() {
impl_test_mul!(Vector4 { x, y, z, w }, 2.0f32, vec4(2.0f32, 4.0f32, 6.0f32, 8.0f32));
impl_test_mul!(
Vector4 { x, y, z, w },
2.0f32,
vec4(2.0f32, 4.0f32, 6.0f32, 8.0f32)
);
}
#[test]
fn test_div() {
impl_test_div!(Vector4 { x, y, z, w }, 2.0f32, vec4(2.0f32, 4.0f32, 6.0f32, 8.0f32));
impl_test_div!(
Vector4 { x, y, z, w },
2.0f32,
vec4(2.0f32, 4.0f32, 6.0f32, 8.0f32)
);
}
#[test]
fn test_rem() {
impl_test_rem!(Vector4 { x, y, z, w }, 2.0f32, vec4(2.0f32, 4.0f32, 6.0f32, 8.0f32));
impl_test_rem!(
Vector4 { x, y, z, w },
2.0f32,
vec4(2.0f32, 4.0f32, 6.0f32, 8.0f32)
);
}
#[test]
fn test_dot() {
assert_eq!(Vector4::new(1.0f32, 2.0f32, 3.0f32, 4.0f32).dot(Vector4::new(5.0f32, 6.0f32, 7.0f32, 8.0f32)), 70.0f32);
assert_eq!(
Vector4::new(1.0f32, 2.0f32, 3.0f32, 4.0f32).dot(Vector4::new(
5.0f32,
6.0f32,
7.0f32,
8.0f32
)),
70.0f32
);
}
#[test]
@ -123,12 +157,22 @@ fn test_sum() {
fn test_product() {
assert_eq!(Vector4::new(1f32, 2f32, 3f32, 4f32).product(), 24f32);
assert_eq!(Vector4::new(5.0f32, 6.0f32, 7.0f32, 8.0f32).product(), 1680.0f32);
assert_eq!(
Vector4::new(5.0f32, 6.0f32, 7.0f32, 8.0f32).product(),
1680.0f32
);
}
#[test]
fn test_is_perpendicular() {
assert!(Vector4::new(1.0f32, 0.0f32, 0.0f32, 0.0f32).is_perpendicular(Vector4::new(0.0f32, 0.0f32, 0.0f32, 1.0f32)));
assert!(
Vector4::new(1.0f32, 0.0f32, 0.0f32, 0.0f32).is_perpendicular(Vector4::new(
0.0f32,
0.0f32,
0.0f32,
1.0f32
))
);
}
#[cfg(test)]
@ -136,7 +180,7 @@ mod test_magnitude {
use cgmath::*;
#[test]
fn test_vector4(){
fn test_vector4() {
let (a, a_res) = (Vector4::new(1.0f32, 2.0f32, 4.0f32, 10.0f32), 11.0f32); // (1, 2, 4, 10, 11) Pythagorean quintuple
let (b, b_res) = (Vector4::new(1.0f32, 2.0f32, 8.0f32, 10.0f32), 13.0f32); // (1, 2, 8, 10, 13) Pythagorean quintuple
@ -150,26 +194,69 @@ mod test_magnitude {
{
let a = Vector4::new(1f32, 4f32, 9f32, 16f32);
assert_ulps_eq!(a.sqrt_element_wide(), Vector4::new(1f32, 2f32, 3f32, 4f32));
assert_relative_eq!(a.sqrt_element_wide().recip_element_wide(), Vector4::new(1f32, 1f32/2f32, 1f32/3f32, 1f32/4f32), max_relative = 0.005f32);
assert_relative_eq!(a.rsqrt_element_wide(), Vector4::new(1f32, 1f32/2f32, 1f32/3f32, 1f32/4f32), max_relative= 0.005f32);
assert_relative_eq!(
a.sqrt_element_wide().recip_element_wide(),
Vector4::new(1f32, 1f32 / 2f32, 1f32 / 3f32, 1f32 / 4f32),
max_relative = 0.005f32
);
assert_relative_eq!(
a.rsqrt_element_wide(),
Vector4::new(1f32, 1f32 / 2f32, 1f32 / 3f32, 1f32 / 4f32),
max_relative = 0.005f32
);
}
}
}
#[test]
fn test_angle() {
assert_ulps_eq!(Vector4::new(1.0f32, 0.0f32, 1.0f32, 0.0f32).angle(Vector4::new(0.0f32, 1.0f32, 0.0f32, 1.0f32)), &Rad(f32::consts::FRAC_PI_2));
assert_ulps_eq!(Vector4::new(10.0f32, 0.0f32, 10.0f32, 0.0f32).angle(Vector4::new(0.0f32, 5.0f32, 0.0f32, 5.0f32)), &Rad(f32::consts::FRAC_PI_2));
assert_ulps_eq!(Vector4::new(-1.0f32, 0.0f32, -1.0f32, 0.0f32).angle(Vector4::new(0.0f32, 1.0f32, 0.0f32, 1.0f32)), &Rad(f32::consts::FRAC_PI_2));
assert_ulps_eq!(
Vector4::new(1.0f32, 0.0f32, 1.0f32, 0.0f32).angle(Vector4::new(
0.0f32,
1.0f32,
0.0f32,
1.0f32
)),
&Rad(f32::consts::FRAC_PI_2)
);
assert_ulps_eq!(
Vector4::new(10.0f32, 0.0f32, 10.0f32, 0.0f32).angle(Vector4::new(
0.0f32,
5.0f32,
0.0f32,
5.0f32
)),
&Rad(f32::consts::FRAC_PI_2)
);
assert_ulps_eq!(
Vector4::new(-1.0f32, 0.0f32, -1.0f32, 0.0f32).angle(Vector4::new(
0.0f32,
1.0f32,
0.0f32,
1.0f32
)),
&Rad(f32::consts::FRAC_PI_2)
);
}
#[test]
fn test_normalize() {
// TODO: test normalize_to, normalize_sel.0f32, and normalize_self_to
assert_ulps_eq!(Vector4::new(1.0f32, 2.0f32, 4.0f32, 10.0f32).normalize(), &Vector4::new(1.0f32/11.0f32, 2.0f32/11.0f32, 4.0f32/11.0f32, 10.0f32/11.0f32));
assert_ulps_eq!(
Vector4::new(1.0f32, 2.0f32, 4.0f32, 10.0f32).normalize(),
&Vector4::new(
1.0f32 / 11.0f32,
2.0f32 / 11.0f32,
4.0f32 / 11.0f32,
10.0f32 / 11.0f32
)
);
}
#[test]
fn test_cast() {
assert_ulps_eq!(Vector4::new(13.5f32, -4.6, -8.3, 2.41).cast().unwrap(), Vector4::new(13.5f32, -4.6, -8.3, 2.41));
assert_ulps_eq!(
Vector4::new(13.5f32, -4.6, -8.3, 2.41).cast().unwrap(),
Vector4::new(13.5f32, -4.6, -8.3, 2.41)
);
}