Api change: deal with inplace/out of place methods.

Before, it was too easy to use an out of place method instead of the inplace one since they name
were pretty mutch the same. This kind of confusion may lead to silly bugs very hard to understand.
Thus the following changes have been made when a method is available both inplace and out-of-place:

* inplace version keep a short name.
* out-of-place version are suffixed by `_cpy` (meaning `copy`), and are static methods.

Methods applying transformations (rotation, translation or general transform) are now prefixed by
`append`, and a `prepend` version is available too.

Also, free functions doing in-place modifications dont really make sense. They have been removed.

Here are the naming changes:
* `invert` -> `inv`
* `inverted` -> `Inv::inv_cpy`
* `transpose` -> `transpose`
* `transposed` -> `Transpose::transpose_cpy`
* `transform_by` -> `append_transformation`
* `transformed` -> `Transform::append_transformation_cpy`
* `rotate_by` -> `apppend_rotation`
* `rotated` -> `Rotation::append_rotation_cpy`
* `translate_by` -> `apppend_translation`
* `translate` -> `Translation::append_translation_cpy`
* `normalized` -> `Norm::normalize_cpy`
* `rotated_wrt_point` -> `RotationWithTranslation::append_rotation_wrt_point_cpy`
* `rotated_wrt_center` -> `RotationWithTranslation::append_rotation_wrt_center_cpy`

Note that using those static methods is very verbose, and using in-place methods require an
explicit import of the related trait.

This is a way to convince the user to use free functions most of the time.
This commit is contained in:
Sébastien Crozet 2013-10-14 10:22:32 +02:00
parent 86d6ff759c
commit ccbc8b4429
17 changed files with 378 additions and 349 deletions

View File

@ -11,9 +11,8 @@ An on-line version of this documentation is available [here](http://crozet.re/na
## Using **nalgebra** ## Using **nalgebra**
All the functionalities of **nalgebra** are grouped in one place: the `na` module. 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. This module re-exports everything and includes free functions for all traits methods doing
Free functions are useful if you prefer doing something like `na::dot(v1, v2)` instead of out-of-place modifications.
`v1.dot(v2)`.
* You can import the whole prelude, including free functions, using: * You can import the whole prelude, including free functions, using:
@ -32,8 +31,23 @@ use nalgebra::traits::*;
```.rust ```.rust
use nalgebra::structs::*; use nalgebra::structs::*;
``` ```
Of course, you can still import `nalgebra::na` alone, and get anything you want using the prefix The preffered way to use **nalgebra** is to import types and traits explicitly, and call
`na`. 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<f64> = na::one();
b.append_rotation(&a);
assert!(na::rotation(&b).approx_eq(&a));
}
```
## Features ## Features
**nalgebra** is meant to be a general-purpose linear algebra library (but is very far from that), **nalgebra** is meant to be a general-purpose linear algebra library (but is very far from that),

197
src/na.rs
View File

@ -166,7 +166,7 @@ pub fn mat4<N>(m11: N, m12: N, m13: N, m14: N,
* Translation<V> * Translation<V>
*/ */
/// Gets the translation applicable by the given object. /// Gets the translation applicable by `m`.
/// ///
/// ```rust /// ```rust
/// extern mod nalgebra; /// extern mod nalgebra;
@ -185,7 +185,7 @@ pub fn translation<V, M: Translation<V>>(m: &M) -> V {
m.translation() m.translation()
} }
/// Gets the inverse translation applicable by the given object. /// Gets the inverse translation applicable by `m`.
/// ///
/// ```rust /// ```rust
/// extern mod nalgebra; /// extern mod nalgebra;
@ -204,22 +204,10 @@ pub fn inv_translation<V, M: Translation<V>>(m: &M) -> V {
m.inv_translation() m.inv_translation()
} }
/// In-place version of `translated`. /// Appied the translation `v` to a copy of `m`.
#[inline(always)] #[inline(always)]
pub fn translate_by<V, M: Translation<V>>(m: &mut M, v: &V) { pub fn append_translation<V, M: Translation<V>>(m: &M, v: &V) -> M {
m.translate_by(v) Translation::append_translation_cpy(m, v)
}
/// Gets a translated copy of the given object.
#[inline(always)]
pub fn translated<V, M: Translation<V>>(m: &M, v: &V) -> M {
m.translated(v)
}
/// Sets the translation of the given object.
#[inline(always)]
pub fn set_translation<V, M: Translation<V>>(m: &mut M, v: V) {
m.set_translation(v)
} }
/* /*
@ -269,7 +257,7 @@ pub fn inv_translate<V, M: Translate<V>>(m: &M, v: &V) -> V {
* Rotation<V> * Rotation<V>
*/ */
/// Gets the rotation applicable by the given object. /// Gets the rotation applicable by `m`.
/// ///
/// ```rust /// ```rust
/// extern mod nalgebra; /// extern mod nalgebra;
@ -287,7 +275,7 @@ pub fn rotation<V, M: Rotation<V>>(m: &M) -> V {
} }
/// Gets the rotation applicable by the given object. /// Gets the inverse rotation applicable by `m`.
/// ///
/// ```rust /// ```rust
/// extern mod nalgebra; /// extern mod nalgebra;
@ -304,27 +292,7 @@ pub fn inv_rotation<V, M: Rotation<V>>(m: &M) -> V {
m.inv_rotation() m.inv_rotation()
} }
/// Rotates an object in-place. /// Applies the rotation `v` to a copy of `m`.
///
/// ```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<V, M: Rotation<V>>(m: &mut M, v: &V) {
m.rotate_by(v)
}
/// Creates a rotated copy of an object.
/// ///
/// ```rust /// ```rust
/// extern mod nalgebra; /// extern mod nalgebra;
@ -333,34 +301,14 @@ pub fn rotate_by<V, M: Rotation<V>>(m: &mut M, v: &V) {
/// pub main() { /// pub main() {
/// let t = na::rot3(0.0, 0.0, 0.0); /// let t = na::rot3(0.0, 0.0, 0.0);
/// let v = na::vec3(1.0, 1.0, 1.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)) /// assert!(na::rotation(&rt) == na::vec3(1.0, 1.0, 1.0))
/// } /// }
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn rotated<V, M: Rotation<V>>(m: &M, v: &V) -> M { pub fn append_rotation<V, M: Rotation<V>>(m: &M, v: &V) -> M {
m.rotated(v) Rotation::append_rotation_cpy(m, 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<V, M: Rotation<V>>(m: &mut M, v: V) {
m.set_rotation(v)
} }
/* /*
@ -395,7 +343,7 @@ pub fn rotate<V, M: Rotate<V>>(m: &M, v: &V) -> V {
/// use nalgebra::na; /// use nalgebra::na;
/// ///
/// pub main() { /// 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 v = na::vec3(0.0, 0.0, na::pi() / 2.0);
/// ///
/// let tv = na::rotate(&t, &v); /// let tv = na::rotate(&t, &v);
@ -412,53 +360,32 @@ pub fn inv_rotate<V, M: Rotate<V>>(m: &M, v: &V) -> V {
* RotationWithTranslation<LV, AV> * RotationWithTranslation<LV, AV>
*/ */
/// 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)] #[inline(always)]
pub fn rotated_wrt_point<LV: Neg<LV>, pub fn append_rotation_wrt_point<LV: Neg<LV>,
AV, AV,
M: RotationWithTranslation<LV, AV>>( M: RotationWithTranslation<LV, AV>>(
m: &M, m: &M,
amount: &AV, amount: &AV,
center: &LV) -> M { center: &LV) -> M {
m.rotated_wrt_point(amount, center) RotationWithTranslation::append_rotation_wrt_point_cpy(m, amount, center)
} }
/// In-place version of `rotated_wrt_point`. /// Rotates a copy of `m` by `amount` using `m.translation()` as the pivot point.
#[inline(always)]
pub fn rotate_wrt_point<LV: Neg<LV>,
AV,
M: RotationWithTranslation<LV, AV>>(
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<LV: Neg<LV>,
AV,
M: RotationWithTranslation<LV, AV>>(
m: &M,
amount: &AV) -> M {
m.rotated_wrt_center(amount)
}
/// In-place version of `rotate_wrt_center`.
#[inline(always)] #[inline(always)]
pub fn rotate_wrt_center<LV: Neg<LV>, pub fn rotate_wrt_center<LV: Neg<LV>,
AV, AV,
M: RotationWithTranslation<LV, AV>>( M: RotationWithTranslation<LV, AV>>(
m: &mut M, m: &M,
amount: &AV) { amount: &AV) -> M {
m.rotate_wrt_center(amount) RotationWithTranslation::append_rotation_wrt_center_cpy(m, amount)
} }
/* /*
* RotationMatrix<LV, AV, R> * RotationMatrix<LV, AV, R>
*/ */
/// Builds a rotation matrix from a rotation-capable object. /// Builds a rotation matrix from `r`.
#[inline(always)] #[inline(always)]
pub fn to_rot_mat<LV, AV, M: Mat<LV, LV> + Rotation<AV>, R: RotationMatrix<LV, AV, M>>(r: &R) -> M { pub fn to_rot_mat<LV, AV, M: Mat<LV, LV> + Rotation<AV>, R: RotationMatrix<LV, AV, M>>(r: &R) -> M {
r.to_rot_mat() r.to_rot_mat()
@ -478,34 +405,22 @@ pub fn absolute_rotate<V, M: AbsoluteRotate<V>>(m: &M, v: &V) -> V {
* Transformation<T> * Transformation<T>
*/ */
/// Gets the transformation applicable by the given object. /// Gets the transformation applicable by `m`.
#[inline(always)] #[inline(always)]
pub fn transformation<T, M: Transformation<T>>(m: &M) -> T { pub fn transformation<T, M: Transformation<T>>(m: &M) -> T {
m.transformation() m.transformation()
} }
/// Gets the inverse transformation applicable by the given object. /// Gets the inverse transformation applicable by `m`.
#[inline(always)] #[inline(always)]
pub fn inv_transformation<T, M: Transformation<T>>(m: &M) -> T { pub fn inv_transformation<T, M: Transformation<T>>(m: &M) -> T {
m.inv_transformation() m.inv_transformation()
} }
/// In-place version of `transformed`. /// Gets a transformed copy of `m`.
#[inline(always)] #[inline(always)]
pub fn transform_by<T, M: Transformation<T>>(m: &mut M, t: &T) { pub fn append_transformation<T, M: Transformation<T>>(m: &M, t: &T) -> M {
m.transform_by(t) Transformation::append_transformation_cpy(m, t)
}
/// Gets a transformed copy of an object.
#[inline(always)]
pub fn transformed<T, M: Transformation<T>>(m: &M, t: &T) -> M {
m.transformed(t)
}
/// Sets the transformation of an object.
#[inline(always)]
pub fn set_transformation<T, M: Transformation<T>>(m: &mut M, t: T) {
m.set_transformation(t)
} }
/* /*
@ -558,14 +473,8 @@ pub fn sqnorm<V: Norm<N>, N: Algebraic>(v: &V) -> N {
/// Gets the normalized version of a vector. /// Gets the normalized version of a vector.
#[inline(always)] #[inline(always)]
pub fn normalized<V: Norm<N>, N: Algebraic>(v: &V) -> V { pub fn normalize<V: Norm<N>, N: Algebraic>(v: &V) -> V {
v.normalized() Norm::normalize_cpy(v)
}
/// In-place version of `normalized`.
#[inline(always)]
pub fn normalize<V: Norm<N>, N: Algebraic>(v: &mut V) -> N {
v.normalize()
} }
/* /*
@ -646,14 +555,8 @@ pub fn absolute<M: Absolute<Res>, Res>(m: &M) -> Res {
/// Gets an inverted copy of a matrix. /// Gets an inverted copy of a matrix.
#[inline(always)] #[inline(always)]
pub fn inverted<M: Inv>(m: &M) -> Option<M> { pub fn inv<M: Inv>(m: &M) -> Option<M> {
m.inverted() Inv::inv_cpy(m)
}
/// In-place version of `inverted`.
#[inline(always)]
pub fn invert<M: Inv>(m: &mut M) -> bool {
m.invert()
} }
/* /*
@ -662,14 +565,8 @@ pub fn invert<M: Inv>(m: &mut M) -> bool {
/// Gets a transposed copy of a matrix. /// Gets a transposed copy of a matrix.
#[inline(always)] #[inline(always)]
pub fn transposed<M: Transpose>(m: &M) -> M { pub fn transpose<M: Transpose>(m: &M) -> M {
m.transposed() Transpose::transpose_cpy(m)
}
/// In-place version of `transposed`.
#[inline(always)]
pub fn transpose<M: Transpose>(m: &mut M) {
m.transpose()
} }
/* /*
@ -749,17 +646,17 @@ pub fn dim<V: Dim>() -> uint {
/// Converts an object from one type to another. /// Converts an object from one type to another.
/// ///
/// For primitive types, this is the same as the `as` keywords. /// For primitive types, this is the same as the `as` keywords.
/// Those properties are preserved by a cast: /// The following properties are preserved by a cast:
/// * Type-level geometric invariants cannot be broken (eg. a cast from Rot3<f64> to Rot3<i64> ///
/// is not possible) /// * Type-level geometric invariants cannot be broken (eg. a cast from Rot3<f64> to Rot3<i64> is
/// * A cast to a type with more type-level invariants cannot be done (eg. a cast from /// not possible)
/// Mat<f64> to Rot3<f64> is not possible) /// * A cast to a type with more type-level invariants cannot be done (eg. a cast from Mat<f64> to
/// * For primitive types an unbounded cast is done using the `as` keyword (this is different /// Rot3<f64> is not possible)
/// from the standard library which makes bound-checking to ensure eg. that a i64 is not out of /// * For primitive types an unbounded cast is done using the `as` keyword (this is different from
/// the range of an i32 when a cast from i64 to i32 is done). /// the standard library which makes bound-checking to ensure eg. that a i64 is not out of the
/// * A cast does not affect the dimension of an algebraic object. Note that this prevents an /// range of an i32 when a cast from i64 to i32 is done).
/// isometric transform to be cast to a raw matrix. Use `to_homogeneous` for that special /// * A cast does not affect the dimension of an algebraic object. Note that this prevents an
/// purpose. /// isometric transform to be cast to a raw matrix. Use `to_homogeneous` for that special purpose.
#[inline(always)] #[inline(always)]
pub fn cast<T, U: Cast<T>>(t: T) -> U { pub fn cast<T, U: Cast<T>>(t: T) -> U {
Cast::from(t) Cast::from(t)

View File

@ -64,6 +64,12 @@ impl<N: Zero + Clone> DMat<N> {
pub fn is_zero(&self) -> bool { pub fn is_zero(&self) -> bool {
self.mij.iter().all(|e| e.is_zero()) self.mij.iter().all(|e| e.is_zero())
} }
pub fn reset(&mut self) {
for mij in self.mij.mut_iter() {
*mij = Zero::zero();
}
}
} }
impl<N: Rand> DMat<N> { impl<N: Rand> DMat<N> {
@ -159,7 +165,6 @@ impl<N: One + Zero + Clone> DMat<N> {
} }
} }
impl<N: Clone> DMat<N> { impl<N: Clone> DMat<N> {
#[inline] #[inline]
fn offset(&self, i: uint, j: uint) -> uint { fn offset(&self, i: uint, j: uint) -> uint {
@ -278,10 +283,10 @@ DVecMulRhs<N, DVec<N>> for DMat<N> {
impl<N: Clone + Num> impl<N: Clone + Num>
Inv for DMat<N> { Inv for DMat<N> {
#[inline] #[inline]
fn inverted(&self) -> Option<DMat<N>> { fn inv_cpy(m: &DMat<N>) -> Option<DMat<N>> {
let mut res : DMat<N> = self.clone(); let mut res : DMat<N> = m.clone();
if res.invert() { if res.inv() {
Some(res) Some(res)
} }
else { else {
@ -289,7 +294,7 @@ Inv for DMat<N> {
} }
} }
fn invert(&mut self) -> bool { fn inv(&mut self) -> bool {
assert!(self.nrows == self.ncols); assert!(self.nrows == self.ncols);
let dim = self.nrows; let dim = self.nrows;
@ -366,21 +371,21 @@ Inv for DMat<N> {
impl<N: Clone> Transpose for DMat<N> { impl<N: Clone> Transpose for DMat<N> {
#[inline] #[inline]
fn transposed(&self) -> DMat<N> { fn transpose_cpy(m: &DMat<N>) -> DMat<N> {
if self.nrows == self.ncols { if m.nrows == m.ncols {
let mut res = self.clone(); let mut res = m.clone();
res.transpose(); res.transpose();
res res
} }
else { 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 i in range(0u, m.nrows) {
for j in range(0u, self.ncols) { for j in range(0u, m.ncols) {
unsafe { 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<N: Clone> Transpose for DMat<N> {
} }
else { else {
// FIXME: implement a better algorithm which does that in-place. // FIXME: implement a better algorithm which does that in-place.
*self = self.transposed(); *self = Transpose::transpose_cpy(self);
} }
} }
} }
@ -449,7 +454,7 @@ impl<N: Clone + Num + Cast<f32> + DMatDivRhs<N, DMat<N>> + ToStr > Cov<DMat<N>>
let fnormalizer: f32 = Cast::from(self.nrows() - 1); let fnormalizer: f32 = Cast::from(self.nrows() - 1);
let normalizer: N = Cast::from(fnormalizer); let normalizer: N = Cast::from(fnormalizer);
// FIXME: this will do 2 allocations for temporaries! // FIXME: this will do 2 allocations for temporaries!
(centered.transposed() * centered) / normalizer (Transpose::transpose_cpy(&centered) * centered) / normalizer
} }
} }

View File

@ -9,7 +9,7 @@ use std::vec;
use std::vec::{VecIterator, VecMutIterator}; use std::vec::{VecIterator, VecMutIterator};
use std::cmp::ApproxEq; use std::cmp::ApproxEq;
use std::iter::FromIterator; use std::iter::FromIterator;
use traits::geometry::{Dot, Norm, Translation}; use traits::geometry::{Dot, Norm};
use traits::structure::{Iterable, IterableMut}; use traits::structure::{Iterable, IterableMut};
#[doc(hidden)] #[doc(hidden)]
@ -204,7 +204,7 @@ impl<N: Clone + Num + Algebraic + ApproxEq<N> + DVecMulRhs<N, DVec<N>>> DVec<N>
}; };
if !elt.sqnorm().approx_eq(&Zero::zero()) { if !elt.sqnorm().approx_eq(&Zero::zero()) {
res.push(elt.normalized()); res.push(Norm::normalize_cpy(&elt));
} }
} }
@ -267,33 +267,6 @@ impl<N: Num + Clone> Dot<N> for DVec<N> {
} }
} }
impl<N: Add<N, N> + Neg<N> + Clone> Translation<DVec<N>> for DVec<N> {
#[inline]
fn translation(&self) -> DVec<N> {
self.clone()
}
#[inline]
fn inv_translation(&self) -> DVec<N> {
-self
}
#[inline]
fn translate_by(&mut self, t: &DVec<N>) {
*self = *self + *t;
}
#[inline]
fn translated(&self, t: &DVec<N>) -> DVec<N> {
self + *t
}
#[inline]
fn set_translation(&mut self, t: DVec<N>) {
*self = t
}
}
impl<N: Num + Algebraic + Clone> Norm<N> for DVec<N> { impl<N: Num + Algebraic + Clone> Norm<N> for DVec<N> {
#[inline] #[inline]
fn sqnorm(&self) -> N { fn sqnorm(&self) -> N {
@ -306,8 +279,8 @@ impl<N: Num + Algebraic + Clone> Norm<N> for DVec<N> {
} }
#[inline] #[inline]
fn normalized(&self) -> DVec<N> { fn normalize_cpy(v: &DVec<N>) -> DVec<N> {
let mut res : DVec<N> = self.clone(); let mut res : DVec<N> = v.clone();
res.normalize(); res.normalize();

View File

@ -85,7 +85,7 @@ macro_rules! vec_mul_iso_impl(
macro_rules! translation_impl( macro_rules! translation_impl(
($t: ident, $tv: ident) => ( ($t: ident, $tv: ident) => (
impl<N: Neg<N> + Add<N, N> + Clone> Translation<$tv<N>> for $t<N> { impl<N: Neg<N> + Add<N, N> + Num + Clone> Translation<$tv<N>> for $t<N> {
#[inline] #[inline]
fn translation(&self) -> $tv<N> { fn translation(&self) -> $tv<N> {
self.translation.clone() self.translation.clone()
@ -97,13 +97,23 @@ macro_rules! translation_impl(
} }
#[inline] #[inline]
fn translate_by(&mut self, t: &$tv<N>) { fn append_translation(&mut self, t: &$tv<N>) {
self.translation = self.translation + *t self.translation = *t + self.translation
} }
#[inline] #[inline]
fn translated(&self, t: &$tv<N>) -> $t<N> { fn append_translation_cpy(iso: &$t<N>, t: &$tv<N>) -> $t<N> {
$t::new(self.translation + *t, self.rotation.clone()) $t::new(*t + iso.translation, iso.rotation.clone())
}
#[inline]
fn prepend_translation(&mut self, t: &$tv<N>) {
self.translation = self.translation + self.rotation * *t
}
#[inline]
fn prepend_translation_cpy(iso: &$t<N>, t: &$tv<N>) -> $t<N> {
$t::new(iso.translation + iso.rotation * *t, iso.rotation.clone())
} }
#[inline] #[inline]
@ -143,23 +153,33 @@ macro_rules! rotation_impl(
self.rotation.inv_rotation() self.rotation.inv_rotation()
} }
#[inline] #[inline]
fn rotate_by(&mut self, rot: &$tav<N>) { fn append_rotation(&mut self, rot: &$tav<N>) {
// FIXME: this does not seem opitmal let delta = $trot::new(rot.clone());
let mut delta: $trot<N> = One::one();
delta.rotate_by(rot); self.rotation = delta * self.rotation;
self.rotation.rotate_by(rot);
self.translation = delta * self.translation; self.translation = delta * self.translation;
} }
#[inline] #[inline]
fn rotated(&self, rot: &$tav<N>) -> $t<N> { fn append_rotation_cpy(t: &$t<N>, rot: &$tav<N>) -> $t<N> {
// FIXME: this does not seem opitmal let delta = $trot::new(rot.clone());
let _1: $trot<N> = One::one();
let delta = _1.rotated(rot);
$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<N>) {
let delta = $trot::new(rot.clone());
self.rotation = self.rotation * delta;
}
#[inline]
fn prepend_rotation_cpy(t: &$t<N>, rot: &$tav<N>) -> $t<N> {
let delta = $trot::new(rot.clone());
$t::new(t.translation.clone(), t.rotation * delta)
} }
#[inline] #[inline]
@ -196,15 +216,23 @@ macro_rules! transformation_impl(
fn inv_transformation(&self) -> $t<N> { fn inv_transformation(&self) -> $t<N> {
// inversion will never fails // inversion will never fails
self.inverted().unwrap() Inv::inv_cpy(self).unwrap()
} }
fn transform_by(&mut self, other: &$t<N>) { fn append_transformation(&mut self, t: &$t<N>) {
*self = other * *self *self = *t * *self
} }
fn transformed(&self, t: &$t<N>) -> $t<N> { fn append_transformation_cpy(iso: &$t<N>, t: &$t<N>) -> $t<N> {
t * *self t * *iso
}
fn prepend_transformation(&mut self, t: &$t<N>) {
*self = *self * *t
}
fn prepend_transformation_cpy(iso: &$t<N>, t: &$t<N>) -> $t<N> {
*iso * *t
} }
fn set_transformation(&mut self, t: $t<N>) { fn set_transformation(&mut self, t: $t<N>) {
@ -234,19 +262,19 @@ macro_rules! inv_impl(
($t: ident) => ( ($t: ident) => (
impl<N: Clone + Num> Inv for $t<N> { impl<N: Clone + Num> Inv for $t<N> {
#[inline] #[inline]
fn invert(&mut self) -> bool { fn inv(&mut self) -> bool {
self.rotation.invert(); self.rotation.inv();
self.translation = self.rotation * -self.translation; self.translation = self.rotation * -self.translation;
// always succeed // always succeed
true true
} }
#[inline] #[inline]
fn inverted(&self) -> Option<$t<N>> { fn inv_cpy(m: &$t<N>) -> Option<$t<N>> {
let mut res = self.clone(); let mut res = m.clone();
res.invert(); res.inv();
// always succeed // always succeed
Some(res) Some(res)

View File

@ -331,10 +331,10 @@ macro_rules! inv_impl(
impl<N: Clone + Eq + Num> impl<N: Clone + Eq + Num>
Inv for $t<N> { Inv for $t<N> {
#[inline] #[inline]
fn inverted(&self) -> Option<$t<N>> { fn inv_cpy(m: &$t<N>) -> Option<$t<N>> {
let mut res : $t<N> = self.clone(); let mut res : $t<N> = m.clone();
if res.invert() { if res.inv() {
Some(res) Some(res)
} }
else { else {
@ -342,7 +342,7 @@ macro_rules! inv_impl(
} }
} }
fn invert(&mut self) -> bool { fn inv(&mut self) -> bool {
let mut res: $t<N> = One::one(); let mut res: $t<N> = One::one();
let _0N: N = Zero::zero(); let _0N: N = Zero::zero();
@ -415,8 +415,8 @@ macro_rules! transpose_impl(
($t: ident, $dim: expr) => ( ($t: ident, $dim: expr) => (
impl<N: Clone> Transpose for $t<N> { impl<N: Clone> Transpose for $t<N> {
#[inline] #[inline]
fn transposed(&self) -> $t<N> { fn transpose_cpy(m: &$t<N>) -> $t<N> {
let mut res = self.clone(); let mut res = m.clone();
res.transpose(); res.transpose();

View File

@ -22,8 +22,8 @@ pub struct Rot2<N> {
impl<N: Clone + Trigonometric + Neg<N>> Rot2<N> { impl<N: Clone + Trigonometric + Neg<N>> Rot2<N> {
/// Builds a 2 dimensional rotation matrix from an angle in radian. /// Builds a 2 dimensional rotation matrix from an angle in radian.
pub fn from_angle(angle: N) -> Rot2<N> { pub fn new(angle: Vec1<N>) -> Rot2<N> {
let (sia, coa) = angle.sin_cos(); let (sia, coa) = angle.x.sin_cos();
Rot2 { Rot2 {
submat: Mat2::new(coa.clone(), -sia, sia.clone(), coa) submat: Mat2::new(coa.clone(), -sia, sia.clone(), coa)
@ -44,25 +44,35 @@ Rotation<Vec1<N>> for Rot2<N> {
} }
#[inline] #[inline]
fn rotate_by(&mut self, rot: &Vec1<N>) { fn append_rotation(&mut self, rot: &Vec1<N>) {
*self = self.rotated(rot) *self = Rotation::append_rotation_cpy(self, rot)
} }
#[inline] #[inline]
fn rotated(&self, rot: &Vec1<N>) -> Rot2<N> { fn append_rotation_cpy(t: &Rot2<N>, rot: &Vec1<N>) -> Rot2<N> {
Rot2::from_angle(rot.x.clone()) * *self Rot2::new(rot.clone()) * *t
}
#[inline]
fn prepend_rotation(&mut self, rot: &Vec1<N>) {
*self = Rotation::prepend_rotation_cpy(self, rot)
}
#[inline]
fn prepend_rotation_cpy(t: &Rot2<N>, rot: &Vec1<N>) -> Rot2<N> {
*t * Rot2::new(rot.clone())
} }
#[inline] #[inline]
fn set_rotation(&mut self, rot: Vec1<N>) { fn set_rotation(&mut self, rot: Vec1<N>) {
*self = Rot2::from_angle(rot.x) *self = Rot2::new(rot)
} }
} }
impl<N: Clone + Rand + Trigonometric + Neg<N>> Rand for Rot2<N> { impl<N: Clone + Rand + Trigonometric + Neg<N>> Rand for Rot2<N> {
#[inline] #[inline]
fn rand<R: Rng>(rng: &mut R) -> Rot2<N> { fn rand<R: Rng>(rng: &mut R) -> Rot2<N> {
Rot2::from_angle(rng.gen()) Rot2::new(rng.gen())
} }
} }
@ -95,7 +105,7 @@ impl<N: Clone + Trigonometric + Num + Algebraic> Rot3<N> {
/// # Arguments /// # Arguments
/// * `axisangle` - A vector representing the rotation. Its magnitude is the amount of rotation /// * `axisangle` - A vector representing the rotation. Its magnitude is the amount of rotation
/// in radian. Its direction is the axis of rotation. /// in radian. Its direction is the axis of rotation.
pub fn from_axis_angle(axisangle: Vec3<N>) -> Rot3<N> { pub fn new(axisangle: Vec3<N>) -> Rot3<N> {
if axisangle.sqnorm().is_zero() { if axisangle.sqnorm().is_zero() {
One::one() One::one()
} }
@ -141,13 +151,14 @@ impl<N: Clone + Num + Algebraic> Rot3<N> {
/// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear /// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear
/// with `at`. Non-colinearity is not checked. /// with `at`. Non-colinearity is not checked.
pub fn look_at(&mut self, at: &Vec3<N>, up: &Vec3<N>) { pub fn look_at(&mut self, at: &Vec3<N>, up: &Vec3<N>) {
let xaxis = at.normalized(); let xaxis = Norm::normalize_cpy(at);
let zaxis = up.cross(&xaxis).normalized(); let zaxis = Norm::normalize_cpy(&up.cross(&xaxis));
let yaxis = zaxis.cross(&xaxis); let yaxis = zaxis.cross(&xaxis);
self.submat = Mat3::new(xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(), self.submat = Mat3::new(
xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(), xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(),
xaxis.z , yaxis.z , zaxis.z) 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. /// Reorient this matrix such that its local `z` axis points to a given point.
@ -158,13 +169,14 @@ impl<N: Clone + Num + Algebraic> Rot3<N> {
/// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear /// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear
/// with `at`. Non-colinearity is not checked. /// with `at`. Non-colinearity is not checked.
pub fn look_at_z(&mut self, at: &Vec3<N>, up: &Vec3<N>) { pub fn look_at_z(&mut self, at: &Vec3<N>, up: &Vec3<N>) {
let zaxis = at.normalized(); let zaxis = Norm::normalize_cpy(at);
let xaxis = up.cross(&zaxis).normalized(); let xaxis = Norm::normalize_cpy(&up.cross(&zaxis));
let yaxis = zaxis.cross(&xaxis); let yaxis = zaxis.cross(&xaxis);
self.submat = Mat3::new(xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(), self.submat = Mat3::new(
xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(), xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(),
xaxis.z , yaxis.z , zaxis.z) xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(),
xaxis.z , yaxis.z , zaxis.z)
} }
} }
@ -208,18 +220,28 @@ Rotation<Vec3<N>> for Rot3<N> {
#[inline] #[inline]
fn rotate_by(&mut self, rot: &Vec3<N>) { fn append_rotation(&mut self, rot: &Vec3<N>) {
*self = self.rotated(rot) *self = Rotation::append_rotation_cpy(self, rot)
} }
#[inline] #[inline]
fn rotated(&self, axisangle: &Vec3<N>) -> Rot3<N> { fn append_rotation_cpy(t: &Rot3<N>, axisangle: &Vec3<N>) -> Rot3<N> {
Rot3::from_axis_angle(axisangle.clone()) * *self Rot3::new(axisangle.clone()) * *t
}
#[inline]
fn prepend_rotation(&mut self, rot: &Vec3<N>) {
*self = Rotation::prepend_rotation_cpy(self, rot)
}
#[inline]
fn prepend_rotation_cpy(t: &Rot3<N>, axisangle: &Vec3<N>) -> Rot3<N> {
*t * Rot3::new(axisangle.clone())
} }
#[inline] #[inline]
fn set_rotation(&mut self, axisangle: Vec3<N>) { fn set_rotation(&mut self, axisangle: Vec3<N>) {
*self = Rot3::from_axis_angle(axisangle) *self = Rot3::new(axisangle)
} }
} }
@ -227,7 +249,7 @@ impl<N: Clone + Rand + Trigonometric + Num + Algebraic>
Rand for Rot3<N> { Rand for Rot3<N> {
#[inline] #[inline]
fn rand<R: Rng>(rng: &mut R) -> Rot3<N> { fn rand<R: Rng>(rng: &mut R) -> Rot3<N> {
Rot3::from_axis_angle(rng.gen()) Rot3::new(rng.gen())
} }
} }

View File

@ -114,7 +114,7 @@ macro_rules! inv_impl(
($t: ident) => ( ($t: ident) => (
impl<N: Clone> Inv for $t<N> { impl<N: Clone> Inv for $t<N> {
#[inline] #[inline]
fn invert(&mut self) -> bool { fn inv(&mut self) -> bool {
self.transpose(); self.transpose();
// always succeed // always succeed
@ -122,9 +122,9 @@ macro_rules! inv_impl(
} }
#[inline] #[inline]
fn inverted(&self) -> Option<$t<N>> { fn inv_cpy(m: &$t<N>) -> Option<$t<N>> {
// always succeed // always succeed
Some(self.transposed()) Some(Transpose::transpose_cpy(m))
} }
} }
) )
@ -134,8 +134,8 @@ macro_rules! transpose_impl(
($t: ident) => ( ($t: ident) => (
impl<N: Clone> Transpose for $t<N> { impl<N: Clone> Transpose for $t<N> {
#[inline] #[inline]
fn transposed(&self) -> $t<N> { fn transpose_cpy(m: &$t<N>) -> $t<N> {
$t { submat: self.submat.transposed() } $t { submat: Transpose::transpose_cpy(&m.submat) }
} }
#[inline] #[inline]

View File

@ -11,11 +11,11 @@ impl One for mat::Identity {
} }
impl Inv for mat::Identity { impl Inv for mat::Identity {
fn inverted(&self) -> Option<mat::Identity> { fn inv_cpy(_: &mat::Identity) -> Option<mat::Identity> {
Some(mat::Identity::new()) Some(mat::Identity::new())
} }
fn invert(&mut self) -> bool { fn inv(&mut self) -> bool {
true true
} }
} }
@ -29,7 +29,7 @@ impl<T: Clone> Mul<T, T> for mat::Identity {
impl Transpose for mat::Identity { impl Transpose for mat::Identity {
#[inline] #[inline]
fn transposed(&self) -> mat::Identity { fn transpose_cpy(_: &mat::Identity) -> mat::Identity {
mat::Identity::new() mat::Identity::new()
} }
@ -50,12 +50,22 @@ impl<V: Zero> Translation<V> for mat::Identity {
} }
#[inline] #[inline]
fn translate_by(&mut self, _: &V) { fn append_translation(&mut self, _: &V) {
fail!("Attempted to translate the identity matrix.") fail!("Attempted to translate the identity matrix.")
} }
#[inline] #[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.") fail!("Attempted to translate the identity matrix.")
} }
@ -89,12 +99,22 @@ impl<V: Zero> Rotation<V> for mat::Identity {
} }
#[inline] #[inline]
fn rotate_by(&mut self, _: &V) { fn append_rotation(&mut self, _: &V) {
fail!("Attempted to rotate the identity matrix.") fail!("Attempted to rotate the identity matrix.")
} }
#[inline] #[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.") fail!("Attempted to rotate the identity matrix.")
} }
@ -128,12 +148,22 @@ impl<M: One> Transformation<M> for mat::Identity {
} }
#[inline] #[inline]
fn transform_by(&mut self, _: &M) { fn append_transformation(&mut self, _: &M) {
fail!("Attempted to transform the identity matrix.") fail!("Attempted to transform the identity matrix.")
} }
#[inline] #[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.") fail!("Attempted to transform the identity matrix.")
} }

View File

@ -9,10 +9,10 @@ use traits::structure::{Cast, Row, Col};
impl<N: Num + Clone> impl<N: Num + Clone>
Inv for Mat1<N> { Inv for Mat1<N> {
#[inline] #[inline]
fn inverted(&self) -> Option<Mat1<N>> { fn inv_cpy(m: &Mat1<N>) -> Option<Mat1<N>> {
let mut res : Mat1<N> = self.clone(); let mut res = m.clone();
if res.invert() { if res.inv() {
Some(res) Some(res)
} }
else { else {
@ -21,7 +21,7 @@ Inv for Mat1<N> {
} }
#[inline] #[inline]
fn invert(&mut self) -> bool { fn inv(&mut self) -> bool {
if self.m11.is_zero() { if self.m11.is_zero() {
false false
} }
@ -36,10 +36,10 @@ Inv for Mat1<N> {
impl<N: Num + Clone> impl<N: Num + Clone>
Inv for Mat2<N> { Inv for Mat2<N> {
#[inline] #[inline]
fn inverted(&self) -> Option<Mat2<N>> { fn inv_cpy(m: &Mat2<N>) -> Option<Mat2<N>> {
let mut res : Mat2<N> = self.clone(); let mut res = m.clone();
if res.invert() { if res.inv() {
Some(res) Some(res)
} }
else { else {
@ -48,7 +48,7 @@ Inv for Mat2<N> {
} }
#[inline] #[inline]
fn invert(&mut self) -> bool { fn inv(&mut self) -> bool {
let det = self.m11 * self.m22 - self.m21 * self.m12; let det = self.m11 * self.m22 - self.m21 * self.m12;
if det.is_zero() { if det.is_zero() {
@ -67,10 +67,10 @@ Inv for Mat2<N> {
impl<N: Num + Clone> impl<N: Num + Clone>
Inv for Mat3<N> { Inv for Mat3<N> {
#[inline] #[inline]
fn inverted(&self) -> Option<Mat3<N>> { fn inv_cpy(m: &Mat3<N>) -> Option<Mat3<N>> {
let mut res = self.clone(); let mut res = m.clone();
if res.invert() { if res.inv() {
Some(res) Some(res)
} }
else { else {
@ -79,7 +79,7 @@ Inv for Mat3<N> {
} }
#[inline] #[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_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_m23 = self.m21 * self.m33 - self.m31 * self.m23;
let minor_m11_m22 = self.m21 * self.m32 - self.m31 * self.m22; let minor_m11_m22 = self.m21 * self.m32 - self.m31 * self.m22;

View File

@ -103,10 +103,10 @@ impl<N: Clone + Ord + Algebraic + Signed> Basis for Vec3<N> {
fn orthonormal_subspace_basis(&self, f: &fn(Vec3<N>) -> bool) { fn orthonormal_subspace_basis(&self, f: &fn(Vec3<N>) -> bool) {
let a = let a =
if self.x.clone().abs() > self.y.clone().abs() { if self.x.clone().abs() > self.y.clone().abs() {
Vec3::new(self.z.clone(), Zero::zero(), -self.x).normalized() Norm::normalize_cpy(&Vec3::new(self.z.clone(), Zero::zero(), -self.x))
} }
else { 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 }; if !f(a.cross(self)) { return };

View File

@ -128,13 +128,23 @@ impl<N: Clone + Add<N, N> + Neg<N>> Translation<vec::Vec0<N>> for vec::Vec0<N> {
} }
#[inline] #[inline]
fn translate_by(&mut self, t: &vec::Vec0<N>) { fn append_translation(&mut self, t: &vec::Vec0<N>) {
*self = *t + *self;
}
#[inline]
fn append_translation_cpy(vec: &vec::Vec0<N>, t: &vec::Vec0<N>) -> vec::Vec0<N> {
*t + vec
}
#[inline]
fn prepend_translation(&mut self, t: &vec::Vec0<N>) {
*self = *self + *t; *self = *self + *t;
} }
#[inline] #[inline]
fn translated(&self, t: &vec::Vec0<N>) -> vec::Vec0<N> { fn prepend_translation_cpy(vec: &vec::Vec0<N>, t: &vec::Vec0<N>) -> vec::Vec0<N> {
self + *t vec + *t
} }
#[inline] #[inline]
@ -154,21 +164,13 @@ impl<N: Clone + Num + Algebraic> Norm<N> for vec::Vec0<N> {
} }
#[inline] #[inline]
fn normalized(&self) -> vec::Vec0<N> { fn normalize_cpy(v: &vec::Vec0<N>) -> vec::Vec0<N> {
let mut res : vec::Vec0<N> = self.clone(); v.clone()
res.normalize();
res
} }
#[inline] #[inline]
fn normalize(&mut self) -> N { fn normalize(&mut self) -> N {
let l = self.norm(); Zero::zero()
*self = *self / l;
l
} }
} }

View File

@ -253,7 +253,7 @@ macro_rules! basis_impl(
}; };
if !elt.sqnorm().approx_eq(&Zero::zero()) { if !elt.sqnorm().approx_eq(&Zero::zero()) {
let new_element = elt.normalized(); let new_element = Norm::normalize_cpy(&elt);
if !f(new_element.clone()) { return }; if !f(new_element.clone()) { return };
@ -394,13 +394,23 @@ macro_rules! translation_impl(
} }
#[inline] #[inline]
fn translate_by(&mut self, t: &$t<N>) { fn append_translation(&mut self, t: &$t<N>) {
*self = *t + *self;
}
#[inline]
fn append_translation_cpy(transform: &$t<N>, t: &$t<N>) -> $t<N> {
*t + *transform
}
#[inline]
fn prepend_translation(&mut self, t: &$t<N>) {
*self = *self + *t; *self = *self + *t;
} }
#[inline] #[inline]
fn translated(&self, t: &$t<N>) -> $t<N> { fn prepend_translation_cpy(transform: &$t<N>, t: &$t<N>) -> $t<N> {
self + *t transform + *t
} }
#[inline] #[inline]
@ -425,8 +435,8 @@ macro_rules! norm_impl(
} }
#[inline] #[inline]
fn normalized(&self) -> $t<N> { fn normalize_cpy(v: &$t<N>) -> $t<N> {
let mut res : $t<N> = self.clone(); let mut res : $t<N> = v.clone();
res.normalize(); res.normalize();

View File

@ -10,7 +10,7 @@ macro_rules! test_inv_mat_impl(
do 10000.times { do 10000.times {
let randmat : $t = random(); 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 { do 10000.times {
let randmat : $t = random(); 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<f64> = na::one(); let randmat: na::Rot2<f64> = na::one();
let ang = na::vec1(abs::<f64>(random()) % Real::pi()); let ang = na::vec1(abs::<f64>(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() { fn test_index_mat2() {
let mat: na::Mat2<f64> = random(); let mat: na::Mat2<f64> = random();
assert!(mat.at((0, 1)) == na::transposed(&mat).at((1, 0))); assert!(mat.at((0, 1)) == na::transpose(&mat).at((1, 0)));
} }
#[test] #[test]
@ -107,10 +107,10 @@ fn test_inv_rotation3() {
do 10000.times { do 10000.times {
let randmat: na::Rot3<f64> = na::one(); let randmat: na::Rot3<f64> = na::one();
let dir: na::Vec3<f64> = random(); let dir: na::Vec3<f64> = random();
let ang = na::normalized(&dir) * (abs::<f64>(random()) % Real::pi()); let ang = na::normalize(&dir) * (abs::<f64>(random()) % Real::pi());
let rot = na::rotated(&randmat, &ang); 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()));
} }
} }

View File

@ -78,7 +78,7 @@ macro_rules! test_subspace_basis_impl(
($t: ty) => ( ($t: ty) => (
do 10000.times { do 10000.times {
let v : $t = random(); let v : $t = random();
let v1 = na::normalized(&v); let v1 = na::normalize(&v);
do na::orthonormal_subspace_basis(&v1) |e1| { do na::orthonormal_subspace_basis(&v1) |e1| {
// check vectors are orthogonal to v1 // check vectors are orthogonal to v1

View File

@ -13,11 +13,17 @@ pub trait Translation<V> {
/// Gets the inverse translation associated with this object. /// Gets the inverse translation associated with this object.
fn inv_translation(&self) -> V; fn inv_translation(&self) -> V;
/// In-place version of `translated`. /// Appends a translation to this object.
fn translate_by(&mut self, &V); fn append_translation(&mut self, &V);
/// Appends a translation. /// Appends the translation `amount` to a copy of `t`.
fn translated(&self, &V) -> Self; 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. /// Sets the translation.
fn set_translation(&mut self, V); fn set_translation(&mut self, V);
@ -27,7 +33,8 @@ pub trait Translation<V> {
/// rotate vectors. /// rotate vectors.
pub trait Translate<V> { pub trait Translate<V> {
/// Apply a translation to an object. /// Apply a translation to an object.
fn translate(&self, &V) -> V; fn translate(&self, &V) -> V;
/// Apply an inverse translation to an object. /// Apply an inverse translation to an object.
fn inv_translate(&self, &V) -> V; fn inv_translate(&self, &V) -> V;
} }
@ -41,11 +48,17 @@ pub trait Rotation<V> {
/// Gets the inverse rotation associated with `self`. /// Gets the inverse rotation associated with `self`.
fn inv_rotation(&self) -> V; fn inv_rotation(&self) -> V;
/// In-place version of `rotated`. /// Appends a rotation to this object.
fn rotate_by(&mut self, &V); fn append_rotation(&mut self, &V);
/// Appends a rotation to `self`. /// Appends the rotation `amount` to a copy of `t`.
fn rotated(&self, &V) -> Self; 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`. /// Sets the rotation of `self`.
fn set_rotation(&mut self, V); fn set_rotation(&mut self, V);
@ -57,6 +70,7 @@ pub trait Rotation<V> {
pub trait Rotate<V> { pub trait Rotate<V> {
/// Applies a rotation to `v`. /// Applies a rotation to `v`.
fn rotate(&self, v: &V) -> V; fn rotate(&self, v: &V) -> V;
/// Applies an inverse rotation to `v`. /// Applies an inverse rotation to `v`.
fn inv_rotate(&self, v: &V) -> V; fn inv_rotate(&self, v: &V) -> V;
} }
@ -72,15 +86,15 @@ pub trait RotationWithTranslation<LV: Neg<LV>, AV>: Rotation<AV> + Translation<L
/// Applies a rotation centered on a specific point. /// Applies a rotation centered on a specific point.
/// ///
/// # Arguments /// # Arguments
/// * `m` - the object to be rotated. /// * `t` - the object to be rotated.
/// * `amount` - the rotation to apply. /// * `amount` - the rotation to apply.
/// * `point` - the center of rotation. /// * `point` - the center of rotation.
#[inline] #[inline]
fn rotated_wrt_point(&self, amount: &AV, center: &LV) -> Self { fn append_rotation_wrt_point_cpy(t: &Self, amount: &AV, center: &LV) -> Self {
let mut res = self.translated(&-center); let mut res = Translation::append_translation_cpy(t, &-center);
res.rotate_by(amount); res.append_rotation(amount);
res.translate_by(center); res.append_translation(center);
res res
} }
@ -90,24 +104,23 @@ pub trait RotationWithTranslation<LV: Neg<LV>, AV>: Rotation<AV> + Translation<L
/// The rotation is applied in-place. /// The rotation is applied in-place.
/// ///
/// # Arguments /// # Arguments
/// * `m` - the object to be rotated
/// * `amount` - the rotation to be applied /// * `amount` - the rotation to be applied
/// * `center` - the new center of rotation /// * `center` - the new center of rotation
#[inline] #[inline]
fn rotate_wrt_point(&mut self, amount: &AV, center: &LV) { fn append_rotation_wrt_point(&mut self, amount: &AV, center: &LV) {
self.translate_by(&-center); self.append_translation(&-center);
self.rotate_by(amount); self.append_rotation(amount);
self.translate_by(center); self.append_translation(center);
} }
/// Applies a rotation centered on the translation of `m`. /// Applies a rotation centered on the translation of `m`.
/// ///
/// # Arguments /// # Arguments
/// * `m` - the object to be rotated. /// * `t` - the object to be rotated.
/// * `amount` - the rotation to apply. /// * `amount` - the rotation to apply.
#[inline] #[inline]
fn rotated_wrt_center(&self, amount: &AV) -> Self { fn append_rotation_wrt_center_cpy(t: &Self, amount: &AV) -> Self {
self.rotated_wrt_point(amount, &self.translation()) RotationWithTranslation::append_rotation_wrt_point_cpy(t, amount, &t.translation())
} }
/// Applies a rotation centered on the translation of `m`. /// Applies a rotation centered on the translation of `m`.
@ -115,12 +128,11 @@ pub trait RotationWithTranslation<LV: Neg<LV>, AV>: Rotation<AV> + Translation<L
/// The rotation os applied on-place. /// The rotation os applied on-place.
/// ///
/// # Arguments /// # Arguments
/// * `m` - the object to be rotated.
/// * `amount` - the rotation to apply. /// * `amount` - the rotation to apply.
#[inline] #[inline]
fn rotate_wrt_center(&mut self, amount: &AV) { fn append_rotation_wrt_center(&mut self, amount: &AV) {
let center = self.translation(); let center = self.translation();
self.rotate_wrt_point(amount, &center) self.append_rotation_wrt_point(amount, &center)
} }
} }
@ -158,11 +170,17 @@ pub trait Transformation<M> {
/// Gets the inverse transformation of `self`. /// Gets the inverse transformation of `self`.
fn inv_transformation(&self) -> M; fn inv_transformation(&self) -> M;
/// In-place version of `transformed`. /// Appends a transformation to this object.
fn transform_by(&mut self, &M); fn append_transformation(&mut self, &M);
/// Appends a transformation to `self`. /// Appends the transformation `amount` to a copy of `t`.
fn transformed(&self, &M) -> Self; 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`. /// Sets the transformation of `self`.
fn set_transformation(&mut self, M); fn set_transformation(&mut self, M);
@ -174,6 +192,7 @@ pub trait Transformation<M> {
pub trait Transform<V> { pub trait Transform<V> {
/// Applies a transformation to `v`. /// Applies a transformation to `v`.
fn transform(&self, &V) -> V; fn transform(&self, &V) -> V;
/// Applies an inverse transformation to `v`. /// Applies an inverse transformation to `v`.
fn inv_transform(&self, &V) -> V; fn inv_transform(&self, &V) -> V;
} }
@ -212,11 +231,11 @@ pub trait Norm<N: Algebraic> {
#[inline] #[inline]
fn sqnorm(&self) -> N; fn sqnorm(&self) -> N;
/// Gets the normalized version of `self`. /// Gets the normalized version of a copy of `v`.
#[inline] #[inline]
fn normalized(&self) -> Self; fn normalize_cpy(v: &Self) -> Self;
/// In-place version of `normalized`. /// Normalizes `self`.
#[inline] #[inline]
fn normalize(&mut self) -> N; fn normalize(&mut self) -> N;
} }

View File

@ -12,15 +12,16 @@ pub trait Absolute<A> {
/// Trait of objects having an inverse. Typically used to implement matrix inverse. /// Trait of objects having an inverse. Typically used to implement matrix inverse.
pub trait Inv { pub trait Inv {
/// Returns the inverse of `self`. /// Returns the inverse of `self`.
fn inverted(&self) -> Option<Self>; fn inv_cpy(m: &Self) -> Option<Self>;
/// In-place version of `inverse`. /// In-place version of `inverse`.
fn invert(&mut self) -> bool; fn inv(&mut self) -> bool;
} }
/// Trait of objects which can be transposed. /// Trait of objects which can be transposed.
pub trait Transpose { pub trait Transpose {
/// Computes the transpose of a matrix. /// Computes the transpose of a matrix.
fn transposed(&self) -> Self; fn transpose_cpy(m: &Self) -> Self;
/// In-place version of `transposed`. /// In-place version of `transposed`.
fn transpose(&mut self); fn transpose(&mut self);
@ -39,6 +40,14 @@ pub trait Cov<M> {
/// * For matrices, observations are stored in its rows. /// * For matrices, observations are stored in its rows.
/// * For vectors, observations are stored in its components (thus are 1-dimensional). /// * For vectors, observations are stored in its components (thus are 1-dimensional).
fn cov(&self) -> M; 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. /// Trait for computing the covariance of a set of data.
@ -50,6 +59,26 @@ pub trait Mean<N> {
fn mean(&self) -> N; 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<Self>;
//
// /// 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 // XXX: those two traits should not exist since there is generalized operator overloading of Add
// and Sub. // and Sub.
// However, using the same trait multiple time as a trait bound (ex: impl<T: Add<N, V> + Add<V, V>) // However, using the same trait multiple time as a trait bound (ex: impl<T: Add<N, V> + Add<V, V>)