From d636fdd3464e0b0add750d8b119c1edf48dcd456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Thu, 16 May 2013 21:30:39 +0000 Subject: [PATCH] Add matrix adaptors and addapted to the now rust features. --- .gitignore | 2 + Makefile | 2 +- src/adaptors/rotmat.rs | 112 ++++++++++++++++++++++++ src/adaptors/transform.rs | 85 ++++++++++++++++++ src/dim2/mat2.rs | 59 ++++++++----- src/dim2/rotmat2.rs | 92 ------------------- src/dim2/vec2.rs | 14 ++- src/dim3/mat3.rs | 63 ++++++++----- src/dim3/vec3.rs | 14 ++- src/nalgebra.rc | 20 +++-- src/ndim/nmat.rs | 80 ++++++++++++++--- src/ndim/nvec.rs | 23 +++-- src/traits/inv.rs | 3 +- src/traits/workarounds/README | 4 + src/traits/workarounds/rlmul.rs | 18 ++++ src/traits/workarounds/sqrt.rs | 17 ---- src/traits/workarounds/trigonometric.rs | 18 +++- 17 files changed, 437 insertions(+), 189 deletions(-) create mode 100644 .gitignore create mode 100644 src/adaptors/rotmat.rs create mode 100644 src/adaptors/transform.rs delete mode 100644 src/dim2/rotmat2.rs create mode 100644 src/traits/workarounds/README create mode 100644 src/traits/workarounds/rlmul.rs delete mode 100644 src/traits/workarounds/sqrt.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..0756691e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.swp +doc diff --git a/Makefile b/Makefile index c2a48074..81dc2535 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ all: - rustpkg install + rust build src/nalgebra.rc --out-dir lib # rustpkg install doc: rust doc src/nalgebra.rc --output-dir doc diff --git a/src/adaptors/rotmat.rs b/src/adaptors/rotmat.rs new file mode 100644 index 00000000..bfe4a89b --- /dev/null +++ b/src/adaptors/rotmat.rs @@ -0,0 +1,112 @@ +use core::num::{One, Zero}; // , Trigonometric}; +use traits::workarounds::rlmul::{RMul, LMul}; +use traits::workarounds::trigonometric::Trigonometric; +use traits::dim::Dim; +use traits::inv::Inv; +use traits::transpose::Transpose; +use dim2::mat2::Mat2; +use dim3::mat3::Mat3; +use dim3::vec3::Vec3; + +// FIXME: use a newtype here? +#[deriving(Eq)] +pub struct Rotmat +{ + priv submat: M +} + +pub fn Rotmat2>(angle: T) -> Rotmat> +{ + let coa = Trigonometric::cos(angle); + let sia = Trigonometric::sin(angle); + + Rotmat + { submat: Mat2(coa, -sia, sia, coa) } +} + +pub fn Rotmat3 + One + Sub + Add + + Mul> +(axis: &Vec3, angle: T) -> Rotmat> +{ + let _1 = One::one::(); + let ux = axis.x; + let uy = axis.y; + let uz = axis.z; + let sqx = ux * ux; + let sqy = uy * uy; + let sqz = uz * uz; + let cos = Trigonometric::cos(angle); + let one_m_cos = _1 - cos; + let sin = Trigonometric::sin(angle); + + Rotmat { + submat: Mat3( + (sqx + (_1 - sqx) * cos), + (ux * uy * one_m_cos - uz * sin), + (ux * uz * one_m_cos + uy * sin), + + (ux * uy * one_m_cos + uz * sin), + (sqy + (_1 - sqy) * cos), + (uy * uz * one_m_cos - ux * sin), + + (ux * uz * one_m_cos - uy * sin), + (uy * uz * one_m_cos + ux * sin), + (sqz + (_1 - sqz) * cos)) + } +} + +impl Dim for Rotmat +{ + fn dim() -> uint + { Dim::dim::() } +} + +impl One for Rotmat +{ + fn one() -> Rotmat + { Rotmat { submat: One::one() } } +} + +impl> Mul, Rotmat> for Rotmat +{ + fn mul(&self, other: &Rotmat) -> Rotmat + { Rotmat { submat: self.submat.mul(&other.submat) } } +} + +impl> RMul for Rotmat +{ + fn rmul(&self, other: &V) -> V + { self.submat.rmul(other) } +} + +impl> LMul for Rotmat +{ + fn lmul(&self, other: &V) -> V + { self.submat.lmul(other) } +} + +impl +Inv for Rotmat +{ + fn invert(&mut self) + { self.transpose() } + + fn inverse(&self) -> Rotmat + { self.transposed() } +} + +impl +Transpose for Rotmat +{ + fn transposed(&self) -> Rotmat + { Rotmat { submat: self.submat.transposed() } } + + fn transpose(&mut self) + { self.submat.transpose() } +} + +impl ToStr for Rotmat +{ + fn to_str(&self) -> ~str + { ~"Rotmat {" + " submat: " + self.submat.to_str() + " }" } +} diff --git a/src/adaptors/transform.rs b/src/adaptors/transform.rs new file mode 100644 index 00000000..bcd14256 --- /dev/null +++ b/src/adaptors/transform.rs @@ -0,0 +1,85 @@ +use core::num::{One, Zero}; +use traits::dim::Dim; +use traits::inv::Inv; +use traits::transpose::Transpose; +use traits::workarounds::rlmul::{RMul, LMul}; + +pub struct Transform +{ + submat : M, + subtrans : V +} + +pub fn Transform(mat: &M, trans: &V) -> Transform +{ Transform { submat: *mat, subtrans: *trans } } + +impl Dim for Transform +{ + fn dim() -> uint + { Dim::dim::() } +} + +impl One for Transform +{ + fn one() -> Transform + { Transform { submat: One::one(), subtrans: Zero::zero() } } +} + +impl Zero for Transform +{ + fn zero() -> Transform + { Transform { submat: Zero::zero(), subtrans: Zero::zero() } } + + fn is_zero(&self) -> bool + { self.submat.is_zero() && self.subtrans.is_zero() } +} + +impl + Mul, V:Copy + Add> +Mul, Transform> for Transform +{ + fn mul(&self, other: &Transform) -> Transform + { + Transform { submat: self.submat * other.submat, + subtrans: self.subtrans + self.submat.rmul(&other.subtrans) } + } +} + +impl, V> RMul for Transform +{ + fn rmul(&self, other: &V) -> V + { self.submat.rmul(other) } +} + +impl, V> LMul for Transform +{ + fn lmul(&self, other: &V) -> V + { self.submat.lmul(other) } +} + +impl, V:Copy + Neg> +Inv for Transform +{ + fn invert(&mut self) + { + self.submat.invert(); + self.subtrans = self.submat.rmul(&-self.subtrans); + } + + fn inverse(&self) -> Transform + { + let mut res = *self; + + res.invert(); + + res + } +} + +impl ToStr for Transform +{ + fn to_str(&self) -> ~str + { + ~"Transform {" + " submat: " + self.submat.to_str() + + " subtrans: " + self.subtrans.to_str() + " }" + } +} diff --git a/src/dim2/mat2.rs b/src/dim2/mat2.rs index 32e0df7d..c257d2ed 100644 --- a/src/dim2/mat2.rs +++ b/src/dim2/mat2.rs @@ -2,6 +2,7 @@ use core::num::{One, Zero}; use traits::dim::Dim; use traits::inv::Inv; use traits::transpose::Transpose; +use traits::workarounds::rlmul::{RMul, LMul}; use dim2::vec2::Vec2; #[deriving(Eq)] @@ -45,11 +46,11 @@ impl Zero for Mat2 _0, _0) } - // fn is_zero(&self) -> bool - // { - // self.m11.is_zero() && self.m11.is_zero() && self.m12.is_zero() - // && self.m21.is_zero() && self.m21.is_zero() && self.m22.is_zero() - // } + fn is_zero(&self) -> bool + { + self.m11.is_zero() && self.m12.is_zero() && + self.m21.is_zero() && self.m22.is_zero() + } } impl + Add> Mul, Mat2> for Mat2 @@ -64,32 +65,48 @@ impl + Add> Mul, Mat2> for Mat2 } } -// FIXME: implementation of multiple classes for the same struct fails -// with "internal compiler error: Asked to compute kind of a type variable". -// -// impl + Add> Mul, Vec2> for Mat2 -// { -// fn mul(&self, v: &Vec2) -> Vec2 -// { Vec2(self.m11 * v.x + self.m12 * v.y, self.m21 * v.x + self.m22 * v.y) } -// } - -impl + Add> Mul, Vec2> for Vec2 +impl + Mul> RMul> for Mat2 { - fn mul(&self, m: &Mat2) -> Vec2 - { Vec2(self.x * m.m11 + self.y * m.m21, self.x * m.m12 + self.y * m.m22) } + fn rmul(&self, other: &Vec2) -> Vec2 + { + Vec2( + self.m11 * other.x + self.m12 * other.y, + self.m21 * other.x + self.m22 * other.y + ) + } } -impl + Div + Sub + Neg + Eq + Zero> +impl + Mul> LMul> for Mat2 +{ + fn lmul(&self, other: &Vec2) -> Vec2 + { + Vec2( + self.m11 * other.x + self.m21 * other.y, + self.m12 * other.x + self.m22 * other.y + ) + } +} + +impl + Quot + Sub + Neg + Eq + Zero> Inv for Mat2 { - fn inv(&self) -> Mat2 + fn inverse(&self) -> Mat2 + { + let mut res : Mat2 = *self; + + res.invert(); + + res + } + + fn invert(&mut self) { let det = self.m11 * self.m22 - self.m21 * self.m12; assert!(det != Zero::zero()); - Mat2(self.m22 / det , -self.m12 / det, - -self.m21 / det, self.m11 / det) + *self = Mat2(self.m22 / det , -self.m12 / det, + -self.m21 / det, self.m11 / det) } } diff --git a/src/dim2/rotmat2.rs b/src/dim2/rotmat2.rs deleted file mode 100644 index 56a3af43..00000000 --- a/src/dim2/rotmat2.rs +++ /dev/null @@ -1,92 +0,0 @@ -use core::num::{One, Zero}; -use traits::workarounds::trigonometric::Trigonometric; -use traits::dim::Dim; -use dim2::mat2::Mat2; -// use dim2::vec2::Vec2; - -// FIXME: using a newtype did not compile (due a compiler bug) -// pub type Rotmat2 = (Mat2) -#[deriving(Eq)] -pub struct Rotmat2 -{ - priv submat: Mat2 -} - -pub fn Rotmat2>(angle: T) -> Rotmat2 -{ - let coa = angle.cos(); - let sia = angle.sin(); - - Rotmat2 - { submat: Mat2(coa, -sia, sia, coa) } -} - -impl Dim for Rotmat2 -{ - fn dim() -> uint - { 2 } -} - -impl One for Rotmat2 -{ - fn one() -> Rotmat2 - { Rotmat2 { submat: One::one() } } -} - -impl + Add> Mul, Rotmat2> for Rotmat2 -{ - fn mul(&self, other: &Rotmat2) -> Rotmat2 - { Rotmat2 { submat: self.submat.mul(&other.submat) } } -} - -// FIXME: implementation of the same classes for the same struct fails -// with "internal compiler error: Asked to compute kind of a type variable". -// -// impl + Add> Mul, Vec2> for Rotmat2 -// { -// fn mul(&self, v: &Vec2) -> Vec2 -// { Vec2(self.m11 * v.x + self.m12 * v.y, self.m21 * v.x + self.m22 * v.y) } -// } - -// FIXME: implementation of the same classes for the same struct (here Vec2) -// fails with "internal compiler error: Asked to compute kind of a type -// variable". -// -// impl + Add> Mul, Vec2> for Vec2 -// { -// fn mul(&self, m: &Rotmat2) -> Vec2 -// { self.mult(&m.submat) } -// } - -/* -impl + Div + Sub + Neg + Eq + Zero> -Inv for Rotmat2 -{ - fn inv(&self) -> Rotmat2 - { - // transpose - Rotmat2( - Mat2( - self.submat.m11, self.submat.m21, - self.submat.m12, self.submat.m22 - ) - ) - } -} -*/ - -/* -impl ToStr for Rotmat2 -{ - fn to_str(&self) -> ~str - { - ~"Rotmat2 {" - + " m11: " + self.m11.to_str() - + " m12: " + self.m12.to_str() - - + " m21: " + self.m21.to_str() - + " m22: " + self.m22.to_str() - + " }" - } -} -*/ diff --git a/src/dim2/vec2.rs b/src/dim2/vec2.rs index 30522083..2a251b1e 100644 --- a/src/dim2/vec2.rs +++ b/src/dim2/vec2.rs @@ -1,8 +1,7 @@ -use core::num::Zero; +use core::num::{Zero, Algebraic}; use traits::dot::Dot; use traits::dim::Dim; use traits::cross::Cross; -use traits::workarounds::sqrt::Sqrt; #[deriving(Eq)] pub struct Vec2 @@ -32,7 +31,7 @@ impl> Sub, Vec2> for Vec2 { Vec2(self.x - other.x, self.y - other.y) } } -impl + Add + Sqrt> Dot for Vec2 +impl + Add + Algebraic> Dot for Vec2 { fn dot(&self, other : &Vec2) -> T { self.x * other.x + self.y * other.y } @@ -50,6 +49,12 @@ impl + Sub> Cross for Vec2 { self.x * other.y - self.y * other.x } } +impl> Neg> for Vec2 +{ + fn neg(&self) -> Vec2 + { Vec2(-self.x, -self.y) } +} + impl Zero for Vec2 { fn zero() -> Vec2 @@ -57,6 +62,9 @@ impl Zero for Vec2 let _0 = Zero::zero(); Vec2(_0, _0) } + + fn is_zero(&self) -> bool + { self.x.is_zero() && self.y.is_zero() } } impl ToStr for Vec2 diff --git a/src/dim3/mat3.rs b/src/dim3/mat3.rs index c0d6f3be..cc58a0c0 100644 --- a/src/dim3/mat3.rs +++ b/src/dim3/mat3.rs @@ -1,8 +1,8 @@ use core::num::{One, Zero}; -// use core::rand::{Rand, Rng}; use traits::dim::Dim; use traits::inv::Inv; use traits::transpose::Transpose; +use traits::workarounds::rlmul::{RMul, LMul}; use dim3::vec3::Vec3; #[deriving(Eq)] @@ -51,11 +51,18 @@ impl Zero for Mat3 _0, _0, _0, _0, _0, _0) } + + fn is_zero(&self) -> bool + { + self.m11.is_zero() && self.m12.is_zero() && self.m13.is_zero() && + self.m21.is_zero() && self.m22.is_zero() && self.m23.is_zero() && + self.m31.is_zero() && self.m32.is_zero() && self.m33.is_zero() + } } impl + Add> Mul, Mat3> for Mat3 { - fn mul(&self, other : &Mat3) -> Mat3 + fn mul(&self, other: &Mat3) -> Mat3 { Mat3( self.m11 * other.m11 + self.m12 * other.m21 + self.m13 * other.m31, @@ -73,34 +80,44 @@ impl + Add> Mul, Mat3> for Mat3 } } -// FIXME: implementation of multiple classes for the same struct fails -// with "internal compiler error: Asked to compute kind of a type variable". -// -// impl + Add> Mul, Vec3> for Mat3 -// { -// fn mul(&self, m : &Mat3) -> Vec3 -// { -// Vec3(self.x * m.m11 + self.y * m.m21 + self.z * m.m31, -// self.x * m.m12 + self.y * m.m22 + self.z * m.m32, -// self.x * m.m13 + self.y * m.m23 + self.z * m.m33) -// } -// } - -impl + Add> Mul, Vec3> for Vec3 +impl + Mul> RMul> for Mat3 { - fn mul(&self, m : &Mat3) -> Vec3 + fn rmul(&self, other: &Vec3) -> Vec3 { - Vec3(self.x * m.m11 + self.y * m.m21 + self.z * m.m31, - self.x * m.m12 + self.y * m.m22 + self.z * m.m32, - self.x * m.m13 + self.y * m.m23 + self.z * m.m33) + Vec3( + self.m11 * other.x + self.m12 * other.y + self.m13 * other.z, + self.m21 * other.x + self.m22 * other.y + self.m33 * other.z, + self.m31 * other.x + self.m32 * other.y + self.m33 * other.z + ) } } -impl + Div + Sub + Add + Neg +impl + Mul> LMul> for Mat3 +{ + fn lmul(&self, other: &Vec3) -> Vec3 + { + Vec3( + self.m11 * other.x + self.m21 * other.y + self.m31 * other.z, + self.m12 * other.x + self.m22 * other.y + self.m32 * other.z, + self.m13 * other.x + self.m23 * other.y + self.m33 * other.z + ) + } +} + +impl + Quot + Sub + Add + Neg + Eq + Zero> Inv for Mat3 { - fn inv(&self) -> Mat3 + fn inverse(&self) -> Mat3 + { + let mut res = *self; + + res.invert(); + + res + } + + fn invert(&mut self) { let minor_m22_m33 = self.m22 * self.m33 - self.m32 * self.m23; let minor_m21_m33 = self.m21 * self.m33 - self.m31 * self.m23; @@ -112,7 +129,7 @@ Inv for Mat3 assert!(det != Zero::zero()); - Mat3( + *self = Mat3( (minor_m22_m33 / det), ((self.m13 * self.m32 - self.m33 * self.m12) / det), ((self.m12 * self.m23 - self.m22 * self.m13) / det), diff --git a/src/dim3/vec3.rs b/src/dim3/vec3.rs index 35bf557c..1797893d 100644 --- a/src/dim3/vec3.rs +++ b/src/dim3/vec3.rs @@ -1,8 +1,7 @@ -use core::num::Zero; +use core::num::{Zero, Algebraic}; use traits::dim::Dim; use traits::dot::Dot; use traits::cross::Cross; -use traits::workarounds::sqrt::Sqrt; #[deriving(Eq)] pub struct Vec3 @@ -33,7 +32,13 @@ impl> Sub, Vec3> for Vec3 { Vec3(self.x - other.x, self.y - other.y, self.z - other.z) } } -impl + Add + Sqrt> Dot for Vec3 +impl> Neg> for Vec3 +{ + fn neg(&self) -> Vec3 + { Vec3(-self.x, -self.y, -self.z) } +} + +impl + Add + Algebraic> Dot for Vec3 { fn dot(&self, other : &Vec3) -> T { self.x * other.x + self.y * other.y + self.z * other.z } @@ -64,6 +69,9 @@ impl Zero for Vec3 let _0 = Zero::zero(); Vec3(_0, _0, _0) } + + fn is_zero(&self) -> bool + { self.x.is_zero() && self.y.is_zero() && self.z.is_zero() } } impl ToStr for Vec3 diff --git a/src/nalgebra.rc b/src/nalgebra.rc index 82c639a4..695f1e3d 100644 --- a/src/nalgebra.rc +++ b/src/nalgebra.rc @@ -12,26 +12,26 @@ pub use dim3::mat3::Mat3; pub use dim2::vec2::Vec2; pub use dim2::mat2::Mat2; -pub use dim2::rotmat2::Rotmat2; pub use ndim::nvec::NVec; pub use ndim::nmat::NMat; +pub use adaptors::rotmat::Rotmat; +pub use adaptors::transform::Transform; + pub use traits::dot::Dot; pub use traits::cross::Cross; pub use traits::dim::Dim; - -pub use traits::workarounds::sqrt::Sqrt; -pub use traits::workarounds::trigonometric::Trigonometric; - pub use traits::inv::Inv; pub use traits::transpose::Transpose; +pub use traits::workarounds::rlmul::{RMul, LMul}; +pub use traits::workarounds::trigonometric::Trigonometric; + mod dim2 { mod vec2; mod mat2; - mod rotmat2; } mod dim3 @@ -46,6 +46,12 @@ mod ndim mod nmat; } +mod adaptors +{ + mod rotmat; + mod transform; +} + mod traits { mod dot; @@ -56,7 +62,7 @@ mod traits mod workarounds { - mod sqrt; + mod rlmul; mod trigonometric; } } diff --git a/src/ndim/nmat.rs b/src/ndim/nmat.rs index 5589e639..34d37b5a 100644 --- a/src/ndim/nmat.rs +++ b/src/ndim/nmat.rs @@ -1,9 +1,10 @@ use core::num::{One, Zero}; -use core::vec::{from_elem, swap}; +use core::vec::{from_elem, swap, all}; use traits::dim::Dim; use traits::inv::Inv; use traits::transpose::Transpose; -// use ndim::nvec::NVec; +use traits::workarounds::rlmul::{RMul, LMul}; +use ndim::nvec::NVec; // D is a phantom type parameter, used only as a dimensional token. // Its allows use to encode the vector dimension at the type-level. @@ -15,6 +16,12 @@ pub struct NMat mij: ~[T] } +impl Clone for NMat +{ + fn clone(&self) -> NMat + { NMat{ mij: self.mij.clone() } } +} + impl NMat { fn offset(i: uint, j: uint) -> uint @@ -59,6 +66,9 @@ impl Zero for NMat NMat{ mij: from_elem(dim * dim, Zero::zero()) } } + + fn is_zero(&self) -> bool + { all(self.mij, |e| e.is_zero()) } } impl + Add + Zero> @@ -86,13 +96,59 @@ Mul, NMat> for NMat } } +impl + Mul + Zero> +RMul> for NMat +{ + fn rmul(&self, other: &NVec) -> NVec + { + let dim = Dim::dim::(); + let mut res : NVec = Zero::zero(); + + for uint::range(0u, dim) |i| + { + for uint::range(0u, dim) |j| + { res.at[i] = res.at[i] + other.at[j] * self[(i, j)]; } + } + + res + } +} + +impl + Mul + Zero> +LMul> for NMat +{ + fn lmul(&self, other: &NVec) -> NVec + { + let dim = Dim::dim::(); + let mut res : NVec = Zero::zero(); + + for uint::range(0u, dim) |i| + { + for uint::range(0u, dim) |j| + { res.at[i] = res.at[i] + other.at[j] * self[(j, i)]; } + } + + res + } +} + impl + Div + Sub + Neg + Eq + One + Zero> + T: Clone + Copy + Eq + One + Zero + + Mul + Quot + Sub + Neg + > Inv for NMat { - fn inv(&self) -> NMat + fn inverse(&self) -> NMat + { + let mut res : NMat = self.clone(); + + res.invert(); + + res + } + + fn invert(&mut self) { - let mut cpy = copy *self; let dim = Dim::dim::(); let mut res = One::one::>(); let _0T = Zero::zero::(); @@ -111,7 +167,7 @@ Inv for NMat while (n0 != dim) { - if (cpy[(n0, k)] != _0T) + if (self[(n0, k)] != _0T) { break; } n0 += 1; @@ -124,7 +180,7 @@ Inv for NMat { for uint::range(0u, dim) |j| { - swap(cpy.mij, + swap(self.mij, NMat::offset::(n0, j), NMat::offset::(k, j)); swap(res.mij, @@ -133,11 +189,11 @@ Inv for NMat } } - let pivot = cpy[(k, k)]; + let pivot = self[(k, k)]; for uint::range(k, dim) |j| { - cpy.set(k, j, &(cpy[(k, j)] / pivot)); + self.set(k, j, &(self[(k, j)] / pivot)); res.set(k, j, &(res[(k, j)] / pivot)); } @@ -145,18 +201,16 @@ Inv for NMat { if (l != k) { - let normalizer = cpy[(l, k)] / pivot; + let normalizer = self[(l, k)] / pivot; for uint::range(k, dim) |j| { - cpy.set(k, j, &(cpy[(l, j)] - cpy[(k, j)] * normalizer)); + self.set(k, j, &(self[(l, j)] - self[(k, j)] * normalizer)); res.set(k, j, &(res[(l, j)] - res[(k, j)] * normalizer)); } } } } - - res } } diff --git a/src/ndim/nvec.rs b/src/ndim/nvec.rs index cd490b8d..fc002a13 100644 --- a/src/ndim/nvec.rs +++ b/src/ndim/nvec.rs @@ -1,8 +1,7 @@ -use core::vec::{map2, from_elem}; -use core::num::Zero; +use core::vec::{map_zip, from_elem, map, all}; +use core::num::{Zero, Algebraic}; use traits::dim::Dim; use traits::dot::Dot; -use traits::workarounds::sqrt::Sqrt; // D is a phantom parameter, used only as a dimensional token. // Its allows use to encode the vector dimension at the type-level. @@ -26,16 +25,23 @@ impl Dim for NVec impl> Add, NVec> for NVec { fn add(&self, other: &NVec) -> NVec - { NVec { at: map2(self.at, other.at, | a, b | { *a + *b }) } } + { NVec { at: map_zip(self.at, other.at, | a, b | { *a + *b }) } } } impl> Sub, NVec> for NVec { fn sub(&self, other: &NVec) -> NVec - { NVec { at: map2(self.at, other.at, | a, b | *a - *b) } } + { NVec { at: map_zip(self.at, other.at, | a, b | *a - *b) } } } -impl + Add + Sqrt + Zero> Dot for NVec +impl> Neg> for NVec +{ + fn neg(&self) -> NVec + { NVec { at: map(self.at, |a| -a) } } +} + +impl + Add + Algebraic + Zero> +Dot for NVec { fn dot(&self, other: &NVec) -> T { @@ -70,6 +76,11 @@ impl Zero for NVec NVec { at: from_elem(Dim::dim::(), _0) } } + + fn is_zero(&self) -> bool + { + all(self.at, |e| e.is_zero()) + } } impl ToStr for NVec diff --git a/src/traits/inv.rs b/src/traits/inv.rs index 907d7452..ac995c77 100644 --- a/src/traits/inv.rs +++ b/src/traits/inv.rs @@ -1,4 +1,5 @@ pub trait Inv { - fn inv(&self) -> Self; + fn inverse(&self) -> Self; + fn invert(&mut self); } diff --git a/src/traits/workarounds/README b/src/traits/workarounds/README new file mode 100644 index 00000000..56f44b6a --- /dev/null +++ b/src/traits/workarounds/README @@ -0,0 +1,4 @@ +This packages contains everything done because current (stable) 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 new file mode 100644 index 00000000..7e2a5758 --- /dev/null +++ b/src/traits/workarounds/rlmul.rs @@ -0,0 +1,18 @@ +/** This is a workaround of the fact we cannot implement the same trait + * (with different type parameters) twice for the same type: + * ~~~ + * trait Mul for M + * trait Mul for M + * ~~~ + */ +pub trait RMul +{ + /// Computes self * v + fn rmul(&self, v : &V) -> V; +} + +pub trait LMul +{ + /// Computes v * self + fn lmul(&self, &V) -> V; +} diff --git a/src/traits/workarounds/sqrt.rs b/src/traits/workarounds/sqrt.rs deleted file mode 100644 index 9da09ca6..00000000 --- a/src/traits/workarounds/sqrt.rs +++ /dev/null @@ -1,17 +0,0 @@ -// FIXME: this does not seem to exist already -// but it will surely be added someday. - -pub trait Sqrt -{ - fn sqrt(&self) -> Self; -} - -impl Sqrt for f64 -{ - fn sqrt(&self) -> f64 { f64::sqrt(*self) } -} - -impl Sqrt for f32 -{ - fn sqrt(&self) -> f32 { f32::sqrt(*self) } -} diff --git a/src/traits/workarounds/trigonometric.rs b/src/traits/workarounds/trigonometric.rs index bf8af8cf..7902a052 100644 --- a/src/traits/workarounds/trigonometric.rs +++ b/src/traits/workarounds/trigonometric.rs @@ -1,5 +1,19 @@ +// Trigonometric is available in core, but compilation fails with internal +// error. + +use core::f64::{cos, sin}; + pub trait Trigonometric { - fn sin(&self) -> Self; - fn cos(&self) -> Self; + fn cos(Self) -> Self; + fn sin(Self) -> Self; +} + +impl Trigonometric for f64 +{ + fn cos(a: f64) -> f64 + { cos(a) } + + fn sin(a: f64) -> f64 + { sin(a) } }