From 344d761be55aff905f282c518b3861806ec5c8d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Sat, 17 Aug 2013 10:48:45 +0200 Subject: [PATCH] Add the ability to stop the basis internal itertors. --- src/tests/vec.rs | 12 ++++++++++-- src/traits/basis.rs | 13 +++++++++---- src/vec0_spec.rs | 4 ++-- src/vec_macros.rs | 8 ++++---- src/vec_spec.rs | 26 +++++++++++++------------- 5 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/tests/vec.rs b/src/tests/vec.rs index d7d99b39..740cd0c2 100644 --- a/src/tests/vec.rs +++ b/src/tests/vec.rs @@ -80,10 +80,14 @@ macro_rules! test_basis_impl( do 10000.times { do Basis::canonical_basis::<$t> |e1| { do Basis::canonical_basis::<$t> |e2| { - assert!(e1 == e2 || e1.dot(&e2).approx_eq(&Zero::zero())) + assert!(e1 == e2 || e1.dot(&e2).approx_eq(&Zero::zero())); + + true } assert!(e1.norm().approx_eq(&One::one())); + + true } } ); @@ -102,8 +106,12 @@ macro_rules! test_subspace_basis_impl( assert!(e1.norm().approx_eq(&One::one())); // check vectors form an ortogonal basis do v1.orthonormal_subspace_basis() |e2| { - assert!(e1 == e2 || e1.dot(&e2).approx_eq(&Zero::zero())) + assert!(e1 == e2 || e1.dot(&e2).approx_eq(&Zero::zero())); + + true } + + true } } ); diff --git a/src/traits/basis.rs b/src/traits/basis.rs index fe60d99c..aec2c6d6 100644 --- a/src/traits/basis.rs +++ b/src/traits/basis.rs @@ -1,17 +1,20 @@ +// FIXME: return an iterator instead /// Traits of objecs which can form a basis. pub trait Basis { /// Iterate through the canonical basis of the space in which this object lives. - fn canonical_basis(&fn(Self)); + fn canonical_basis(&fn(Self) -> bool); /// Iterate through a basis of the subspace orthogonal to `self`. - fn orthonormal_subspace_basis(&self, &fn(Self)); + fn orthonormal_subspace_basis(&self, &fn(Self) -> bool); /// Creates the canonical basis of the space in which this object lives. fn canonical_basis_list() -> ~[Self] { let mut res = ~[]; do Basis::canonical_basis:: |elem| { - res.push(elem) + res.push(elem); + + true } res @@ -22,7 +25,9 @@ pub trait Basis { let mut res = ~[]; do self.orthonormal_subspace_basis |elem| { - res.push(elem) + res.push(elem); + + true } res diff --git a/src/vec0_spec.rs b/src/vec0_spec.rs index 5bbcb887..b7917fd2 100644 --- a/src/vec0_spec.rs +++ b/src/vec0_spec.rs @@ -72,10 +72,10 @@ impl Dim for vec::Vec0 { impl> Basis for vec::Vec0 { #[inline(always)] - fn canonical_basis(_: &fn(vec::Vec0)) { } + fn canonical_basis(_: &fn(vec::Vec0) -> bool) { } #[inline(always)] - fn orthonormal_subspace_basis(&self, _: &fn(vec::Vec0)) { } + fn orthonormal_subspace_basis(&self, _: &fn(vec::Vec0) -> bool) { } } impl> Add, vec::Vec0> for vec::Vec0 { diff --git a/src/vec_macros.rs b/src/vec_macros.rs index d978da6c..be956974 100644 --- a/src/vec_macros.rs +++ b/src/vec_macros.rs @@ -185,18 +185,18 @@ macro_rules! basis_impl( ($t: ident, $dim: expr) => ( impl> Basis for $t { #[inline] - fn canonical_basis(f: &fn($t)) { + fn canonical_basis(f: &fn($t) -> bool) { for i in range(0u, $dim) { let mut basis_element : $t = Zero::zero(); basis_element.set(i, One::one()); - f(basis_element); + if !f(basis_element) { return } } } #[inline] - fn orthonormal_subspace_basis(&self, f: &fn($t)) { + fn orthonormal_subspace_basis(&self, f: &fn($t) -> bool) { // compute the basis of the orthogonal subspace using Gram-Schmidt // orthogonalization algorithm let mut basis: ~[$t] = ~[]; @@ -221,7 +221,7 @@ macro_rules! basis_impl( if !elt.sqnorm().approx_eq(&Zero::zero()) { let new_element = elt.normalized(); - f(new_element.clone()); + if !f(new_element.clone()) { return }; basis.push(new_element); } diff --git a/src/vec_spec.rs b/src/vec_spec.rs index 3859fe92..176aa8b6 100644 --- a/src/vec_spec.rs +++ b/src/vec_spec.rs @@ -26,38 +26,38 @@ impl + Sub> Cross> for Vec3 { impl Basis for Vec1 { #[inline(always)] - fn canonical_basis(f: &fn(Vec1)) { - f(Vec1::new(One::one())) + fn canonical_basis(f: &fn(Vec1) -> bool) { + f(Vec1::new(One::one())); } #[inline(always)] - fn orthonormal_subspace_basis(&self, _: &fn(Vec1)) { } + fn orthonormal_subspace_basis(&self, _: &fn(Vec1) -> bool ) { } } impl> Basis for Vec2 { - #[inline] - fn canonical_basis(f: &fn(Vec2)) { - f(Vec2::new(One::one(), Zero::zero())); + #[inline(always)] + fn canonical_basis(f: &fn(Vec2) -> bool) { + if !f(Vec2::new(One::one(), Zero::zero())) { return }; f(Vec2::new(Zero::zero(), One::one())); } #[inline] - fn orthonormal_subspace_basis(&self, f: &fn(Vec2)) { - f(Vec2::new(-self.y, self.x.clone())) + fn orthonormal_subspace_basis(&self, f: &fn(Vec2) -> bool) { + f(Vec2::new(-self.y, self.x.clone())); } } impl Basis for Vec3 { #[inline(always)] - fn canonical_basis(f: &fn(Vec3)) { - f(Vec3::new(One::one(), Zero::zero(), Zero::zero())); - f(Vec3::new(Zero::zero(), One::one(), Zero::zero())); + fn canonical_basis(f: &fn(Vec3) -> bool) { + if !f(Vec3::new(One::one(), Zero::zero(), Zero::zero())) { return }; + if !f(Vec3::new(Zero::zero(), One::one(), Zero::zero())) { return }; f(Vec3::new(Zero::zero(), Zero::zero(), One::one())); } #[inline(always)] - fn orthonormal_subspace_basis(&self, f: &fn(Vec3)) { + fn orthonormal_subspace_basis(&self, f: &fn(Vec3) -> bool) { let a = if self.x.clone().abs() > self.y.clone().abs() { Vec3::new(self.z.clone(), Zero::zero(), -self.x).normalized() @@ -66,7 +66,7 @@ Basis for Vec3 { Vec3::new(Zero::zero(), -self.z, self.y.clone()).normalized() }; - f(a.cross(self)); + if !f(a.cross(self)) { return }; f(a); } }