Use the new ApproxEq trait in core

This commit is contained in:
Brendan Zabarauskas 2013-05-08 01:00:06 +10:00
parent 0cb3314bf8
commit ebf6a9529d
4 changed files with 173 additions and 140 deletions

View file

@ -1,6 +1,6 @@
use core::cmp::ApproxEq;
use core::num::Zero::zero; use core::num::Zero::zero;
use core::num::One::one; use core::num::One::one;
use std::cmp::{FuzzyEq, FUZZY_EPSILON};
use vec::*; use vec::*;
use quat::Quat; use quat::Quat;
@ -123,7 +123,7 @@ pub trait BaseMat<T,V>: Index<uint, V> + Eq + Neg<Self> {
* The transposed matrix * The transposed matrix
*/ */
fn transpose(&self) -> Self; fn transpose(&self) -> Self;
/** /**
* # Return value * # Return value
* *
@ -313,7 +313,7 @@ pub trait BaseMat4<T,V>: BaseMat<T,V> {
#[deriving(Eq)] #[deriving(Eq)]
pub struct Mat2<T> { x: Vec2<T>, y: Vec2<T> } pub struct Mat2<T> { x: Vec2<T>, y: Vec2<T> }
impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat<T, Vec2<T>> for Mat2<T> { impl<T:Copy + Float + NumAssign> BaseMat<T, Vec2<T>> for Mat2<T> {
#[inline(always)] #[inline(always)]
fn col(&self, i: uint) -> Vec2<T> { self[i] } fn col(&self, i: uint) -> Vec2<T> { self[i] }
@ -424,7 +424,7 @@ impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat<T, Vec2<T>> for Mat2<T> {
#[inline(always)] #[inline(always)]
fn inverse(&self) -> Option<Mat2<T>> { fn inverse(&self) -> Option<Mat2<T>> {
let d = self.determinant(); let d = self.determinant();
if d.fuzzy_eq(&zero()) { if d.approx_eq(&zero()) {
None None
} else { } else {
Some(BaseMat2::new( self[1][1]/d, -self[0][1]/d, Some(BaseMat2::new( self[1][1]/d, -self[0][1]/d,
@ -437,7 +437,7 @@ impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat<T, Vec2<T>> for Mat2<T> {
BaseMat2::new(self[0][0], self[1][0], BaseMat2::new(self[0][0], self[1][0],
self[0][1], self[1][1]) self[0][1], self[1][1])
} }
#[inline(always)] #[inline(always)]
fn col_mut<'a>(&'a mut self, i: uint) -> &'a mut Vec2<T> { fn col_mut<'a>(&'a mut self, i: uint) -> &'a mut Vec2<T> {
match i { match i {
@ -507,29 +507,29 @@ impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat<T, Vec2<T>> for Mat2<T> {
#[inline(always)] #[inline(always)]
fn is_identity(&self) -> bool { fn is_identity(&self) -> bool {
self.fuzzy_eq(&BaseMat::identity()) self.approx_eq(&BaseMat::identity())
} }
#[inline(always)] #[inline(always)]
fn is_diagonal(&self) -> bool { fn is_diagonal(&self) -> bool {
self[0][1].fuzzy_eq(&zero()) && self[0][1].approx_eq(&zero()) &&
self[1][0].fuzzy_eq(&zero()) self[1][0].approx_eq(&zero())
} }
#[inline(always)] #[inline(always)]
fn is_rotated(&self) -> bool { fn is_rotated(&self) -> bool {
!self.fuzzy_eq(&BaseMat::identity()) !self.approx_eq(&BaseMat::identity())
} }
#[inline(always)] #[inline(always)]
fn is_symmetric(&self) -> bool { fn is_symmetric(&self) -> bool {
self[0][1].fuzzy_eq(&self[1][0]) && self[0][1].approx_eq(&self[1][0]) &&
self[1][0].fuzzy_eq(&self[0][1]) self[1][0].approx_eq(&self[0][1])
} }
#[inline(always)] #[inline(always)]
fn is_invertible(&self) -> bool { fn is_invertible(&self) -> bool {
!self.determinant().fuzzy_eq(&zero()) !self.determinant().approx_eq(&zero())
} }
#[inline(always)] #[inline(always)]
@ -538,7 +538,7 @@ impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat<T, Vec2<T>> for Mat2<T> {
} }
} }
impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat2<T, Vec2<T>> for Mat2<T> { impl<T:Copy + Float + NumAssign> BaseMat2<T, Vec2<T>> for Mat2<T> {
/** /**
* Construct a 2 x 2 matrix * Construct a 2 x 2 matrix
* *
@ -645,23 +645,28 @@ impl<T:Copy> Index<uint, Vec2<T>> for Mat2<T> {
} }
} }
impl<T:Copy + Float + NumAssign + FuzzyEq<T>> Neg<Mat2<T>> for Mat2<T> { impl<T:Copy + Float + NumAssign> Neg<Mat2<T>> for Mat2<T> {
#[inline(always)] #[inline(always)]
fn neg(&self) -> Mat2<T> { fn neg(&self) -> Mat2<T> {
BaseMat2::from_cols(-self[0], -self[1]) BaseMat2::from_cols(-self[0], -self[1])
} }
} }
impl<T:Copy + Float + FuzzyEq<T>> FuzzyEq<T> for Mat2<T> { impl<T:Copy + Eq + ApproxEq<T>> ApproxEq<T> for Mat2<T> {
#[inline(always)] #[inline(always)]
fn fuzzy_eq(&self, other: &Mat2<T>) -> bool { fn approx_epsilon() -> T {
self.fuzzy_eq_eps(other, &num::cast(FUZZY_EPSILON)) ApproxEq::approx_epsilon::<T,T>()
} }
#[inline(always)] #[inline(always)]
fn fuzzy_eq_eps(&self, other: &Mat2<T>, epsilon: &T) -> bool { fn approx_eq(&self, other: &Mat2<T>) -> bool {
self[0].fuzzy_eq_eps(&other[0], epsilon) && self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
self[1].fuzzy_eq_eps(&other[1], epsilon) }
#[inline(always)]
fn approx_eq_eps(&self, other: &Mat2<T>, epsilon: &T) -> bool {
self[0].approx_eq_eps(&other[0], epsilon) &&
self[1].approx_eq_eps(&other[1], epsilon)
} }
} }
@ -681,7 +686,7 @@ impl<T:Copy + Float + FuzzyEq<T>> FuzzyEq<T> for Mat2<T> {
#[deriving(Eq)] #[deriving(Eq)]
pub struct Mat3<T> { x: Vec3<T>, y: Vec3<T>, z: Vec3<T> } pub struct Mat3<T> { x: Vec3<T>, y: Vec3<T>, z: Vec3<T> }
impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat<T, Vec3<T>> for Mat3<T> { impl<T:Copy + Float + NumAssign> BaseMat<T, Vec3<T>> for Mat3<T> {
#[inline(always)] #[inline(always)]
fn col(&self, i: uint) -> Vec3<T> { self[i] } fn col(&self, i: uint) -> Vec3<T> { self[i] }
@ -815,7 +820,7 @@ impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat<T, Vec3<T>> for Mat3<T> {
// #[inline(always)] // #[inline(always)]
fn inverse(&self) -> Option<Mat3<T>> { fn inverse(&self) -> Option<Mat3<T>> {
let d = self.determinant(); let d = self.determinant();
if d.fuzzy_eq(&zero()) { if d.approx_eq(&zero()) {
None None
} else { } else {
let m: Mat3<T> = BaseMat3::from_cols(self[1].cross(&self[2]).div_t(d), let m: Mat3<T> = BaseMat3::from_cols(self[1].cross(&self[2]).div_t(d),
@ -831,7 +836,7 @@ impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat<T, Vec3<T>> for Mat3<T> {
self[0][1], self[1][1], self[2][1], self[0][1], self[1][1], self[2][1],
self[0][2], self[1][2], self[2][2]) self[0][2], self[1][2], self[2][2])
} }
#[inline(always)] #[inline(always)]
fn col_mut<'a>(&'a mut self, i: uint) -> &'a mut Vec3<T> { fn col_mut<'a>(&'a mut self, i: uint) -> &'a mut Vec3<T> {
match i { match i {
@ -912,41 +917,41 @@ impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat<T, Vec3<T>> for Mat3<T> {
#[inline(always)] #[inline(always)]
fn is_identity(&self) -> bool { fn is_identity(&self) -> bool {
self.fuzzy_eq(&BaseMat::identity()) self.approx_eq(&BaseMat::identity())
} }
#[inline(always)] #[inline(always)]
fn is_diagonal(&self) -> bool { fn is_diagonal(&self) -> bool {
self[0][1].fuzzy_eq(&zero()) && self[0][1].approx_eq(&zero()) &&
self[0][2].fuzzy_eq(&zero()) && self[0][2].approx_eq(&zero()) &&
self[1][0].fuzzy_eq(&zero()) && self[1][0].approx_eq(&zero()) &&
self[1][2].fuzzy_eq(&zero()) && self[1][2].approx_eq(&zero()) &&
self[2][0].fuzzy_eq(&zero()) && self[2][0].approx_eq(&zero()) &&
self[2][1].fuzzy_eq(&zero()) self[2][1].approx_eq(&zero())
} }
#[inline(always)] #[inline(always)]
fn is_rotated(&self) -> bool { fn is_rotated(&self) -> bool {
!self.fuzzy_eq(&BaseMat::identity()) !self.approx_eq(&BaseMat::identity())
} }
#[inline(always)] #[inline(always)]
fn is_symmetric(&self) -> bool { fn is_symmetric(&self) -> bool {
self[0][1].fuzzy_eq(&self[1][0]) && self[0][1].approx_eq(&self[1][0]) &&
self[0][2].fuzzy_eq(&self[2][0]) && self[0][2].approx_eq(&self[2][0]) &&
self[1][0].fuzzy_eq(&self[0][1]) && self[1][0].approx_eq(&self[0][1]) &&
self[1][2].fuzzy_eq(&self[2][1]) && self[1][2].approx_eq(&self[2][1]) &&
self[2][0].fuzzy_eq(&self[0][2]) && self[2][0].approx_eq(&self[0][2]) &&
self[2][1].fuzzy_eq(&self[1][2]) self[2][1].approx_eq(&self[1][2])
} }
#[inline(always)] #[inline(always)]
fn is_invertible(&self) -> bool { fn is_invertible(&self) -> bool {
!self.determinant().fuzzy_eq(&zero()) !self.determinant().approx_eq(&zero())
} }
#[inline(always)] #[inline(always)]
@ -955,7 +960,7 @@ impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat<T, Vec3<T>> for Mat3<T> {
} }
} }
impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat3<T, Vec3<T>> for Mat3<T> { impl<T:Copy + Float + NumAssign> BaseMat3<T, Vec3<T>> for Mat3<T> {
/** /**
* Construct a 3 x 3 matrix * Construct a 3 x 3 matrix
* *
@ -1187,24 +1192,29 @@ impl<T:Copy> Index<uint, Vec3<T>> for Mat3<T> {
} }
} }
impl<T:Copy + Float + NumAssign + FuzzyEq<T>> Neg<Mat3<T>> for Mat3<T> { impl<T:Copy + Float + NumAssign> Neg<Mat3<T>> for Mat3<T> {
#[inline(always)] #[inline(always)]
fn neg(&self) -> Mat3<T> { fn neg(&self) -> Mat3<T> {
BaseMat3::from_cols(-self[0], -self[1], -self[2]) BaseMat3::from_cols(-self[0], -self[1], -self[2])
} }
} }
impl<T:Copy + Float + FuzzyEq<T>> FuzzyEq<T> for Mat3<T> { impl<T:Copy + Eq + ApproxEq<T>> ApproxEq<T> for Mat3<T> {
#[inline(always)] #[inline(always)]
fn fuzzy_eq(&self, other: &Mat3<T>) -> bool { fn approx_epsilon() -> T {
self.fuzzy_eq_eps(other, &num::cast(FUZZY_EPSILON)) ApproxEq::approx_epsilon::<T,T>()
} }
#[inline(always)] #[inline(always)]
fn fuzzy_eq_eps(&self, other: &Mat3<T>, epsilon: &T) -> bool { fn approx_eq(&self, other: &Mat3<T>) -> bool {
self[0].fuzzy_eq_eps(&other[0], epsilon) && self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
self[1].fuzzy_eq_eps(&other[1], epsilon) && }
self[2].fuzzy_eq_eps(&other[2], epsilon)
#[inline(always)]
fn approx_eq_eps(&self, other: &Mat3<T>, epsilon: &T) -> bool {
self[0].approx_eq_eps(&other[0], epsilon) &&
self[1].approx_eq_eps(&other[1], epsilon) &&
self[2].approx_eq_eps(&other[2], epsilon)
} }
} }
@ -1225,7 +1235,7 @@ impl<T:Copy + Float + FuzzyEq<T>> FuzzyEq<T> for Mat3<T> {
#[deriving(Eq)] #[deriving(Eq)]
pub struct Mat4<T> { x: Vec4<T>, y: Vec4<T>, z: Vec4<T>, w: Vec4<T> } pub struct Mat4<T> { x: Vec4<T>, y: Vec4<T>, z: Vec4<T>, w: Vec4<T> }
impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat<T, Vec4<T>> for Mat4<T> { impl<T:Copy + Float + NumAssign> BaseMat<T, Vec4<T>> for Mat4<T> {
#[inline(always)] #[inline(always)]
fn col(&self, i: uint) -> Vec4<T> { self[i] } fn col(&self, i: uint) -> Vec4<T> { self[i] }
@ -1397,7 +1407,7 @@ impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat<T, Vec4<T>> for Mat4<T> {
fn inverse(&self) -> Option<Mat4<T>> { fn inverse(&self) -> Option<Mat4<T>> {
let d = self.determinant(); let d = self.determinant();
if d.fuzzy_eq(&zero()) { if d.approx_eq(&zero()) {
None None
} else { } else {
@ -1446,7 +1456,7 @@ impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat<T, Vec4<T>> for Mat4<T> {
self[0][2], self[1][2], self[2][2], self[3][2], self[0][2], self[1][2], self[2][2], self[3][2],
self[0][3], self[1][3], self[2][3], self[3][3]) self[0][3], self[1][3], self[2][3], self[3][3])
} }
#[inline(always)] #[inline(always)]
fn col_mut<'a>(&'a mut self, i: uint) -> &'a mut Vec4<T> { fn col_mut<'a>(&'a mut self, i: uint) -> &'a mut Vec4<T> {
match i { match i {
@ -1539,55 +1549,55 @@ impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat<T, Vec4<T>> for Mat4<T> {
#[inline(always)] #[inline(always)]
fn is_identity(&self) -> bool { fn is_identity(&self) -> bool {
self.fuzzy_eq(&BaseMat::identity()) self.approx_eq(&BaseMat::identity())
} }
#[inline(always)] #[inline(always)]
fn is_diagonal(&self) -> bool { fn is_diagonal(&self) -> bool {
self[0][1].fuzzy_eq(&zero()) && self[0][1].approx_eq(&zero()) &&
self[0][2].fuzzy_eq(&zero()) && self[0][2].approx_eq(&zero()) &&
self[0][3].fuzzy_eq(&zero()) && self[0][3].approx_eq(&zero()) &&
self[1][0].fuzzy_eq(&zero()) && self[1][0].approx_eq(&zero()) &&
self[1][2].fuzzy_eq(&zero()) && self[1][2].approx_eq(&zero()) &&
self[1][3].fuzzy_eq(&zero()) && self[1][3].approx_eq(&zero()) &&
self[2][0].fuzzy_eq(&zero()) && self[2][0].approx_eq(&zero()) &&
self[2][1].fuzzy_eq(&zero()) && self[2][1].approx_eq(&zero()) &&
self[2][3].fuzzy_eq(&zero()) && self[2][3].approx_eq(&zero()) &&
self[3][0].fuzzy_eq(&zero()) && self[3][0].approx_eq(&zero()) &&
self[3][1].fuzzy_eq(&zero()) && self[3][1].approx_eq(&zero()) &&
self[3][2].fuzzy_eq(&zero()) self[3][2].approx_eq(&zero())
} }
#[inline(always)] #[inline(always)]
fn is_rotated(&self) -> bool { fn is_rotated(&self) -> bool {
!self.fuzzy_eq(&BaseMat::identity()) !self.approx_eq(&BaseMat::identity())
} }
#[inline(always)] #[inline(always)]
fn is_symmetric(&self) -> bool { fn is_symmetric(&self) -> bool {
self[0][1].fuzzy_eq(&self[1][0]) && self[0][1].approx_eq(&self[1][0]) &&
self[0][2].fuzzy_eq(&self[2][0]) && self[0][2].approx_eq(&self[2][0]) &&
self[0][3].fuzzy_eq(&self[3][0]) && self[0][3].approx_eq(&self[3][0]) &&
self[1][0].fuzzy_eq(&self[0][1]) && self[1][0].approx_eq(&self[0][1]) &&
self[1][2].fuzzy_eq(&self[2][1]) && self[1][2].approx_eq(&self[2][1]) &&
self[1][3].fuzzy_eq(&self[3][1]) && self[1][3].approx_eq(&self[3][1]) &&
self[2][0].fuzzy_eq(&self[0][2]) && self[2][0].approx_eq(&self[0][2]) &&
self[2][1].fuzzy_eq(&self[1][2]) && self[2][1].approx_eq(&self[1][2]) &&
self[2][3].fuzzy_eq(&self[3][2]) && self[2][3].approx_eq(&self[3][2]) &&
self[3][0].fuzzy_eq(&self[0][3]) && self[3][0].approx_eq(&self[0][3]) &&
self[3][1].fuzzy_eq(&self[1][3]) && self[3][1].approx_eq(&self[1][3]) &&
self[3][2].fuzzy_eq(&self[2][3]) self[3][2].approx_eq(&self[2][3])
} }
#[inline(always)] #[inline(always)]
fn is_invertible(&self) -> bool { fn is_invertible(&self) -> bool {
!self.determinant().fuzzy_eq(&zero()) !self.determinant().approx_eq(&zero())
} }
#[inline(always)] #[inline(always)]
@ -1596,7 +1606,7 @@ impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat<T, Vec4<T>> for Mat4<T> {
} }
} }
impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat4<T, Vec4<T>> for Mat4<T> { impl<T:Copy + Float + NumAssign> BaseMat4<T, Vec4<T>> for Mat4<T> {
/** /**
* Construct a 4 x 4 matrix * Construct a 4 x 4 matrix
* *
@ -1660,7 +1670,7 @@ impl<T:Copy + Float + NumAssign + FuzzyEq<T>> BaseMat4<T, Vec4<T>> for Mat4<T> {
} }
} }
impl<T:Copy + Float + NumAssign + FuzzyEq<T>> Neg<Mat4<T>> for Mat4<T> { impl<T:Copy + Float + NumAssign> Neg<Mat4<T>> for Mat4<T> {
#[inline(always)] #[inline(always)]
fn neg(&self) -> Mat4<T> { fn neg(&self) -> Mat4<T> {
BaseMat4::from_cols(-self[0], -self[1], -self[2], -self[3]) BaseMat4::from_cols(-self[0], -self[1], -self[2], -self[3])
@ -1674,17 +1684,22 @@ impl<T:Copy> Index<uint, Vec4<T>> for Mat4<T> {
} }
} }
impl<T:Copy + Float + FuzzyEq<T>> FuzzyEq<T> for Mat4<T> { impl<T:Copy + Eq + ApproxEq<T>> ApproxEq<T> for Mat4<T> {
#[inline(always)] #[inline(always)]
fn fuzzy_eq(&self, other: &Mat4<T>) -> bool { fn approx_epsilon() -> T {
self.fuzzy_eq_eps(other, &num::cast(FUZZY_EPSILON)) ApproxEq::approx_epsilon::<T,T>()
} }
#[inline(always)] #[inline(always)]
fn fuzzy_eq_eps(&self, other: &Mat4<T>, epsilon: &T) -> bool { fn approx_eq(&self, other: &Mat4<T>) -> bool {
self[0].fuzzy_eq_eps(&other[0], epsilon) && self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
self[1].fuzzy_eq_eps(&other[1], epsilon) && }
self[2].fuzzy_eq_eps(&other[2], epsilon) &&
self[3].fuzzy_eq_eps(&other[3], epsilon) #[inline(always)]
fn approx_eq_eps(&self, other: &Mat4<T>, epsilon: &T) -> bool {
self[0].approx_eq_eps(&other[0], epsilon) &&
self[1].approx_eq_eps(&other[1], epsilon) &&
self[2].approx_eq_eps(&other[2], epsilon) &&
self[3].approx_eq_eps(&other[3], epsilon)
} }
} }

View file

@ -1,5 +1,3 @@
use std::cmp::FuzzyEq;
use mat::{Mat4, BaseMat4}; use mat::{Mat4, BaseMat4};
use num::NumAssign; use num::NumAssign;
@ -13,7 +11,7 @@ use num::NumAssign;
* can be found [here](http://www.opengl.org/wiki/GluPerspective_code). * can be found [here](http://www.opengl.org/wiki/GluPerspective_code).
*/ */
#[inline(always)] #[inline(always)]
pub fn perspective<T:Copy + Float + NumAssign + FuzzyEq<T>>(fovy: T, aspectRatio: T, near: T, far: T) -> Mat4<T> { pub fn perspective<T:Copy + Float + NumAssign>(fovy: T, aspectRatio: T, near: T, far: T) -> Mat4<T> {
let _2: T = num::cast(2); let _2: T = num::cast(2);
let ymax = near * (fovy / _2).to_radians().tan(); let ymax = near * (fovy / _2).to_radians().tan();
@ -29,7 +27,7 @@ pub fn perspective<T:Copy + Float + NumAssign + FuzzyEq<T>>(fovy: T, aspectRatio
* (http://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml) function. * (http://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml) function.
*/ */
#[inline(always)] #[inline(always)]
pub fn frustum<T:Copy + Float + NumAssign + FuzzyEq<T>>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4<T> { pub fn frustum<T:Copy + Float + NumAssign>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4<T> {
let _0: T = num::cast(0); let _0: T = num::cast(0);
let _1: T = num::cast(1); let _1: T = num::cast(1);
let _2: T = num::cast(2); let _2: T = num::cast(2);
@ -67,7 +65,7 @@ pub fn frustum<T:Copy + Float + NumAssign + FuzzyEq<T>>(left: T, right: T, botto
* (http://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml) function. * (http://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml) function.
*/ */
#[inline(always)] #[inline(always)]
pub fn ortho<T:Copy + Float + NumAssign + FuzzyEq<T>>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4<T> { pub fn ortho<T:Copy + Float + NumAssign>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4<T> {
let _0: T = num::cast(0); let _0: T = num::cast(0);
let _1: T = num::cast(1); let _1: T = num::cast(1);
let _2: T = num::cast(2); let _2: T = num::cast(2);

View file

@ -7,9 +7,9 @@
* Sir William Hamilton * Sir William Hamilton
*/ */
use core::cmp::ApproxEq;
use core::num::Zero::zero; use core::num::Zero::zero;
use core::num::One::one; use core::num::One::one;
use std::cmp::{FuzzyEq, FUZZY_EPSILON};
use mat::{Mat3, BaseMat3}; use mat::{Mat3, BaseMat3};
use vec::{Vec3, BaseVec3, AffineVec, NumVec, NumVec3}; use vec::{Vec3, BaseVec3, AffineVec, NumVec, NumVec3};
@ -31,7 +31,7 @@ use num::NumAssign;
#[deriving(Eq)] #[deriving(Eq)]
pub struct Quat<T> { s: T, v: Vec3<T> } pub struct Quat<T> { s: T, v: Vec3<T> }
pub impl<T:Copy + Float + NumAssign + FuzzyEq<T>> Quat<T> { pub impl<T:Copy + Float + NumAssign> Quat<T> {
/** /**
* Construct the quaternion from one scalar component and three * Construct the quaternion from one scalar component and three
* imaginary components * imaginary components
@ -377,24 +377,29 @@ impl<T:Copy> Index<uint, T> for Quat<T> {
} }
} }
impl<T:Copy + Float + NumAssign + FuzzyEq<T>> Neg<Quat<T>> for Quat<T> { impl<T:Copy + Float + NumAssign> Neg<Quat<T>> for Quat<T> {
#[inline(always)] #[inline(always)]
fn neg(&self) -> Quat<T> { fn neg(&self) -> Quat<T> {
Quat::new(-self[0], -self[1], -self[2], -self[3]) Quat::new(-self[0], -self[1], -self[2], -self[3])
} }
} }
impl<T:Copy + Float + FuzzyEq<T>> FuzzyEq<T> for Quat<T> { impl<T:Copy + Eq + ApproxEq<T>> ApproxEq<T> for Quat<T> {
#[inline(always)] #[inline(always)]
fn fuzzy_eq(&self, other: &Quat<T>) -> bool { fn approx_epsilon() -> T {
self.fuzzy_eq_eps(other, &num::cast(FUZZY_EPSILON)) ApproxEq::approx_epsilon::<T,T>()
} }
#[inline(always)] #[inline(always)]
fn fuzzy_eq_eps(&self, other: &Quat<T>, epsilon: &T) -> bool { fn approx_eq(&self, other: &Quat<T>) -> bool {
self[0].fuzzy_eq_eps(&other[0], epsilon) && self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
self[1].fuzzy_eq_eps(&other[1], epsilon) && }
self[2].fuzzy_eq_eps(&other[2], epsilon) &&
self[3].fuzzy_eq_eps(&other[3], epsilon) #[inline(always)]
fn approx_eq_eps(&self, other: &Quat<T>, epsilon: &T) -> bool {
self[0].approx_eq_eps(&other[0], epsilon) &&
self[1].approx_eq_eps(&other[1], epsilon) &&
self[2].approx_eq_eps(&other[2], epsilon) &&
self[3].approx_eq_eps(&other[3], epsilon)
} }
} }

View file

@ -1,6 +1,6 @@
use core::cmp::ApproxEq;
use core::num::Zero::zero; use core::num::Zero::zero;
use core::num::One::one; use core::num::One::one;
use std::cmp::{FuzzyEq, FUZZY_EPSILON};
use num::NumAssign; use num::NumAssign;
@ -24,7 +24,7 @@ pub trait BaseVec<T>: Index<uint,T> + Eq {
* A pointer to the first component of the vector * A pointer to the first component of the vector
*/ */
fn to_ptr(&self) -> *T; fn to_ptr(&self) -> *T;
/** /**
* Get a mutable reference to the component at `i` * Get a mutable reference to the component at `i`
*/ */
@ -126,7 +126,7 @@ pub trait NumVec<T>: BaseVec<T> + Neg<Self> {
* The dot product of the vector and `other` * The dot product of the vector and `other`
*/ */
fn dot(&self, other: &Self) -> T; fn dot(&self, other: &Self) -> T;
/** /**
* Negate the vector * Negate the vector
*/ */
@ -192,7 +192,7 @@ pub trait NumVec3<T>: NumVec<T> {
* The cross product of the vector and `other` * The cross product of the vector and `other`
*/ */
fn cross(&self, other: &Self) -> Self; fn cross(&self, other: &Self) -> Self;
/** /**
* Set to the cross product of the vector and `other` * Set to the cross product of the vector and `other`
*/ */
@ -286,7 +286,7 @@ pub trait AffineVec<T>: NumVec<T> {
* The intoperlated vector * The intoperlated vector
*/ */
fn lerp(&self, other: &Self, amount: T) -> Self; fn lerp(&self, other: &Self, amount: T) -> Self;
/** /**
* Normalize the vector * Normalize the vector
*/ */
@ -500,7 +500,7 @@ macro_rules! zip_assign(
($a:ident[] $method:ident $b:ident[] ..2) => ({ $a.index_mut(0).$method(&$b[0]); $a.index_mut(1).$method(&$b[1]); }); ($a:ident[] $method:ident $b:ident[] ..2) => ({ $a.index_mut(0).$method(&$b[0]); $a.index_mut(1).$method(&$b[1]); });
($a:ident[] $method:ident $b:ident[] ..3) => ({ zip_assign!($a[] $method $b[] ..2); $a.index_mut(2).$method(&$b[2]); }); ($a:ident[] $method:ident $b:ident[] ..3) => ({ zip_assign!($a[] $method $b[] ..2); $a.index_mut(2).$method(&$b[2]); });
($a:ident[] $method:ident $b:ident[] ..4) => ({ zip_assign!($a[] $method $b[] ..3); $a.index_mut(3).$method(&$b[3]); }); ($a:ident[] $method:ident $b:ident[] ..4) => ({ zip_assign!($a[] $method $b[] ..3); $a.index_mut(3).$method(&$b[3]); });
($a:ident[] $method:ident $b:ident ..2) => ({ $a.index_mut(0).$method(&$b); $a.index_mut(1).$method(&$b); }); ($a:ident[] $method:ident $b:ident ..2) => ({ $a.index_mut(0).$method(&$b); $a.index_mut(1).$method(&$b); });
($a:ident[] $method:ident $b:ident ..3) => ({ zip_assign!($a[] $method $b ..2); $a.index_mut(2).$method(&$b); }); ($a:ident[] $method:ident $b:ident ..3) => ({ zip_assign!($a[] $method $b ..2); $a.index_mut(2).$method(&$b); });
($a:ident[] $method:ident $b:ident ..4) => ({ zip_assign!($a[] $method $b ..3); $a.index_mut(3).$method(&$b); }); ($a:ident[] $method:ident $b:ident ..4) => ({ zip_assign!($a[] $method $b ..3); $a.index_mut(3).$method(&$b); });
@ -532,7 +532,7 @@ impl<T:Copy + Eq> BaseVec<T> for Vec2<T> {
fn to_ptr(&self) -> *T { fn to_ptr(&self) -> *T {
unsafe { cast::transmute(self) } unsafe { cast::transmute(self) }
} }
#[inline(always)] #[inline(always)]
fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T { fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T {
match i { match i {
@ -614,7 +614,7 @@ impl<T:Copy + Num + NumAssign> NumVec<T> for Vec2<T> {
self[0] * other[0] + self[0] * other[0] +
self[1] * other[1] self[1] * other[1]
} }
#[inline(always)] #[inline(always)]
fn neg_self(&mut self) { fn neg_self(&mut self) {
*self.index_mut(0) = -self[0]; *self.index_mut(0) = -self[0];
@ -723,7 +723,7 @@ impl<T:Copy + Real + NumAssign> AffineVec<T> for Vec2<T> {
fn lerp(&self, other: &Vec2<T>, amount: T) -> Vec2<T> { fn lerp(&self, other: &Vec2<T>, amount: T) -> Vec2<T> {
self.add_v(&other.sub_v(self).mul_t(amount)) self.add_v(&other.sub_v(self).mul_t(amount))
} }
#[inline(always)] #[inline(always)]
fn normalize_self(&mut self) { fn normalize_self(&mut self) {
let n = one::<T>() / self.length(); let n = one::<T>() / self.length();
@ -742,16 +742,21 @@ impl<T:Copy + Real + NumAssign> AffineVec<T> for Vec2<T> {
} }
} }
impl<T:Copy + NumCast + Eq + FuzzyEq<T>> FuzzyEq<T> for Vec2<T> { impl<T:Copy + Eq + ApproxEq<T>> ApproxEq<T> for Vec2<T> {
#[inline(always)] #[inline(always)]
fn fuzzy_eq(&self, other: &Vec2<T>) -> bool { fn approx_epsilon() -> T {
self.fuzzy_eq_eps(other, &num::cast(FUZZY_EPSILON)) ApproxEq::approx_epsilon::<T,T>()
} }
#[inline(always)] #[inline(always)]
fn fuzzy_eq_eps(&self, other: &Vec2<T>, epsilon: &T) -> bool { fn approx_eq(&self, other: &Vec2<T>) -> bool {
self[0].fuzzy_eq_eps(&other[0], epsilon) && self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
self[1].fuzzy_eq_eps(&other[1], epsilon) }
#[inline(always)]
fn approx_eq_eps(&self, other: &Vec2<T>, epsilon: &T) -> bool {
self[0].approx_eq_eps(&other[0], epsilon) &&
self[1].approx_eq_eps(&other[1], epsilon)
} }
} }
@ -833,7 +838,7 @@ impl<T:Copy + Eq> BaseVec<T> for Vec3<T> {
fn to_ptr(&self) -> *T { fn to_ptr(&self) -> *T {
unsafe { cast::transmute(self) } unsafe { cast::transmute(self) }
} }
#[inline(always)] #[inline(always)]
fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T { fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T {
match i { match i {
@ -918,7 +923,7 @@ impl<T:Copy + Num + NumAssign> NumVec<T> for Vec3<T> {
self[1] * other[1] + self[1] * other[1] +
self[2] * other[2] self[2] * other[2]
} }
#[inline(always)] #[inline(always)]
fn neg_self(&mut self) { fn neg_self(&mut self) {
*self.index_mut(0) = -self[0]; *self.index_mut(0) = -self[0];
@ -986,7 +991,7 @@ impl<T:Copy + Num> NumVec3<T> for Vec3<T> {
(self[2] * other[0]) - (self[0] * other[2]), (self[2] * other[0]) - (self[0] * other[2]),
(self[0] * other[1]) - (self[1] * other[0])) (self[0] * other[1]) - (self[1] * other[0]))
} }
#[inline(always)] #[inline(always)]
fn cross_self(&mut self, other: &Vec3<T>) { fn cross_self(&mut self, other: &Vec3<T>) {
*self = self.cross(other); *self = self.cross(other);
@ -1040,7 +1045,7 @@ impl<T:Copy + Real + NumAssign> AffineVec<T> for Vec3<T> {
fn lerp(&self, other: &Vec3<T>, amount: T) -> Vec3<T> { fn lerp(&self, other: &Vec3<T>, amount: T) -> Vec3<T> {
self.add_v(&other.sub_v(self).mul_t(amount)) self.add_v(&other.sub_v(self).mul_t(amount))
} }
#[inline(always)] #[inline(always)]
fn normalize_self(&mut self) { fn normalize_self(&mut self) {
let n = one::<T>() / self.length(); let n = one::<T>() / self.length();
@ -1059,17 +1064,22 @@ impl<T:Copy + Real + NumAssign> AffineVec<T> for Vec3<T> {
} }
} }
impl<T:Copy + NumCast + Eq + FuzzyEq<T>> FuzzyEq<T> for Vec3<T> { impl<T:Copy + Eq + ApproxEq<T>> ApproxEq<T> for Vec3<T> {
#[inline(always)] #[inline(always)]
fn fuzzy_eq(&self, other: &Vec3<T>) -> bool { fn approx_epsilon() -> T {
self.fuzzy_eq_eps(other, &num::cast(FUZZY_EPSILON)) ApproxEq::approx_epsilon::<T,T>()
} }
#[inline(always)] #[inline(always)]
fn fuzzy_eq_eps(&self, other: &Vec3<T>, epsilon: &T) -> bool { fn approx_eq(&self, other: &Vec3<T>) -> bool {
self[0].fuzzy_eq_eps(&other[0], epsilon) && self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
self[1].fuzzy_eq_eps(&other[1], epsilon) && }
self[2].fuzzy_eq_eps(&other[2], epsilon)
#[inline(always)]
fn approx_eq_eps(&self, other: &Vec3<T>, epsilon: &T) -> bool {
self[0].approx_eq_eps(&other[0], epsilon) &&
self[1].approx_eq_eps(&other[1], epsilon) &&
self[2].approx_eq_eps(&other[2], epsilon)
} }
} }
@ -1152,7 +1162,7 @@ impl<T:Copy + Eq> BaseVec<T> for Vec4<T> {
fn to_ptr(&self) -> *T { fn to_ptr(&self) -> *T {
unsafe { cast::transmute(self) } unsafe { cast::transmute(self) }
} }
#[inline(always)] #[inline(always)]
fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T { fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T {
match i { match i {
@ -1240,7 +1250,7 @@ impl<T:Copy + Num + NumAssign> NumVec<T> for Vec4<T> {
self[2] * other[2] + self[2] * other[2] +
self[3] * other[3] self[3] * other[3]
} }
#[inline(always)] #[inline(always)]
fn neg_self(&mut self) { fn neg_self(&mut self) {
*self.index_mut(0) = -self[0]; *self.index_mut(0) = -self[0];
@ -1349,7 +1359,7 @@ impl<T:Copy + Real + NumAssign> AffineVec<T> for Vec4<T> {
fn lerp(&self, other: &Vec4<T>, amount: T) -> Vec4<T> { fn lerp(&self, other: &Vec4<T>, amount: T) -> Vec4<T> {
self.add_v(&other.sub_v(self).mul_t(amount)) self.add_v(&other.sub_v(self).mul_t(amount))
} }
#[inline(always)] #[inline(always)]
fn normalize_self(&mut self) { fn normalize_self(&mut self) {
let n = one::<T>() / self.length(); let n = one::<T>() / self.length();
@ -1368,18 +1378,23 @@ impl<T:Copy + Real + NumAssign> AffineVec<T> for Vec4<T> {
} }
} }
impl<T:Copy + NumCast + Eq + FuzzyEq<T>> FuzzyEq<T> for Vec4<T> { impl<T:Copy + Eq + ApproxEq<T>> ApproxEq<T> for Vec4<T> {
#[inline(always)] #[inline(always)]
fn fuzzy_eq(&self, other: &Vec4<T>) -> bool { fn approx_epsilon() -> T {
self.fuzzy_eq_eps(other, &num::cast(FUZZY_EPSILON)) ApproxEq::approx_epsilon::<T,T>()
} }
#[inline(always)] #[inline(always)]
fn fuzzy_eq_eps(&self, other: &Vec4<T>, epsilon: &T) -> bool { fn approx_eq(&self, other: &Vec4<T>) -> bool {
self[0].fuzzy_eq_eps(&other[0], epsilon) && self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
self[1].fuzzy_eq_eps(&other[1], epsilon) && }
self[2].fuzzy_eq_eps(&other[2], epsilon) &&
self[3].fuzzy_eq_eps(&other[3], epsilon) #[inline(always)]
fn approx_eq_eps(&self, other: &Vec4<T>, epsilon: &T) -> bool {
self[0].approx_eq_eps(&other[0], epsilon) &&
self[1].approx_eq_eps(&other[1], epsilon) &&
self[2].approx_eq_eps(&other[2], epsilon) &&
self[3].approx_eq_eps(&other[3], epsilon)
} }
} }