Add the ability to stop the basis internal itertors.

This commit is contained in:
Sébastien Crozet 2013-08-17 10:48:45 +02:00
parent d8db04cce5
commit 344d761be5
5 changed files with 38 additions and 25 deletions

View File

@ -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
}
}
);

View File

@ -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::<Self> |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

View File

@ -72,10 +72,10 @@ impl<N> Dim for vec::Vec0<N> {
impl<N: Clone + DivisionRing + Algebraic + ApproxEq<N>> Basis for vec::Vec0<N> {
#[inline(always)]
fn canonical_basis(_: &fn(vec::Vec0<N>)) { }
fn canonical_basis(_: &fn(vec::Vec0<N>) -> bool) { }
#[inline(always)]
fn orthonormal_subspace_basis(&self, _: &fn(vec::Vec0<N>)) { }
fn orthonormal_subspace_basis(&self, _: &fn(vec::Vec0<N>) -> bool) { }
}
impl<N: Clone + Add<N,N>> Add<vec::Vec0<N>, vec::Vec0<N>> for vec::Vec0<N> {

View File

@ -185,18 +185,18 @@ macro_rules! basis_impl(
($t: ident, $dim: expr) => (
impl<N: Clone + DivisionRing + Algebraic + ApproxEq<N>> Basis for $t<N> {
#[inline]
fn canonical_basis(f: &fn($t<N>)) {
fn canonical_basis(f: &fn($t<N>) -> bool) {
for i in range(0u, $dim) {
let mut basis_element : $t<N> = 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<N>)) {
fn orthonormal_subspace_basis(&self, f: &fn($t<N>) -> bool) {
// compute the basis of the orthogonal subspace using Gram-Schmidt
// orthogonalization algorithm
let mut basis: ~[$t<N>] = ~[];
@ -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);
}

View File

@ -26,38 +26,38 @@ impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec3<N>> for Vec3<N> {
impl<N: One> Basis for Vec1<N> {
#[inline(always)]
fn canonical_basis(f: &fn(Vec1<N>)) {
f(Vec1::new(One::one()))
fn canonical_basis(f: &fn(Vec1<N>) -> bool) {
f(Vec1::new(One::one()));
}
#[inline(always)]
fn orthonormal_subspace_basis(&self, _: &fn(Vec1<N>)) { }
fn orthonormal_subspace_basis(&self, _: &fn(Vec1<N>) -> bool ) { }
}
impl<N: Clone + One + Zero + Neg<N>> Basis for Vec2<N> {
#[inline]
fn canonical_basis(f: &fn(Vec2<N>)) {
f(Vec2::new(One::one(), Zero::zero()));
#[inline(always)]
fn canonical_basis(f: &fn(Vec2<N>) -> 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<N>)) {
f(Vec2::new(-self.y, self.x.clone()))
fn orthonormal_subspace_basis(&self, f: &fn(Vec2<N>) -> bool) {
f(Vec2::new(-self.y, self.x.clone()));
}
}
impl<N: Clone + DivisionRing + Ord + Algebraic + Signed>
Basis for Vec3<N> {
#[inline(always)]
fn canonical_basis(f: &fn(Vec3<N>)) {
f(Vec3::new(One::one(), Zero::zero(), Zero::zero()));
f(Vec3::new(Zero::zero(), One::one(), Zero::zero()));
fn canonical_basis(f: &fn(Vec3<N>) -> 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<N>)) {
fn orthonormal_subspace_basis(&self, f: &fn(Vec3<N>) -> 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<N> {
Vec3::new(Zero::zero(), -self.z, self.y.clone()).normalized()
};
f(a.cross(self));
if !f(a.cross(self)) { return };
f(a);
}
}