diff --git a/Cargo.toml b/Cargo.toml index 933eac4..905eb68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ unstable = [] swizzle = [] [dependencies] -approx = "0.1" +approx = "0.2" mint = { version = "0.5", optional = true } num-traits = "0.2" rand = "0.4" diff --git a/src/angle.rs b/src/angle.rs index 1ab5938..188b90e 100644 --- a/src/angle.rs +++ b/src/angle.rs @@ -26,7 +26,7 @@ use num_traits::{cast, Bounded}; use structure::*; -use approx::ApproxEq; +use approx; use num::BaseFloat; /// An angle, in radians. @@ -170,7 +170,7 @@ macro_rules! impl_angle { fn div_assign(&mut self, scalar) { self.0 /= scalar; } }); - impl ApproxEq for $Angle { + impl approx::AbsDiffEq for $Angle { type Epsilon = S::Epsilon; #[inline] @@ -178,20 +178,29 @@ macro_rules! impl_angle { S::default_epsilon() } + #[inline] + fn abs_diff_eq(&self, other: &Self, epsilon: S::Epsilon) -> bool { + S::abs_diff_eq(&self.0, &other.0, epsilon) + } + } + + impl approx::RelativeEq for $Angle { #[inline] fn default_max_relative() -> S::Epsilon { S::default_max_relative() } - #[inline] - fn default_max_ulps() -> u32 { - S::default_max_ulps() - } - #[inline] fn relative_eq(&self, other: &Self, epsilon: S::Epsilon, max_relative: S::Epsilon) -> bool { S::relative_eq(&self.0, &other.0, epsilon, max_relative) } + } + + impl approx::UlpsEq for $Angle { + #[inline] + fn default_max_ulps() -> u32 { + S::default_max_ulps() + } #[inline] fn ulps_eq(&self, other: &Self, epsilon: S::Epsilon, max_ulps: u32) -> bool { diff --git a/src/euler.rs b/src/euler.rs index b3661fd..c5bfa31 100644 --- a/src/euler.rs +++ b/src/euler.rs @@ -19,7 +19,7 @@ use num_traits::cast; use structure::*; use angle::Rad; -use approx::ApproxEq; +use approx; use quaternion::Quaternion; #[cfg(feature = "mint")] use mint; @@ -141,7 +141,7 @@ impl From> for Euler> { } } -impl ApproxEq for Euler { +impl approx::AbsDiffEq for Euler { type Epsilon = A::Epsilon; #[inline] @@ -149,22 +149,33 @@ impl ApproxEq for Euler { A::default_epsilon() } + #[inline] + fn abs_diff_eq(&self, other: &Self, epsilon: A::Epsilon) -> bool { + A::abs_diff_eq(&self.x, &other.x, epsilon) + && A::abs_diff_eq(&self.y, &other.y, epsilon) + && A::abs_diff_eq(&self.z, &other.z, epsilon) + } +} + +impl approx::RelativeEq for Euler { #[inline] fn default_max_relative() -> A::Epsilon { A::default_max_relative() } - #[inline] - fn default_max_ulps() -> u32 { - A::default_max_ulps() - } - #[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) } +} + +impl approx::UlpsEq for Euler { + #[inline] + fn default_max_ulps() -> u32 { + A::default_max_ulps() + } #[inline] fn ulps_eq(&self, other: &Self, epsilon: A::Epsilon, max_ulps: u32) -> bool { diff --git a/src/matrix.rs b/src/matrix.rs index c5606d1..f000b4f 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -24,7 +24,7 @@ use std::ptr; use structure::*; use angle::Rad; -use approx::ApproxEq; +use approx; use euler::Euler; use num::BaseFloat; use point::{Point2, Point3}; @@ -831,7 +831,7 @@ impl SquareMatrix for Matrix4 { } } -impl ApproxEq for Matrix2 { +impl approx::AbsDiffEq for Matrix2 { type Epsilon = S::Epsilon; #[inline] @@ -839,21 +839,31 @@ impl ApproxEq for Matrix2 { cast(1.0e-6f64).unwrap() } + #[inline] + fn abs_diff_eq(&self, other: &Self, epsilon: S::Epsilon) -> bool { + Vector2::abs_diff_eq(&self[0], &other[0], epsilon) + && Vector2::abs_diff_eq(&self[1], &other[1], epsilon) + } +} + +impl approx::RelativeEq for Matrix2 { #[inline] fn default_max_relative() -> S::Epsilon { S::default_max_relative() } - #[inline] - fn default_max_ulps() -> u32 { - S::default_max_ulps() - } - #[inline] fn relative_eq(&self, other: &Self, epsilon: S::Epsilon, max_relative: S::Epsilon) -> bool { Vector2::relative_eq(&self[0], &other[0], epsilon, max_relative) && Vector2::relative_eq(&self[1], &other[1], epsilon, max_relative) } +} + +impl approx::UlpsEq for Matrix2 { + #[inline] + fn default_max_ulps() -> u32 { + S::default_max_ulps() + } #[inline] fn ulps_eq(&self, other: &Self, epsilon: S::Epsilon, max_ulps: u32) -> bool { @@ -862,7 +872,7 @@ impl ApproxEq for Matrix2 { } } -impl ApproxEq for Matrix3 { +impl approx::AbsDiffEq for Matrix3 { type Epsilon = S::Epsilon; #[inline] @@ -870,22 +880,33 @@ impl ApproxEq for Matrix3 { cast(1.0e-6f64).unwrap() } + #[inline] + fn abs_diff_eq(&self, other: &Self, epsilon: S::Epsilon) -> bool { + Vector3::abs_diff_eq(&self[0], &other[0], epsilon) + && Vector3::abs_diff_eq(&self[1], &other[1], epsilon) + && Vector3::abs_diff_eq(&self[2], &other[2], epsilon) + } +} + +impl approx::RelativeEq for Matrix3 { #[inline] fn default_max_relative() -> S::Epsilon { S::default_max_relative() } - #[inline] - fn default_max_ulps() -> u32 { - S::default_max_ulps() - } - #[inline] fn relative_eq(&self, other: &Self, epsilon: S::Epsilon, max_relative: S::Epsilon) -> bool { Vector3::relative_eq(&self[0], &other[0], epsilon, max_relative) && Vector3::relative_eq(&self[1], &other[1], epsilon, max_relative) && Vector3::relative_eq(&self[2], &other[2], epsilon, max_relative) } +} + +impl approx::UlpsEq for Matrix3 { + #[inline] + fn default_max_ulps() -> u32 { + S::default_max_ulps() + } #[inline] fn ulps_eq(&self, other: &Self, epsilon: S::Epsilon, max_ulps: u32) -> bool { @@ -895,7 +916,7 @@ impl ApproxEq for Matrix3 { } } -impl ApproxEq for Matrix4 { +impl approx::AbsDiffEq for Matrix4 { type Epsilon = S::Epsilon; #[inline] @@ -903,16 +924,21 @@ impl ApproxEq for Matrix4 { cast(1.0e-6f64).unwrap() } + #[inline] + fn abs_diff_eq(&self, other: &Self, epsilon: S::Epsilon) -> bool { + Vector4::abs_diff_eq(&self[0], &other[0], epsilon) + && Vector4::abs_diff_eq(&self[1], &other[1], epsilon) + && Vector4::abs_diff_eq(&self[2], &other[2], epsilon) + && Vector4::abs_diff_eq(&self[3], &other[3], epsilon) + } +} + +impl approx::RelativeEq for Matrix4 { #[inline] fn default_max_relative() -> S::Epsilon { S::default_max_relative() } - #[inline] - fn default_max_ulps() -> u32 { - S::default_max_ulps() - } - #[inline] fn relative_eq(&self, other: &Self, epsilon: S::Epsilon, max_relative: S::Epsilon) -> bool { Vector4::relative_eq(&self[0], &other[0], epsilon, max_relative) @@ -920,6 +946,13 @@ impl ApproxEq for Matrix4 { && Vector4::relative_eq(&self[2], &other[2], epsilon, max_relative) && Vector4::relative_eq(&self[3], &other[3], epsilon, max_relative) } +} + +impl approx::UlpsEq for Matrix4 { + #[inline] + fn default_max_ulps() -> u32 { + S::default_max_ulps() + } #[inline] fn ulps_eq(&self, other: &Self, epsilon: S::Epsilon, max_ulps: u32) -> bool { diff --git a/src/num.rs b/src/num.rs index bcf57f5..113a4f2 100644 --- a/src/num.rs +++ b/src/num.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use approx::ApproxEq; +use approx; use std::fmt; use std::ops::*; @@ -21,8 +21,8 @@ use std::ops::*; use num_traits::{Float, Num, NumCast}; /// Base numeric types with partial ordering -pub trait BaseNum - : Copy +pub trait BaseNum: + Copy + Clone + fmt::Debug + Num @@ -32,7 +32,8 @@ pub trait BaseNum + SubAssign + MulAssign + DivAssign - + RemAssign { + + RemAssign +{ } impl BaseNum for T @@ -52,10 +53,21 @@ where } /// Base floating point types -pub trait BaseFloat: BaseNum + Float + ApproxEq {} +pub trait BaseFloat: + BaseNum + + Float + + approx::AbsDiffEq + + approx::RelativeEq + + approx::UlpsEq +{ +} impl BaseFloat for T where - T: BaseNum + Float + ApproxEq, + T: BaseNum + + Float + + approx::AbsDiffEq + + approx::RelativeEq + + approx::UlpsEq, { } diff --git a/src/point.rs b/src/point.rs index 980d496..aef5e0c 100644 --- a/src/point.rs +++ b/src/point.rs @@ -24,7 +24,7 @@ use std::ops::*; use structure::*; -use approx::ApproxEq; +use approx; use num::{BaseFloat, BaseNum}; use vector::{Vector1, Vector2, Vector3, Vector4}; @@ -172,7 +172,7 @@ macro_rules! impl_point { } } - impl ApproxEq for $PointN { + impl approx::AbsDiffEq for $PointN { type Epsilon = S::Epsilon; #[inline] @@ -180,20 +180,31 @@ macro_rules! impl_point { S::default_epsilon() } + #[inline] + fn abs_diff_eq(&self, other: &Self, epsilon: S::Epsilon) + -> bool + { + $(S::abs_diff_eq(&self.$field, &other.$field, epsilon))&&+ + } + } + + impl approx::RelativeEq for $PointN { #[inline] fn default_max_relative() -> S::Epsilon { S::default_max_relative() } - #[inline] - fn default_max_ulps() -> u32 { - S::default_max_ulps() - } - #[inline] fn relative_eq(&self, other: &Self, epsilon: S::Epsilon, max_relative: S::Epsilon) -> bool { $(S::relative_eq(&self.$field, &other.$field, epsilon, max_relative))&&+ } + } + + impl approx::UlpsEq for $PointN { + #[inline] + fn default_max_ulps() -> u32 { + S::default_max_ulps() + } #[inline] fn ulps_eq(&self, other: &Self, epsilon: S::Epsilon, max_ulps: u32) -> bool { diff --git a/src/quaternion.rs b/src/quaternion.rs index 8723785..b2f01a4 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -23,7 +23,7 @@ use num_traits::{cast, NumCast}; use structure::*; use angle::Rad; -use approx::ApproxEq; +use approx; use euler::Euler; use matrix::{Matrix3, Matrix4}; use num::BaseFloat; @@ -587,7 +587,7 @@ impl_scalar_mul!(f64); impl_scalar_div!(f32); impl_scalar_div!(f64); -impl ApproxEq for Quaternion { +impl approx::AbsDiffEq for Quaternion { type Epsilon = S::Epsilon; #[inline] @@ -595,21 +595,31 @@ impl ApproxEq for Quaternion { S::default_epsilon() } + #[inline] + fn abs_diff_eq(&self, other: &Self, epsilon: S::Epsilon) -> bool { + S::abs_diff_eq(&self.s, &other.s, epsilon) + && Vector3::abs_diff_eq(&self.v, &other.v, epsilon) + } +} + +impl approx::RelativeEq for Quaternion { #[inline] fn default_max_relative() -> S::Epsilon { S::default_max_relative() } - #[inline] - fn default_max_ulps() -> u32 { - S::default_max_ulps() - } - #[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) } +} + +impl approx::UlpsEq for Quaternion { + #[inline] + fn default_max_ulps() -> u32 { + S::default_max_ulps() + } #[inline] fn ulps_eq(&self, other: &Self, epsilon: S::Epsilon, max_ulps: u32) -> bool { diff --git a/src/rotation.rs b/src/rotation.rs index 70344ec..86a6ea5 100644 --- a/src/rotation.rs +++ b/src/rotation.rs @@ -20,7 +20,7 @@ use std::ops::*; use structure::*; use angle::Rad; -use approx::ApproxEq; +use approx; use euler::Euler; use matrix::{Matrix2, Matrix3}; use num::BaseFloat; @@ -33,7 +33,9 @@ use vector::{Vector2, Vector3}; pub trait Rotation: Sized + Copy + One where // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 - Self: ApproxEq, + Self: approx::AbsDiffEq, + Self: approx::RelativeEq, + Self: approx::UlpsEq, P::Scalar: BaseFloat, Self: iter::Product, { @@ -113,7 +115,7 @@ pub trait Rotation3 /// use cgmath::Vector2; /// use cgmath::{Matrix, Matrix2}; /// use cgmath::{Rotation, Rotation2, Basis2}; -/// use cgmath::ApproxEq; +/// use cgmath::UlpsEq; /// use std::f64; /// /// // For simplicity, we will rotate the unit x vector to the unit y vector -- @@ -213,7 +215,7 @@ impl_operator!( Mul > for Basis2 { fn mul(lhs, rhs) -> Basis2 { Basis2 { mat: lhs.mat * rhs.mat } } }); -impl ApproxEq for Basis2 { +impl approx::AbsDiffEq for Basis2 { type Epsilon = S::Epsilon; #[inline] @@ -221,20 +223,29 @@ impl ApproxEq for Basis2 { S::default_epsilon() } + #[inline] + fn abs_diff_eq(&self, other: &Self, epsilon: S::Epsilon) -> bool { + Matrix2::abs_diff_eq(&self.mat, &other.mat, epsilon) + } +} + +impl approx::RelativeEq for Basis2 { #[inline] fn default_max_relative() -> S::Epsilon { S::default_max_relative() } - #[inline] - fn default_max_ulps() -> u32 { - S::default_max_ulps() - } - #[inline] fn relative_eq(&self, other: &Self, epsilon: S::Epsilon, max_relative: S::Epsilon) -> bool { Matrix2::relative_eq(&self.mat, &other.mat, epsilon, max_relative) } +} + +impl approx::UlpsEq for Basis2 { + #[inline] + fn default_max_ulps() -> u32 { + S::default_max_ulps() + } #[inline] fn ulps_eq(&self, other: &Self, epsilon: S::Epsilon, max_ulps: u32) -> bool { @@ -356,7 +367,7 @@ impl_operator!( Mul > for Basis3 { fn mul(lhs, rhs) -> Basis3 { Basis3 { mat: lhs.mat * rhs.mat } } }); -impl ApproxEq for Basis3 { +impl approx::AbsDiffEq for Basis3 { type Epsilon = S::Epsilon; #[inline] @@ -364,20 +375,29 @@ impl ApproxEq for Basis3 { S::default_epsilon() } + #[inline] + fn abs_diff_eq(&self, other: &Self, epsilon: S::Epsilon) -> bool { + Matrix3::abs_diff_eq(&self.mat, &other.mat, epsilon) + } +} + +impl approx::RelativeEq for Basis3 { #[inline] fn default_max_relative() -> S::Epsilon { S::default_max_relative() } - #[inline] - fn default_max_ulps() -> u32 { - S::default_max_ulps() - } - #[inline] fn relative_eq(&self, other: &Self, epsilon: S::Epsilon, max_relative: S::Epsilon) -> bool { Matrix3::relative_eq(&self.mat, &other.mat, epsilon, max_relative) } +} + +impl approx::UlpsEq for Basis3 { + #[inline] + fn default_max_ulps() -> u32 { + S::default_max_ulps() + } #[inline] fn ulps_eq(&self, other: &Self, epsilon: S::Epsilon, max_ulps: u32) -> bool { diff --git a/src/structure.rs b/src/structure.rs index 75eadeb..299d6f0 100644 --- a/src/structure.rs +++ b/src/structure.rs @@ -20,7 +20,7 @@ use std::cmp; use std::iter; use std::ops::*; -use approx::ApproxEq; +use approx; use angle::Rad; use num::{BaseFloat, BaseNum}; @@ -215,7 +215,9 @@ where // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 ::Scalar: BaseFloat, Self: MetricSpace::Scalar>, - Self: ApproxEq::Scalar>, + // Self: approx::AbsDiffEq::Scalar>, + // Self: approx::RelativeEq::Scalar>, + Self: approx::UlpsEq::Scalar>, { /// Vector dot (or inner) product. fn dot(self, other: Self) -> Self::Scalar; @@ -430,7 +432,9 @@ where // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 Self: Index::Column>, Self: IndexMut::Column>, - Self: ApproxEq::Scalar>, + Self: approx::AbsDiffEq::Scalar>, + Self: approx::RelativeEq::Scalar>, + Self: approx::UlpsEq::Scalar>, { /// The row vector of the matrix. type Row: VectorSpace + Array; @@ -570,7 +574,9 @@ where Self: Copy + Clone, Self: PartialEq + cmp::PartialOrd, // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 - Self: ApproxEq::Unitless>, + Self: approx::AbsDiffEq::Unitless>, + Self: approx::RelativeEq::Unitless>, + Self: approx::UlpsEq::Unitless>, Self: Zero, diff --git a/src/transform.rs b/src/transform.rs index 1d09358..f3d3113 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -15,7 +15,7 @@ use structure::*; -use approx::ApproxEq; +use approx; use matrix::{Matrix2, Matrix3, Matrix4}; use num::{BaseFloat, BaseNum}; use point::{Point2, Point3}; @@ -62,7 +62,7 @@ pub trait Transform: Sized { /// A generic transformation consisting of a rotation, /// displacement vector and scale amount. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq)] pub struct Decomposed { pub scale: V::Scalar, pub rot: R, @@ -163,11 +163,11 @@ impl> Transform2 for Decomposed, R> impl> Transform3 for Decomposed, R> {} -impl ApproxEq for Decomposed +impl approx::AbsDiffEq for Decomposed where - S: ApproxEq, - S::Scalar: ApproxEq, - R: ApproxEq, + S: approx::AbsDiffEq, + S::Scalar: approx::AbsDiffEq, + R: approx::AbsDiffEq, { type Epsilon = E; @@ -176,22 +176,43 @@ where E::default_epsilon() } + #[inline] + fn abs_diff_eq(&self, other: &Self, epsilon: E) -> bool { + S::Scalar::abs_diff_eq(&self.scale, &other.scale, epsilon) + && R::abs_diff_eq(&self.rot, &other.rot, epsilon) + && S::abs_diff_eq(&self.disp, &other.disp, epsilon) + } +} + +impl approx::RelativeEq for Decomposed +where + S: approx::RelativeEq, + S::Scalar: approx::RelativeEq, + R: approx::RelativeEq, +{ #[inline] fn default_max_relative() -> E { E::default_max_relative() } - #[inline] - fn default_max_ulps() -> u32 { - E::default_max_ulps() - } - #[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) } +} + +impl approx::UlpsEq for Decomposed +where + S: approx::UlpsEq, + S::Scalar: approx::UlpsEq, + R: approx::UlpsEq, +{ + #[inline] + fn default_max_ulps() -> u32 { + E::default_max_ulps() + } #[inline] fn ulps_eq(&self, other: &Self, epsilon: E, max_ulps: u32) -> bool { diff --git a/src/vector.rs b/src/vector.rs index 055c7e0..0e9da00 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -23,7 +23,7 @@ use std::ops::*; use structure::*; use angle::Rad; -use approx::ApproxEq; +use approx; use num::{BaseFloat, BaseNum}; #[cfg(feature = "simd")] @@ -206,7 +206,7 @@ macro_rules! impl_vector { fn neg(self) -> $VectorN { $VectorN::new($(-self.$field),+) } } - impl ApproxEq for $VectorN { + impl approx::AbsDiffEq for $VectorN { type Epsilon = S::Epsilon; #[inline] @@ -214,20 +214,29 @@ macro_rules! impl_vector { S::default_epsilon() } + #[inline] + fn abs_diff_eq(&self, other: &Self, epsilon: S::Epsilon) -> bool { + $(S::abs_diff_eq(&self.$field, &other.$field, epsilon))&&+ + } + } + + impl approx::RelativeEq for $VectorN { #[inline] fn default_max_relative() -> S::Epsilon { S::default_max_relative() } - #[inline] - fn default_max_ulps() -> u32 { - S::default_max_ulps() - } - #[inline] fn relative_eq(&self, other: &Self, epsilon: S::Epsilon, max_relative: S::Epsilon) -> bool { $(S::relative_eq(&self.$field, &other.$field, epsilon, max_relative))&&+ } + } + + impl approx::UlpsEq for $VectorN { + #[inline] + fn default_max_ulps() -> u32 { + S::default_max_ulps() + } #[inline] fn ulps_eq(&self, other: &Self, epsilon: S::Epsilon, max_ulps: u32) -> bool { @@ -452,7 +461,7 @@ macro_rules! impl_vector_default { default fn neg(self) -> $VectorN { $VectorN::new($(-self.$field),+) } } - impl ApproxEq for $VectorN { + impl approx::AbsDiffEq for $VectorN { type Epsilon = S::Epsilon; #[inline] @@ -460,20 +469,29 @@ macro_rules! impl_vector_default { S::default_epsilon() } + #[inline] + fn abs_diff_eq(&self, other: &Self, epsilon: S::Epsilon) -> bool { + $(S::abs_diff_eq(&self.$field, &other.$field, epsilon))&&+ + } + } + + impl approx::RelativeEq for $VectorN { #[inline] fn default_max_relative() -> S::Epsilon { S::default_max_relative() } - #[inline] - fn default_max_ulps() -> u32 { - S::default_max_ulps() - } - #[inline] fn relative_eq(&self, other: &Self, epsilon: S::Epsilon, max_relative: S::Epsilon) -> bool { $(S::relative_eq(&self.$field, &other.$field, epsilon, max_relative))&&+ } + } + + impl approx::UlpsEq for $VectorN { + #[inline] + fn default_max_ulps() -> u32 { + S::default_max_ulps() + } #[inline] fn ulps_eq(&self, other: &Self, epsilon: S::Epsilon, max_ulps: u32) -> bool {