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**
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<f64> = 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),

197
src/na.rs
View File

@ -166,7 +166,7 @@ pub fn mat4<N>(m11: N, m12: N, m13: N, m14: N,
* Translation<V>
*/
/// 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<V, M: Translation<V>>(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<V, M: Translation<V>>(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<V, M: Translation<V>>(m: &mut M, v: &V) {
m.translate_by(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)
pub fn append_translation<V, M: Translation<V>>(m: &M, v: &V) -> M {
Translation::append_translation_cpy(m, v)
}
/*
@ -269,7 +257,7 @@ pub fn inv_translate<V, M: Translate<V>>(m: &M, v: &V) -> V {
* Rotation<V>
*/
/// 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<V, M: Rotation<V>>(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<V, M: Rotation<V>>(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<V, M: Rotation<V>>(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<V, M: Rotation<V>>(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<V, M: Rotation<V>>(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<V, M: Rotation<V>>(m: &mut M, v: V) {
m.set_rotation(v)
pub fn append_rotation<V, M: Rotation<V>>(m: &M, v: &V) -> M {
Rotation::append_rotation_cpy(m, v)
}
/*
@ -395,7 +343,7 @@ pub fn rotate<V, M: Rotate<V>>(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<V, M: Rotate<V>>(m: &M, v: &V) -> V {
* 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)]
pub fn rotated_wrt_point<LV: Neg<LV>,
AV,
M: RotationWithTranslation<LV, AV>>(
m: &M,
amount: &AV,
center: &LV) -> M {
m.rotated_wrt_point(amount, center)
pub fn append_rotation_wrt_point<LV: Neg<LV>,
AV,
M: RotationWithTranslation<LV, AV>>(
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<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`.
/// Rotates a copy of `m` by `amount` using `m.translation()` as the pivot point.
#[inline(always)]
pub fn rotate_wrt_center<LV: Neg<LV>,
AV,
M: RotationWithTranslation<LV, AV>>(
m: &mut M,
amount: &AV) {
m.rotate_wrt_center(amount)
m: &M,
amount: &AV) -> M {
RotationWithTranslation::append_rotation_wrt_center_cpy(m, amount)
}
/*
* RotationMatrix<LV, AV, R>
*/
/// Builds a rotation matrix from a rotation-capable object.
/// Builds a rotation matrix from `r`.
#[inline(always)]
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()
@ -478,34 +405,22 @@ pub fn absolute_rotate<V, M: AbsoluteRotate<V>>(m: &M, v: &V) -> V {
* Transformation<T>
*/
/// Gets the transformation applicable by the given object.
/// Gets the transformation applicable by `m`.
#[inline(always)]
pub fn transformation<T, M: Transformation<T>>(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<T, M: Transformation<T>>(m: &M) -> T {
m.inv_transformation()
}
/// In-place version of `transformed`.
/// Gets a transformed copy of `m`.
#[inline(always)]
pub fn transform_by<T, M: Transformation<T>>(m: &mut M, t: &T) {
m.transform_by(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)
pub fn append_transformation<T, M: Transformation<T>>(m: &M, t: &T) -> M {
Transformation::append_transformation_cpy(m, t)
}
/*
@ -558,14 +473,8 @@ pub fn sqnorm<V: Norm<N>, N: Algebraic>(v: &V) -> N {
/// Gets the normalized version of a vector.
#[inline(always)]
pub fn normalized<V: Norm<N>, N: Algebraic>(v: &V) -> V {
v.normalized()
}
/// In-place version of `normalized`.
#[inline(always)]
pub fn normalize<V: Norm<N>, N: Algebraic>(v: &mut V) -> N {
v.normalize()
pub fn normalize<V: Norm<N>, N: Algebraic>(v: &V) -> V {
Norm::normalize_cpy(v)
}
/*
@ -646,14 +555,8 @@ pub fn absolute<M: Absolute<Res>, Res>(m: &M) -> Res {
/// Gets an inverted copy of a matrix.
#[inline(always)]
pub fn inverted<M: Inv>(m: &M) -> Option<M> {
m.inverted()
}
/// In-place version of `inverted`.
#[inline(always)]
pub fn invert<M: Inv>(m: &mut M) -> bool {
m.invert()
pub fn inv<M: Inv>(m: &M) -> Option<M> {
Inv::inv_cpy(m)
}
/*
@ -662,14 +565,8 @@ pub fn invert<M: Inv>(m: &mut M) -> bool {
/// Gets a transposed copy of a matrix.
#[inline(always)]
pub fn transposed<M: Transpose>(m: &M) -> M {
m.transposed()
}
/// In-place version of `transposed`.
#[inline(always)]
pub fn transpose<M: Transpose>(m: &mut M) {
m.transpose()
pub fn transpose<M: Transpose>(m: &M) -> M {
Transpose::transpose_cpy(m)
}
/*
@ -749,17 +646,17 @@ pub fn dim<V: 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<f64> to Rot3<i64>
/// is not possible)
/// * A cast to a type with more type-level invariants cannot be done (eg. a cast from
/// Mat<f64> to Rot3<f64> 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<f64> to Rot3<i64> is
/// not possible)
/// * A cast to a type with more type-level invariants cannot be done (eg. a cast from Mat<f64> to
/// Rot3<f64> 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, U: Cast<T>>(t: T) -> U {
Cast::from(t)

View File

@ -64,6 +64,12 @@ impl<N: Zero + Clone> DMat<N> {
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<N: Rand> DMat<N> {
@ -159,7 +165,6 @@ impl<N: One + Zero + Clone> DMat<N> {
}
}
impl<N: Clone> DMat<N> {
#[inline]
fn offset(&self, i: uint, j: uint) -> uint {
@ -278,10 +283,10 @@ DVecMulRhs<N, DVec<N>> for DMat<N> {
impl<N: Clone + Num>
Inv for DMat<N> {
#[inline]
fn inverted(&self) -> Option<DMat<N>> {
let mut res : DMat<N> = self.clone();
fn inv_cpy(m: &DMat<N>) -> Option<DMat<N>> {
let mut res : DMat<N> = m.clone();
if res.invert() {
if res.inv() {
Some(res)
}
else {
@ -289,7 +294,7 @@ Inv for DMat<N> {
}
}
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<N> {
impl<N: Clone> Transpose for DMat<N> {
#[inline]
fn transposed(&self) -> DMat<N> {
if self.nrows == self.ncols {
let mut res = self.clone();
fn transpose_cpy(m: &DMat<N>) -> DMat<N> {
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<N: Clone> Transpose for DMat<N> {
}
else {
// 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 normalizer: N = Cast::from(fnormalizer);
// 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::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<N: Clone + Num + Algebraic + ApproxEq<N> + DVecMulRhs<N, DVec<N>>> DVec<N>
};
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> {
#[inline]
fn sqnorm(&self) -> N {
@ -306,8 +279,8 @@ impl<N: Num + Algebraic + Clone> Norm<N> for DVec<N> {
}
#[inline]
fn normalized(&self) -> DVec<N> {
let mut res : DVec<N> = self.clone();
fn normalize_cpy(v: &DVec<N>) -> DVec<N> {
let mut res : DVec<N> = v.clone();
res.normalize();

View File

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

View File

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

View File

@ -22,8 +22,8 @@ pub struct Rot2<N> {
impl<N: Clone + Trigonometric + Neg<N>> Rot2<N> {
/// Builds a 2 dimensional rotation matrix from an angle in radian.
pub fn from_angle(angle: N) -> Rot2<N> {
let (sia, coa) = angle.sin_cos();
pub fn new(angle: Vec1<N>) -> Rot2<N> {
let (sia, coa) = angle.x.sin_cos();
Rot2 {
submat: Mat2::new(coa.clone(), -sia, sia.clone(), coa)
@ -44,25 +44,35 @@ Rotation<Vec1<N>> for Rot2<N> {
}
#[inline]
fn rotate_by(&mut self, rot: &Vec1<N>) {
*self = self.rotated(rot)
fn append_rotation(&mut self, rot: &Vec1<N>) {
*self = Rotation::append_rotation_cpy(self, rot)
}
#[inline]
fn rotated(&self, rot: &Vec1<N>) -> Rot2<N> {
Rot2::from_angle(rot.x.clone()) * *self
fn append_rotation_cpy(t: &Rot2<N>, rot: &Vec1<N>) -> Rot2<N> {
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]
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> {
#[inline]
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
/// * `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<N>) -> Rot3<N> {
pub fn new(axisangle: Vec3<N>) -> Rot3<N> {
if axisangle.sqnorm().is_zero() {
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
/// with `at`. Non-colinearity is not checked.
pub fn look_at(&mut self, at: &Vec3<N>, up: &Vec3<N>) {
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<N: Clone + Num + Algebraic> Rot3<N> {
/// * 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<N>, up: &Vec3<N>) {
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<Vec3<N>> for Rot3<N> {
#[inline]
fn rotate_by(&mut self, rot: &Vec3<N>) {
*self = self.rotated(rot)
fn append_rotation(&mut self, rot: &Vec3<N>) {
*self = Rotation::append_rotation_cpy(self, rot)
}
#[inline]
fn rotated(&self, axisangle: &Vec3<N>) -> Rot3<N> {
Rot3::from_axis_angle(axisangle.clone()) * *self
fn append_rotation_cpy(t: &Rot3<N>, axisangle: &Vec3<N>) -> Rot3<N> {
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]
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> {
#[inline]
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) => (
impl<N: Clone> Inv for $t<N> {
#[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<N>> {
fn inv_cpy(m: &$t<N>) -> Option<$t<N>> {
// always succeed
Some(self.transposed())
Some(Transpose::transpose_cpy(m))
}
}
)
@ -134,8 +134,8 @@ macro_rules! transpose_impl(
($t: ident) => (
impl<N: Clone> Transpose for $t<N> {
#[inline]
fn transposed(&self) -> $t<N> {
$t { submat: self.submat.transposed() }
fn transpose_cpy(m: &$t<N>) -> $t<N> {
$t { submat: Transpose::transpose_cpy(&m.submat) }
}
#[inline]

View File

@ -11,11 +11,11 @@ impl One 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())
}
fn invert(&mut self) -> bool {
fn inv(&mut self) -> bool {
true
}
}
@ -29,7 +29,7 @@ impl<T: Clone> Mul<T, T> 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<V: Zero> Translation<V> 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<V: Zero> Rotation<V> 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<M: One> Transformation<M> 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.")
}

View File

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

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) {
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 };

View File

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

View File

@ -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<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;
}
#[inline]
fn translated(&self, t: &$t<N>) -> $t<N> {
self + *t
fn prepend_translation_cpy(transform: &$t<N>, t: &$t<N>) -> $t<N> {
transform + *t
}
#[inline]
@ -425,8 +435,8 @@ macro_rules! norm_impl(
}
#[inline]
fn normalized(&self) -> $t<N> {
let mut res : $t<N> = self.clone();
fn normalize_cpy(v: &$t<N>) -> $t<N> {
let mut res : $t<N> = v.clone();
res.normalize();

View File

@ -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<f64> = na::one();
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() {
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]
@ -107,10 +107,10 @@ fn test_inv_rotation3() {
do 10000.times {
let randmat: na::Rot3<f64> = na::one();
let dir: na::Vec3<f64> = random();
let ang = na::normalized(&dir) * (abs::<f64>(random()) % Real::pi());
let rot = na::rotated(&randmat, &ang);
let ang = na::normalize(&dir) * (abs::<f64>(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()));
}
}

View File

@ -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

View File

@ -13,11 +13,17 @@ pub trait Translation<V> {
/// 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<V> {
/// rotate vectors.
pub trait Translate<V> {
/// 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<V> {
/// 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<V> {
pub trait Rotate<V> {
/// 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<LV: Neg<LV>, AV>: Rotation<AV> + Translation<L
/// Applies a rotation centered on a specific point.
///
/// # Arguments
/// * `m` - the object to be rotated.
/// * `t` - the object to be rotated.
/// * `amount` - the rotation to apply.
/// * `point` - the center of rotation.
#[inline]
fn rotated_wrt_point(&self, amount: &AV, center: &LV) -> 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<LV: Neg<LV>, AV>: Rotation<AV> + Translation<L
/// The rotation is applied in-place.
///
/// # Arguments
/// * `m` - the object to be rotated
/// * `amount` - the rotation to be applied
/// * `center` - the new center of rotation
#[inline]
fn rotate_wrt_point(&mut self, amount: &AV, center: &LV) {
self.translate_by(&-center);
self.rotate_by(amount);
self.translate_by(center);
fn append_rotation_wrt_point(&mut self, amount: &AV, center: &LV) {
self.append_translation(&-center);
self.append_rotation(amount);
self.append_translation(center);
}
/// Applies a rotation centered on the translation of `m`.
///
/// # Arguments
/// * `m` - the object to be rotated.
/// * `t` - the object to be rotated.
/// * `amount` - the rotation to apply.
#[inline]
fn rotated_wrt_center(&self, amount: &AV) -> 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<LV: Neg<LV>, AV>: Rotation<AV> + Translation<L
/// The rotation os applied on-place.
///
/// # Arguments
/// * `m` - the object to be rotated.
/// * `amount` - the rotation to apply.
#[inline]
fn rotate_wrt_center(&mut self, amount: &AV) {
fn append_rotation_wrt_center(&mut self, amount: &AV) {
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`.
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<M> {
pub trait Transform<V> {
/// 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<N: Algebraic> {
#[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;
}

View File

@ -12,15 +12,16 @@ pub trait Absolute<A> {
/// Trait of objects having an inverse. Typically used to implement matrix inverse.
pub trait Inv {
/// Returns the inverse of `self`.
fn inverted(&self) -> Option<Self>;
fn inv_cpy(m: &Self) -> Option<Self>;
/// 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<M> {
/// * 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<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
// and Sub.
// However, using the same trait multiple time as a trait bound (ex: impl<T: Add<N, V> + Add<V, V>)