diff --git a/.gitignore b/.gitignore index 2cb7d551..cc67d9ea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ *.swp -doc +*.html lib diff --git a/Makefile b/Makefile index c628ff3a..167385e4 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ nalgebra_lib_path=lib +nalgebra_doc_path=doc all: rust build src/nalgebra.rc --out-dir $(nalgebra_lib_path) @@ -7,6 +8,7 @@ test: rm nalgebratest~ doc: - rust test src/nalgebra.rc + rust doc src/nalgebra.rc --output-dir $(nalgebra_doc_path) -.PHONY:doc, test +.PHONY:doc +.PHONY:test diff --git a/src/adaptors/rotmat.rs b/src/adaptors/rotmat.rs index c60b982e..f790b764 100644 --- a/src/adaptors/rotmat.rs +++ b/src/adaptors/rotmat.rs @@ -1,6 +1,6 @@ use core::num::{One, Zero}; use core::rand::{Rand, Rng, RngUtil}; -use std::cmp::FuzzyEq; +use core::cmp::ApproxEq; use traits::workarounds::rlmul::{RMul, LMul}; use traits::dim::Dim; use traits::inv::Inv; @@ -64,7 +64,7 @@ pub fn rotmat3 + One + Sub + Add + } } -impl + Trigonometric + Neg + Mul + Add + Copy> +impl + Trigonometric + Neg + Mul + Add + Copy> Rotation> for Rotmat> { fn rotation(&self) -> Vec1 @@ -77,7 +77,7 @@ Rotation> for Rotmat> { *self = self.rotated(rot) } } -impl + Trigonometric + Neg + Mul + Add + Copy + +impl + Trigonometric + Neg + Mul + Add + Copy + One + Sub> Rotation<(Vec3, T)> for Rotmat> { @@ -93,7 +93,7 @@ Rotation<(Vec3, T)> for Rotmat> impl> Rand for Rotmat> { - fn rand(rng: &R) -> Rotmat> + fn rand(rng: &mut R) -> Rotmat> { rotmat2(rng.gen()) } } @@ -101,7 +101,7 @@ impl + One + Sub + Add + Mul> Rand for Rotmat> { - fn rand(rng: &R) -> Rotmat> + fn rand(rng: &mut R) -> Rotmat> { rotmat3(&rng.gen(), rng.gen()) } } @@ -160,13 +160,16 @@ Transpose for Rotmat { self.submat.transpose() } } -impl> FuzzyEq for Rotmat +impl, M: ApproxEq> ApproxEq for Rotmat { - fn fuzzy_eq(&self, other: &Rotmat) -> bool - { self.submat.fuzzy_eq(&other.submat) } + fn approx_epsilon() -> T + { ApproxEq::approx_epsilon::() } - fn fuzzy_eq_eps(&self, other: &Rotmat, epsilon: &T) -> bool - { self.submat.fuzzy_eq_eps(&other.submat, epsilon) } + fn approx_eq(&self, other: &Rotmat) -> bool + { self.submat.approx_eq(&other.submat) } + + fn approx_eq_eps(&self, other: &Rotmat, epsilon: &T) -> bool + { self.submat.approx_eq_eps(&other.submat, epsilon) } } impl ToStr for Rotmat diff --git a/src/adaptors/transform.rs b/src/adaptors/transform.rs index b2d90413..0bb26ea6 100644 --- a/src/adaptors/transform.rs +++ b/src/adaptors/transform.rs @@ -1,6 +1,6 @@ use core::num::{One, Zero}; use core::rand::{Rand, Rng, RngUtil}; -use std::cmp::FuzzyEq; +use core::cmp::ApproxEq; use traits::dim::Dim; use traits::inv::Inv; use traits::rotation::Rotation; @@ -122,24 +122,28 @@ Inv for Transform } } -impl, V:FuzzyEq> FuzzyEq for Transform +impl, M:ApproxEq, V:ApproxEq> +ApproxEq for Transform { - fn fuzzy_eq(&self, other: &Transform) -> bool + fn approx_epsilon() -> T + { ApproxEq::approx_epsilon::() } + + fn approx_eq(&self, other: &Transform) -> bool { - self.submat.fuzzy_eq(&other.submat) && - self.subtrans.fuzzy_eq(&other.subtrans) + self.submat.approx_eq(&other.submat) && + self.subtrans.approx_eq(&other.subtrans) } - fn fuzzy_eq_eps(&self, other: &Transform, epsilon: &T) -> bool + fn approx_eq_eps(&self, other: &Transform, epsilon: &T) -> bool { - self.submat.fuzzy_eq_eps(&other.submat, epsilon) && - self.subtrans.fuzzy_eq_eps(&other.subtrans, epsilon) + self.submat.approx_eq_eps(&other.submat, epsilon) && + self.subtrans.approx_eq_eps(&other.subtrans, epsilon) } } impl Rand for Transform { - fn rand(rng: &R) -> Transform + fn rand(rng: &mut R) -> Transform { transform(&rng.gen(), &rng.gen()) } } diff --git a/src/dim1/mat1.rs b/src/dim1/mat1.rs index 296dbc30..9a2d4c2e 100644 --- a/src/dim1/mat1.rs +++ b/src/dim1/mat1.rs @@ -1,6 +1,6 @@ use core::num::{One, Zero}; use core::rand::{Rand, Rng, RngUtil}; -use std::cmp::FuzzyEq; +use core::cmp::ApproxEq; use traits::dim::Dim; use traits::inv::Inv; use traits::transpose::Transpose; @@ -56,7 +56,7 @@ impl + Mul> LMul> for Mat1 { vec1(self.m11 * other.x) } } -impl + Quot + Sub + Neg + Zero + One> +impl + Div + Sub + Neg + Zero + One> Inv for Mat1 { fn inverse(&self) -> Mat1 @@ -85,18 +85,21 @@ impl Transpose for Mat1 { } } -impl> FuzzyEq for Mat1 +impl> ApproxEq for Mat1 { - fn fuzzy_eq(&self, other: &Mat1) -> bool - { self.m11.fuzzy_eq(&other.m11) } + fn approx_epsilon() -> T + { ApproxEq::approx_epsilon::() } - fn fuzzy_eq_eps(&self, other: &Mat1, epsilon: &T) -> bool - { self.m11.fuzzy_eq_eps(&other.m11, epsilon) } + fn approx_eq(&self, other: &Mat1) -> bool + { self.m11.approx_eq(&other.m11) } + + fn approx_eq_eps(&self, other: &Mat1, epsilon: &T) -> bool + { self.m11.approx_eq_eps(&other.m11, epsilon) } } impl Rand for Mat1 { - fn rand(rng: &R) -> Mat1 + fn rand(rng: &mut R) -> Mat1 { mat1(rng.gen()) } } diff --git a/src/dim1/vec1.rs b/src/dim1/vec1.rs index b081c0bb..c0f19908 100644 --- a/src/dim1/vec1.rs +++ b/src/dim1/vec1.rs @@ -1,6 +1,6 @@ use core::num::{Zero, One, Algebraic}; use core::rand::{Rand, Rng, RngUtil}; -use std::cmp::FuzzyEq; +use core::cmp::ApproxEq; use traits::basis::Basis; use traits::dim::Dim; use traits::dot::Dot; @@ -44,7 +44,7 @@ ScalarMul for Vec1 } -impl> +impl> ScalarDiv for Vec1 { fn scalar_div(&self, s: &T) -> Vec1 @@ -92,7 +92,7 @@ impl + Add + Algebraic> Dot for Vec1 { self.x * other.x } } -impl + Add + Quot + Algebraic> +impl + Add + Div + Algebraic> Norm for Vec1 { fn sqnorm(&self) -> T @@ -141,18 +141,21 @@ impl Basis for Vec1 { ~[] } } -impl> FuzzyEq for Vec1 +impl> ApproxEq for Vec1 { - fn fuzzy_eq(&self, other: &Vec1) -> bool - { self.x.fuzzy_eq(&other.x) } + fn approx_epsilon() -> T + { ApproxEq::approx_epsilon::() } - fn fuzzy_eq_eps(&self, other: &Vec1, epsilon: &T) -> bool - { self.x.fuzzy_eq_eps(&other.x, epsilon) } + fn approx_eq(&self, other: &Vec1) -> bool + { self.x.approx_eq(&other.x) } + + fn approx_eq_eps(&self, other: &Vec1, epsilon: &T) -> bool + { self.x.approx_eq_eps(&other.x, epsilon) } } impl Rand for Vec1 { - fn rand(rng: &R) -> Vec1 + fn rand(rng: &mut R) -> Vec1 { vec1(rng.gen()) } } diff --git a/src/dim2/mat2.rs b/src/dim2/mat2.rs index 31033787..81a41fb4 100644 --- a/src/dim2/mat2.rs +++ b/src/dim2/mat2.rs @@ -1,6 +1,7 @@ use core::num::{One, Zero}; use core::rand::{Rand, Rng, RngUtil}; -use std::cmp::FuzzyEq; +use core::cmp::ApproxEq; +use core::util::swap; use traits::dim::Dim; use traits::inv::Inv; use traits::transpose::Transpose; @@ -89,7 +90,7 @@ impl + Mul> LMul> for Mat2 } } -impl + Quot + Sub + Neg + Zero> +impl + Div + Sub + Neg + Zero> Inv for Mat2 { fn inverse(&self) -> Mat2 @@ -121,33 +122,36 @@ impl Transpose for Mat2 } fn transpose(&mut self) - { self.m21 <-> self.m12; } + { swap(&mut self.m21, &mut self.m12); } } -impl> FuzzyEq for Mat2 +impl> ApproxEq for Mat2 { - fn fuzzy_eq(&self, other: &Mat2) -> bool - { - self.m11.fuzzy_eq(&other.m11) && - self.m12.fuzzy_eq(&other.m12) && + fn approx_epsilon() -> T + { ApproxEq::approx_epsilon::() } - self.m21.fuzzy_eq(&other.m21) && - self.m22.fuzzy_eq(&other.m22) + fn approx_eq(&self, other: &Mat2) -> bool + { + self.m11.approx_eq(&other.m11) && + self.m12.approx_eq(&other.m12) && + + self.m21.approx_eq(&other.m21) && + self.m22.approx_eq(&other.m22) } - fn fuzzy_eq_eps(&self, other: &Mat2, epsilon: &T) -> bool + fn approx_eq_eps(&self, other: &Mat2, epsilon: &T) -> bool { - self.m11.fuzzy_eq_eps(&other.m11, epsilon) && - self.m12.fuzzy_eq_eps(&other.m12, epsilon) && + self.m11.approx_eq_eps(&other.m11, epsilon) && + self.m12.approx_eq_eps(&other.m12, epsilon) && - self.m21.fuzzy_eq_eps(&other.m21, epsilon) && - self.m22.fuzzy_eq_eps(&other.m22, epsilon) + self.m21.approx_eq_eps(&other.m21, epsilon) && + self.m22.approx_eq_eps(&other.m22, epsilon) } } impl Rand for Mat2 { - fn rand(rng: &R) -> Mat2 + fn rand(rng: &mut R) -> Mat2 { mat2(rng.gen(), rng.gen(), rng.gen(), rng.gen()) } } diff --git a/src/dim2/vec2.rs b/src/dim2/vec2.rs index 8798584e..bde7270c 100644 --- a/src/dim2/vec2.rs +++ b/src/dim2/vec2.rs @@ -1,7 +1,7 @@ use core::num::{Zero, One, Algebraic}; use core::rand::{Rand, Rng, RngUtil}; use dim1::vec1::{Vec1, vec1}; -use std::cmp::FuzzyEq; +use core::cmp::ApproxEq; use traits::basis::Basis; use traits::cross::Cross; use traits::dim::Dim; @@ -52,7 +52,7 @@ ScalarMul for Vec2 } -impl> +impl> ScalarDiv for Vec2 { fn scalar_div(&self, s: &T) -> Vec2 @@ -109,7 +109,7 @@ impl + Add + Algebraic> Dot for Vec2 { self.x * other.x + self.y * other.y } } -impl + Add + Quot + Algebraic> +impl + Add + Div + Algebraic> Norm for Vec2 { fn sqnorm(&self) -> T @@ -173,21 +173,24 @@ impl> Basis for Vec2 { ~[ vec2(-self.y, self.x) ] } } -impl> FuzzyEq for Vec2 +impl> ApproxEq for Vec2 { - fn fuzzy_eq(&self, other: &Vec2) -> bool - { self.x.fuzzy_eq(&other.x) && self.y.fuzzy_eq(&other.y) } + fn approx_epsilon() -> T + { ApproxEq::approx_epsilon::() } - fn fuzzy_eq_eps(&self, other: &Vec2, epsilon: &T) -> bool + fn approx_eq(&self, other: &Vec2) -> bool + { self.x.approx_eq(&other.x) && self.y.approx_eq(&other.y) } + + fn approx_eq_eps(&self, other: &Vec2, epsilon: &T) -> bool { - self.x.fuzzy_eq_eps(&other.x, epsilon) && - self.y.fuzzy_eq_eps(&other.y, epsilon) + self.x.approx_eq_eps(&other.x, epsilon) && + self.y.approx_eq_eps(&other.y, epsilon) } } impl Rand for Vec2 { - fn rand(rng: &R) -> Vec2 + fn rand(rng: &mut R) -> Vec2 { vec2(rng.gen(), rng.gen()) } } diff --git a/src/dim3/mat3.rs b/src/dim3/mat3.rs index 9f90c28e..df495fef 100644 --- a/src/dim3/mat3.rs +++ b/src/dim3/mat3.rs @@ -1,6 +1,7 @@ use core::num::{One, Zero}; use core::rand::{Rand, Rng, RngUtil}; -use std::cmp::FuzzyEq; +use core::cmp::ApproxEq; +use core::util::swap; use traits::dim::Dim; use traits::inv::Inv; use traits::transpose::Transpose; @@ -106,7 +107,7 @@ impl + Mul> LMul> for Mat3 } } -impl + Quot + Sub + Add + Neg + Zero> +impl + Div + Sub + Add + Neg + Zero> Inv for Mat3 { fn inverse(&self) -> Mat3 @@ -157,48 +158,51 @@ impl Transpose for Mat3 fn transpose(&mut self) { - self.m12 <-> self.m21; - self.m13 <-> self.m31; - self.m23 <-> self.m32; + swap(&mut self.m12, &mut self.m21); + swap(&mut self.m13, &mut self.m31); + swap(&mut self.m23, &mut self.m32); } } -impl> FuzzyEq for Mat3 +impl> ApproxEq for Mat3 { - fn fuzzy_eq(&self, other: &Mat3) -> bool + fn approx_epsilon() -> T + { ApproxEq::approx_epsilon::() } + + fn approx_eq(&self, other: &Mat3) -> bool { - self.m11.fuzzy_eq(&other.m11) && - self.m12.fuzzy_eq(&other.m12) && - self.m13.fuzzy_eq(&other.m13) && + self.m11.approx_eq(&other.m11) && + self.m12.approx_eq(&other.m12) && + self.m13.approx_eq(&other.m13) && - self.m21.fuzzy_eq(&other.m21) && - self.m22.fuzzy_eq(&other.m22) && - self.m23.fuzzy_eq(&other.m23) && + self.m21.approx_eq(&other.m21) && + self.m22.approx_eq(&other.m22) && + self.m23.approx_eq(&other.m23) && - self.m31.fuzzy_eq(&other.m31) && - self.m32.fuzzy_eq(&other.m32) && - self.m33.fuzzy_eq(&other.m33) + self.m31.approx_eq(&other.m31) && + self.m32.approx_eq(&other.m32) && + self.m33.approx_eq(&other.m33) } - fn fuzzy_eq_eps(&self, other: &Mat3, epsilon: &T) -> bool + fn approx_eq_eps(&self, other: &Mat3, epsilon: &T) -> bool { - self.m11.fuzzy_eq_eps(&other.m11, epsilon) && - self.m12.fuzzy_eq_eps(&other.m12, epsilon) && - self.m13.fuzzy_eq_eps(&other.m13, epsilon) && + self.m11.approx_eq_eps(&other.m11, epsilon) && + self.m12.approx_eq_eps(&other.m12, epsilon) && + self.m13.approx_eq_eps(&other.m13, epsilon) && - self.m21.fuzzy_eq_eps(&other.m21, epsilon) && - self.m22.fuzzy_eq_eps(&other.m22, epsilon) && - self.m23.fuzzy_eq_eps(&other.m23, epsilon) && + self.m21.approx_eq_eps(&other.m21, epsilon) && + self.m22.approx_eq_eps(&other.m22, epsilon) && + self.m23.approx_eq_eps(&other.m23, epsilon) && - self.m31.fuzzy_eq_eps(&other.m31, epsilon) && - self.m32.fuzzy_eq_eps(&other.m32, epsilon) && - self.m33.fuzzy_eq_eps(&other.m33, epsilon) + self.m31.approx_eq_eps(&other.m31, epsilon) && + self.m32.approx_eq_eps(&other.m32, epsilon) && + self.m33.approx_eq_eps(&other.m33, epsilon) } } impl Rand for Mat3 { - fn rand(rng: &R) -> Mat3 + fn rand(rng: &mut R) -> Mat3 { mat3(rng.gen(), rng.gen(), rng.gen(), rng.gen(), rng.gen(), rng.gen(), diff --git a/src/dim3/vec3.rs b/src/dim3/vec3.rs index 074c3781..103aeeb3 100644 --- a/src/dim3/vec3.rs +++ b/src/dim3/vec3.rs @@ -1,6 +1,6 @@ use core::num::{Zero, One, Algebraic, abs}; use core::rand::{Rand, Rng, RngUtil}; -use std::cmp::FuzzyEq; +use core::cmp::ApproxEq; use traits::basis::Basis; use traits::cross::Cross; use traits::dim::Dim; @@ -53,7 +53,7 @@ ScalarMul for Vec3 } -impl> +impl> ScalarDiv for Vec3 { fn scalar_div(&self, s: &T) -> Vec3 @@ -121,7 +121,7 @@ impl + Add + Algebraic> Dot for Vec3 { self.x * other.x + self.y * other.y + self.z * other.z } } -impl + Add + Quot + Algebraic> +impl + Add + Div + Algebraic> Norm for Vec3 { fn sqnorm(&self) -> T @@ -174,7 +174,7 @@ impl Zero for Vec3 } impl + Ord + Mul + Sub + Add + - Quot + Algebraic> + Div + Algebraic> Basis for Vec3 { fn canonical_basis() -> ~[Vec3] @@ -197,26 +197,29 @@ Basis for Vec3 } } -impl> FuzzyEq for Vec3 +impl> ApproxEq for Vec3 { - fn fuzzy_eq(&self, other: &Vec3) -> bool + fn approx_epsilon() -> T + { ApproxEq::approx_epsilon::() } + + fn approx_eq(&self, other: &Vec3) -> bool { - self.x.fuzzy_eq(&other.x) && - self.y.fuzzy_eq(&other.y) && - self.z.fuzzy_eq(&other.z) + self.x.approx_eq(&other.x) && + self.y.approx_eq(&other.y) && + self.z.approx_eq(&other.z) } - fn fuzzy_eq_eps(&self, other: &Vec3, epsilon: &T) -> bool + fn approx_eq_eps(&self, other: &Vec3, epsilon: &T) -> bool { - self.x.fuzzy_eq_eps(&other.x, epsilon) && - self.y.fuzzy_eq_eps(&other.y, epsilon) && - self.z.fuzzy_eq_eps(&other.z, epsilon) + self.x.approx_eq_eps(&other.x, epsilon) && + self.y.approx_eq_eps(&other.y, epsilon) && + self.z.approx_eq_eps(&other.z, epsilon) } } impl Rand for Vec3 { - fn rand(rng: &R) -> Vec3 + fn rand(rng: &mut R) -> Vec3 { vec3(rng.gen(), rng.gen(), rng.gen()) } } diff --git a/src/nalgebra.rc b/src/nalgebra.rc index 9a2d05fe..b79749e2 100644 --- a/src/nalgebra.rc +++ b/src/nalgebra.rc @@ -1,3 +1,11 @@ +/*! + +# The n-dimensional linear algebra library. + +*/ + + + #[link(name = "nalgebra" , vers = "0.0" , author = "Sébastien Crozet" @@ -7,61 +15,72 @@ extern mod std; -mod dim2 +/// 1-dimensional linear algebra. +pub mod dim1 { - mod vec2; - mod mat2; + pub mod vec1; + pub mod mat1; } -mod dim1 +/// 2-dimensional linear algebra. +pub mod dim2 { - mod vec1; - mod mat1; + pub mod vec2; + pub mod mat2; } -mod dim3 +/// 3-dimensional linear algebra. +pub mod dim3 { - mod vec3; - mod mat3; + pub mod vec3; + pub mod mat3; } -mod ndim +/// n-dimensional linear algebra (slower). +pub mod ndim { - mod nvec; - mod nmat; + pub mod nvec; + pub mod nmat; } -mod adaptors +/// Wrappers around raw matrices to restrict their behaviour. +pub mod adaptors { - mod rotmat; - mod transform; + pub mod rotmat; + pub mod transform; } -mod traits +/// Useful linear-algebra related traits. +pub mod traits { - mod dot; - mod cross; - mod inv; - mod transpose; - mod dim; - mod basis; - mod norm; - mod rotation; - mod translation; - mod delta_transform; - mod vector_space; - mod ring; - mod division_ring; + pub mod dot; + pub mod cross; + pub mod inv; + pub mod transpose; + pub mod dim; + pub mod basis; + pub mod norm; + pub mod rotation; + pub mod translation; + pub mod delta_transform; + pub mod vector_space; + pub mod ring; + pub mod division_ring; - mod workarounds + /// This package contains everything done because the current compiler either + /// crashes or miss features. + /// Therefore, keep in mind anything in there will be inevitably removed some + /// days. So dont rely on them too much. + pub mod workarounds { - mod rlmul; - mod scalar_op; + pub mod rlmul; + pub mod scalar_op; } } -mod tests +#[cfg(test)] +pub mod tests { - mod mat; - mod vec; + pub mod mat; + pub mod vec; } diff --git a/src/ndim/nmat.rs b/src/ndim/nmat.rs index 9dec7038..e9c9452b 100644 --- a/src/ndim/nmat.rs +++ b/src/ndim/nmat.rs @@ -1,7 +1,7 @@ use core::num::{One, Zero}; use core::rand::{Rand, Rng, RngUtil}; use core::vec::{from_elem, swap, all, all2}; -use std::cmp::FuzzyEq; +use core::cmp::ApproxEq; use traits::dim::Dim; use traits::inv::Inv; use traits::transpose::Transpose; @@ -136,7 +136,7 @@ LMul> for NMat impl + Quot + Sub + Neg> + Mul + Div + Sub + Neg> Inv for NMat { fn inverse(&self) -> NMat @@ -194,8 +194,13 @@ Inv for NMat for uint::range(k, dim) |j| { - self.set(k, j, &(self[(k, j)] / pivot)); - res.set(k, j, &(res[(k, j)] / pivot)); + // FIXME: not to putting selfal exression directly on the nuction call + // is uggly but does not seem to compile any more… + let selfval = &(self[(k, j)] / pivot); + let resval = &(res[(k, j)] / pivot); + + self.set(k, j, selfval); + res.set(k, j, resval); } for uint::range(0u, dim) |l| @@ -206,8 +211,11 @@ Inv for NMat for uint::range(k, dim) |j| { - self.set(k, j, &(self[(l, j)] - self[(k, j)] * normalizer)); - res.set(k, j, &(res[(l, j)] - res[(k, j)] * normalizer)); + let selfval = &(self[(l, j)] - self[(k, j)] * normalizer); + let resval = &(res[(l, j)] - res[(k, j)] * normalizer); + + self.set(k, j, selfval); + res.set(k, j, resval); } } } @@ -242,18 +250,21 @@ impl Transpose for NMat } } -impl> FuzzyEq for NMat +impl> ApproxEq for NMat { - fn fuzzy_eq(&self, other: &NMat) -> bool - { all2(self.mij, other.mij, |a, b| a.fuzzy_eq(b)) } + fn approx_epsilon() -> T + { ApproxEq::approx_epsilon::() } - fn fuzzy_eq_eps(&self, other: &NMat, epsilon: &T) -> bool - { all2(self.mij, other.mij, |a, b| a.fuzzy_eq_eps(b, epsilon)) } + fn approx_eq(&self, other: &NMat) -> bool + { all2(self.mij, other.mij, |a, b| a.approx_eq(b)) } + + fn approx_eq_eps(&self, other: &NMat, epsilon: &T) -> bool + { all2(self.mij, other.mij, |a, b| a.approx_eq_eps(b, epsilon)) } } impl Rand for NMat { - fn rand(rng: &R) -> NMat + fn rand(rng: &mut R) -> NMat { let dim = Dim::dim::(); let mut res : NMat = Zero::zero(); diff --git a/src/ndim/nvec.rs b/src/ndim/nvec.rs index 536cf8e8..eb20aeea 100644 --- a/src/ndim/nvec.rs +++ b/src/ndim/nvec.rs @@ -1,7 +1,7 @@ use core::num::{Zero, One, Algebraic}; use core::rand::{Rand, Rng, RngUtil}; use core::vec::{map_zip, from_elem, map, all, all2}; -use std::cmp::FuzzyEq; +use core::cmp::ApproxEq; use traits::basis::Basis; use traits::dim::Dim; use traits::dot::Dot; @@ -80,7 +80,7 @@ ScalarMul for NVec } -impl> +impl> ScalarDiv for NVec { fn scalar_div(&self, s: &T) -> NVec @@ -131,7 +131,7 @@ impl> Translation> for NVec { *self = *self + *t; } } -impl + Add + Quot + Algebraic + Zero + +impl + Add + Div + Algebraic + Zero + Clone> Norm for NVec { @@ -163,7 +163,7 @@ Norm for NVec impl + Ord + Mul + Sub + Add + - Quot + Algebraic + Clone + FuzzyEq> + Div + Algebraic + Clone + ApproxEq> Basis for NVec { fn canonical_basis() -> ~[NVec] @@ -206,7 +206,7 @@ Basis for NVec for res.each |v| { elt -= v.scalar_mul(&elt.dot(v)) }; - if (!elt.sqnorm().fuzzy_eq(&Zero::zero())) + if (!elt.sqnorm().approx_eq(&Zero::zero())) { res.push(elt.normalized()); } } @@ -239,18 +239,21 @@ impl Zero for NVec } } -impl> FuzzyEq for NVec +impl> ApproxEq for NVec { - fn fuzzy_eq(&self, other: &NVec) -> bool - { all2(self.at, other.at, |a, b| a.fuzzy_eq(b)) } + fn approx_epsilon() -> T + { ApproxEq::approx_epsilon::() } - fn fuzzy_eq_eps(&self, other: &NVec, epsilon: &T) -> bool - { all2(self.at, other.at, |a, b| a.fuzzy_eq_eps(b, epsilon)) } + fn approx_eq(&self, other: &NVec) -> bool + { all2(self.at, other.at, |a, b| a.approx_eq(b)) } + + fn approx_eq_eps(&self, other: &NVec, epsilon: &T) -> bool + { all2(self.at, other.at, |a, b| a.approx_eq_eps(b, epsilon)) } } impl Rand for NVec { - fn rand(rng: &R) -> NVec + fn rand(rng: &mut R) -> NVec { let dim = Dim::dim::(); let mut res : NVec = Zero::zero(); diff --git a/src/tests/mat.rs b/src/tests/mat.rs index 290615fe..8eb4b34e 100644 --- a/src/tests/mat.rs +++ b/src/tests/mat.rs @@ -3,7 +3,7 @@ use core::num::{One, abs}; #[test] use core::rand::{random}; #[test] -use std::cmp::FuzzyEq; +use core::cmp::ApproxEq; #[test] use traits::inv::Inv; #[test] @@ -25,7 +25,7 @@ use adaptors::rotmat::Rotmat; // { // let randmat : NMat = random(); // -// assert!((randmat.inverse() * randmat).fuzzy_eq(&One::one())); +// assert!((randmat.inverse() * randmat).approx_eq(&One::one())); // } #[test] @@ -35,7 +35,7 @@ fn test_inv_mat1() { let randmat : Mat1 = random(); - assert!((randmat.inverse() * randmat).fuzzy_eq(&One::one())); + assert!((randmat.inverse() * randmat).approx_eq(&One::one())); } } @@ -46,7 +46,7 @@ fn test_inv_mat2() { let randmat : Mat2 = random(); - assert!((randmat.inverse() * randmat).fuzzy_eq(&One::one())); + assert!((randmat.inverse() * randmat).approx_eq(&One::one())); } } @@ -57,7 +57,7 @@ fn test_inv_mat3() { let randmat : Mat3 = random(); - assert!((randmat.inverse() * randmat).fuzzy_eq(&One::one())); + assert!((randmat.inverse() * randmat).approx_eq(&One::one())); } } @@ -69,6 +69,6 @@ fn test_rotation2() let randmat = One::one::>>(); let ang = &vec1(abs::(random()) % f64::consts::pi); - assert!(randmat.rotated(ang).rotation().fuzzy_eq(ang)); + assert!(randmat.rotated(ang).rotation().approx_eq(ang)); } } diff --git a/src/tests/vec.rs b/src/tests/vec.rs index f8593f77..72d552f8 100644 --- a/src/tests/vec.rs +++ b/src/tests/vec.rs @@ -5,7 +5,7 @@ use core::rand::{random}; #[test] use core::vec::{all, all2}; #[test] -use std::cmp::FuzzyEq; +use core::cmp::ApproxEq; #[test] use dim3::vec3::Vec3; #[test] @@ -35,8 +35,8 @@ fn test_cross_vec3() let v2 : Vec3 = random(); let v3 : Vec3 = v1.cross(&v2); - assert!(v3.dot(&v2).fuzzy_eq(&Zero::zero())); - assert!(v3.dot(&v1).fuzzy_eq(&Zero::zero())); + assert!(v3.dot(&v2).approx_eq(&Zero::zero())); + assert!(v3.dot(&v1).approx_eq(&Zero::zero())); } } @@ -48,7 +48,7 @@ fn test_dot_nvec() let v1 : NVec = random(); let v2 : NVec = random(); - assert!(v1.dot(&v2).fuzzy_eq(&v2.dot(&v1))); + assert!(v1.dot(&v2).approx_eq(&v2.dot(&v1))); } } @@ -60,7 +60,7 @@ fn test_commut_dot_vec3() let v1 : Vec3 = random(); let v2 : Vec3 = random(); - assert!(v1.dot(&v2).fuzzy_eq(&v2.dot(&v1))); + assert!(v1.dot(&v2).approx_eq(&v2.dot(&v1))); } } @@ -72,7 +72,7 @@ fn test_commut_dot_vec2() let v1 : Vec2 = random(); let v2 : Vec2 = random(); - assert!(v1.dot(&v2).fuzzy_eq(&v2.dot(&v1))); + assert!(v1.dot(&v2).approx_eq(&v2.dot(&v1))); } } @@ -84,7 +84,7 @@ fn test_commut_dot_vec1() let v1 : Vec1 = random(); let v2 : Vec1 = random(); - assert!(v1.dot(&v2).fuzzy_eq(&v2.dot(&v1))); + assert!(v1.dot(&v2).approx_eq(&v2.dot(&v1))); } } @@ -94,9 +94,9 @@ fn test_basis_vec1() let basis = Basis::canonical_basis::>(); // check vectors form an ortogonal basis - assert!(all2(basis, basis, |e1, e2| e1 == e2 || e1.dot(e2).fuzzy_eq(&Zero::zero()))); + assert!(all2(basis, basis, |e1, e2| e1 == e2 || e1.dot(e2).approx_eq(&Zero::zero()))); // check vectors form an orthonormal basis - assert!(all(basis, |e| e.norm().fuzzy_eq(&One::one()))); + assert!(all(basis, |e| e.norm().approx_eq(&One::one()))); } #[test] @@ -105,9 +105,9 @@ fn test_basis_vec2() let basis = Basis::canonical_basis::>(); // check vectors form an ortogonal basis - assert!(all2(basis, basis, |e1, e2| e1 == e2 || e1.dot(e2).fuzzy_eq(&Zero::zero()))); + assert!(all2(basis, basis, |e1, e2| e1 == e2 || e1.dot(e2).approx_eq(&Zero::zero()))); // check vectors form an orthonormal basis - assert!(all(basis, |e| e.norm().fuzzy_eq(&One::one()))); + assert!(all(basis, |e| e.norm().approx_eq(&One::one()))); } #[test] @@ -116,9 +116,9 @@ fn test_basis_vec3() let basis = Basis::canonical_basis::>(); // check vectors form an ortogonal basis - assert!(all2(basis, basis, |e1, e2| e1 == e2 || e1.dot(e2).fuzzy_eq(&Zero::zero()))); + assert!(all2(basis, basis, |e1, e2| e1 == e2 || e1.dot(e2).approx_eq(&Zero::zero()))); // check vectors form an orthonormal basis - assert!(all(basis, |e| e.norm().fuzzy_eq(&One::one()))); + assert!(all(basis, |e| e.norm().approx_eq(&One::one()))); } #[test] @@ -127,9 +127,9 @@ fn test_basis_nvec() let basis = Basis::canonical_basis::>(); // check vectors form an ortogonal basis - assert!(all2(basis, basis, |e1, e2| e1 == e2 || e1.dot(e2).fuzzy_eq(&Zero::zero()))); + assert!(all2(basis, basis, |e1, e2| e1 == e2 || e1.dot(e2).approx_eq(&Zero::zero()))); // check vectors form an orthonormal basis - assert!(all(basis, |e| e.norm().fuzzy_eq(&One::one()))); + assert!(all(basis, |e| e.norm().approx_eq(&One::one()))); } #[test] @@ -142,11 +142,11 @@ fn test_subspace_basis_vec1() let subbasis = v1.orthogonal_subspace_basis(); // check vectors are orthogonal to v1 - assert!(all(subbasis, |e| v1.dot(e).fuzzy_eq(&Zero::zero()))); + assert!(all(subbasis, |e| v1.dot(e).approx_eq(&Zero::zero()))); // check vectors form an ortogonal basis - assert!(all2(subbasis, subbasis, |e1, e2| e1 == e2 || e1.dot(e2).fuzzy_eq(&Zero::zero()))); + assert!(all2(subbasis, subbasis, |e1, e2| e1 == e2 || e1.dot(e2).approx_eq(&Zero::zero()))); // check vectors form an orthonormal basis - assert!(all(subbasis, |e| e.norm().fuzzy_eq(&One::one()))); + assert!(all(subbasis, |e| e.norm().approx_eq(&One::one()))); } } @@ -160,11 +160,11 @@ fn test_subspace_basis_vec2() let subbasis = v1.orthogonal_subspace_basis(); // check vectors are orthogonal to v1 - assert!(all(subbasis, |e| v1.dot(e).fuzzy_eq(&Zero::zero()))); + assert!(all(subbasis, |e| v1.dot(e).approx_eq(&Zero::zero()))); // check vectors form an ortogonal basis - assert!(all2(subbasis, subbasis, |e1, e2| e1 == e2 || e1.dot(e2).fuzzy_eq(&Zero::zero()))); + assert!(all2(subbasis, subbasis, |e1, e2| e1 == e2 || e1.dot(e2).approx_eq(&Zero::zero()))); // check vectors form an orthonormal basis - assert!(all(subbasis, |e| e.norm().fuzzy_eq(&One::one()))); + assert!(all(subbasis, |e| e.norm().approx_eq(&One::one()))); } } @@ -178,11 +178,11 @@ fn test_subspace_basis_vec3() let subbasis = v1.orthogonal_subspace_basis(); // check vectors are orthogonal to v1 - assert!(all(subbasis, |e| v1.dot(e).fuzzy_eq(&Zero::zero()))); + assert!(all(subbasis, |e| v1.dot(e).approx_eq(&Zero::zero()))); // check vectors form an ortogonal basis - assert!(all2(subbasis, subbasis, |e1, e2| e1 == e2 || e1.dot(e2).fuzzy_eq(&Zero::zero()))); + assert!(all2(subbasis, subbasis, |e1, e2| e1 == e2 || e1.dot(e2).approx_eq(&Zero::zero()))); // check vectors form an orthonormal basis - assert!(all(subbasis, |e| e.norm().fuzzy_eq(&One::one()))); + assert!(all(subbasis, |e| e.norm().approx_eq(&One::one()))); } } @@ -198,10 +198,10 @@ fn test_subspace_basis_vec3() // let subbasis = v1.orthogonal_subspace_basis(); // // // check vectors are orthogonal to v1 -// assert!(all(subbasis, |e| v1.dot(e).fuzzy_eq(&Zero::zero()))); +// assert!(all(subbasis, |e| v1.dot(e).approx_eq(&Zero::zero()))); // // check vectors form an ortogonal basis -// assert!(all2(subbasis, subbasis, |e1, e2| e1 == e2 || e1.dot(e2).fuzzy_eq(&Zero::zero()))); +// assert!(all2(subbasis, subbasis, |e1, e2| e1 == e2 || e1.dot(e2).approx_eq(&Zero::zero()))); // // check vectors form an orthonormal basis -// assert!(all(subbasis, |e| e.norm().fuzzy_eq(&One::one()))); +// assert!(all(subbasis, |e| e.norm().approx_eq(&One::one()))); // } // } diff --git a/src/traits/basis.rs b/src/traits/basis.rs index 9fca5b86..a25cae60 100644 --- a/src/traits/basis.rs +++ b/src/traits/basis.rs @@ -1,5 +1,7 @@ pub trait Basis { - fn canonical_basis() -> ~[Self]; // FIXME: is it the right pointer? + /// Computes the canonical basis of the space in which this object lives. + // FIXME: need type-associated values + fn canonical_basis() -> ~[Self]; fn orthogonal_subspace_basis(&self) -> ~[Self]; } diff --git a/src/traits/cross.rs b/src/traits/cross.rs index 87fafae2..2d795b3e 100644 --- a/src/traits/cross.rs +++ b/src/traits/cross.rs @@ -1,3 +1,6 @@ +/** + * Trait of elements having a cross product. + */ pub trait Cross { /// Computes the cross product between two elements (usually vectors). diff --git a/src/traits/delta_transform.rs b/src/traits/delta_transform.rs index 93bd96a9..73f16c33 100644 --- a/src/traits/delta_transform.rs +++ b/src/traits/delta_transform.rs @@ -1,6 +1,8 @@ -/// A delta-transformation is the generalization of rotation. A delta transform -/// can apply any transformation to the object without translating it. -/// In partilular, 0 is neutral wrt. the delta-transform. +/** + * A delta-transformation is the generalization of rotation. A delta transform + * can apply any transformation to the object without translating it. + * In partilular, 0 is neutral wrt. the delta-transform. + */ pub trait DeltaTransform
{ /// Extracts the delta transformation associated with this transformation. diff --git a/src/traits/dim.rs b/src/traits/dim.rs index e58e8ed6..6cc56c66 100644 --- a/src/traits/dim.rs +++ b/src/traits/dim.rs @@ -1,3 +1,6 @@ +/** + * Trait of objects having a dimension (in term of spacial dimension). + */ pub trait Dim { /// The dimension of the object. fn dim() -> uint; @@ -5,6 +8,7 @@ pub trait Dim { // Some dimension token. Useful to restrict the dimension of n-dimensional // object at the type-level. + /// Dimensional token for 0-dimensions. Dimensional tokens are the preferred /// way to specify at the type level the dimension of n-dimensional objects. #[deriving(Eq)] diff --git a/src/traits/division_ring.rs b/src/traits/division_ring.rs index ae1d3f5f..69394c6e 100644 --- a/src/traits/division_ring.rs +++ b/src/traits/division_ring.rs @@ -1,4 +1,8 @@ use traits::ring::Ring; -pub trait DivisionRing : Ring + Quot +/** + * Trait of elements of a division ring. A division ring is an algebraic + * structure like a ring, but with the division operator. + */ +pub trait DivisionRing : Ring + Div { } diff --git a/src/traits/dot.rs b/src/traits/dot.rs index 05ae90ea..256aed98 100644 --- a/src/traits/dot.rs +++ b/src/traits/dot.rs @@ -1,3 +1,6 @@ +/** + * Trait of objects having a dot product (also called inner product). + */ pub trait Dot { /// Computes the dot (inner) product of two objects. diff --git a/src/traits/inv.rs b/src/traits/inv.rs index 4b5dc283..fc42bebe 100644 --- a/src/traits/inv.rs +++ b/src/traits/inv.rs @@ -1,3 +1,6 @@ +/** + * Trait of inversible objects. Typically used to implement matrix inverse. + */ pub trait Inv { /// Returns the inverse of an element. diff --git a/src/traits/norm.rs b/src/traits/norm.rs index 109b6d30..90a20cc3 100644 --- a/src/traits/norm.rs +++ b/src/traits/norm.rs @@ -1,3 +1,6 @@ +/** + * Trait of objects having a L² norm and which can be normalized. + */ pub trait Norm { /// Computes the norm a an object. @@ -11,9 +14,9 @@ pub trait Norm */ fn sqnorm(&self) -> T; - /// Returns the normalized version of the argument. + /// Gets the normalized version of the argument. fn normalized(&self) -> Self; - /// Inplace version of `normalized`. + /// In-place version of `normalized`. fn normalize(&mut self) -> T; } diff --git a/src/traits/ring.rs b/src/traits/ring.rs index 418b4af0..fbc49e91 100644 --- a/src/traits/ring.rs +++ b/src/traits/ring.rs @@ -1,5 +1,11 @@ use core::num::{One, Zero}; +/** + * Trait of elements of a ring. A rings is an algebraic structure, the + * elements of which have all the common numeric operation but the division: + * addition, subtraction, multiplication and distinct elements (`One` and + * `Zero`) respectively neutral and absorbant wrt the multiplication. + */ pub trait Ring : Sub + Add + Neg + Mul + One + Zero { } diff --git a/src/traits/rotation.rs b/src/traits/rotation.rs index 7a0307d3..59b6c499 100644 --- a/src/traits/rotation.rs +++ b/src/traits/rotation.rs @@ -1,6 +1,15 @@ +/// Trait of object which represent a rotation, and to wich new rotations can +/// be appended. A rotation is assumed to be an isomitry without translation +/// and without reflexion. pub trait Rotation { + /// Gets the rotation associated with this object. fn rotation(&self) -> V; + + /// Appends a rotation from an alternative representation. Such + /// representation has the same format as the one returned by `rotation`. fn rotated(&self, &V) -> Self; + + /// In-place version of `rotated`. fn rotate(&mut self, &V); } diff --git a/src/traits/translation.rs b/src/traits/translation.rs index 1e1e58ae..58fd7cdd 100644 --- a/src/traits/translation.rs +++ b/src/traits/translation.rs @@ -1,6 +1,14 @@ +/// Trait of object which represent a translation, and to wich new translation +/// can be appended. pub trait Translation { + /// Gets the translation associated with this object. fn translation(&self) -> V; + + /// Appends a translation from an alternative representation. Such + /// representation has the same format as the one returned by `translation`. fn translated(&self, &V) -> Self; + + /// In-place version of `translate`. fn translate(&mut self, &V); } diff --git a/src/traits/transpose.rs b/src/traits/transpose.rs index 4eedec92..552648ff 100644 --- a/src/traits/transpose.rs +++ b/src/traits/transpose.rs @@ -1,8 +1,12 @@ // FIXME: valid only for square matrices… +/// Trait of objects which can be transposed. Note that, for the moment, this +/// does not allow the implementation by non-square matrix (or anything which +/// is not stable by transposition). pub trait Transpose { /// Computes the transpose of a matrix. fn transposed(&self) -> Self; - /// Inplace version of `transposed`. + + /// In-place version of `transposed`. fn transpose(&mut self); } diff --git a/src/traits/vector_space.rs b/src/traits/vector_space.rs index 986bd0a2..4dd5acc8 100644 --- a/src/traits/vector_space.rs +++ b/src/traits/vector_space.rs @@ -2,6 +2,11 @@ use core::num::Zero; use traits::division_ring::DivisionRing; use traits::workarounds::scalar_op::{ScalarMul, ScalarDiv}; -pub trait VectorSpace : Sub + Add + - Neg + Zero + ScalarMul + ScalarDiv +/// Trait of elements of a vector space. A vector space is an algebraic +/// structure, the elements of which have addition, substraction, negation, +/// scalar multiplication (the scalar being a element of a `DivisionRing`), and +/// has a distinct element (`Zero`) neutral wrt the addition. +pub trait VectorSpace +: Sub + Add + Neg + Zero + + ScalarMul + ScalarDiv { } diff --git a/src/traits/workarounds/README b/src/traits/workarounds/README deleted file mode 100644 index c40aa4a6..00000000 --- a/src/traits/workarounds/README +++ /dev/null @@ -1,4 +0,0 @@ -This packages contains everything done because current compiler either -bugs or miss features. -Therefore, keep in mind anything in there will be inevitably removed some days. -So dont rely on them too much. diff --git a/src/traits/workarounds/rlmul.rs b/src/traits/workarounds/rlmul.rs index 7e2a5758..4d11c6bf 100644 --- a/src/traits/workarounds/rlmul.rs +++ b/src/traits/workarounds/rlmul.rs @@ -1,8 +1,12 @@ -/** This is a workaround of the fact we cannot implement the same trait - * (with different type parameters) twice for the same type: +/** + * Trait of objects having a right multiplication with another element. + * This is a workaround of the fact we cannot implement the same trait + * (with different type parameters) twice for the same type. The following + * exemple does not compile (end with an ICE): + * * ~~~ - * trait Mul for M - * trait Mul for M + * trait Mul for M + * trait Mul for M * ~~~ */ pub trait RMul @@ -11,6 +15,17 @@ pub trait RMul fn rmul(&self, v : &V) -> V; } +/** + * Trait of objects having a left multiplication with another element. + * This is a workaround of the fact we cannot implement the same trait + * (with different type parameters) twice for the same type. The following + * exemple does not compile (end with an ICE): + * + * ~~~ + * trait Mul for M + * trait Mul for M + * ~~~ + */ pub trait LMul { /// Computes v * self diff --git a/src/traits/workarounds/scalar_op.rs b/src/traits/workarounds/scalar_op.rs index bcd0ba80..720a910b 100644 --- a/src/traits/workarounds/scalar_op.rs +++ b/src/traits/workarounds/scalar_op.rs @@ -1,23 +1,79 @@ +/** + * Trait of objects having a multiplication with a scalar. + * This is a workaround of the fact we cannot implement the same trait + * (with different type parameters) twice for the same type. The following + * exemple does not compile (end with an ICE): + * + * ~~~ + * trait Mul for T + * trait Mul for T + * ~~~ + */ pub trait ScalarMul { + /// Gets the result of a multiplication by a scalar. fn scalar_mul(&self, &T) -> Self; + + /// In-place version of `scalar_mul`. fn scalar_mul_inplace(&mut self, &T); } +/** + * Trait of objects having a division with a scalar. + * This is a workaround of the fact we cannot implement the same trait + * (with different type parameters) twice for the same type. The following + * exemple does not compile (end with an ICE): + * + * ~~~ + * trait Div for T + * trait Div for T + * ~~~ + */ pub trait ScalarDiv { + /// Gets the result of a division by a scalar. fn scalar_div(&self, &T) -> Self; + + /// In-place version of `scalar_div`. fn scalar_div_inplace(&mut self, &T); } +/** + * Trait of objects having an addition with a scalar. + * This is a workaround of the fact we cannot implement the same trait + * (with different type parameters) twice for the same type. The following + * exemple does not compile (end with an ICE): + * + * ~~~ + * trait Add for T + * trait Add for T + * ~~~ + */ pub trait ScalarAdd { + /// Gets the result of an addition by a scalar. fn scalar_add(&self, &T) -> Self; + + /// In-place version of `scalar_add`. fn scalar_add_inplace(&mut self, &T); } +/** + * Trait of objects having a subtraction with a scalar. + * This is a workaround of the fact we cannot implement the same trait + * (with different type parameters) twice for the same type. The following + * exemple does not compile (end with an ICE): + * + * ~~~ + * trait Sub for T + * trait Sub for T + * ~~~ + */ pub trait ScalarSub { + /// Gets the result of a subtraction by a scalar. fn scalar_sub(&self, &T) -> Self; + + /// In-place version of `scalar_sub`. fn scalar_sub_inplace(&mut self, &T); }