Add the ability to stop the basis internal itertors.
This commit is contained in:
parent
d8db04cce5
commit
344d761be5
@ -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
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -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
|
||||
|
@ -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> {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user