From 890cdb73f2f8ef8968afbb7e982b52f0a996a0d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Sat, 18 May 2013 17:04:03 +0000 Subject: [PATCH] Add tests and basis generation. --- Makefile | 10 +- src/dim1/vec1.rs | 29 +++- src/dim2/vec2.rs | 38 ++++- src/dim3/mat3.rs | 2 +- src/dim3/vec3.rs | 50 ++++++- src/nalgebra.rc | 12 ++ src/ndim/nvec.rs | 148 +++++++++++++++++-- src/tests/mat.rs | 63 +++++++++ src/tests/vec.rs | 212 ++++++++++++++++++++++++++++ src/traits/basis.rs | 5 + src/traits/dim.rs | 36 ++++- src/traits/dot.rs | 9 -- src/traits/norm.rs | 19 +++ src/traits/workarounds/scalar_op.rs | 12 ++ 14 files changed, 617 insertions(+), 28 deletions(-) create mode 100644 src/tests/mat.rs create mode 100644 src/tests/vec.rs create mode 100644 src/traits/basis.rs create mode 100644 src/traits/norm.rs create mode 100644 src/traits/workarounds/scalar_op.rs diff --git a/Makefile b/Makefile index 81dc2535..d616d6ee 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,11 @@ +nalgebra_lib_path=lib all: - rust build src/nalgebra.rc --out-dir lib # rustpkg install + rust build src/nalgebra.rc --out-dir $(nalgebra_lib_path) + +test: + rust test src/nalgebra.rc doc: - rust doc src/nalgebra.rc --output-dir doc + rust test src/nalgebra.rc -.PHONY:doc +.PHONY:doc, test diff --git a/src/dim1/vec1.rs b/src/dim1/vec1.rs index 0bd2ad2e..20e8bd24 100644 --- a/src/dim1/vec1.rs +++ b/src/dim1/vec1.rs @@ -1,8 +1,10 @@ -use core::num::{Zero, Algebraic}; +use core::num::{Zero, One, Algebraic}; use core::rand::{Rand, Rng, RngUtil}; use std::cmp::FuzzyEq; use traits::dot::Dot; use traits::dim::Dim; +use traits::basis::Basis; +use traits::norm::Norm; #[deriving(Eq)] pub struct Vec1 @@ -33,12 +35,28 @@ impl + Add + Algebraic> Dot for Vec1 { fn dot(&self, other : &Vec1) -> T { self.x * other.x } +} +impl + Add + Quot + Algebraic> +Norm for Vec1 +{ fn sqnorm(&self) -> T { self.dot(self) } fn norm(&self) -> T { self.sqnorm().sqrt() } + + fn normalized(&self) -> Vec1 + { Vec1(self.x / self.norm()) } + + fn normalize(&mut self) -> T + { + let l = self.norm(); + + self.x /= l; + + l + } } impl> Neg> for Vec1 @@ -59,6 +77,15 @@ impl Zero for Vec1 { self.x.is_zero() } } +impl Basis for Vec1 +{ + fn canonical_basis() -> ~[Vec1] + { ~[ Vec1(One::one()) ] } // FIXME: this should be static + + fn orthogonal_subspace_basis(&self) -> ~[Vec1] + { ~[] } +} + impl> FuzzyEq for Vec1 { fn fuzzy_eq(&self, other: &Vec1) -> bool diff --git a/src/dim2/vec2.rs b/src/dim2/vec2.rs index 1a603200..0d23228f 100644 --- a/src/dim2/vec2.rs +++ b/src/dim2/vec2.rs @@ -1,9 +1,11 @@ -use core::num::{Zero, Algebraic}; +use core::num::{Zero, One, Algebraic}; use core::rand::{Rand, Rng, RngUtil}; use std::cmp::FuzzyEq; use traits::dot::Dot; use traits::dim::Dim; use traits::cross::Cross; +use traits::basis::Basis; +use traits::norm::Norm; use dim1::vec1::Vec1; #[deriving(Eq)] @@ -38,12 +40,33 @@ impl + Add + Algebraic> Dot for Vec2 { fn dot(&self, other : &Vec2) -> T { self.x * other.x + self.y * other.y } +} +impl + Add + Quot + Algebraic> +Norm for Vec2 +{ fn sqnorm(&self) -> T { self.dot(self) } fn norm(&self) -> T { self.sqnorm().sqrt() } + + fn normalized(&self) -> Vec2 + { + let l = self.norm(); + + Vec2(self.x / l, self.y / l) + } + + fn normalize(&mut self) -> T + { + let l = self.norm(); + + self.x /= l; + self.y /= l; + + l + } } impl + Sub> Cross> for Vec2 @@ -70,6 +93,19 @@ impl Zero for Vec2 { self.x.is_zero() && self.y.is_zero() } } +impl> Basis for Vec2 +{ + fn canonical_basis() -> ~[Vec2] + { + // FIXME: this should be static + ~[ Vec2(One::one(), Zero::zero()), + Vec2(Zero::zero(), One::one()) ] + } + + fn orthogonal_subspace_basis(&self) -> ~[Vec2] + { ~[ Vec2(-self.y, self.x) ] } +} + impl> FuzzyEq for Vec2 { fn fuzzy_eq(&self, other: &Vec2) -> bool diff --git a/src/dim3/mat3.rs b/src/dim3/mat3.rs index d86a5e43..81c3cc54 100644 --- a/src/dim3/mat3.rs +++ b/src/dim3/mat3.rs @@ -128,7 +128,7 @@ Inv for Mat3 - self.m12 * minor_m21_m33 + self.m13 * minor_m21_m32; - assert!(det.is_zero()); + assert!(!det.is_zero()); *self = Mat3( (minor_m22_m33 / det), diff --git a/src/dim3/vec3.rs b/src/dim3/vec3.rs index 1cfc5875..ef0c7cee 100644 --- a/src/dim3/vec3.rs +++ b/src/dim3/vec3.rs @@ -1,9 +1,11 @@ -use core::num::{Zero, Algebraic}; +use core::num::{Zero, One, Algebraic, abs}; use core::rand::{Rand, Rng, RngUtil}; use std::cmp::FuzzyEq; use traits::dim::Dim; use traits::dot::Dot; use traits::cross::Cross; +use traits::basis::Basis; +use traits::norm::Norm; #[deriving(Eq)] pub struct Vec3 @@ -44,12 +46,34 @@ impl + Add + Algebraic> Dot for Vec3 { fn dot(&self, other : &Vec3) -> T { self.x * other.x + self.y * other.y + self.z * other.z } +} +impl + Add + Quot + Algebraic> +Norm for Vec3 +{ fn sqnorm(&self) -> T { self.dot(self) } fn norm(&self) -> T { self.sqnorm().sqrt() } + + fn normalized(&self) -> Vec3 + { + let l = self.norm(); + + Vec3(self.x / l, self.y / l, self.z / l) + } + + fn normalize(&mut self) -> T + { + let l = self.norm(); + + self.x /= l; + self.y /= l; + self.z /= l; + + l + } } impl + Sub> Cross> for Vec3 @@ -76,6 +100,30 @@ impl Zero for Vec3 { self.x.is_zero() && self.y.is_zero() && self.z.is_zero() } } +impl + Ord + Mul + Sub + Add + + Quot + Algebraic> +Basis for Vec3 +{ + fn canonical_basis() -> ~[Vec3] + { + // FIXME: this should be static + ~[ Vec3(One::one(), Zero::zero(), Zero::zero()), + Vec3(Zero::zero(), One::one(), Zero::zero()), + Vec3(Zero::zero(), Zero::zero(), One::one()) ] + } + + fn orthogonal_subspace_basis(&self) -> ~[Vec3] + { + let a = + if (abs(self.x) > abs(self.y)) + { Vec3(self.z, Zero::zero(), -self.x).normalized() } + else + { Vec3(Zero::zero(), -self.z, self.y).normalized() }; + + ~[ a, a.cross(self) ] + } +} + impl> FuzzyEq for Vec3 { fn fuzzy_eq(&self, other: &Vec3) -> bool diff --git a/src/nalgebra.rc b/src/nalgebra.rc index 27956944..137dd029 100644 --- a/src/nalgebra.rc +++ b/src/nalgebra.rc @@ -27,9 +27,12 @@ pub use traits::cross::Cross; pub use traits::dim::Dim; pub use traits::inv::Inv; pub use traits::transpose::Transpose; +pub use traits::basis::Basis; +pub use traits::norm::Norm; pub use traits::workarounds::rlmul::{RMul, LMul}; pub use traits::workarounds::trigonometric::Trigonometric; +pub use traits::workarounds::scalar_op::ScalarOp; mod dim2 { @@ -68,10 +71,19 @@ mod traits mod inv; mod transpose; mod dim; + mod basis; + mod norm; mod workarounds { mod rlmul; mod trigonometric; + mod scalar_op; } } + +mod tests +{ + mod mat; + mod vec; +} diff --git a/src/ndim/nvec.rs b/src/ndim/nvec.rs index abfda5bd..ec389c1c 100644 --- a/src/ndim/nvec.rs +++ b/src/ndim/nvec.rs @@ -1,9 +1,12 @@ -use core::vec::{map_zip, from_elem, map, all, all2}; +use core::num::{Zero, One, Algebraic}; use core::rand::{Rand, Rng, RngUtil}; -use core::num::{Zero, Algebraic}; +use core::vec::{map_zip, from_elem, map, all, all2}; use std::cmp::FuzzyEq; use traits::dim::Dim; use traits::dot::Dot; +use traits::norm::Norm; +use traits::basis::Basis; +use traits::workarounds::scalar_op::ScalarOp; // D is a phantom parameter, used only as a dimensional token. // Its allows use to encode the vector dimension at the type-level. @@ -24,25 +27,31 @@ impl Dim for NVec { Dim::dim::() } } -impl> Add, NVec> for NVec +impl Clone for NVec +{ + fn clone(&self) -> NVec + { NVec{ at: self.at.clone() } } +} + +impl> Add, NVec> for NVec { fn add(&self, other: &NVec) -> NVec { NVec { at: map_zip(self.at, other.at, | a, b | { *a + *b }) } } } -impl> Sub, NVec> for NVec +impl> Sub, NVec> for NVec { fn sub(&self, other: &NVec) -> NVec { NVec { at: map_zip(self.at, other.at, | a, b | *a - *b) } } } -impl> Neg> for NVec +impl> Neg> for NVec { fn neg(&self) -> NVec { NVec { at: map(self.at, |a| -a) } } } -impl + Add + Algebraic + Zero> +impl + Add + Algebraic + Zero> Dot for NVec { fn dot(&self, other: &NVec) -> T @@ -54,23 +63,142 @@ Dot for NVec res } +} +impl + Quot + Add + Sub> +ScalarOp for NVec +{ + fn scalar_mul(&self, s: &T) -> NVec + { NVec { at: map(self.at, |a| a * *s) } } + + fn scalar_div(&self, s: &T) -> NVec + { NVec { at: map(self.at, |a| a / *s) } } + + fn scalar_add(&self, s: &T) -> NVec + { NVec { at: map(self.at, |a| a + *s) } } + + fn scalar_sub(&self, s: &T) -> NVec + { NVec { at: map(self.at, |a| a - *s) } } + + fn scalar_mul_inplace(&mut self, s: &T) + { + for uint::range(0u, Dim::dim::()) |i| + { self.at[i] *= *s; } + } + + fn scalar_div_inplace(&mut self, s: &T) + { + for uint::range(0u, Dim::dim::()) |i| + { self.at[i] /= *s; } + } + + fn scalar_add_inplace(&mut self, s: &T) + { + for uint::range(0u, Dim::dim::()) |i| + { self.at[i] += *s; } + } + + fn scalar_sub_inplace(&mut self, s: &T) + { + for uint::range(0u, Dim::dim::()) |i| + { self.at[i] -= *s; } + } +} + +impl + Add + Quot + Algebraic + Zero + + Clone> +Norm for NVec +{ fn sqnorm(&self) -> T { self.dot(self) } fn norm(&self) -> T { self.sqnorm().sqrt() } + + fn normalized(&self) -> NVec + { + let mut res : NVec = self.clone(); + + res.normalize(); + + res + } + + fn normalize(&mut self) -> T + { + let l = self.norm(); + + for uint::range(0u, Dim::dim::()) |i| + { self.at[i] /= l; } + + l + } +} + +impl + Ord + Mul + Sub + Add + + Quot + Algebraic + Clone + FuzzyEq> +Basis for NVec +{ + fn canonical_basis() -> ~[NVec] + { + let dim = Dim::dim::(); + let mut res : ~[NVec] = ~[]; + + for uint::range(0u, dim) |i| + { + let mut basis_element : NVec = Zero::zero(); + + basis_element.at[i] = One::one(); + + res.push(basis_element); + } + + res + } + + fn orthogonal_subspace_basis(&self) -> ~[NVec] + { + // compute the basis of the orthogonal subspace using Gram-Schmidt + // orthogonalization algorithm + let dim = Dim::dim::(); + let mut res : ~[NVec] = ~[]; + + for uint::range(0u, dim) |i| + { + let mut basis_element : NVec = Zero::zero(); + + basis_element.at[i] = One::one(); + + if (res.len() == dim - 1) + { break; } + + let mut elt = basis_element.clone(); + + elt -= self.scalar_mul(&basis_element.dot(self)); + + for res.each |v| + { elt -= v.scalar_mul(&elt.dot(v)) }; + + if (!elt.sqnorm().fuzzy_eq(&Zero::zero())) + { res.push(elt.normalized()); } + } + + assert!(res.len() == dim - 1); + + res + } } // FIXME: I dont really know how te generalize the cross product int // n-dimensions… -// impl + Sub> Cross for NVec +// impl + Sub> Cross for NVec // { // fn cross(&self, other: &NVec) -> T // { self.x * other.y - self.y * other.x } // } -impl Zero for NVec +impl Zero for NVec { fn zero() -> NVec { @@ -85,7 +213,7 @@ impl Zero for NVec } } -impl> FuzzyEq for NVec +impl> FuzzyEq for NVec { fn fuzzy_eq(&self, other: &NVec) -> bool { all2(self.at, other.at, |a, b| a.fuzzy_eq(b)) } @@ -108,7 +236,7 @@ impl Rand for NVec } } -impl ToStr for NVec +impl ToStr for NVec { fn to_str(&self) -> ~str { ~"Vec" + Dim::dim::().to_str() + self.at.to_str() } diff --git a/src/tests/mat.rs b/src/tests/mat.rs new file mode 100644 index 00000000..8b8e6c6a --- /dev/null +++ b/src/tests/mat.rs @@ -0,0 +1,63 @@ +#[test] +use core::num::{One}; +#[test] +use core::rand::{random}; +#[test] +use std::cmp::FuzzyEq; +// #[test] +// use ndim::nmat::NMat; +#[test] +use dim1::mat1::Mat1; +#[test] +use dim2::mat2::Mat2; +#[test] +use dim3::mat3::Mat3; +// #[test] +// use traits::dim::d7; + +// FIXME: this one fails with an ICE: node_id_to_type: no type for node [...] +// #[test] +// fn test_inv_nmat() +// { +// let randmat : NMat = random(); +// +// assert!((randmat.inverse() * randmat).fuzzy_eq(&One::one())); +// } + +#[test] +fn test_inv_mat1() +{ + for uint::range(0u, 10000u) |_| + { + let randmat : Mat1 = random(); + + assert!((randmat.inverse() * randmat).fuzzy_eq(&One::one())); + } +} + +#[test] +fn test_inv_mat2() +{ + for uint::range(0u, 10000u) |_| + { + let randmat : Mat2 = random(); + + assert!((randmat.inverse() * randmat).fuzzy_eq(&One::one())); + } +} + +#[test] +fn test_inv_mat3() +{ + for uint::range(0u, 10000u) |_| + { + let randmat : Mat3 = random(); + + assert!((randmat.inverse() * randmat).fuzzy_eq(&One::one())); + } +} + +#[test] +fn test_rot2() +{ +} diff --git a/src/tests/vec.rs b/src/tests/vec.rs new file mode 100644 index 00000000..50d0b392 --- /dev/null +++ b/src/tests/vec.rs @@ -0,0 +1,212 @@ +#[test] +use core::num::{Zero, One}; +#[test] +use core::rand::{random}; +#[test] +use core::vec::{all, all2}; +#[test] +use std::cmp::FuzzyEq; +#[test] +use dim3::vec3::Vec3; +#[test] +use dim2::vec2::Vec2; +#[test] +use dim1::vec1::Vec1; +#[test] +use ndim::nvec::NVec; +#[test] +use traits::dim::d7; +#[test] +use traits::basis::Basis; + +#[test] +fn test_cross_vec3() +{ + for uint::range(0u, 10000u) |_| + { + let v1 : Vec3 = random(); + 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())); + } +} + +#[test] +fn test_dot_nvec() +{ + for uint::range(0u, 10000u) |_| + { + let v1 : NVec = random(); + let v2 : NVec = random(); + + assert!(v1.dot(&v2).fuzzy_eq(&v2.dot(&v1))); + } +} + +#[test] +fn test_commut_dot_vec3() +{ + for uint::range(0u, 10000u) |_| + { + let v1 : Vec3 = random(); + let v2 : Vec3 = random(); + + assert!(v1.dot(&v2).fuzzy_eq(&v2.dot(&v1))); + } +} + +#[test] +fn test_commut_dot_vec2() +{ + for uint::range(0u, 10000u) |_| + { + let v1 : Vec2 = random(); + let v2 : Vec2 = random(); + + assert!(v1.dot(&v2).fuzzy_eq(&v2.dot(&v1))); + } +} + +#[test] +fn test_commut_dot_vec1() +{ + for uint::range(0u, 10000u) |_| + { + let v1 : Vec1 = random(); + let v2 : Vec1 = random(); + + assert!(v1.dot(&v2).fuzzy_eq(&v2.dot(&v1))); + } +} + +#[test] +fn test_basis_vec1() +{ + for uint::range(0u, 10000u) |_| + { + 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()))); + // check vectors form an orthonormal basis + assert!(all(basis, |e| e.norm().fuzzy_eq(&One::one()))); + } +} + +#[test] +fn test_basis_vec2() +{ + for uint::range(0u, 10000u) |_| + { + 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()))); + // check vectors form an orthonormal basis + assert!(all(basis, |e| e.norm().fuzzy_eq(&One::one()))); + } +} + +#[test] +fn test_basis_vec3() +{ + for uint::range(0u, 10000u) |_| + { + 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()))); + // check vectors form an orthonormal basis + assert!(all(basis, |e| e.norm().fuzzy_eq(&One::one()))); + } +} + +#[test] +fn test_basis_nvec() +{ + for uint::range(0u, 10000u) |_| + { + 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()))); + // check vectors form an orthonormal basis + assert!(all(basis, |e| e.norm().fuzzy_eq(&One::one()))); + } +} + +#[test] +fn test_subspace_basis_vec1() +{ + for uint::range(0u, 10000u) |_| + { + let v : Vec1 = random(); + let v1 = v.normalized(); + let subbasis = v1.orthogonal_subspace_basis(); + + // check vectors are orthogonal to v1 + assert!(all(subbasis, |e| v1.dot(e).fuzzy_eq(&Zero::zero()))); + // check vectors form an ortogonal basis + assert!(all2(subbasis, subbasis, |e1, e2| e1 == e2 || e1.dot(e2).fuzzy_eq(&Zero::zero()))); + // check vectors form an orthonormal basis + assert!(all(subbasis, |e| e.norm().fuzzy_eq(&One::one()))); + } +} + +#[test] +fn test_subspace_basis_vec2() +{ + for uint::range(0u, 10000u) |_| + { + let v : Vec2 = random(); + let v1 = v.normalized(); + let subbasis = v1.orthogonal_subspace_basis(); + + // check vectors are orthogonal to v1 + assert!(all(subbasis, |e| v1.dot(e).fuzzy_eq(&Zero::zero()))); + // check vectors form an ortogonal basis + assert!(all2(subbasis, subbasis, |e1, e2| e1 == e2 || e1.dot(e2).fuzzy_eq(&Zero::zero()))); + // check vectors form an orthonormal basis + assert!(all(subbasis, |e| e.norm().fuzzy_eq(&One::one()))); + } +} + +#[test] +fn test_subspace_basis_vec3() +{ + for uint::range(0u, 10000u) |_| + { + let v : Vec3 = random(); + let v1 = v.normalized(); + let subbasis = v1.orthogonal_subspace_basis(); + + // check vectors are orthogonal to v1 + assert!(all(subbasis, |e| v1.dot(e).fuzzy_eq(&Zero::zero()))); + // check vectors form an ortogonal basis + assert!(all2(subbasis, subbasis, |e1, e2| e1 == e2 || e1.dot(e2).fuzzy_eq(&Zero::zero()))); + // check vectors form an orthonormal basis + assert!(all(subbasis, |e| e.norm().fuzzy_eq(&One::one()))); + } +} + +// ICE +// +// #[test] +// fn test_subspace_basis_vecn() +// { +// for uint::range(0u, 10000u) |_| +// { +// let v : NVec = random(); +// let v1 = v.normalized(); +// let subbasis = v1.orthogonal_subspace_basis(); +// +// // check vectors are orthogonal to v1 +// assert!(all(subbasis, |e| v1.dot(e).fuzzy_eq(&Zero::zero()))); +// // check vectors form an ortogonal basis +// assert!(all2(subbasis, subbasis, |e1, e2| e1 == e2 || e1.dot(e2).fuzzy_eq(&Zero::zero()))); +// // check vectors form an orthonormal basis +// assert!(all(subbasis, |e| e.norm().fuzzy_eq(&One::one()))); +// } +// } diff --git a/src/traits/basis.rs b/src/traits/basis.rs new file mode 100644 index 00000000..9fca5b86 --- /dev/null +++ b/src/traits/basis.rs @@ -0,0 +1,5 @@ +pub trait Basis +{ + fn canonical_basis() -> ~[Self]; // FIXME: is it the right pointer? + fn orthogonal_subspace_basis(&self) -> ~[Self]; +} diff --git a/src/traits/dim.rs b/src/traits/dim.rs index fd91c070..e58e8ed6 100644 --- a/src/traits/dim.rs +++ b/src/traits/dim.rs @@ -1,5 +1,4 @@ -pub trait Dim -{ +pub trait Dim { /// The dimension of the object. fn dim() -> uint; } @@ -8,20 +7,44 @@ pub trait Dim // 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)] pub struct d0; + /// Dimensional token for 1-dimension. Dimensional tokens are the preferred /// way to specify at the type level the dimension of n-dimensional objects. +#[deriving(Eq)] pub struct d1; + /// Dimensional token for 2-dimensions. Dimensional tokens are the preferred /// way to specify at the type level the dimension of n-dimensional objects. +#[deriving(Eq)] pub struct d2; + /// Dimensional token for 3-dimensions. Dimensional tokens are the preferred /// way to specify at the type level the dimension of n-dimensional objects. +#[deriving(Eq)] pub struct d3; + /// Dimensional token for 4-dimensions. Dimensional tokens are the preferred /// way to specify at the type level the dimension of n-dimensional objects. +#[deriving(Eq)] pub struct d4; +/// Dimensional token for 5-dimensions. Dimensional tokens are the preferred +/// way to specify at the type level the dimension of n-dimensional objects. +#[deriving(Eq)] +pub struct d5; + +/// Dimensional token for 6-dimensions. Dimensional tokens are the preferred +/// way to specify at the type level the dimension of n-dimensional objects. +#[deriving(Eq)] +pub struct d6; + +/// Dimensional token for 7-dimensions. Dimensional tokens are the preferred +/// way to specify at the type level the dimension of n-dimensional objects. +#[deriving(Eq)] +pub struct d7; + impl Dim for d0 { fn dim() -> uint { 0 } } @@ -36,3 +59,12 @@ impl Dim for d3 impl Dim for d4 { fn dim() -> uint { 4 } } + +impl Dim for d5 +{ fn dim() -> uint { 5 } } + +impl Dim for d6 +{ fn dim() -> uint { 6 } } + +impl Dim for d7 +{ fn dim() -> uint { 7 } } diff --git a/src/traits/dot.rs b/src/traits/dot.rs index ead40d7f..05ae90ea 100644 --- a/src/traits/dot.rs +++ b/src/traits/dot.rs @@ -2,13 +2,4 @@ pub trait Dot { /// Computes the dot (inner) product of two objects. fn dot(&self, &Self) -> T; - /// Computes the norm a an object. - fn norm(&self) -> T; - /** - * Computes the squared norm of an object. - * - * Computes the squared norm of an object. Computation of the squared norm - * is usually faster than the norm itself. - */ - fn sqnorm(&self) -> T; // { self.dot(self); } } diff --git a/src/traits/norm.rs b/src/traits/norm.rs new file mode 100644 index 00000000..109b6d30 --- /dev/null +++ b/src/traits/norm.rs @@ -0,0 +1,19 @@ +pub trait Norm +{ + /// Computes the norm a an object. + fn norm(&self) -> T; + + /** + * Computes the squared norm of an object. + * + * Computes the squared norm of an object. Computation of the squared norm + * is usually faster than the norm itself. + */ + fn sqnorm(&self) -> T; + + /// Returns the normalized version of the argument. + fn normalized(&self) -> Self; + + /// Inplace version of `normalized`. + fn normalize(&mut self) -> T; +} diff --git a/src/traits/workarounds/scalar_op.rs b/src/traits/workarounds/scalar_op.rs new file mode 100644 index 00000000..f35c11a9 --- /dev/null +++ b/src/traits/workarounds/scalar_op.rs @@ -0,0 +1,12 @@ +pub trait ScalarOp +{ + fn scalar_mul(&self, &T) -> Self; + fn scalar_div(&self, &T) -> Self; + fn scalar_add(&self, &T) -> Self; + fn scalar_sub(&self, &T) -> Self; + + fn scalar_mul_inplace(&mut self, &T); + fn scalar_div_inplace(&mut self, &T); + fn scalar_add_inplace(&mut self, &T); + fn scalar_sub_inplace(&mut self, &T); +}