diff --git a/src/lib.rs b/src/lib.rs index df6ccbfd..aadc5418 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,9 +11,8 @@ An on-line version of this documentation is available [here](http://crozet.re/na ## Using **nalgebra** All the functionalities of **nalgebra** are grouped in one place: the `na` module. -This module re-exports everything and includes free functions for all traits methods. -Free functions are useful if you prefer doing something like `na::dot(v1, v2)` instead of -`v1.dot(v2)`. +This module re-exports everything and includes free functions for all traits methods doing +out-of-place modifications. * You can import the whole prelude, including free functions, using: @@ -32,8 +31,23 @@ use nalgebra::traits::*; ```.rust use nalgebra::structs::*; ``` -Of course, you can still import `nalgebra::na` alone, and get anything you want using the prefix -`na`. +The preffered way to use **nalgebra** is to import types and traits explicitly, and call +free-functions using the `na::` prefix: + +```.rust +extern mod nalgebra; +use nalgebra::na::{Rot3, Rotation}; +use nalgebra::na; + +fn main() { + let a = na::vec3(1.0f64, 1.0, 1.0); + let mut b: Rot3 = na::one(); + + b.append_rotation(&a); + + assert!(na::rotation(&b).approx_eq(&a)); +} +``` ## Features **nalgebra** is meant to be a general-purpose linear algebra library (but is very far from that…), diff --git a/src/na.rs b/src/na.rs index d78bf0ec..421a3c91 100644 --- a/src/na.rs +++ b/src/na.rs @@ -166,7 +166,7 @@ pub fn mat4(m11: N, m12: N, m13: N, m14: N, * Translation */ -/// Gets the translation applicable by the given object. +/// Gets the translation applicable by `m`. /// /// ```rust /// extern mod nalgebra; @@ -185,7 +185,7 @@ pub fn translation>(m: &M) -> V { m.translation() } -/// Gets the inverse translation applicable by the given object. +/// Gets the inverse translation applicable by `m`. /// /// ```rust /// extern mod nalgebra; @@ -204,22 +204,10 @@ pub fn inv_translation>(m: &M) -> V { m.inv_translation() } -/// In-place version of `translated`. +/// Appied the translation `v` to a copy of `m`. #[inline(always)] -pub fn translate_by>(m: &mut M, v: &V) { - m.translate_by(v) -} - -/// Gets a translated copy of the given object. -#[inline(always)] -pub fn translated>(m: &M, v: &V) -> M { - m.translated(v) -} - -/// Sets the translation of the given object. -#[inline(always)] -pub fn set_translation>(m: &mut M, v: V) { - m.set_translation(v) +pub fn append_translation>(m: &M, v: &V) -> M { + Translation::append_translation_cpy(m, v) } /* @@ -269,7 +257,7 @@ pub fn inv_translate>(m: &M, v: &V) -> V { * Rotation */ -/// Gets the rotation applicable by the given object. +/// Gets the rotation applicable by `m`. /// /// ```rust /// extern mod nalgebra; @@ -287,7 +275,7 @@ pub fn rotation>(m: &M) -> V { } -/// Gets the rotation applicable by the given object. +/// Gets the inverse rotation applicable by `m`. /// /// ```rust /// extern mod nalgebra; @@ -304,27 +292,7 @@ pub fn inv_rotation>(m: &M) -> V { m.inv_rotation() } -/// Rotates an object in-place. -/// -/// ```rust -/// extern mod nalgebra; -/// use nalgebra::na; -/// -/// pub main() { -/// let mut t = na::rot3(0.0, 0.0, 0.0); -/// let v = na::vec3(1.0, 1.0, 1.0); -/// -/// na::rotate_by(&mut t, &v); -/// -/// assert!(na::rotation(&t) == na::vec3(1.0, 1.0, 1.0)) -/// } -/// ``` -#[inline(always)] -pub fn rotate_by>(m: &mut M, v: &V) { - m.rotate_by(v) -} - -/// Creates a rotated copy of an object. +/// Applies the rotation `v` to a copy of `m`. /// /// ```rust /// extern mod nalgebra; @@ -333,34 +301,14 @@ pub fn rotate_by>(m: &mut M, v: &V) { /// pub main() { /// let t = na::rot3(0.0, 0.0, 0.0); /// let v = na::vec3(1.0, 1.0, 1.0); -/// let rt = na::rotated(&mut t, &v); +/// let rt = na::append_rotation(&t, &v); /// /// assert!(na::rotation(&rt) == na::vec3(1.0, 1.0, 1.0)) /// } /// ``` #[inline(always)] -pub fn rotated>(m: &M, v: &V) -> M { - m.rotated(v) -} - -/// Sets the rotation of an object. -/// -/// ```rust -/// extern mod nalgebra; -/// use nalgebra::na; -/// -/// pub main() { -/// let mut t = na::rot3(1.0, 0.5, 0.2); -/// let v = na::vec3(1.0, 1.0, 1.0); -/// -/// na::set_rotation(&mut t, &v); -/// -/// assert!(na::rotation(&t) == na::vec3(1.0, 1.0, 1.0)) -/// } -/// ``` -#[inline(always)] -pub fn set_rotation>(m: &mut M, v: V) { - m.set_rotation(v) +pub fn append_rotation>(m: &M, v: &V) -> M { + Rotation::append_rotation_cpy(m, v) } /* @@ -395,7 +343,7 @@ pub fn rotate>(m: &M, v: &V) -> V { /// use nalgebra::na; /// /// pub main() { -/// let t = na::rot3(1.0, 0.0, 0.0); +/// let t = na::rot3(na::vec3(1.0, 0.0, 0.0)); /// let v = na::vec3(0.0, 0.0, na::pi() / 2.0); /// /// let tv = na::rotate(&t, &v); @@ -412,53 +360,32 @@ pub fn inv_rotate>(m: &M, v: &V) -> V { * RotationWithTranslation */ -/// Creates a rotated copy of an object using a specific center of rotation. +/// Rotates a copy of `m` by `amount` using `center` ase the pivot point. #[inline(always)] -pub fn rotated_wrt_point, - AV, - M: RotationWithTranslation>( - m: &M, - amount: &AV, - center: &LV) -> M { - m.rotated_wrt_point(amount, center) +pub fn append_rotation_wrt_point, + AV, + M: RotationWithTranslation>( + m: &M, + amount: &AV, + center: &LV) -> M { + RotationWithTranslation::append_rotation_wrt_point_cpy(m, amount, center) } -/// In-place version of `rotated_wrt_point`. -#[inline(always)] -pub fn rotate_wrt_point, - AV, - M: RotationWithTranslation>( - m: &mut M, - amount: &AV, - center: &LV) { - m.rotate_wrt_point(amount, center) -} - -/// Creates a rotated copy of an object using its own translation as the center of rotation. -#[inline(always)] -pub fn rotated_wrt_center, - AV, - M: RotationWithTranslation>( - m: &M, - amount: &AV) -> M { - m.rotated_wrt_center(amount) -} - -/// In-place version of `rotate_wrt_center`. +/// Rotates a copy of `m` by `amount` using `m.translation()` as the pivot point. #[inline(always)] pub fn rotate_wrt_center, AV, M: RotationWithTranslation>( - m: &mut M, - amount: &AV) { - m.rotate_wrt_center(amount) + m: &M, + amount: &AV) -> M { + RotationWithTranslation::append_rotation_wrt_center_cpy(m, amount) } /* * RotationMatrix */ -/// Builds a rotation matrix from a rotation-capable object. +/// Builds a rotation matrix from `r`. #[inline(always)] pub fn to_rot_mat + Rotation, R: RotationMatrix>(r: &R) -> M { r.to_rot_mat() @@ -478,34 +405,22 @@ pub fn absolute_rotate>(m: &M, v: &V) -> V { * Transformation */ -/// Gets the transformation applicable by the given object. +/// Gets the transformation applicable by `m`. #[inline(always)] pub fn transformation>(m: &M) -> T { m.transformation() } -/// Gets the inverse transformation applicable by the given object. +/// Gets the inverse transformation applicable by `m`. #[inline(always)] pub fn inv_transformation>(m: &M) -> T { m.inv_transformation() } -/// In-place version of `transformed`. +/// Gets a transformed copy of `m`. #[inline(always)] -pub fn transform_by>(m: &mut M, t: &T) { - m.transform_by(t) -} - -/// Gets a transformed copy of an object. -#[inline(always)] -pub fn transformed>(m: &M, t: &T) -> M { - m.transformed(t) -} - -/// Sets the transformation of an object. -#[inline(always)] -pub fn set_transformation>(m: &mut M, t: T) { - m.set_transformation(t) +pub fn append_transformation>(m: &M, t: &T) -> M { + Transformation::append_transformation_cpy(m, t) } /* @@ -558,14 +473,8 @@ pub fn sqnorm, N: Algebraic>(v: &V) -> N { /// Gets the normalized version of a vector. #[inline(always)] -pub fn normalized, N: Algebraic>(v: &V) -> V { - v.normalized() -} - -/// In-place version of `normalized`. -#[inline(always)] -pub fn normalize, N: Algebraic>(v: &mut V) -> N { - v.normalize() +pub fn normalize, N: Algebraic>(v: &V) -> V { + Norm::normalize_cpy(v) } /* @@ -646,14 +555,8 @@ pub fn absolute, Res>(m: &M) -> Res { /// Gets an inverted copy of a matrix. #[inline(always)] -pub fn inverted(m: &M) -> Option { - m.inverted() -} - -/// In-place version of `inverted`. -#[inline(always)] -pub fn invert(m: &mut M) -> bool { - m.invert() +pub fn inv(m: &M) -> Option { + Inv::inv_cpy(m) } /* @@ -662,14 +565,8 @@ pub fn invert(m: &mut M) -> bool { /// Gets a transposed copy of a matrix. #[inline(always)] -pub fn transposed(m: &M) -> M { - m.transposed() -} - -/// In-place version of `transposed`. -#[inline(always)] -pub fn transpose(m: &mut M) { - m.transpose() +pub fn transpose(m: &M) -> M { + Transpose::transpose_cpy(m) } /* @@ -749,17 +646,17 @@ pub fn dim() -> uint { /// Converts an object from one type to another. /// /// For primitive types, this is the same as the `as` keywords. -/// Those properties are preserved by a cast: -/// * Type-level geometric invariants cannot be broken (eg. a cast from Rot3 to Rot3 -/// is not possible) -/// * A cast to a type with more type-level invariants cannot be done (eg. a cast from -/// Mat to Rot3 is not possible) -/// * For primitive types an unbounded cast is done using the `as` keyword (this is different -/// from the standard library which makes bound-checking to ensure eg. that a i64 is not out of -/// the range of an i32 when a cast from i64 to i32 is done). -/// * A cast does not affect the dimension of an algebraic object. Note that this prevents an -/// isometric transform to be cast to a raw matrix. Use `to_homogeneous` for that special -/// purpose. +/// The following properties are preserved by a cast: +/// +/// * Type-level geometric invariants cannot be broken (eg. a cast from Rot3 to Rot3 is +/// not possible) +/// * A cast to a type with more type-level invariants cannot be done (eg. a cast from Mat to +/// Rot3 is not possible) +/// * For primitive types an unbounded cast is done using the `as` keyword (this is different from +/// the standard library which makes bound-checking to ensure eg. that a i64 is not out of the +/// range of an i32 when a cast from i64 to i32 is done). +/// * A cast does not affect the dimension of an algebraic object. Note that this prevents an +/// isometric transform to be cast to a raw matrix. Use `to_homogeneous` for that special purpose. #[inline(always)] pub fn cast>(t: T) -> U { Cast::from(t) diff --git a/src/structs/dmat.rs b/src/structs/dmat.rs index 8a03280e..8286a05a 100644 --- a/src/structs/dmat.rs +++ b/src/structs/dmat.rs @@ -64,6 +64,12 @@ impl DMat { pub fn is_zero(&self) -> bool { self.mij.iter().all(|e| e.is_zero()) } + + pub fn reset(&mut self) { + for mij in self.mij.mut_iter() { + *mij = Zero::zero(); + } + } } impl DMat { @@ -159,7 +165,6 @@ impl DMat { } } - impl DMat { #[inline] fn offset(&self, i: uint, j: uint) -> uint { @@ -278,10 +283,10 @@ DVecMulRhs> for DMat { impl Inv for DMat { #[inline] - fn inverted(&self) -> Option> { - let mut res : DMat = self.clone(); + fn inv_cpy(m: &DMat) -> Option> { + let mut res : DMat = m.clone(); - if res.invert() { + if res.inv() { Some(res) } else { @@ -289,7 +294,7 @@ Inv for DMat { } } - fn invert(&mut self) -> bool { + fn inv(&mut self) -> bool { assert!(self.nrows == self.ncols); let dim = self.nrows; @@ -366,21 +371,21 @@ Inv for DMat { impl Transpose for DMat { #[inline] - fn transposed(&self) -> DMat { - if self.nrows == self.ncols { - let mut res = self.clone(); + fn transpose_cpy(m: &DMat) -> DMat { + if m.nrows == m.ncols { + let mut res = m.clone(); res.transpose(); res } else { - let mut res = unsafe { DMat::new_uninitialized(self.ncols, self.nrows) }; + let mut res = unsafe { DMat::new_uninitialized(m.ncols, m.nrows) }; - for i in range(0u, self.nrows) { - for j in range(0u, self.ncols) { + for i in range(0u, m.nrows) { + for j in range(0u, m.ncols) { unsafe { - res.set_fast(j, i, self.at_fast(i, j)) + res.set_fast(j, i, m.at_fast(i, j)) } } } @@ -405,7 +410,7 @@ impl Transpose for DMat { } else { // FIXME: implement a better algorithm which does that in-place. - *self = self.transposed(); + *self = Transpose::transpose_cpy(self); } } } @@ -449,7 +454,7 @@ impl + DMatDivRhs> + ToStr > Cov> let fnormalizer: f32 = Cast::from(self.nrows() - 1); let normalizer: N = Cast::from(fnormalizer); // FIXME: this will do 2 allocations for temporaries! - (centered.transposed() * centered) / normalizer + (Transpose::transpose_cpy(¢ered) * centered) / normalizer } } diff --git a/src/structs/dvec.rs b/src/structs/dvec.rs index cbccaed8..ed9f7eff 100644 --- a/src/structs/dvec.rs +++ b/src/structs/dvec.rs @@ -9,7 +9,7 @@ use std::vec; use std::vec::{VecIterator, VecMutIterator}; use std::cmp::ApproxEq; use std::iter::FromIterator; -use traits::geometry::{Dot, Norm, Translation}; +use traits::geometry::{Dot, Norm}; use traits::structure::{Iterable, IterableMut}; #[doc(hidden)] @@ -204,7 +204,7 @@ impl + DVecMulRhs>> DVec }; if !elt.sqnorm().approx_eq(&Zero::zero()) { - res.push(elt.normalized()); + res.push(Norm::normalize_cpy(&elt)); } } @@ -267,33 +267,6 @@ impl Dot for DVec { } } -impl + Neg + Clone> Translation> for DVec { - #[inline] - fn translation(&self) -> DVec { - self.clone() - } - - #[inline] - fn inv_translation(&self) -> DVec { - -self - } - - #[inline] - fn translate_by(&mut self, t: &DVec) { - *self = *self + *t; - } - - #[inline] - fn translated(&self, t: &DVec) -> DVec { - self + *t - } - - #[inline] - fn set_translation(&mut self, t: DVec) { - *self = t - } -} - impl Norm for DVec { #[inline] fn sqnorm(&self) -> N { @@ -306,8 +279,8 @@ impl Norm for DVec { } #[inline] - fn normalized(&self) -> DVec { - let mut res : DVec = self.clone(); + fn normalize_cpy(v: &DVec) -> DVec { + let mut res : DVec = v.clone(); res.normalize(); diff --git a/src/structs/iso_macros.rs b/src/structs/iso_macros.rs index bf22e1a6..b2dc92e1 100644 --- a/src/structs/iso_macros.rs +++ b/src/structs/iso_macros.rs @@ -85,7 +85,7 @@ macro_rules! vec_mul_iso_impl( macro_rules! translation_impl( ($t: ident, $tv: ident) => ( - impl + Add + Clone> Translation<$tv> for $t { + impl + Add + Num + Clone> Translation<$tv> for $t { #[inline] fn translation(&self) -> $tv { self.translation.clone() @@ -97,13 +97,23 @@ macro_rules! translation_impl( } #[inline] - fn translate_by(&mut self, t: &$tv) { - self.translation = self.translation + *t + fn append_translation(&mut self, t: &$tv) { + self.translation = *t + self.translation } #[inline] - fn translated(&self, t: &$tv) -> $t { - $t::new(self.translation + *t, self.rotation.clone()) + fn append_translation_cpy(iso: &$t, t: &$tv) -> $t { + $t::new(*t + iso.translation, iso.rotation.clone()) + } + + #[inline] + fn prepend_translation(&mut self, t: &$tv) { + self.translation = self.translation + self.rotation * *t + } + + #[inline] + fn prepend_translation_cpy(iso: &$t, t: &$tv) -> $t { + $t::new(iso.translation + iso.rotation * *t, iso.rotation.clone()) } #[inline] @@ -143,23 +153,33 @@ macro_rules! rotation_impl( self.rotation.inv_rotation() } - #[inline] - fn rotate_by(&mut self, rot: &$tav) { - // FIXME: this does not seem opitmal - let mut delta: $trot = One::one(); - delta.rotate_by(rot); - self.rotation.rotate_by(rot); + fn append_rotation(&mut self, rot: &$tav) { + let delta = $trot::new(rot.clone()); + + self.rotation = delta * self.rotation; self.translation = delta * self.translation; } #[inline] - fn rotated(&self, rot: &$tav) -> $t { - // FIXME: this does not seem opitmal - let _1: $trot = One::one(); - let delta = _1.rotated(rot); + fn append_rotation_cpy(t: &$t, rot: &$tav) -> $t { + let delta = $trot::new(rot.clone()); - $t::new(delta * self.translation, self.rotation.rotated(rot)) + $t::new(delta * t.translation, delta * t.rotation) + } + + #[inline] + fn prepend_rotation(&mut self, rot: &$tav) { + let delta = $trot::new(rot.clone()); + + self.rotation = self.rotation * delta; + } + + #[inline] + fn prepend_rotation_cpy(t: &$t, rot: &$tav) -> $t { + let delta = $trot::new(rot.clone()); + + $t::new(t.translation.clone(), t.rotation * delta) } #[inline] @@ -196,15 +216,23 @@ macro_rules! transformation_impl( fn inv_transformation(&self) -> $t { // inversion will never fails - self.inverted().unwrap() + Inv::inv_cpy(self).unwrap() } - fn transform_by(&mut self, other: &$t) { - *self = other * *self + fn append_transformation(&mut self, t: &$t) { + *self = *t * *self } - fn transformed(&self, t: &$t) -> $t { - t * *self + fn append_transformation_cpy(iso: &$t, t: &$t) -> $t { + t * *iso + } + + fn prepend_transformation(&mut self, t: &$t) { + *self = *self * *t + } + + fn prepend_transformation_cpy(iso: &$t, t: &$t) -> $t { + *iso * *t } fn set_transformation(&mut self, t: $t) { @@ -234,19 +262,19 @@ macro_rules! inv_impl( ($t: ident) => ( impl Inv for $t { #[inline] - fn invert(&mut self) -> bool { - self.rotation.invert(); - self.translation = self.rotation * -self.translation; + fn inv(&mut self) -> bool { + self.rotation.inv(); + self.translation = self.rotation * -self.translation; // always succeed true } #[inline] - fn inverted(&self) -> Option<$t> { - let mut res = self.clone(); + fn inv_cpy(m: &$t) -> Option<$t> { + let mut res = m.clone(); - res.invert(); + res.inv(); // always succeed Some(res) diff --git a/src/structs/mat_macros.rs b/src/structs/mat_macros.rs index dc64703c..fbe6659a 100644 --- a/src/structs/mat_macros.rs +++ b/src/structs/mat_macros.rs @@ -331,10 +331,10 @@ macro_rules! inv_impl( impl Inv for $t { #[inline] - fn inverted(&self) -> Option<$t> { - let mut res : $t = self.clone(); + fn inv_cpy(m: &$t) -> Option<$t> { + let mut res : $t = m.clone(); - if res.invert() { + if res.inv() { Some(res) } else { @@ -342,7 +342,7 @@ macro_rules! inv_impl( } } - fn invert(&mut self) -> bool { + fn inv(&mut self) -> bool { let mut res: $t = One::one(); let _0N: N = Zero::zero(); @@ -415,8 +415,8 @@ macro_rules! transpose_impl( ($t: ident, $dim: expr) => ( impl Transpose for $t { #[inline] - fn transposed(&self) -> $t { - let mut res = self.clone(); + fn transpose_cpy(m: &$t) -> $t { + let mut res = m.clone(); res.transpose(); diff --git a/src/structs/rot.rs b/src/structs/rot.rs index 10c2a2c3..0eca0c63 100644 --- a/src/structs/rot.rs +++ b/src/structs/rot.rs @@ -22,8 +22,8 @@ pub struct Rot2 { impl> Rot2 { /// Builds a 2 dimensional rotation matrix from an angle in radian. - pub fn from_angle(angle: N) -> Rot2 { - let (sia, coa) = angle.sin_cos(); + pub fn new(angle: Vec1) -> Rot2 { + let (sia, coa) = angle.x.sin_cos(); Rot2 { submat: Mat2::new(coa.clone(), -sia, sia.clone(), coa) @@ -44,25 +44,35 @@ Rotation> for Rot2 { } #[inline] - fn rotate_by(&mut self, rot: &Vec1) { - *self = self.rotated(rot) + fn append_rotation(&mut self, rot: &Vec1) { + *self = Rotation::append_rotation_cpy(self, rot) } #[inline] - fn rotated(&self, rot: &Vec1) -> Rot2 { - Rot2::from_angle(rot.x.clone()) * *self + fn append_rotation_cpy(t: &Rot2, rot: &Vec1) -> Rot2 { + Rot2::new(rot.clone()) * *t + } + + #[inline] + fn prepend_rotation(&mut self, rot: &Vec1) { + *self = Rotation::prepend_rotation_cpy(self, rot) + } + + #[inline] + fn prepend_rotation_cpy(t: &Rot2, rot: &Vec1) -> Rot2 { + *t * Rot2::new(rot.clone()) } #[inline] fn set_rotation(&mut self, rot: Vec1) { - *self = Rot2::from_angle(rot.x) + *self = Rot2::new(rot) } } impl> Rand for Rot2 { #[inline] fn rand(rng: &mut R) -> Rot2 { - Rot2::from_angle(rng.gen()) + Rot2::new(rng.gen()) } } @@ -95,7 +105,7 @@ impl Rot3 { /// # Arguments /// * `axisangle` - A vector representing the rotation. Its magnitude is the amount of rotation /// in radian. Its direction is the axis of rotation. - pub fn from_axis_angle(axisangle: Vec3) -> Rot3 { + pub fn new(axisangle: Vec3) -> Rot3 { if axisangle.sqnorm().is_zero() { One::one() } @@ -141,13 +151,14 @@ impl Rot3 { /// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear /// with `at`. Non-colinearity is not checked. pub fn look_at(&mut self, at: &Vec3, up: &Vec3) { - let xaxis = at.normalized(); - let zaxis = up.cross(&xaxis).normalized(); + let xaxis = Norm::normalize_cpy(at); + let zaxis = Norm::normalize_cpy(&up.cross(&xaxis)); let yaxis = zaxis.cross(&xaxis); - self.submat = Mat3::new(xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(), - xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(), - xaxis.z , yaxis.z , zaxis.z) + self.submat = Mat3::new( + xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(), + xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(), + xaxis.z , yaxis.z , zaxis.z) } /// Reorient this matrix such that its local `z` axis points to a given point. @@ -158,13 +169,14 @@ impl Rot3 { /// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear /// with `at`. Non-colinearity is not checked. pub fn look_at_z(&mut self, at: &Vec3, up: &Vec3) { - let zaxis = at.normalized(); - let xaxis = up.cross(&zaxis).normalized(); + let zaxis = Norm::normalize_cpy(at); + let xaxis = Norm::normalize_cpy(&up.cross(&zaxis)); let yaxis = zaxis.cross(&xaxis); - self.submat = Mat3::new(xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(), - xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(), - xaxis.z , yaxis.z , zaxis.z) + self.submat = Mat3::new( + xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(), + xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(), + xaxis.z , yaxis.z , zaxis.z) } } @@ -208,18 +220,28 @@ Rotation> for Rot3 { #[inline] - fn rotate_by(&mut self, rot: &Vec3) { - *self = self.rotated(rot) + fn append_rotation(&mut self, rot: &Vec3) { + *self = Rotation::append_rotation_cpy(self, rot) } #[inline] - fn rotated(&self, axisangle: &Vec3) -> Rot3 { - Rot3::from_axis_angle(axisangle.clone()) * *self + fn append_rotation_cpy(t: &Rot3, axisangle: &Vec3) -> Rot3 { + Rot3::new(axisangle.clone()) * *t + } + + #[inline] + fn prepend_rotation(&mut self, rot: &Vec3) { + *self = Rotation::prepend_rotation_cpy(self, rot) + } + + #[inline] + fn prepend_rotation_cpy(t: &Rot3, axisangle: &Vec3) -> Rot3 { + *t * Rot3::new(axisangle.clone()) } #[inline] fn set_rotation(&mut self, axisangle: Vec3) { - *self = Rot3::from_axis_angle(axisangle) + *self = Rot3::new(axisangle) } } @@ -227,7 +249,7 @@ impl Rand for Rot3 { #[inline] fn rand(rng: &mut R) -> Rot3 { - Rot3::from_axis_angle(rng.gen()) + Rot3::new(rng.gen()) } } diff --git a/src/structs/rot_macros.rs b/src/structs/rot_macros.rs index 308807cd..d5c19367 100644 --- a/src/structs/rot_macros.rs +++ b/src/structs/rot_macros.rs @@ -114,7 +114,7 @@ macro_rules! inv_impl( ($t: ident) => ( impl Inv for $t { #[inline] - fn invert(&mut self) -> bool { + fn inv(&mut self) -> bool { self.transpose(); // always succeed @@ -122,9 +122,9 @@ macro_rules! inv_impl( } #[inline] - fn inverted(&self) -> Option<$t> { + fn inv_cpy(m: &$t) -> Option<$t> { // always succeed - Some(self.transposed()) + Some(Transpose::transpose_cpy(m)) } } ) @@ -134,8 +134,8 @@ macro_rules! transpose_impl( ($t: ident) => ( impl Transpose for $t { #[inline] - fn transposed(&self) -> $t { - $t { submat: self.submat.transposed() } + fn transpose_cpy(m: &$t) -> $t { + $t { submat: Transpose::transpose_cpy(&m.submat) } } #[inline] diff --git a/src/structs/spec/identity.rs b/src/structs/spec/identity.rs index 11a05763..235f541b 100644 --- a/src/structs/spec/identity.rs +++ b/src/structs/spec/identity.rs @@ -11,11 +11,11 @@ impl One for mat::Identity { } impl Inv for mat::Identity { - fn inverted(&self) -> Option { + fn inv_cpy(_: &mat::Identity) -> Option { Some(mat::Identity::new()) } - fn invert(&mut self) -> bool { + fn inv(&mut self) -> bool { true } } @@ -29,7 +29,7 @@ impl Mul for mat::Identity { impl Transpose for mat::Identity { #[inline] - fn transposed(&self) -> mat::Identity { + fn transpose_cpy(_: &mat::Identity) -> mat::Identity { mat::Identity::new() } @@ -50,12 +50,22 @@ impl Translation for mat::Identity { } #[inline] - fn translate_by(&mut self, _: &V) { + fn append_translation(&mut self, _: &V) { fail!("Attempted to translate the identity matrix.") } #[inline] - fn translated(&self, _: &V) -> mat::Identity { + fn append_translation_cpy(_: &mat::Identity, _: &V) -> mat::Identity { + fail!("Attempted to translate the identity matrix.") + } + + #[inline] + fn prepend_translation(&mut self, _: &V) { + fail!("Attempted to translate the identity matrix.") + } + + #[inline] + fn prepend_translation_cpy(_: &mat::Identity, _: &V) -> mat::Identity { fail!("Attempted to translate the identity matrix.") } @@ -89,12 +99,22 @@ impl Rotation for mat::Identity { } #[inline] - fn rotate_by(&mut self, _: &V) { + fn append_rotation(&mut self, _: &V) { fail!("Attempted to rotate the identity matrix.") } #[inline] - fn rotated(&self, _: &V) -> mat::Identity { + fn append_rotation_cpy(_: &mat::Identity, _: &V) -> mat::Identity { + fail!("Attempted to rotate the identity matrix.") + } + + #[inline] + fn prepend_rotation(&mut self, _: &V) { + fail!("Attempted to rotate the identity matrix.") + } + + #[inline] + fn prepend_rotation_cpy(_: &mat::Identity, _: &V) -> mat::Identity { fail!("Attempted to rotate the identity matrix.") } @@ -128,12 +148,22 @@ impl Transformation for mat::Identity { } #[inline] - fn transform_by(&mut self, _: &M) { + fn append_transformation(&mut self, _: &M) { fail!("Attempted to transform the identity matrix.") } #[inline] - fn transformed(&self, _: &M) -> mat::Identity { + fn append_transformation_cpy(_: &mat::Identity, _: &M) -> mat::Identity { + fail!("Attempted to transform the identity matrix.") + } + + #[inline] + fn prepend_transformation(&mut self, _: &M) { + fail!("Attempted to transform the identity matrix.") + } + + #[inline] + fn prepend_transformation_cpy(_: &mat::Identity, _: &M) -> mat::Identity { fail!("Attempted to transform the identity matrix.") } diff --git a/src/structs/spec/mat.rs b/src/structs/spec/mat.rs index e54c404c..8a1d0446 100644 --- a/src/structs/spec/mat.rs +++ b/src/structs/spec/mat.rs @@ -9,10 +9,10 @@ use traits::structure::{Cast, Row, Col}; impl Inv for Mat1 { #[inline] - fn inverted(&self) -> Option> { - let mut res : Mat1 = self.clone(); + fn inv_cpy(m: &Mat1) -> Option> { + let mut res = m.clone(); - if res.invert() { + if res.inv() { Some(res) } else { @@ -21,7 +21,7 @@ Inv for Mat1 { } #[inline] - fn invert(&mut self) -> bool { + fn inv(&mut self) -> bool { if self.m11.is_zero() { false } @@ -36,10 +36,10 @@ Inv for Mat1 { impl Inv for Mat2 { #[inline] - fn inverted(&self) -> Option> { - let mut res : Mat2 = self.clone(); + fn inv_cpy(m: &Mat2) -> Option> { + let mut res = m.clone(); - if res.invert() { + if res.inv() { Some(res) } else { @@ -48,7 +48,7 @@ Inv for Mat2 { } #[inline] - fn invert(&mut self) -> bool { + fn inv(&mut self) -> bool { let det = self.m11 * self.m22 - self.m21 * self.m12; if det.is_zero() { @@ -67,10 +67,10 @@ Inv for Mat2 { impl Inv for Mat3 { #[inline] - fn inverted(&self) -> Option> { - let mut res = self.clone(); + fn inv_cpy(m: &Mat3) -> Option> { + let mut res = m.clone(); - if res.invert() { + if res.inv() { Some(res) } else { @@ -79,7 +79,7 @@ Inv for Mat3 { } #[inline] - fn invert(&mut self) -> bool { + fn inv(&mut self) -> bool { let minor_m12_m23 = self.m22 * self.m33 - self.m32 * self.m23; let minor_m11_m23 = self.m21 * self.m33 - self.m31 * self.m23; let minor_m11_m22 = self.m21 * self.m32 - self.m31 * self.m22; diff --git a/src/structs/spec/vec.rs b/src/structs/spec/vec.rs index 61bef91f..34c2f7e9 100644 --- a/src/structs/spec/vec.rs +++ b/src/structs/spec/vec.rs @@ -103,10 +103,10 @@ impl Basis for Vec3 { fn orthonormal_subspace_basis(&self, f: &fn(Vec3) -> bool) { let a = if self.x.clone().abs() > self.y.clone().abs() { - Vec3::new(self.z.clone(), Zero::zero(), -self.x).normalized() + Norm::normalize_cpy(&Vec3::new(self.z.clone(), Zero::zero(), -self.x)) } else { - Vec3::new(Zero::zero(), -self.z, self.y.clone()).normalized() + Norm::normalize_cpy(&Vec3::new(Zero::zero(), -self.z, self.y.clone())) }; if !f(a.cross(self)) { return }; diff --git a/src/structs/spec/vec0.rs b/src/structs/spec/vec0.rs index eed3a6e4..d8f65d3d 100644 --- a/src/structs/spec/vec0.rs +++ b/src/structs/spec/vec0.rs @@ -128,13 +128,23 @@ impl + Neg> Translation> for vec::Vec0 { } #[inline] - fn translate_by(&mut self, t: &vec::Vec0) { + fn append_translation(&mut self, t: &vec::Vec0) { + *self = *t + *self; + } + + #[inline] + fn append_translation_cpy(vec: &vec::Vec0, t: &vec::Vec0) -> vec::Vec0 { + *t + vec + } + + #[inline] + fn prepend_translation(&mut self, t: &vec::Vec0) { *self = *self + *t; } #[inline] - fn translated(&self, t: &vec::Vec0) -> vec::Vec0 { - self + *t + fn prepend_translation_cpy(vec: &vec::Vec0, t: &vec::Vec0) -> vec::Vec0 { + vec + *t } #[inline] @@ -154,21 +164,13 @@ impl Norm for vec::Vec0 { } #[inline] - fn normalized(&self) -> vec::Vec0 { - let mut res : vec::Vec0 = self.clone(); - - res.normalize(); - - res + fn normalize_cpy(v: &vec::Vec0) -> vec::Vec0 { + v.clone() } #[inline] fn normalize(&mut self) -> N { - let l = self.norm(); - - *self = *self / l; - - l + Zero::zero() } } diff --git a/src/structs/vec_macros.rs b/src/structs/vec_macros.rs index 1e402352..5bb3e5f7 100644 --- a/src/structs/vec_macros.rs +++ b/src/structs/vec_macros.rs @@ -253,7 +253,7 @@ macro_rules! basis_impl( }; if !elt.sqnorm().approx_eq(&Zero::zero()) { - let new_element = elt.normalized(); + let new_element = Norm::normalize_cpy(&elt); if !f(new_element.clone()) { return }; @@ -394,13 +394,23 @@ macro_rules! translation_impl( } #[inline] - fn translate_by(&mut self, t: &$t) { + fn append_translation(&mut self, t: &$t) { + *self = *t + *self; + } + + #[inline] + fn append_translation_cpy(transform: &$t, t: &$t) -> $t { + *t + *transform + } + + #[inline] + fn prepend_translation(&mut self, t: &$t) { *self = *self + *t; } #[inline] - fn translated(&self, t: &$t) -> $t { - self + *t + fn prepend_translation_cpy(transform: &$t, t: &$t) -> $t { + transform + *t } #[inline] @@ -425,8 +435,8 @@ macro_rules! norm_impl( } #[inline] - fn normalized(&self) -> $t { - let mut res : $t = self.clone(); + fn normalize_cpy(v: &$t) -> $t { + let mut res : $t = v.clone(); res.normalize(); diff --git a/src/tests/mat.rs b/src/tests/mat.rs index 4d13d628..7c10e525 100644 --- a/src/tests/mat.rs +++ b/src/tests/mat.rs @@ -10,7 +10,7 @@ macro_rules! test_inv_mat_impl( do 10000.times { let randmat : $t = random(); - assert!((na::inverted(&randmat).unwrap() * randmat).approx_eq(&na::one())); + assert!((na::inv(&randmat).unwrap() * randmat).approx_eq(&na::one())); } ); ) @@ -20,7 +20,7 @@ macro_rules! test_transpose_mat_impl( do 10000.times { let randmat : $t = random(); - assert!(na::transposed(&na::transposed(&randmat)) == randmat); + assert!(na::transpose(&na::transpose(&randmat)) == randmat); } ); ) @@ -91,7 +91,7 @@ fn test_rotation2() { let randmat: na::Rot2 = na::one(); let ang = na::vec1(abs::(random()) % Real::pi()); - assert!(na::rotation(&na::rotated(&randmat, &ang)).approx_eq(&ang)); + assert!(na::rotation(&na::append_rotation(&randmat, &ang)).approx_eq(&ang)); } } @@ -99,7 +99,7 @@ fn test_rotation2() { fn test_index_mat2() { let mat: na::Mat2 = random(); - assert!(mat.at((0, 1)) == na::transposed(&mat).at((1, 0))); + assert!(mat.at((0, 1)) == na::transpose(&mat).at((1, 0))); } #[test] @@ -107,10 +107,10 @@ fn test_inv_rotation3() { do 10000.times { let randmat: na::Rot3 = na::one(); let dir: na::Vec3 = random(); - let ang = na::normalized(&dir) * (abs::(random()) % Real::pi()); - let rot = na::rotated(&randmat, &ang); + let ang = na::normalize(&dir) * (abs::(random()) % Real::pi()); + let rot = na::append_rotation(&randmat, &ang); - assert!((na::transposed(&rot) * rot).approx_eq(&na::one())); + assert!((na::transpose(&rot) * rot).approx_eq(&na::one())); } } diff --git a/src/tests/vec.rs b/src/tests/vec.rs index e2bffd8e..b5cac522 100644 --- a/src/tests/vec.rs +++ b/src/tests/vec.rs @@ -78,7 +78,7 @@ macro_rules! test_subspace_basis_impl( ($t: ty) => ( do 10000.times { let v : $t = random(); - let v1 = na::normalized(&v); + let v1 = na::normalize(&v); do na::orthonormal_subspace_basis(&v1) |e1| { // check vectors are orthogonal to v1 diff --git a/src/traits/geometry.rs b/src/traits/geometry.rs index a364c2dd..7f9f396c 100644 --- a/src/traits/geometry.rs +++ b/src/traits/geometry.rs @@ -13,11 +13,17 @@ pub trait Translation { /// Gets the inverse translation associated with this object. fn inv_translation(&self) -> V; - /// In-place version of `translated`. - fn translate_by(&mut self, &V); + /// Appends a translation to this object. + fn append_translation(&mut self, &V); - /// Appends a translation. - fn translated(&self, &V) -> Self; + /// Appends the translation `amount` to a copy of `t`. + fn append_translation_cpy(t: &Self, amount: &V) -> Self; + + /// Prepends a translation to this object. + fn prepend_translation(&mut self, &V); + + /// Prepends the translation `amount` to a copy of `t`. + fn prepend_translation_cpy(t: &Self, amount: &V) -> Self; /// Sets the translation. fn set_translation(&mut self, V); @@ -27,7 +33,8 @@ pub trait Translation { /// rotate vectors. pub trait Translate { /// Apply a translation to an object. - fn translate(&self, &V) -> V; + fn translate(&self, &V) -> V; + /// Apply an inverse translation to an object. fn inv_translate(&self, &V) -> V; } @@ -41,11 +48,17 @@ pub trait Rotation { /// Gets the inverse rotation associated with `self`. fn inv_rotation(&self) -> V; - /// In-place version of `rotated`. - fn rotate_by(&mut self, &V); + /// Appends a rotation to this object. + fn append_rotation(&mut self, &V); - /// Appends a rotation to `self`. - fn rotated(&self, &V) -> Self; + /// Appends the rotation `amount` to a copy of `t`. + fn append_rotation_cpy(t: &Self, amount: &V) -> Self; + + /// Prepends a rotation to this object. + fn prepend_rotation(&mut self, &V); + + /// Prepends the rotation `amount` to a copy of `t`. + fn prepend_rotation_cpy(t: &Self, amount: &V) -> Self; /// Sets the rotation of `self`. fn set_rotation(&mut self, V); @@ -57,6 +70,7 @@ pub trait Rotation { pub trait Rotate { /// Applies a rotation to `v`. fn rotate(&self, v: &V) -> V; + /// Applies an inverse rotation to `v`. fn inv_rotate(&self, v: &V) -> V; } @@ -72,15 +86,15 @@ pub trait RotationWithTranslation, AV>: Rotation + Translation Self { - let mut res = self.translated(&-center); + fn append_rotation_wrt_point_cpy(t: &Self, amount: &AV, center: &LV) -> Self { + let mut res = Translation::append_translation_cpy(t, &-center); - res.rotate_by(amount); - res.translate_by(center); + res.append_rotation(amount); + res.append_translation(center); res } @@ -90,24 +104,23 @@ pub trait RotationWithTranslation, AV>: Rotation + Translation Self { - self.rotated_wrt_point(amount, &self.translation()) + fn append_rotation_wrt_center_cpy(t: &Self, amount: &AV) -> Self { + RotationWithTranslation::append_rotation_wrt_point_cpy(t, amount, &t.translation()) } /// Applies a rotation centered on the translation of `m`. @@ -115,12 +128,11 @@ pub trait RotationWithTranslation, AV>: Rotation + Translation { /// Gets the inverse transformation of `self`. fn inv_transformation(&self) -> M; - /// In-place version of `transformed`. - fn transform_by(&mut self, &M); + /// Appends a transformation to this object. + fn append_transformation(&mut self, &M); - /// Appends a transformation to `self`. - fn transformed(&self, &M) -> Self; + /// Appends the transformation `amount` to a copy of `t`. + fn append_transformation_cpy(t: &Self, amount: &M) -> Self; + + /// Prepends a transformation to this object. + fn prepend_transformation(&mut self, &M); + + /// Prepends the transformation `amount` to a copy of `t`. + fn prepend_transformation_cpy(t: &Self, amount: &M) -> Self; /// Sets the transformation of `self`. fn set_transformation(&mut self, M); @@ -174,6 +192,7 @@ pub trait Transformation { pub trait Transform { /// Applies a transformation to `v`. fn transform(&self, &V) -> V; + /// Applies an inverse transformation to `v`. fn inv_transform(&self, &V) -> V; } @@ -212,11 +231,11 @@ pub trait Norm { #[inline] fn sqnorm(&self) -> N; - /// Gets the normalized version of `self`. + /// Gets the normalized version of a copy of `v`. #[inline] - fn normalized(&self) -> Self; + fn normalize_cpy(v: &Self) -> Self; - /// In-place version of `normalized`. + /// Normalizes `self`. #[inline] fn normalize(&mut self) -> N; } diff --git a/src/traits/operations.rs b/src/traits/operations.rs index 6de2620b..6b981f71 100644 --- a/src/traits/operations.rs +++ b/src/traits/operations.rs @@ -12,15 +12,16 @@ pub trait Absolute { /// Trait of objects having an inverse. Typically used to implement matrix inverse. pub trait Inv { /// Returns the inverse of `self`. - fn inverted(&self) -> Option; + fn inv_cpy(m: &Self) -> Option; + /// In-place version of `inverse`. - fn invert(&mut self) -> bool; + fn inv(&mut self) -> bool; } /// Trait of objects which can be transposed. pub trait Transpose { /// Computes the transpose of a matrix. - fn transposed(&self) -> Self; + fn transpose_cpy(m: &Self) -> Self; /// In-place version of `transposed`. fn transpose(&mut self); @@ -39,6 +40,14 @@ pub trait Cov { /// * For matrices, observations are stored in its rows. /// * For vectors, observations are stored in its components (thus are 1-dimensional). fn cov(&self) -> M; + + /// Computes the covariance of the obsevations stored by `self`: + /// + /// * For matrices, observations are stored in its rows. + /// * For vectors, observations are stored in its components (thus are 1-dimensional). + fn cov_to(&self, out: &mut M) { + *out = self.cov() + } } /// Trait for computing the covariance of a set of data. @@ -50,6 +59,26 @@ pub trait Mean { fn mean(&self) -> N; } +// /// Cholesky decomposition. +// pub trait Chol { +// /// Performs the cholesky decomposition on `self`. The resulting upper-triangular matrix is +// /// returned. Returns `None` if the matrix is not symetric positive-definite. +// fn chol(self) -> Option; +// +// /// Performs the cholesky decomposition on `self`. The resulting upper-triangular matrix is +// /// written to a given parameter. If the decomposition fails `false` is returned; the state of +// /// the output parameter is undefined. +// fn chol_to(&self, out: &mut Self) -> bool { +// match self.chol() { +// None => false, +// Some(decomp) => { +// *out = decomp; +// true +// } +// } +// } +// } + // XXX: those two traits should not exist since there is generalized operator overloading of Add // and Sub. // However, using the same trait multiple time as a trait bound (ex: impl + Add)