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 10000.times {
|
||||||
do Basis::canonical_basis::<$t> |e1| {
|
do Basis::canonical_basis::<$t> |e1| {
|
||||||
do Basis::canonical_basis::<$t> |e2| {
|
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()));
|
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()));
|
assert!(e1.norm().approx_eq(&One::one()));
|
||||||
// check vectors form an ortogonal basis
|
// check vectors form an ortogonal basis
|
||||||
do v1.orthonormal_subspace_basis() |e2| {
|
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.
|
/// Traits of objecs which can form a basis.
|
||||||
pub trait Basis {
|
pub trait Basis {
|
||||||
/// Iterate through the canonical basis of the space in which this object lives.
|
/// 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`.
|
/// 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.
|
/// Creates the canonical basis of the space in which this object lives.
|
||||||
fn canonical_basis_list() -> ~[Self] {
|
fn canonical_basis_list() -> ~[Self] {
|
||||||
let mut res = ~[];
|
let mut res = ~[];
|
||||||
|
|
||||||
do Basis::canonical_basis::<Self> |elem| {
|
do Basis::canonical_basis::<Self> |elem| {
|
||||||
res.push(elem)
|
res.push(elem);
|
||||||
|
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
|
@ -22,7 +25,9 @@ pub trait Basis {
|
||||||
let mut res = ~[];
|
let mut res = ~[];
|
||||||
|
|
||||||
do self.orthonormal_subspace_basis |elem| {
|
do self.orthonormal_subspace_basis |elem| {
|
||||||
res.push(elem)
|
res.push(elem);
|
||||||
|
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
|
|
|
@ -72,10 +72,10 @@ impl<N> Dim for vec::Vec0<N> {
|
||||||
|
|
||||||
impl<N: Clone + DivisionRing + Algebraic + ApproxEq<N>> Basis for vec::Vec0<N> {
|
impl<N: Clone + DivisionRing + Algebraic + ApproxEq<N>> Basis for vec::Vec0<N> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn canonical_basis(_: &fn(vec::Vec0<N>)) { }
|
fn canonical_basis(_: &fn(vec::Vec0<N>) -> bool) { }
|
||||||
|
|
||||||
#[inline(always)]
|
#[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> {
|
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) => (
|
($t: ident, $dim: expr) => (
|
||||||
impl<N: Clone + DivisionRing + Algebraic + ApproxEq<N>> Basis for $t<N> {
|
impl<N: Clone + DivisionRing + Algebraic + ApproxEq<N>> Basis for $t<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn canonical_basis(f: &fn($t<N>)) {
|
fn canonical_basis(f: &fn($t<N>) -> bool) {
|
||||||
for i in range(0u, $dim) {
|
for i in range(0u, $dim) {
|
||||||
let mut basis_element : $t<N> = Zero::zero();
|
let mut basis_element : $t<N> = Zero::zero();
|
||||||
|
|
||||||
basis_element.set(i, One::one());
|
basis_element.set(i, One::one());
|
||||||
|
|
||||||
f(basis_element);
|
if !f(basis_element) { return }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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
|
// compute the basis of the orthogonal subspace using Gram-Schmidt
|
||||||
// orthogonalization algorithm
|
// orthogonalization algorithm
|
||||||
let mut basis: ~[$t<N>] = ~[];
|
let mut basis: ~[$t<N>] = ~[];
|
||||||
|
@ -221,7 +221,7 @@ macro_rules! basis_impl(
|
||||||
if !elt.sqnorm().approx_eq(&Zero::zero()) {
|
if !elt.sqnorm().approx_eq(&Zero::zero()) {
|
||||||
let new_element = elt.normalized();
|
let new_element = elt.normalized();
|
||||||
|
|
||||||
f(new_element.clone());
|
if !f(new_element.clone()) { return };
|
||||||
|
|
||||||
basis.push(new_element);
|
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> {
|
impl<N: One> Basis for Vec1<N> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn canonical_basis(f: &fn(Vec1<N>)) {
|
fn canonical_basis(f: &fn(Vec1<N>) -> bool) {
|
||||||
f(Vec1::new(One::one()))
|
f(Vec1::new(One::one()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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> {
|
impl<N: Clone + One + Zero + Neg<N>> Basis for Vec2<N> {
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
fn canonical_basis(f: &fn(Vec2<N>)) {
|
fn canonical_basis(f: &fn(Vec2<N>) -> bool) {
|
||||||
f(Vec2::new(One::one(), Zero::zero()));
|
if !f(Vec2::new(One::one(), Zero::zero())) { return };
|
||||||
f(Vec2::new(Zero::zero(), One::one()));
|
f(Vec2::new(Zero::zero(), One::one()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn orthonormal_subspace_basis(&self, f: &fn(Vec2<N>)) {
|
fn orthonormal_subspace_basis(&self, f: &fn(Vec2<N>) -> bool) {
|
||||||
f(Vec2::new(-self.y, self.x.clone()))
|
f(Vec2::new(-self.y, self.x.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Clone + DivisionRing + Ord + Algebraic + Signed>
|
impl<N: Clone + DivisionRing + Ord + Algebraic + Signed>
|
||||||
Basis for Vec3<N> {
|
Basis for Vec3<N> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn canonical_basis(f: &fn(Vec3<N>)) {
|
fn canonical_basis(f: &fn(Vec3<N>) -> bool) {
|
||||||
f(Vec3::new(One::one(), Zero::zero(), Zero::zero()));
|
if !f(Vec3::new(One::one(), Zero::zero(), Zero::zero())) { return };
|
||||||
f(Vec3::new(Zero::zero(), One::one(), Zero::zero()));
|
if !f(Vec3::new(Zero::zero(), One::one(), Zero::zero())) { return };
|
||||||
f(Vec3::new(Zero::zero(), Zero::zero(), One::one()));
|
f(Vec3::new(Zero::zero(), Zero::zero(), One::one()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn orthonormal_subspace_basis(&self, f: &fn(Vec3<N>)) {
|
fn orthonormal_subspace_basis(&self, f: &fn(Vec3<N>) -> bool) {
|
||||||
let a =
|
let a =
|
||||||
if self.x.clone().abs() > self.y.clone().abs() {
|
if self.x.clone().abs() > self.y.clone().abs() {
|
||||||
Vec3::new(self.z.clone(), Zero::zero(), -self.x).normalized()
|
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()
|
Vec3::new(Zero::zero(), -self.z, self.y.clone()).normalized()
|
||||||
};
|
};
|
||||||
|
|
||||||
f(a.cross(self));
|
if !f(a.cross(self)) { return };
|
||||||
f(a);
|
f(a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue