Update to approx 0.2.

This commit is contained in:
sebcrozet 2018-05-19 15:41:58 +02:00 committed by Sébastien Crozet
parent 118227d6b9
commit 88055dfc45
10 changed files with 314 additions and 126 deletions

View File

@ -1,12 +1,12 @@
use num::Zero; use num::Zero;
use num_complex::Complex; use num_complex::Complex;
use std::cmp::Ordering; use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use std::marker::PhantomData;
use std::fmt;
use std::any::TypeId; use std::any::TypeId;
use std::cmp::Ordering;
use std::fmt;
use std::marker::PhantomData;
use std::mem; use std::mem;
use approx::ApproxEq;
#[cfg(feature = "serde-serialize")] #[cfg(feature = "serde-serialize")]
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
@ -16,13 +16,14 @@ use abomonation::Abomonation;
use alga::general::{Real, Ring}; use alga::general::{Real, Ring};
use core::{DefaultAllocator, MatrixMN, MatrixN, Scalar, Unit, VectorN};
use core::dimension::{Dim, DimAdd, DimSum, U1, U2, U3};
use core::constraint::{DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
use core::iter::{MatrixIter, MatrixIterMut};
use core::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR}; use core::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR};
use core::storage::{ContiguousStorage, ContiguousStorageMut, Owned, SameShapeStorage, Storage, use core::constraint::{DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
StorageMut}; use core::dimension::{Dim, DimAdd, DimSum, U1, U2, U3};
use core::iter::{MatrixIter, MatrixIterMut};
use core::storage::{
ContiguousStorage, ContiguousStorageMut, Owned, SameShapeStorage, Storage, StorageMut,
};
use core::{DefaultAllocator, MatrixMN, MatrixN, Scalar, Unit, VectorN};
/// A square matrix. /// A square matrix.
pub type SquareMatrix<N, D, S> = Matrix<N, D, D, S>; pub type SquareMatrix<N, D, S> = Matrix<N, D, D, S>;
@ -80,7 +81,8 @@ pub struct Matrix<N: Scalar, R: Dim, C: Dim, S> {
impl<N: Scalar, R: Dim, C: Dim, S: fmt::Debug> fmt::Debug for Matrix<N, R, C, S> { impl<N: Scalar, R: Dim, C: Dim, S: fmt::Debug> fmt::Debug for Matrix<N, R, C, S> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.debug_struct("Matrix") formatter
.debug_struct("Matrix")
.field("data", &self.data) .field("data", &self.data)
.finish() .finish()
} }
@ -224,7 +226,7 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
/// Tests whether `self` and `rhs` are equal up to a given epsilon. /// Tests whether `self` and `rhs` are equal up to a given epsilon.
/// ///
/// See `relative_eq` from the `ApproxEq` trait for more details. /// See `relative_eq` from the `RelativeEq` trait for more details.
#[inline] #[inline]
pub fn relative_eq<R2, C2, SB>( pub fn relative_eq<R2, C2, SB>(
&self, &self,
@ -233,7 +235,7 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
max_relative: N::Epsilon, max_relative: N::Epsilon,
) -> bool ) -> bool
where where
N: ApproxEq, N: RelativeEq,
R2: Dim, R2: Dim,
C2: Dim, C2: Dim,
SB: Storage<N, R2, C2>, SB: Storage<N, R2, C2>,
@ -740,9 +742,9 @@ impl<N: Scalar + Zero, D: DimAdd<U1>, S: Storage<N, D>> Vector<N, D, S> {
} }
} }
impl<N, R: Dim, C: Dim, S> ApproxEq for Matrix<N, R, C, S> impl<N, R: Dim, C: Dim, S> AbsDiffEq for Matrix<N, R, C, S>
where where
N: Scalar + ApproxEq, N: Scalar + AbsDiffEq,
S: Storage<N, R, C>, S: Storage<N, R, C>,
N::Epsilon: Copy, N::Epsilon: Copy,
{ {
@ -754,13 +756,22 @@ where
} }
#[inline] #[inline]
fn default_max_relative() -> Self::Epsilon { fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
N::default_max_relative() self.iter()
.zip(other.iter())
.all(|(a, b)| a.abs_diff_eq(b, epsilon))
}
} }
impl<N, R: Dim, C: Dim, S> RelativeEq for Matrix<N, R, C, S>
where
N: Scalar + RelativeEq,
S: Storage<N, R, C>,
N::Epsilon: Copy,
{
#[inline] #[inline]
fn default_max_ulps() -> u32 { fn default_max_relative() -> Self::Epsilon {
N::default_max_ulps() N::default_max_relative()
} }
#[inline] #[inline]
@ -772,6 +783,18 @@ where
) -> bool { ) -> bool {
self.relative_eq(other, epsilon, max_relative) self.relative_eq(other, epsilon, max_relative)
} }
}
impl<N, R: Dim, C: Dim, S> UlpsEq for Matrix<N, R, C, S>
where
N: Scalar + UlpsEq,
S: Storage<N, R, C>,
N::Epsilon: Copy,
{
#[inline]
fn default_max_ulps() -> u32 {
N::default_max_ulps()
}
#[inline] #[inline]
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
@ -1165,9 +1188,9 @@ impl<N: Real, R: Dim, C: Dim, S: StorageMut<N, R, C>> Matrix<N, R, C, S> {
} }
} }
impl<N, R: Dim, C: Dim, S> ApproxEq for Unit<Matrix<N, R, C, S>> impl<N, R: Dim, C: Dim, S> AbsDiffEq for Unit<Matrix<N, R, C, S>>
where where
N: Scalar + ApproxEq, N: Scalar + AbsDiffEq,
S: Storage<N, R, C>, S: Storage<N, R, C>,
N::Epsilon: Copy, N::Epsilon: Copy,
{ {
@ -1179,13 +1202,20 @@ where
} }
#[inline] #[inline]
fn default_max_relative() -> Self::Epsilon { fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
N::default_max_relative() self.as_ref().abs_diff_eq(other.as_ref(), epsilon)
}
} }
impl<N, R: Dim, C: Dim, S> RelativeEq for Unit<Matrix<N, R, C, S>>
where
N: Scalar + RelativeEq,
S: Storage<N, R, C>,
N::Epsilon: Copy,
{
#[inline] #[inline]
fn default_max_ulps() -> u32 { fn default_max_relative() -> Self::Epsilon {
N::default_max_ulps() N::default_max_relative()
} }
#[inline] #[inline]
@ -1198,6 +1228,18 @@ where
self.as_ref() self.as_ref()
.relative_eq(other.as_ref(), epsilon, max_relative) .relative_eq(other.as_ref(), epsilon, max_relative)
} }
}
impl<N, R: Dim, C: Dim, S> UlpsEq for Unit<Matrix<N, R, C, S>>
where
N: Scalar + UlpsEq,
S: Storage<N, R, C>,
N::Epsilon: Copy,
{
#[inline]
fn default_max_ulps() -> u32 {
N::default_max_ulps()
}
#[inline] #[inline]
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {

View File

@ -1,13 +1,13 @@
// Matrix properties checks. // Matrix properties checks.
use approx::RelativeEq;
use num::{One, Zero}; use num::{One, Zero};
use approx::ApproxEq;
use alga::general::{ClosedAdd, ClosedMul, Real}; use alga::general::{ClosedAdd, ClosedMul, Real};
use core::{DefaultAllocator, Matrix, Scalar, SquareMatrix}; use core::allocator::Allocator;
use core::dimension::{Dim, DimMin}; use core::dimension::{Dim, DimMin};
use core::storage::Storage; use core::storage::Storage;
use core::allocator::Allocator; use core::{DefaultAllocator, Matrix, Scalar, SquareMatrix};
impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> { impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
/// Indicates if this is a square matrix. /// Indicates if this is a square matrix.
@ -24,7 +24,7 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
nrows == ncols nrows == ncols
} }
// FIXME: ApproxEq prevents us from using those methods on integer matrices… // FIXME: RelativeEq prevents us from using those methods on integer matrices…
/// Indicated if this is the identity matrix within a relative error of `eps`. /// Indicated if this is the identity matrix within a relative error of `eps`.
/// ///
/// If the matrix is diagonal, this checks that diagonal elements (i.e. at coordinates `(i, i)` /// If the matrix is diagonal, this checks that diagonal elements (i.e. at coordinates `(i, i)`
@ -32,7 +32,7 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
#[inline] #[inline]
pub fn is_identity(&self, eps: N::Epsilon) -> bool pub fn is_identity(&self, eps: N::Epsilon) -> bool
where where
N: Zero + One + ApproxEq, N: Zero + One + RelativeEq,
N::Epsilon: Copy, N::Epsilon: Copy,
{ {
let (nrows, ncols) = self.shape(); let (nrows, ncols) = self.shape();
@ -90,7 +90,7 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
#[inline] #[inline]
pub fn is_orthogonal(&self, eps: N::Epsilon) -> bool pub fn is_orthogonal(&self, eps: N::Epsilon) -> bool
where where
N: Zero + One + ClosedAdd + ClosedMul + ApproxEq, N: Zero + One + ClosedAdd + ClosedMul + RelativeEq,
S: Storage<N, R, C>, S: Storage<N, R, C>,
N::Epsilon: Copy, N::Epsilon: Copy,
DefaultAllocator: Allocator<N, C, C>, DefaultAllocator: Allocator<N, C, C>,

View File

@ -1,6 +1,6 @@
use approx::RelativeEq;
use std::mem; use std::mem;
use std::ops::{Deref, Neg}; use std::ops::{Deref, Neg};
use approx::ApproxEq;
#[cfg(feature = "serde-serialize")] #[cfg(feature = "serde-serialize")]
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
@ -138,7 +138,7 @@ impl<T> AsRef<T> for Unit<T> {
*/ */
impl<T: NormedSpace> SubsetOf<T> for Unit<T> impl<T: NormedSpace> SubsetOf<T> for Unit<T>
where where
T::Field: ApproxEq, T::Field: RelativeEq,
{ {
#[inline] #[inline]
fn to_superset(&self) -> T { fn to_superset(&self) -> T {
@ -156,7 +156,7 @@ where
} }
} }
// impl<T: ApproxEq> ApproxEq for Unit<T> { // impl<T: RelativeEq> RelativeEq for Unit<T> {
// type Epsilon = T::Epsilon; // type Epsilon = T::Epsilon;
// //
// #[inline] // #[inline]

View File

@ -1,7 +1,7 @@
use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use std::fmt; use std::fmt;
use std::hash; use std::hash;
use std::marker::PhantomData; use std::marker::PhantomData;
use approx::ApproxEq;
#[cfg(feature = "serde-serialize")] #[cfg(feature = "serde-serialize")]
use serde; use serde;
@ -12,24 +12,36 @@ use abomonation::Abomonation;
use alga::general::{Real, SubsetOf}; use alga::general::{Real, SubsetOf};
use alga::linear::Rotation; use alga::linear::Rotation;
use core::{DefaultAllocator, MatrixN}; use core::allocator::Allocator;
use core::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use core::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use core::storage::Owned; use core::storage::Owned;
use core::allocator::Allocator; use core::{DefaultAllocator, MatrixN};
use geometry::{Point, Translation}; use geometry::{Point, Translation};
/// A direct isometry, i.e., a rotation followed by a translation. /// A direct isometry, i.e., a rotation followed by a translation.
#[repr(C)] #[repr(C)]
#[derive(Debug)] #[derive(Debug)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde-serialize", #[cfg_attr(
serde(bound(serialize = "R: serde::Serialize, feature = "serde-serialize",
serde(
bound(
serialize = "R: serde::Serialize,
DefaultAllocator: Allocator<N, D>, DefaultAllocator: Allocator<N, D>,
Owned<N, D>: serde::Serialize")))] Owned<N, D>: serde::Serialize"
#[cfg_attr(feature = "serde-serialize", )
serde(bound(deserialize = "R: serde::Deserialize<'de>, )
)]
#[cfg_attr(
feature = "serde-serialize",
serde(
bound(
deserialize = "R: serde::Deserialize<'de>,
DefaultAllocator: Allocator<N, D>, DefaultAllocator: Allocator<N, D>,
Owned<N, D>: serde::Deserialize<'de>")))] Owned<N, D>: serde::Deserialize<'de>"
)
)
)]
pub struct Isometry<N: Real, D: DimName, R> pub struct Isometry<N: Real, D: DimName, R>
where where
DefaultAllocator: Allocator<N, D>, DefaultAllocator: Allocator<N, D>,
@ -201,9 +213,9 @@ where
} }
} }
impl<N: Real, D: DimName, R> ApproxEq for Isometry<N, D, R> impl<N: Real, D: DimName, R> AbsDiffEq for Isometry<N, D, R>
where where
R: Rotation<Point<N, D>> + ApproxEq<Epsilon = N::Epsilon>, R: Rotation<Point<N, D>> + AbsDiffEq<Epsilon = N::Epsilon>,
DefaultAllocator: Allocator<N, D>, DefaultAllocator: Allocator<N, D>,
N::Epsilon: Copy, N::Epsilon: Copy,
{ {
@ -215,13 +227,21 @@ where
} }
#[inline] #[inline]
fn default_max_relative() -> Self::Epsilon { fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
N::default_max_relative() self.translation.abs_diff_eq(&other.translation, epsilon)
&& self.rotation.abs_diff_eq(&other.rotation, epsilon)
}
} }
impl<N: Real, D: DimName, R> RelativeEq for Isometry<N, D, R>
where
R: Rotation<Point<N, D>> + RelativeEq<Epsilon = N::Epsilon>,
DefaultAllocator: Allocator<N, D>,
N::Epsilon: Copy,
{
#[inline] #[inline]
fn default_max_ulps() -> u32 { fn default_max_relative() -> Self::Epsilon {
N::default_max_ulps() N::default_max_relative()
} }
#[inline] #[inline]
@ -236,6 +256,18 @@ where
&& self.rotation && self.rotation
.relative_eq(&other.rotation, epsilon, max_relative) .relative_eq(&other.rotation, epsilon, max_relative)
} }
}
impl<N: Real, D: DimName, R> UlpsEq for Isometry<N, D, R>
where
R: Rotation<Point<N, D>> + UlpsEq<Epsilon = N::Epsilon>,
DefaultAllocator: Allocator<N, D>,
N::Epsilon: Copy,
{
#[inline]
fn default_max_ulps() -> u32 {
N::default_max_ulps()
}
#[inline] #[inline]
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {

View File

@ -1,8 +1,8 @@
use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use num::One; use num::One;
use std::hash;
use std::fmt;
use std::cmp::Ordering; use std::cmp::Ordering;
use approx::ApproxEq; use std::fmt;
use std::hash;
#[cfg(feature = "serde-serialize")] #[cfg(feature = "serde-serialize")]
use serde; use serde;
@ -10,10 +10,10 @@ use serde;
#[cfg(feature = "abomonation-serialize")] #[cfg(feature = "abomonation-serialize")]
use abomonation::Abomonation; use abomonation::Abomonation;
use core::{DefaultAllocator, Scalar, VectorN};
use core::iter::{MatrixIter, MatrixIterMut};
use core::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use core::allocator::Allocator; use core::allocator::Allocator;
use core::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use core::iter::{MatrixIter, MatrixIterMut};
use core::{DefaultAllocator, Scalar, VectorN};
/// A point in a n-dimensional euclidean space. /// A point in a n-dimensional euclidean space.
#[repr(C)] #[repr(C)]
@ -183,7 +183,7 @@ where
} }
} }
impl<N: Scalar + ApproxEq, D: DimName> ApproxEq for Point<N, D> impl<N: Scalar + AbsDiffEq, D: DimName> AbsDiffEq for Point<N, D>
where where
DefaultAllocator: Allocator<N, D>, DefaultAllocator: Allocator<N, D>,
N::Epsilon: Copy, N::Epsilon: Copy,
@ -196,13 +196,19 @@ where
} }
#[inline] #[inline]
fn default_max_relative() -> Self::Epsilon { fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
N::default_max_relative() self.coords.abs_diff_eq(&other.coords, epsilon)
}
} }
impl<N: Scalar + RelativeEq, D: DimName> RelativeEq for Point<N, D>
where
DefaultAllocator: Allocator<N, D>,
N::Epsilon: Copy,
{
#[inline] #[inline]
fn default_max_ulps() -> u32 { fn default_max_relative() -> Self::Epsilon {
N::default_max_ulps() N::default_max_relative()
} }
#[inline] #[inline]
@ -215,6 +221,17 @@ where
self.coords self.coords
.relative_eq(&other.coords, epsilon, max_relative) .relative_eq(&other.coords, epsilon, max_relative)
} }
}
impl<N: Scalar + UlpsEq, D: DimName> UlpsEq for Point<N, D>
where
DefaultAllocator: Allocator<N, D>,
N::Epsilon: Copy,
{
#[inline]
fn default_max_ulps() -> u32 {
N::default_max_ulps()
}
#[inline] #[inline]
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {

View File

@ -1,21 +1,21 @@
use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use num::Zero;
use std::fmt; use std::fmt;
use std::hash; use std::hash;
use num::Zero;
use approx::ApproxEq;
#[cfg(feature = "serde-serialize")]
use serde;
#[cfg(feature = "serde-serialize")] #[cfg(feature = "serde-serialize")]
use core::storage::Owned; use core::storage::Owned;
#[cfg(feature = "serde-serialize")]
use serde;
#[cfg(feature = "abomonation-serialize")] #[cfg(feature = "abomonation-serialize")]
use abomonation::Abomonation; use abomonation::Abomonation;
use alga::general::Real; use alga::general::Real;
use core::{Matrix3, MatrixN, MatrixSlice, MatrixSliceMut, Unit, Vector3, Vector4};
use core::dimension::{U1, U3, U4}; use core::dimension::{U1, U3, U4};
use core::storage::{CStride, RStride}; use core::storage::{CStride, RStride};
use core::{Matrix3, MatrixN, MatrixSlice, MatrixSliceMut, Unit, Vector3, Vector4};
use geometry::Rotation; use geometry::Rotation;
@ -281,7 +281,7 @@ impl<N: Real> Quaternion<N> {
} }
} }
impl<N: Real + ApproxEq<Epsilon = N>> ApproxEq for Quaternion<N> { impl<N: Real + AbsDiffEq<Epsilon = N>> AbsDiffEq for Quaternion<N> {
type Epsilon = N; type Epsilon = N;
#[inline] #[inline]
@ -290,13 +290,17 @@ impl<N: Real + ApproxEq<Epsilon = N>> ApproxEq for Quaternion<N> {
} }
#[inline] #[inline]
fn default_max_relative() -> Self::Epsilon { fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
N::default_max_relative() self.as_vector().abs_diff_eq(other.as_vector(), epsilon) ||
// Account for the double-covering of S², i.e. q = -q
self.as_vector().iter().zip(other.as_vector().iter()).all(|(a, b)| a.abs_diff_eq(&-*b, epsilon))
}
} }
impl<N: Real + RelativeEq<Epsilon = N>> RelativeEq for Quaternion<N> {
#[inline] #[inline]
fn default_max_ulps() -> u32 { fn default_max_relative() -> Self::Epsilon {
N::default_max_ulps() N::default_max_relative()
} }
#[inline] #[inline]
@ -310,6 +314,13 @@ impl<N: Real + ApproxEq<Epsilon = N>> ApproxEq for Quaternion<N> {
// Account for the double-covering of S², i.e. q = -q // Account for the double-covering of S², i.e. q = -q
self.as_vector().iter().zip(other.as_vector().iter()).all(|(a, b)| a.relative_eq(&-*b, epsilon, max_relative)) self.as_vector().iter().zip(other.as_vector().iter()).all(|(a, b)| a.relative_eq(&-*b, epsilon, max_relative))
} }
}
impl<N: Real + UlpsEq<Epsilon = N>> UlpsEq for Quaternion<N> {
#[inline]
fn default_max_ulps() -> u32 {
N::default_max_ulps()
}
#[inline] #[inline]
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
@ -613,7 +624,7 @@ impl<N: Real + fmt::Display> fmt::Display for UnitQuaternion<N> {
} }
} }
impl<N: Real + ApproxEq<Epsilon = N>> ApproxEq for UnitQuaternion<N> { impl<N: Real + AbsDiffEq<Epsilon = N>> AbsDiffEq for UnitQuaternion<N> {
type Epsilon = N; type Epsilon = N;
#[inline] #[inline]
@ -622,13 +633,15 @@ impl<N: Real + ApproxEq<Epsilon = N>> ApproxEq for UnitQuaternion<N> {
} }
#[inline] #[inline]
fn default_max_relative() -> Self::Epsilon { fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
N::default_max_relative() self.as_ref().abs_diff_eq(other.as_ref(), epsilon)
}
} }
impl<N: Real + RelativeEq<Epsilon = N>> RelativeEq for UnitQuaternion<N> {
#[inline] #[inline]
fn default_max_ulps() -> u32 { fn default_max_relative() -> Self::Epsilon {
N::default_max_ulps() N::default_max_relative()
} }
#[inline] #[inline]
@ -641,6 +654,13 @@ impl<N: Real + ApproxEq<Epsilon = N>> ApproxEq for UnitQuaternion<N> {
self.as_ref() self.as_ref()
.relative_eq(other.as_ref(), epsilon, max_relative) .relative_eq(other.as_ref(), epsilon, max_relative)
} }
}
impl<N: Real + UlpsEq<Epsilon = N>> UlpsEq for UnitQuaternion<N> {
#[inline]
fn default_max_ulps() -> u32 {
N::default_max_ulps()
}
#[inline] #[inline]
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {

View File

@ -1,7 +1,7 @@
use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use num::{One, Zero}; use num::{One, Zero};
use std::hash;
use std::fmt; use std::fmt;
use approx::ApproxEq; use std::hash;
#[cfg(feature = "serde-serialize")] #[cfg(feature = "serde-serialize")]
use serde; use serde;
@ -14,9 +14,9 @@ use abomonation::Abomonation;
use alga::general::Real; use alga::general::Real;
use core::{DefaultAllocator, MatrixN, Scalar};
use core::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use core::allocator::Allocator; use core::allocator::Allocator;
use core::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use core::{DefaultAllocator, MatrixN, Scalar};
/// A rotation matrix. /// A rotation matrix.
#[repr(C)] #[repr(C)]
@ -201,9 +201,9 @@ where
} }
} }
impl<N, D: DimName> ApproxEq for Rotation<N, D> impl<N, D: DimName> AbsDiffEq for Rotation<N, D>
where where
N: Scalar + ApproxEq, N: Scalar + AbsDiffEq,
DefaultAllocator: Allocator<N, D, D>, DefaultAllocator: Allocator<N, D, D>,
N::Epsilon: Copy, N::Epsilon: Copy,
{ {
@ -215,13 +215,20 @@ where
} }
#[inline] #[inline]
fn default_max_relative() -> Self::Epsilon { fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
N::default_max_relative() self.matrix.abs_diff_eq(&other.matrix, epsilon)
}
} }
impl<N, D: DimName> RelativeEq for Rotation<N, D>
where
N: Scalar + RelativeEq,
DefaultAllocator: Allocator<N, D, D>,
N::Epsilon: Copy,
{
#[inline] #[inline]
fn default_max_ulps() -> u32 { fn default_max_relative() -> Self::Epsilon {
N::default_max_ulps() N::default_max_relative()
} }
#[inline] #[inline]
@ -234,6 +241,18 @@ where
self.matrix self.matrix
.relative_eq(&other.matrix, epsilon, max_relative) .relative_eq(&other.matrix, epsilon, max_relative)
} }
}
impl<N, D: DimName> UlpsEq for Rotation<N, D>
where
N: Scalar + UlpsEq,
DefaultAllocator: Allocator<N, D, D>,
N::Epsilon: Copy,
{
#[inline]
fn default_max_ulps() -> u32 {
N::default_max_ulps()
}
#[inline] #[inline]
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {

View File

@ -1,6 +1,6 @@
use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use std::fmt; use std::fmt;
use std::hash; use std::hash;
use approx::ApproxEq;
#[cfg(feature = "serde-serialize")] #[cfg(feature = "serde-serialize")]
use serde; use serde;
@ -11,26 +11,38 @@ use abomonation::Abomonation;
use alga::general::{Real, SubsetOf}; use alga::general::{Real, SubsetOf};
use alga::linear::Rotation; use alga::linear::Rotation;
use core::{DefaultAllocator, MatrixN}; use core::allocator::Allocator;
use core::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use core::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use core::storage::Owned; use core::storage::Owned;
use core::allocator::Allocator; use core::{DefaultAllocator, MatrixN};
use geometry::{Isometry, Point, Translation}; use geometry::{Isometry, Point, Translation};
/// A similarity, i.e., an uniform scaling, followed by a rotation, followed by a translation. /// A similarity, i.e., an uniform scaling, followed by a rotation, followed by a translation.
#[repr(C)] #[repr(C)]
#[derive(Debug)] #[derive(Debug)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde-serialize", #[cfg_attr(
serde(bound(serialize = "N: serde::Serialize, feature = "serde-serialize",
serde(
bound(
serialize = "N: serde::Serialize,
R: serde::Serialize, R: serde::Serialize,
DefaultAllocator: Allocator<N, D>, DefaultAllocator: Allocator<N, D>,
Owned<N, D>: serde::Serialize")))] Owned<N, D>: serde::Serialize"
#[cfg_attr(feature = "serde-serialize", )
serde(bound(deserialize = "N: serde::Deserialize<'de>, )
)]
#[cfg_attr(
feature = "serde-serialize",
serde(
bound(
deserialize = "N: serde::Deserialize<'de>,
R: serde::Deserialize<'de>, R: serde::Deserialize<'de>,
DefaultAllocator: Allocator<N, D>, DefaultAllocator: Allocator<N, D>,
Owned<N, D>: serde::Deserialize<'de>")))] Owned<N, D>: serde::Deserialize<'de>"
)
)
)]
pub struct Similarity<N: Real, D: DimName, R> pub struct Similarity<N: Real, D: DimName, R>
where where
DefaultAllocator: Allocator<N, D>, DefaultAllocator: Allocator<N, D>,
@ -276,9 +288,9 @@ where
} }
} }
impl<N: Real, D: DimName, R> ApproxEq for Similarity<N, D, R> impl<N: Real, D: DimName, R> AbsDiffEq for Similarity<N, D, R>
where where
R: Rotation<Point<N, D>> + ApproxEq<Epsilon = N::Epsilon>, R: Rotation<Point<N, D>> + AbsDiffEq<Epsilon = N::Epsilon>,
DefaultAllocator: Allocator<N, D>, DefaultAllocator: Allocator<N, D>,
N::Epsilon: Copy, N::Epsilon: Copy,
{ {
@ -290,13 +302,21 @@ where
} }
#[inline] #[inline]
fn default_max_relative() -> Self::Epsilon { fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
N::default_max_relative() self.isometry.abs_diff_eq(&other.isometry, epsilon)
&& self.scaling.abs_diff_eq(&other.scaling, epsilon)
}
} }
impl<N: Real, D: DimName, R> RelativeEq for Similarity<N, D, R>
where
R: Rotation<Point<N, D>> + RelativeEq<Epsilon = N::Epsilon>,
DefaultAllocator: Allocator<N, D>,
N::Epsilon: Copy,
{
#[inline] #[inline]
fn default_max_ulps() -> u32 { fn default_max_relative() -> Self::Epsilon {
N::default_max_ulps() N::default_max_relative()
} }
#[inline] #[inline]
@ -311,6 +331,18 @@ where
&& self.scaling && self.scaling
.relative_eq(&other.scaling, epsilon, max_relative) .relative_eq(&other.scaling, epsilon, max_relative)
} }
}
impl<N: Real, D: DimName, R> UlpsEq for Similarity<N, D, R>
where
R: Rotation<Point<N, D>> + UlpsEq<Epsilon = N::Epsilon>,
DefaultAllocator: Allocator<N, D>,
N::Epsilon: Copy,
{
#[inline]
fn default_max_ulps() -> u32 {
N::default_max_ulps()
}
#[inline] #[inline]
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {

View File

@ -1,7 +1,7 @@
use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use num::{One, Zero}; use num::{One, Zero};
use std::hash;
use std::fmt; use std::fmt;
use approx::ApproxEq; use std::hash;
#[cfg(feature = "serde-serialize")] #[cfg(feature = "serde-serialize")]
use serde; use serde;
@ -11,10 +11,10 @@ use abomonation::Abomonation;
use alga::general::{ClosedNeg, Real}; use alga::general::{ClosedNeg, Real};
use core::{DefaultAllocator, MatrixN, Scalar, VectorN}; use core::allocator::Allocator;
use core::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use core::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use core::storage::Owned; use core::storage::Owned;
use core::allocator::Allocator; use core::{DefaultAllocator, MatrixN, Scalar, VectorN};
/// A translation. /// A translation.
#[repr(C)] #[repr(C)]
@ -167,7 +167,7 @@ where
} }
} }
impl<N: Scalar + ApproxEq, D: DimName> ApproxEq for Translation<N, D> impl<N: Scalar + AbsDiffEq, D: DimName> AbsDiffEq for Translation<N, D>
where where
DefaultAllocator: Allocator<N, D>, DefaultAllocator: Allocator<N, D>,
N::Epsilon: Copy, N::Epsilon: Copy,
@ -180,13 +180,19 @@ where
} }
#[inline] #[inline]
fn default_max_relative() -> Self::Epsilon { fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
N::default_max_relative() self.vector.abs_diff_eq(&other.vector, epsilon)
}
} }
impl<N: Scalar + RelativeEq, D: DimName> RelativeEq for Translation<N, D>
where
DefaultAllocator: Allocator<N, D>,
N::Epsilon: Copy,
{
#[inline] #[inline]
fn default_max_ulps() -> u32 { fn default_max_relative() -> Self::Epsilon {
N::default_max_ulps() N::default_max_relative()
} }
#[inline] #[inline]
@ -199,6 +205,17 @@ where
self.vector self.vector
.relative_eq(&other.vector, epsilon, max_relative) .relative_eq(&other.vector, epsilon, max_relative)
} }
}
impl<N: Scalar + UlpsEq, D: DimName> UlpsEq for Translation<N, D>
where
DefaultAllocator: Allocator<N, D>,
N::Epsilon: Copy,
{
#[inline]
fn default_max_ulps() -> u32 {
N::default_max_ulps()
}
#[inline] #[inline]
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {

View File

@ -1,6 +1,6 @@
use std::fmt; use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use approx::ApproxEq;
use num_complex::Complex; use num_complex::Complex;
use std::fmt;
use alga::general::Real; use alga::general::Real;
use core::{Matrix2, Matrix3, Unit, Vector1}; use core::{Matrix2, Matrix3, Unit, Vector1};
@ -129,7 +129,7 @@ impl<N: Real + fmt::Display> fmt::Display for UnitComplex<N> {
} }
} }
impl<N: Real> ApproxEq for UnitComplex<N> { impl<N: Real> AbsDiffEq for UnitComplex<N> {
type Epsilon = N; type Epsilon = N;
#[inline] #[inline]
@ -138,13 +138,15 @@ impl<N: Real> ApproxEq for UnitComplex<N> {
} }
#[inline] #[inline]
fn default_max_relative() -> Self::Epsilon { fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
N::default_max_relative() self.re.abs_diff_eq(&other.re, epsilon) && self.im.abs_diff_eq(&other.im, epsilon)
}
} }
impl<N: Real> RelativeEq for UnitComplex<N> {
#[inline] #[inline]
fn default_max_ulps() -> u32 { fn default_max_relative() -> Self::Epsilon {
N::default_max_ulps() N::default_max_relative()
} }
#[inline] #[inline]
@ -157,6 +159,13 @@ impl<N: Real> ApproxEq for UnitComplex<N> {
self.re.relative_eq(&other.re, epsilon, max_relative) self.re.relative_eq(&other.re, epsilon, max_relative)
&& self.im.relative_eq(&other.im, epsilon, max_relative) && self.im.relative_eq(&other.im, epsilon, max_relative)
} }
}
impl<N: Real> UlpsEq for UnitComplex<N> {
#[inline]
fn default_max_ulps() -> u32 {
N::default_max_ulps()
}
#[inline] #[inline]
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {