Add the ApproxEq trait.

It is no longer part of std::num
This commit is contained in:
Sébastien Crozet 2014-01-09 20:48:30 +01:00
parent 31904cad6f
commit f5b0b76d8d
19 changed files with 171 additions and 129 deletions

View File

@ -4,8 +4,9 @@ use std::num::{Zero, One};
pub use traits::{
Absolute,
AbsoluteRotate,
AlgebraicVec,
AlgebraicVecExt,
ApproxEq,
RealVec,
RealVecExt,
Basis,
Cast,
Col,
@ -431,19 +432,19 @@ pub fn sub_dot<V: Dot<N>, N>(a: &V, b: &V, c: &V) -> N {
/// Computes the L2 norm of a vector.
#[inline(always)]
pub fn norm<V: Norm<N>, N: Algebraic>(v: &V) -> N {
pub fn norm<V: Norm<N>, N: Real>(v: &V) -> N {
Norm::norm(v)
}
/// Computes the squared L2 norm of a vector.
#[inline(always)]
pub fn sqnorm<V: Norm<N>, N: Algebraic>(v: &V) -> N {
pub fn sqnorm<V: Norm<N>, N: Real>(v: &V) -> N {
Norm::sqnorm(v)
}
/// Gets the normalized version of a vector.
#[inline(always)]
pub fn normalize<V: Norm<N>, N: Algebraic>(v: &V) -> V {
pub fn normalize<V: Norm<N>, N: Real>(v: &V) -> V {
Norm::normalize_cpy(v)
}
@ -508,6 +509,21 @@ pub fn sample_sphere<V: UniformSphereSample>(f: |V| -> ()) {
//
//
/*
* AproxEq<N>
*/
/// Tests approximate equality.
#[inline(always)]
pub fn approx_eq<T: ApproxEq<N>, N>(a: &T, b: &T) -> bool {
ApproxEq::approx_eq(a, b)
}
/// Tests approximate equality using a custom epsilon.
#[inline(always)]
pub fn approx_eq_eps<T: ApproxEq<N>, N>(a: &T, b: &T, eps: &N) -> bool {
ApproxEq::approx_eq_eps(a, b, eps)
}
/*
* Absolute<A>

View File

@ -6,7 +6,7 @@ use std::rand::Rand;
use std::rand;
use std::num::{One, Zero};
use std::vec;
use std::cmp::ApproxEq;
use traits::operations::ApproxEq;
use std::util;
use structs::dvec::{DVec, DVecMulRhs};
use traits::operations::{Inv, Transpose, Mean, Cov};
@ -499,25 +499,22 @@ impl<N: Clone + Num + Cast<f32> + DMatDivRhs<N, DMat<N>> + ToStr > Cov<DMat<N>>
impl<N: ApproxEq<N>> ApproxEq<N> for DMat<N> {
#[inline]
fn approx_epsilon() -> N {
fail!("This function cannot work due to a compiler bug.")
// let res: N = ApproxEq::<N>::approx_epsilon();
// res
fn approx_epsilon(_: Option<DMat<N>>) -> N {
ApproxEq::approx_epsilon(None::<N>)
}
#[inline]
fn approx_eq(&self, other: &DMat<N>) -> bool {
let mut zip = self.mij.iter().zip(other.mij.iter());
fn approx_eq(a: &DMat<N>, b: &DMat<N>) -> bool {
let mut zip = a.mij.iter().zip(b.mij.iter());
zip.all(|(a, b)| a.approx_eq(b))
zip.all(|(a, b)| ApproxEq::approx_eq(a, b))
}
#[inline]
fn approx_eq_eps(&self, other: &DMat<N>, epsilon: &N) -> bool {
let mut zip = self.mij.iter().zip(other.mij.iter());
fn approx_eq_eps(a: &DMat<N>, b: &DMat<N>, epsilon: &N) -> bool {
let mut zip = a.mij.iter().zip(b.mij.iter());
zip.all(|(a, b)| a.approx_eq_eps(b, epsilon))
zip.all(|(a, b)| ApproxEq::approx_eq_eps(a, b, epsilon))
}
}

View File

@ -2,12 +2,12 @@
#[allow(missing_doc)]; // we hide doc to not have to document the $trhs double dispatch trait.
use std::num::{Zero, One, Algebraic};
use std::num::{Zero, One, Real};
use std::rand::Rand;
use std::rand;
use std::vec;
use std::vec::{VecIterator, VecMutIterator};
use std::cmp::ApproxEq;
use traits::operations::ApproxEq;
use std::iter::FromIterator;
use traits::geometry::{Dot, Norm};
use traits::structure::{Iterable, IterableMut};
@ -177,7 +177,7 @@ impl<N> FromIterator<N> for DVec<N> {
}
}
impl<N: Clone + Num + Algebraic + ApproxEq<N> + DVecMulRhs<N, DVec<N>>> DVec<N> {
impl<N: Clone + Num + Real + ApproxEq<N> + DVecMulRhs<N, DVec<N>>> DVec<N> {
/// Computes the canonical basis for the given dimension. A canonical basis is a set of
/// vectors, mutually orthogonal, with all its component equal to 0.0 exept one which is equal
/// to 1.0.
@ -220,7 +220,7 @@ impl<N: Clone + Num + Algebraic + ApproxEq<N> + DVecMulRhs<N, DVec<N>>> DVec<N>
elt = elt - v * Dot::dot(&elt, v)
};
if !Norm::sqnorm(&elt).approx_eq(&Zero::zero()) {
if !ApproxEq::approx_eq(&Norm::sqnorm(&elt), &Zero::zero()) {
res.push(Norm::normalize_cpy(&elt));
}
}
@ -284,7 +284,7 @@ impl<N: Num + Clone> Dot<N> for DVec<N> {
}
}
impl<N: Num + Algebraic + Clone> Norm<N> for DVec<N> {
impl<N: Num + Real + Clone> Norm<N> for DVec<N> {
#[inline]
fn sqnorm(v: &DVec<N>) -> N {
Dot::dot(v, v)
@ -318,25 +318,22 @@ impl<N: Num + Algebraic + Clone> Norm<N> for DVec<N> {
impl<N: ApproxEq<N>> ApproxEq<N> for DVec<N> {
#[inline]
fn approx_epsilon() -> N {
fail!("Fix me.")
// let res: N = ApproxEq::<N>::approx_epsilon();
// res
fn approx_epsilon(_: Option<DVec<N>>) -> N {
ApproxEq::approx_epsilon(None::<N>)
}
#[inline]
fn approx_eq(&self, other: &DVec<N>) -> bool {
let mut zip = self.at.iter().zip(other.at.iter());
fn approx_eq(a: &DVec<N>, b: &DVec<N>) -> bool {
let mut zip = a.at.iter().zip(b.at.iter());
zip.all(|(a, b)| a.approx_eq(b))
zip.all(|(a, b)| ApproxEq::approx_eq(a, b))
}
#[inline]
fn approx_eq_eps(&self, other: &DVec<N>, epsilon: &N) -> bool {
let mut zip = self.at.iter().zip(other.at.iter());
fn approx_eq_eps(a: &DVec<N>, b: &DVec<N>, epsilon: &N) -> bool {
let mut zip = a.at.iter().zip(b.at.iter());
zip.all(|(a, b)| a.approx_eq_eps(b, epsilon))
zip.all(|(a, b)| ApproxEq::approx_eq_eps(a, b, epsilon))
}
}

View File

@ -6,7 +6,7 @@ use std::num::{Zero, One};
use std::rand::{Rand, Rng};
use structs::mat::{Mat3, Mat4, Mat5};
use traits::structure::{Cast, Dim, Col};
use traits::operations::{Inv};
use traits::operations::{Inv, ApproxEq};
use traits::geometry::{RotationMatrix, Rotation, Rotate, AbsoluteRotate, Transform, Transformation,
Translate, Translation, ToHomogeneous};
@ -51,7 +51,7 @@ pub struct Iso4<N> {
translation: Vec4<N>
}
impl<N: Clone + Num + Algebraic> Iso3<N> {
impl<N: Clone + Num + Real> Iso3<N> {
/// Reorient and translate this transformation such that its local `x` axis points to a given
/// direction. Note that the usually known `look_at` function does the same thing but with the
/// `z` axis. See `look_at_z` for that.

View File

@ -2,7 +2,7 @@
macro_rules! iso_impl(
($t: ident, $submat: ident, $subvec: ident, $subrotvec: ident) => (
impl<N: Clone + Trigonometric + Algebraic + Num> $t<N> {
impl<N: Clone + Real + Real + Num> $t<N> {
/// Creates a new isometry from a rotation matrix and a vector.
#[inline]
pub fn new(translation: $subvec<N>, rotation: $subrotvec<N>) -> $t<N> {
@ -26,7 +26,7 @@ macro_rules! iso_impl(
macro_rules! rotation_matrix_impl(
($t: ident, $trot: ident, $tlv: ident, $tav: ident) => (
impl<N: Cast<f32> + Algebraic + Trigonometric + Num + Clone>
impl<N: Cast<f32> + Real + Real + Num + Clone>
RotationMatrix<$tlv<N>, $tav<N>, $trot<N>> for $t<N> {
#[inline]
fn to_rot_mat(&self) -> $trot<N> {
@ -50,7 +50,7 @@ macro_rules! dim_impl(
macro_rules! one_impl(
($t: ident) => (
impl<N: Trigonometric + Algebraic + Num + Clone> One for $t<N> {
impl<N: Real + Real + Num + Clone> One for $t<N> {
#[inline]
fn one() -> $t<N> {
$t::new_with_rotmat(Zero::zero(), One::one())
@ -61,7 +61,7 @@ macro_rules! one_impl(
macro_rules! iso_mul_iso_impl(
($t: ident, $tmul: ident) => (
impl<N: Num + Trigonometric + Algebraic + Clone> $tmul<N, $t<N>> for $t<N> {
impl<N: Num + Real + Real + Clone> $tmul<N, $t<N>> for $t<N> {
#[inline]
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
$t::new_with_rotmat(
@ -96,7 +96,7 @@ macro_rules! vec_mul_iso_impl(
macro_rules! translation_impl(
($t: ident, $tv: ident) => (
impl<N: Trigonometric + Num + Algebraic + Clone> Translation<$tv<N>> for $t<N> {
impl<N: Real + Num + Real + Clone> Translation<$tv<N>> for $t<N> {
#[inline]
fn translation(&self) -> $tv<N> {
self.translation.clone()
@ -153,7 +153,7 @@ macro_rules! translate_impl(
macro_rules! rotation_impl(
($t: ident, $trot: ident, $tav: ident) => (
impl<N: Cast<f32> + Num + Trigonometric + Algebraic + Clone> Rotation<$tav<N>> for $t<N> {
impl<N: Cast<f32> + Num + Real + Real + Clone> Rotation<$tav<N>> for $t<N> {
#[inline]
fn rotation(&self) -> $tav<N> {
self.rotation.rotation()
@ -220,7 +220,7 @@ macro_rules! rotate_impl(
macro_rules! transformation_impl(
($t: ident) => (
impl<N: Num + Trigonometric + Algebraic + Clone> Transformation<$t<N>> for $t<N> {
impl<N: Num + Real + Real + Clone> Transformation<$t<N>> for $t<N> {
fn transformation(&self) -> $t<N> {
self.clone()
}
@ -315,21 +315,20 @@ macro_rules! approx_eq_impl(
($t: ident) => (
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
#[inline]
fn approx_epsilon() -> N {
fail!("approx_epsilon is broken since rust revision 8693943676487c01fa09f5f3daf0df6a1f71e24d.")
// ApproxEq::<N>::approx_epsilon()
fn approx_epsilon(_: Option<$t<N>>) -> N {
ApproxEq::approx_epsilon(None::<N>)
}
#[inline]
fn approx_eq(&self, other: &$t<N>) -> bool {
self.rotation.approx_eq(&other.rotation) &&
self.translation.approx_eq(&other.translation)
fn approx_eq(a: &$t<N>, b: &$t<N>) -> bool {
ApproxEq::approx_eq(&a.rotation, &b.rotation) &&
ApproxEq::approx_eq(&a.translation, &b.translation)
}
#[inline]
fn approx_eq_eps(&self, other: &$t<N>, epsilon: &N) -> bool {
self.rotation.approx_eq_eps(&other.rotation, epsilon) &&
self.translation.approx_eq_eps(&other.translation, epsilon)
fn approx_eq_eps(a: &$t<N>, b: &$t<N>, epsilon: &N) -> bool {
ApproxEq::approx_eq_eps(&a.rotation, &b.rotation, epsilon) &&
ApproxEq::approx_eq_eps(&a.translation, &b.translation, epsilon)
}
}
)
@ -337,7 +336,7 @@ macro_rules! approx_eq_impl(
macro_rules! rand_impl(
($t: ident) => (
impl<N: Rand + Clone + Trigonometric + Algebraic + Num> Rand for $t<N> {
impl<N: Rand + Clone + Real + Real + Num> Rand for $t<N> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> $t<N> {
$t::new(rng.gen(), rng.gen())

View File

@ -4,7 +4,7 @@
use std::cast;
use std::num::{One, Zero};
use std::cmp::ApproxEq;
use traits::operations::ApproxEq;
use std::vec::{VecIterator, VecMutIterator};
use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, Vec1MulRhs, Vec4MulRhs,
Vec5MulRhs, Vec6MulRhs};

View File

@ -449,23 +449,22 @@ macro_rules! approx_eq_impl(
($t: ident) => (
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
#[inline]
fn approx_epsilon() -> N {
fail!("approx_epsilon is broken since rust revision 8693943676487c01fa09f5f3daf0df6a1f71e24d.")
// ApproxEq::<N>::approx_epsilon()
fn approx_epsilon(_: Option<$t<N>>) -> N {
ApproxEq::approx_epsilon(None::<N>)
}
#[inline]
fn approx_eq(&self, other: &$t<N>) -> bool {
let mut zip = self.iter().zip(other.iter());
fn approx_eq(a: &$t<N>, b: &$t<N>) -> bool {
let mut zip = a.iter().zip(b.iter());
zip.all(|(a, b)| a.approx_eq(b))
zip.all(|(a, b)| ApproxEq::approx_eq(a, b))
}
#[inline]
fn approx_eq_eps(&self, other: &$t<N>, epsilon: &N) -> bool {
let mut zip = self.iter().zip(other.iter());
fn approx_eq_eps(a: &$t<N>, b: &$t<N>, epsilon: &N) -> bool {
let mut zip = a.iter().zip(b.iter());
zip.all(|(a, b)| a.approx_eq_eps(b, epsilon))
zip.all(|(a, b)| ApproxEq::approx_eq_eps(a, b, epsilon))
}
}
)

View File

@ -7,7 +7,7 @@ use std::rand::{Rand, Rng};
use traits::geometry::{Rotate, Rotation, AbsoluteRotate, RotationMatrix, Transform, ToHomogeneous,
Norm, Cross};
use traits::structure::{Cast, Dim, Row, Col};
use traits::operations::{Absolute, Inv, Transpose};
use traits::operations::{Absolute, Inv, Transpose, ApproxEq};
use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec2MulRhs, Vec3MulRhs, Vec4MulRhs};
use structs::mat::{Mat2, Mat3, Mat4, Mat5};
@ -20,7 +20,7 @@ pub struct Rot2<N> {
priv submat: Mat2<N>
}
impl<N: Clone + Trigonometric + Neg<N>> Rot2<N> {
impl<N: Clone + Real + Neg<N>> Rot2<N> {
/// Builds a 2 dimensional rotation matrix from an angle in radian.
pub fn new(angle: Vec1<N>) -> Rot2<N> {
let (sia, coa) = angle.x.sin_cos();
@ -31,7 +31,7 @@ impl<N: Clone + Trigonometric + Neg<N>> Rot2<N> {
}
}
impl<N: Trigonometric + Num + Clone>
impl<N: Real + Num + Clone>
Rotation<Vec1<N>> for Rot2<N> {
#[inline]
fn rotation(&self) -> Vec1<N> {
@ -69,7 +69,7 @@ Rotation<Vec1<N>> for Rot2<N> {
}
}
impl<N: Clone + Rand + Trigonometric + Neg<N>> Rand for Rot2<N> {
impl<N: Clone + Rand + Real + Neg<N>> Rand for Rot2<N> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Rot2<N> {
Rot2::new(rng.gen())
@ -99,7 +99,7 @@ pub struct Rot3<N> {
}
impl<N: Clone + Trigonometric + Num + Algebraic> Rot3<N> {
impl<N: Clone + Real + Num + Real> Rot3<N> {
/// Builds a 3 dimensional rotation matrix from an axis and an angle.
///
/// # Arguments
@ -140,7 +140,7 @@ impl<N: Clone + Trigonometric + Num + Algebraic> Rot3<N> {
}
}
impl<N: Clone + Num + Algebraic> Rot3<N> {
impl<N: Clone + Num + Real> Rot3<N> {
/// Reorient this matrix such that its local `x` axis points to a given point. Note that the
/// usually known `look_at` function does the same thing but with the `z` axis. See `look_at_z`
/// for that.
@ -180,7 +180,7 @@ impl<N: Clone + Num + Algebraic> Rot3<N> {
}
}
impl<N: Clone + Trigonometric + Num + Algebraic + Cast<f32>>
impl<N: Clone + Real + Num + Real + Cast<f32>>
Rotation<Vec3<N>> for Rot3<N> {
#[inline]
fn rotation(&self) -> Vec3<N> {
@ -245,7 +245,7 @@ Rotation<Vec3<N>> for Rot3<N> {
}
}
impl<N: Clone + Rand + Trigonometric + Num + Algebraic>
impl<N: Clone + Rand + Real + Num + Real>
Rand for Rot3<N> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Rot3<N> {
@ -309,7 +309,7 @@ impl<N: Signed> AbsoluteRotate<Vec4<N>> for Rot4<N> {
}
}
impl<N: Trigonometric + Num + Clone>
impl<N: Real + Num + Clone>
Rotation<Vec4<N>> for Rot4<N> {
#[inline]
fn rotation(&self) -> Vec4<N> {

View File

@ -56,7 +56,7 @@ macro_rules! dim_impl(
macro_rules! rotation_matrix_impl(
($t: ident, $tlv: ident, $tav: ident) => (
impl<N: Cast<f32> + Algebraic + Trigonometric + Num + Clone>
impl<N: Cast<f32> + Real + Real + Num + Clone>
RotationMatrix<$tlv<N>, $tav<N>, $t<N>> for $t<N> {
#[inline]
fn to_rot_mat(&self) -> $t<N> {
@ -201,19 +201,18 @@ macro_rules! approx_eq_impl(
($t: ident) => (
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
#[inline]
fn approx_epsilon() -> N {
// ApproxEq::<N>::approx_epsilon()
fail!("approx_epsilon is broken since rust revision 8693943676487c01fa09f5f3daf0df6a1f71e24d.")
fn approx_epsilon(_: Option<$t<N>>) -> N {
ApproxEq::approx_epsilon(None::<N>)
}
#[inline]
fn approx_eq(&self, other: &$t<N>) -> bool {
self.submat.approx_eq(&other.submat)
fn approx_eq(a: &$t<N>, b: &$t<N>) -> bool {
ApproxEq::approx_eq(&a.submat, &b.submat)
}
#[inline]
fn approx_eq_eps(&self, other: &$t<N>, epsilon: &N) -> bool {
self.submat.approx_eq_eps(&other.submat, epsilon)
fn approx_eq_eps(a: &$t<N>, b: &$t<N>, epsilon: &N) -> bool {
ApproxEq::approx_eq_eps(&a.submat, &b.submat, epsilon)
}
}
)

View File

@ -91,7 +91,7 @@ impl<N: Clone + One + Zero + Neg<N>> Basis for Vec2<N> {
}
}
impl<N: Clone + Ord + Algebraic + Signed> Basis for Vec3<N> {
impl<N: Clone + Ord + Real + Signed> Basis for Vec3<N> {
#[inline(always)]
fn canonical_basis(f: |Vec3<N>| -> bool) {
if !f(Vec3::new(One::one(), Zero::zero(), Zero::zero())) { return };

View File

@ -1,8 +1,8 @@
use std::cast;
use std::num::{Zero, One, Algebraic, Bounded};
use std::num::{Zero, One, Real, Bounded};
use std::vec::{VecIterator, VecMutIterator};
use std::iter::{Iterator, FromIterator};
use std::cmp::ApproxEq;
use traits::operations::ApproxEq;
use traits::structure::{Iterable, IterableMut, Indexable, Basis, Dim};
use traits::geometry::{Translation, Dot, Norm};
use structs::vec;
@ -159,7 +159,7 @@ impl<N: Clone + Add<N, N> + Neg<N>> Translation<vec::Vec0<N>> for vec::Vec0<N> {
}
}
impl<N: Clone + Num + Algebraic> Norm<N> for vec::Vec0<N> {
impl<N: Clone + Num + Real> Norm<N> for vec::Vec0<N> {
#[inline]
fn sqnorm(_: &vec::Vec0<N>) -> N {
Zero::zero()
@ -183,18 +183,17 @@ impl<N: Clone + Num + Algebraic> Norm<N> for vec::Vec0<N> {
impl<N: ApproxEq<N>> ApproxEq<N> for vec::Vec0<N> {
#[inline]
fn approx_epsilon() -> N {
fail!("approx_epsilon is broken since rust revision 8693943676487c01fa09f5f3daf0df6a1f71e24d.")
// ApproxEq::<N>::approx_epsilon()
fn approx_epsilon(_: Option<vec::Vec0<N>>) -> N {
ApproxEq::approx_epsilon(None::<N>)
}
#[inline]
fn approx_eq(&self, _: &vec::Vec0<N>) -> bool {
fn approx_eq(_: &vec::Vec0<N>, _: &vec::Vec0<N>) -> bool {
true
}
#[inline]
fn approx_eq_eps(&self, _: &vec::Vec0<N>, _: &N) -> bool {
fn approx_eq_eps(_: &vec::Vec0<N>, _: &vec::Vec0<N>, _: &N) -> bool {
true
}
}

View File

@ -3,10 +3,10 @@
#[allow(missing_doc)]; // we allow missing to avoid having to document the vector components.
use std::cast;
use std::num::{Zero, One, Algebraic, Bounded};
use std::num::{Zero, One, Real, Bounded};
use std::vec::{VecIterator, VecMutIterator};
use std::iter::{Iterator, FromIterator};
use std::cmp::ApproxEq;
use traits::operations::ApproxEq;
use traits::geometry::{Transform, Rotate, FromHomogeneous, ToHomogeneous, Dot, Norm,
Translation, Translate};

View File

@ -223,7 +223,7 @@ macro_rules! container_impl(
macro_rules! basis_impl(
($t: ident, $trhs: ident, $dim: expr) => (
impl<N: Clone + Num + Algebraic + ApproxEq<N> + $trhs<N, $t<N>>> Basis for $t<N> {
impl<N: Clone + Num + Real + ApproxEq<N> + $trhs<N, $t<N>>> Basis for $t<N> {
#[inline]
fn canonical_basis(f: |$t<N>| -> bool) {
for i in range(0u, $dim) {
@ -262,7 +262,7 @@ macro_rules! basis_impl(
elt = elt - v * Dot::dot(&elt, v)
};
if !Norm::sqnorm(&elt).approx_eq(&Zero::zero()) {
if !ApproxEq::approx_eq(&Norm::sqnorm(&elt), &Zero::zero()) {
let new_element = Norm::normalize_cpy(&elt);
if !f(new_element.clone()) { return };
@ -433,7 +433,7 @@ macro_rules! translation_impl(
macro_rules! norm_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + Num + Algebraic> Norm<N> for $t<N> {
impl<N: Clone + Num + Real> Norm<N> for $t<N> {
#[inline]
fn sqnorm(v: &$t<N>) -> N {
Dot::dot(v, v)
@ -496,19 +496,20 @@ macro_rules! approx_eq_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
#[inline]
fn approx_epsilon() -> N {
fail!("approx_epsilon is broken since rust revision 8693943676487c01fa09f5f3daf0df6a1f71e24d.")
// ApproxEq::<N>::approx_epsilon()
fn approx_epsilon(_: Option<$t<N>>) -> N {
ApproxEq::approx_epsilon(None::<N>)
}
#[inline]
fn approx_eq(&self, other: &$t<N>) -> bool {
self.$comp0.approx_eq(&other.$comp0) $(&& self.$compN.approx_eq(&other.$compN))*
fn approx_eq(a: &$t<N>, b: &$t<N>) -> bool {
ApproxEq::approx_eq(&a.$comp0, &b.$comp0)
$(&& ApproxEq::approx_eq(&a.$compN, &b.$compN))*
}
#[inline]
fn approx_eq_eps(&self, other: &$t<N>, eps: &N) -> bool {
self.$comp0.approx_eq_eps(&other.$comp0, eps) $(&& self.$compN.approx_eq_eps(&other.$compN, eps))*
fn approx_eq_eps(a: &$t<N>, b: &$t<N>, eps: &N) -> bool {
ApproxEq::approx_eq_eps(&a.$comp0, &b.$comp0, eps)
$(&& ApproxEq::approx_eq_eps(&a.$compN, &b.$compN, eps))*
}
}
)

View File

@ -1,6 +1,5 @@
use std::num::{Real, abs};
use std::rand::random;
use std::cmp::ApproxEq;
use na::{Vec1, Vec3, Mat1, Mat2, Mat3, Mat4, Mat5, Mat6, Rot3, DMat, DVec, Indexable};
use na;
@ -9,7 +8,7 @@ macro_rules! test_inv_mat_impl(
10000.times(|| {
let randmat : $t = random();
assert!((na::inv(&randmat).unwrap() * randmat).approx_eq(&na::one()));
assert!(na::approx_eq(&(na::inv(&randmat).unwrap() * randmat), &na::one()));
})
);
)
@ -90,7 +89,7 @@ fn test_rotation2() {
let randmat: na::Rot2<f64> = na::one();
let ang = Vec1::new(abs::<f64>(random()) % Real::pi());
assert!(na::rotation(&na::append_rotation(&randmat, &ang)).approx_eq(&ang));
assert!(na::approx_eq(&na::rotation(&na::append_rotation(&randmat, &ang)), &ang));
})
}
@ -109,7 +108,7 @@ fn test_inv_rotation3() {
let ang = na::normalize(&dir) * (abs::<f64>(random()) % Real::pi());
let rot = na::append_rotation(&randmat, &ang);
assert!((na::transpose(&rot) * rot).approx_eq(&na::one()));
assert!(na::approx_eq(&(na::transpose(&rot) * rot), &na::one()));
})
}
@ -125,7 +124,7 @@ fn test_mean_dmat() {
]
);
assert!(na::mean(&mat).approx_eq(&DVec::from_vec(3, [4.0f64, 5.0, 6.0])));
assert!(na::approx_eq(&na::mean(&mat), &DVec::from_vec(3, [4.0f64, 5.0, 6.0])));
}
#[test]
@ -152,7 +151,7 @@ fn test_cov_dmat() {
]
);
assert!(na::cov(&mat).approx_eq(&expected));
assert!(na::approx_eq(&na::cov(&mat), &expected));
}
#[test]

View File

@ -1,5 +1,4 @@
use std::rand::{random};
use std::cmp::ApproxEq;
use na::{Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6};
use na::{Mat3, Iterable, IterableMut}; // FIXME: get rid of that
use na;
@ -28,7 +27,7 @@ macro_rules! test_commut_dot_impl(
let v1 : $t = random();
let v2 : $t = random();
assert!(na::dot(&v1, &v2).approx_eq(&na::dot(&v2, &v1)));
assert!(na::approx_eq(&na::dot(&v1, &v2), &na::dot(&v2, &v1)));
})
);
)
@ -39,10 +38,10 @@ macro_rules! test_scalar_op_impl(
let v1 : $t = random();
let n : $n = random();
assert!(((v1 * n) / n).approx_eq(&v1));
assert!(((v1 / n) * n).approx_eq(&v1));
assert!(((v1 - n) + n).approx_eq(&v1));
assert!(((v1 + n) - n).approx_eq(&v1));
assert!(na::approx_eq(&((v1 * n) / n), &v1));
assert!(na::approx_eq(&((v1 / n) * n), &v1));
assert!(na::approx_eq(&((v1 - n) + n), &v1));
assert!(na::approx_eq(&((v1 + n) - n), &v1));
let mut v1 : $t = random();
let v0 : $t = v1.clone();
@ -51,7 +50,7 @@ macro_rules! test_scalar_op_impl(
v1 = v1 * n;
v1 = v1 / n;
assert!(v1.approx_eq(&v0));
assert!(na::approx_eq(&v1, &v0));
})
);
)
@ -61,12 +60,12 @@ macro_rules! test_basis_impl(
10000.times(|| {
na::canonical_basis(|e1: $t| {
na::canonical_basis(|e2: $t| {
assert!(e1 == e2 || na::dot(&e1, &e2).approx_eq(&na::zero()));
assert!(e1 == e2 || na::approx_eq(&na::dot(&e1, &e2), &na::zero()));
true
});
assert!(na::norm(&e1).approx_eq(&na::one()));
assert!(na::approx_eq(&na::norm(&e1), &na::one()));
true
})
@ -82,12 +81,12 @@ macro_rules! test_subspace_basis_impl(
na::orthonormal_subspace_basis(&v1, |e1| {
// check vectors are orthogonal to v1
assert!(na::dot(&v1, &e1).approx_eq(&na::zero()));
assert!(na::approx_eq(&na::dot(&v1, &e1), &na::zero()));
// check vectors form an orthonormal basis
assert!(na::norm(&e1).approx_eq(&na::one()));
assert!(na::approx_eq(&na::norm(&e1), &na::one()));
// check vectors form an ortogonal basis
na::orthonormal_subspace_basis(&v1, |e2| {
assert!(e1 == e2 || na::dot(&e1, &e2).approx_eq(&na::zero()));
assert!(e1 == e2 || na::approx_eq(&na::dot(&e1, &e2), &na::zero()));
true
});
@ -105,8 +104,8 @@ fn test_cross_vec3() {
let v2 : Vec3<f64> = random();
let v3 : Vec3<f64> = na::cross(&v1, &v2);
assert!(na::dot(&v3, &v2).approx_eq(&na::zero()));
assert!(na::dot(&v3, &v1).approx_eq(&na::zero()));
assert!(na::approx_eq(&na::dot(&v3, &v2), &na::zero()));
assert!(na::approx_eq(&na::dot(&v3, &v1), &na::zero()));
})
}

View File

@ -218,7 +218,7 @@ pub trait Dot<N> {
}
/// Traits of objects having an euclidian norm.
pub trait Norm<N: Algebraic> {
pub trait Norm<N: Real> {
/// Computes the norm of `self`.
#[inline]
fn norm(v: &Self) -> N {

View File

@ -4,11 +4,11 @@ pub use self::geometry::{AbsoluteRotate, Cross, CrossMatrix, Dot, FromHomogeneou
Rotation, RotationMatrix, RotationWithTranslation, ToHomogeneous,
Transform, Transformation, Translate, Translation, UniformSphereSample};
pub use self::structure::{AlgebraicVec, AlgebraicVecExt, Basis, Cast, Col, Dim, Indexable,
pub use self::structure::{RealVec, RealVecExt, Basis, Cast, Col, Dim, Indexable,
Iterable, IterableMut, Mat, Row, Vec, VecExt};
pub use self::operations::{Absolute, Cov, Inv, LMul, Mean, Outer, RMul, ScalarAdd, ScalarSub,
Transpose};
pub use self::operations::{Absolute, ApproxEq, Cov, Inv, LMul, Mean, Outer, RMul, ScalarAdd,
ScalarSub, Transpose};
pub mod geometry;
pub mod structure;

View File

@ -1,5 +1,42 @@
//! Low level operations on vectors and matrices.
/// Trait for testing approximate equality
pub trait ApproxEq<Eps> {
/// Default epsilon for approximation.
fn approx_epsilon(unused_self: Option<Self>) -> Eps;
/// Tests approximate equality using a custom epsilon.
fn approx_eq_eps(a: &Self, other: &Self, epsilon: &Eps) -> bool;
/// Tests approximate equality.
fn approx_eq(a: &Self, b: &Self) -> bool {
ApproxEq::approx_eq_eps(a, b, &ApproxEq::approx_epsilon(None::<Self>))
}
}
impl ApproxEq<f32> for f32 {
#[inline]
fn approx_epsilon(_: Option<f32>) -> f32 {
1.0e-6
}
#[inline]
fn approx_eq_eps(a: &f32, b: &f32, epsilon: &f32) -> bool {
(*a - *b).abs() < *epsilon
}
}
impl ApproxEq<f64> for f64 {
#[inline]
fn approx_epsilon(_: Option<f64>) -> f64 {
1.0e-6
}
#[inline]
fn approx_eq_eps(a: &f64, b: &f64, approx_epsilon: &f64) -> bool {
(*a - *b).abs() < *approx_epsilon
}
}
/// Trait of objects having an absolute value.
/// This is useful if the object does not have the same type as its absolute value.

View File

@ -27,8 +27,8 @@ pub trait Vec<N>: Dim + Sub<Self, Self> + Add<Self, Self> + Neg<Self> + Zero + E
+ Div<N, Self> + Dot<N> {
}
/// Trait of vector with components implementing the `Algebraic` trait.
pub trait AlgebraicVec<N: Algebraic>: Vec<N> + Norm<N> {
/// Trait of vector with components implementing the `Real` trait.
pub trait RealVec<N: Real>: Vec<N> + Norm<N> {
}
/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
@ -39,19 +39,19 @@ pub trait VecExt<N>: Vec<N> + Indexable<uint, N> + Iterable<N> +
/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
/// operations on vectors.
pub trait AlgebraicVecExt<N: Algebraic>: AlgebraicVec<N> + VecExt<N> + Basis + Round { }
pub trait RealVecExt<N: Real>: RealVec<N> + VecExt<N> + Basis + Round { }
impl<N, V: Dim + Sub<V, V> + Add<V, V> + Neg<V> + Zero + Eq + Mul<N, V> + Div<N, V> + Dot<N>>
Vec<N> for V { }
impl<N: Algebraic, V: Vec<N> + Norm<N>> AlgebraicVec<N> for V { }
impl<N: Real, V: Vec<N> + Norm<N>> RealVec<N> for V { }
impl<N,
V: Vec<N> + Indexable<uint, N> + Iterable<N> +
UniformSphereSample + ScalarAdd<N> + ScalarSub<N> + Bounded + Orderable>
VecExt<N> for V { }
impl<N: Algebraic, V: AlgebraicVec<N> + VecExt<N> + Basis + Round> AlgebraicVecExt<N> for V { }
impl<N: Real, V: RealVec<N> + VecExt<N> + Basis + Round> RealVecExt<N> for V { }
// FIXME: return an iterator instead
/// Traits of objects which can form a basis (typically vectors).