Huge api change!

Everything changed, hopefully for the best.

* everything is accessible from the `na` module. It re-export
  everything and provides free functions (i-e: na::dot(a, b) instead of
  a.dot(b)) for most functionalities.
* matrix/vector adaptors (Rotmat, Transform) are replaced by plain
  types: Rot{2, 3, 4} for rotation matrices and Iso{2, 3, 4} for
  isometries (rotation + translation).  This old adaptors system was to
  hard to understand and to document.
* each file related to data structures moved to the `structs` folder.
  This makes the doc a lot more readable and make people prefer the
  `na` module instead of individual small modules.
* Because `na` exists now, the modules `structs::vec` and
  `structs::mat` dont re-export anything now.

As a side effect, this makes the documentation more readable.
This commit is contained in:
Sébastien Crozet 2013-10-06 16:54:09 +02:00
parent 2356723e90
commit 84212f1449
34 changed files with 2216 additions and 1354 deletions

View File

@ -1,8 +1,36 @@
nalgebra # nalgebra
========
**nalgebra** is a _n_-dimensional linear algebra library written with the rust **nalgebra** is a linear algebra library written for Rust targeting:
programming language.
* general-purpose linear algebra (still misses a lot of features…).
* real time computer graphics.
* real time computer physics.
## 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)`.
* You can import the whole prelude, including free functions, using:
```.rust
pub use nalgebra::na::*;
```
* If you dont want to import everything but only every trait:
```.rust
pub use nalgebra::traits::*;
```
* If you dont want to import everything but only every structure:
```.rust
pub use nalgebra::structs::*;
```
Of course, you can still import `nalgebra::na` alone, and get anything you want using the `na`
prefix.
## 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…),
@ -10,25 +38,30 @@ and keeps an optimized set of tools for computational graphics and physics. Thos
* Vectors with static sizes: `Vec0`, `Vec1`, `Vec2`, ..., `Vec6`. * Vectors with static sizes: `Vec0`, `Vec1`, `Vec2`, ..., `Vec6`.
* Square matrices with static sizes: `Mat1`, `Mat2`, ..., `Mat6 `. * Square matrices with static sizes: `Mat1`, `Mat2`, ..., `Mat6 `.
* Rotation matrices: `Rot2`, `Rot3`, `Rot4`.
* Isometries: `Iso2`, `Iso3`, `Iso4`.
* Dynamically sized vector: `DVec`. * Dynamically sized vector: `DVec`.
* Dynamically sized (square or rectangular) matrix: `DMat`. * Dynamically sized (square or rectangular) matrix: `DMat`.
* Geometry-specific matrix wrapper to ensure at compile-time some properties: `Rotmat`, `Transform`. * A few methods for data analysis: `Cov`, `Mean`.
* Most well-known geometric functions. * Operator overloading using the double trait dispatch [trick](http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/). For example, the following work:
* A few methods for data analysis: `Cov` (covariance), `Mean` (mean).
* Operator overloading using the double trait dispatch [trick](http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/).
This allows using operators for both matrix/matrix multiplication and matrix/vector
multiplication for example.
* Almost one trait per functionality. This is very useful for generic programming.
Since there is almost one trait per functionality, one might end up importing a lot of traits. To
lighten your `use` prelude, all trait are re-exported by the `nalgebra::vec` and `nalgebra::mat`
modules. Thus, to bring every functionalities of `nalgebra` in scope, you can do:
```rust ```rust
use nalgebra::vec::*; extern mod nalgebra;
use nalgebra::mat::*; use nalgebra::na::{Vec3, Mat3};
fn main() {
let v: Vec3<f64> = Zero::zero();
let m: Mat3<f64> = One::one();
let _ = m * v; // matrix-vector multiplication.
let _ = v * m; // vector-matrix multiplication.
let _ = m * m; // matrix-matrix multiplication.
let _ = v * 2.0; // vector-scalar multiplication.
}
``` ```
* Almost one trait per functionality: useful for generic programming.
## Compilation ## Compilation
You will need the last rust compiler from the master branch. You will need the last rust compiler from the master branch.
If you encounter problems, make sure you have the last version before creating an issue. If you encounter problems, make sure you have the last version before creating an issue.
@ -37,21 +70,8 @@ If you encounter problems, make sure you have the last version before creating a
cd nalgebra cd nalgebra
make make
There is also a light, but existing, documentation for most functionalities. Use `make doc` to You can build the documentation on the `doc` folder using:
generate it on the `doc` folder.
## nalgebra in use ```.rust
Feel free to add your project to this list if you happen to use **nalgebra**! make doc
```
* [nphysics](https://github.com/sebcrozet/nphysics): a real-time physics engine.
* [ncollide](https://github.com/sebcrozet/ncollide): a collision detection library.
* [kiss3d](https://github.com/sebcrozet/kiss3d): a minimalistic graphics engine.
* [frog](https://github.com/natal/frog): a machine learning library.
## Design note
**nalgebra** is mostly written with non-idiomatic rust code. This is mostly because of limitations
of the trait system not allowing (easy) multiple overloading. Those overloading problems ares
worked around by this
[hack](http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/)
(section _What if I want overloading_).

View File

@ -1,478 +0,0 @@
use std::num::{One, Zero};
use std::rand::{Rand, Rng};
use std::cmp::ApproxEq;
use traits::geometry::{Cross, Rotation, Rotate, RotationMatrix, AbsoluteRotate, Transform,
ToHomogeneous, Norm};
use traits::structure::{Dim, Row, Col, Indexable};
use traits::operations::{Inv, Transpose, Absolute};
use vec::{Vec1, Vec2, Vec3, Vec4, Vec2MulRhs, Vec3MulRhs, Vec4MulRhs};
use mat::{Mat2, Mat3, Mat4};
#[path = "../metal.rs"]
mod metal;
/// Matrix wrapper representing rotation matrix.
///
/// It is built uppon another matrix and ensures (at the type-level) that it will always represent
/// a rotation. Rotation matrices have some properties useful for performances, like the fact that
/// the inversion is simply a transposition.
#[deriving(Eq, ToStr, Clone)]
pub struct Rotmat<M> {
priv submat: M
}
/// Trait of object `o` which can be multiplied by a `Rotmat` `r`: `r * o`.
pub trait RotmatMulRhs<M, Res> {
/// Multiplies a rotation matrix by `Self`.
fn binop(left: &Rotmat<M>, right: &Self) -> Res;
}
impl<M, Rhs: RotmatMulRhs<M, Res>, Res> Mul<Rhs, Res> for Rotmat<M> {
#[inline(always)]
fn mul(&self, other: &Rhs) -> Res {
RotmatMulRhs::binop(self, other)
}
}
impl<M: Clone> Rotmat<M> {
/// Gets a copy of the internal representation of the rotation.
pub fn submat(&self) -> M {
self.submat.clone()
}
}
impl<N: Clone + Trigonometric + Neg<N>> Rotmat<Mat2<N>> {
/// Builds a 2 dimensional rotation matrix from an angle in radian.
pub fn from_angle(angle: N) -> Rotmat<Mat2<N>> {
let (sia, coa) = angle.sin_cos();
Rotmat {
submat: Mat2::new(coa.clone(), -sia, sia.clone(), coa)
}
}
}
impl<N: Clone + Trigonometric + Num + Algebraic> Rotmat<Mat3<N>> {
/// Builds a 3 dimensional rotation matrix from an axis and an angle.
///
/// # 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>) -> Rotmat<Mat3<N>> {
if axisangle.sqnorm().is_zero() {
One::one()
}
else {
let mut axis = axisangle;
let angle = axis.normalize();
let _1: N = One::one();
let ux = axis.x.clone();
let uy = axis.y.clone();
let uz = axis.z.clone();
let sqx = ux * ux;
let sqy = uy * uy;
let sqz = uz * uz;
let (sin, cos) = angle.sin_cos();
let one_m_cos = _1 - cos;
Rotmat {
submat: Mat3::new(
(sqx + (_1 - sqx) * cos),
(ux * uy * one_m_cos - uz * sin),
(ux * uz * one_m_cos + uy * sin),
(ux * uy * one_m_cos + uz * sin),
(sqy + (_1 - sqy) * cos),
(uy * uz * one_m_cos - ux * sin),
(ux * uz * one_m_cos - uy * sin),
(uy * uz * one_m_cos + ux * sin),
(sqz + (_1 - sqz) * cos))
}
}
}
}
impl<N: Clone + Num + Algebraic> Rotmat<Mat3<N>> {
/// Reorient this matrix such that its local `x` axis points to a given point. Note that the
/// usually known `look_at` function does the same thing but with the `z` axis. See `look_at_z`
/// for that.
///
/// # Arguments
/// * at - The point to look at. It is also the direction the matrix `x` axis will be aligned
/// with
/// * 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 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)
}
/// Reorient this matrix such that its local `z` axis points to a given point.
///
/// # Arguments
/// * at - The point to look at. It is also the direction the matrix `y` axis will be aligned
/// with
/// * 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 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)
}
}
impl<N: Trigonometric + Num + Clone>
RotationMatrix<Vec2<N>, Vec1<N>, Rotmat<Mat2<N>>> for Rotmat<Mat2<N>> {
#[inline]
fn to_rot_mat(&self) -> Rotmat<Mat2<N>> {
self.clone()
}
}
impl<N: Trigonometric + Num + Clone>
Rotation<Vec1<N>> for Rotmat<Mat2<N>> {
#[inline]
fn rotation(&self) -> Vec1<N> {
Vec1::new((-self.submat.at((0, 1))).atan2(&self.submat.at((0, 0))))
}
#[inline]
fn inv_rotation(&self) -> Vec1<N> {
-self.rotation()
}
#[inline]
fn rotate_by(&mut self, rot: &Vec1<N>) {
*self = self.rotated(rot)
}
#[inline]
fn rotated(&self, rot: &Vec1<N>) -> Rotmat<Mat2<N>> {
Rotmat::from_angle(rot.x.clone()) * *self
}
#[inline]
fn set_rotation(&mut self, rot: Vec1<N>) {
*self = Rotmat::from_angle(rot.x)
}
}
impl<N: NumCast + Algebraic + Trigonometric + Num + Clone>
RotationMatrix<Vec3<N>, Vec3<N>, Rotmat<Mat3<N>>> for Rotmat<Mat3<N>> {
#[inline]
fn to_rot_mat(&self) -> Rotmat<Mat3<N>> {
self.clone()
}
}
impl<N: Clone + Trigonometric + Num + Algebraic + NumCast>
Rotation<Vec3<N>> for Rotmat<Mat3<N>> {
#[inline]
fn rotation(&self) -> Vec3<N> {
let angle = ((self.submat.m11 + self.submat.m22 + self.submat.m33 - One::one()) / NumCast::from(2.0)).acos();
if angle != angle {
// FIXME: handle that correctly
Zero::zero()
}
else if angle.is_zero() {
Zero::zero()
}
else {
let m32_m23 = self.submat.m32 - self.submat.m23;
let m13_m31 = self.submat.m13 - self.submat.m31;
let m21_m12 = self.submat.m21 - self.submat.m12;
let denom = (m32_m23 * m32_m23 + m13_m31 * m13_m31 + m21_m12 * m21_m12).sqrt();
if denom.is_zero() {
// XXX: handle that properly
// fail!("Internal error: singularity.")
Zero::zero()
}
else {
let a_d = angle / denom;
Vec3::new(m32_m23 * a_d, m13_m31 * a_d, m21_m12 * a_d)
}
}
}
#[inline]
fn inv_rotation(&self) -> Vec3<N> {
-self.rotation()
}
#[inline]
fn rotate_by(&mut self, rot: &Vec3<N>) {
*self = self.rotated(rot)
}
#[inline]
fn rotated(&self, axisangle: &Vec3<N>) -> Rotmat<Mat3<N>> {
Rotmat::from_axis_angle(axisangle.clone()) * *self
}
#[inline]
fn set_rotation(&mut self, axisangle: Vec3<N>) {
*self = Rotmat::from_axis_angle(axisangle)
}
}
impl<N: Clone + Rand + Trigonometric + Neg<N>> Rand for Rotmat<Mat2<N>> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Rotmat<Mat2<N>> {
Rotmat::from_angle(rng.gen())
}
}
impl<M, V: RotmatMulRhs<M, V> + Mul<Rotmat<M>, V>> Rotate<V> for Rotmat<M> {
#[inline]
fn rotate(&self, v: &V) -> V {
self * *v
}
#[inline]
fn inv_rotate(&self, v: &V) -> V {
v * *self
}
}
impl<M, V: RotmatMulRhs<M, V> + Mul<Rotmat<M>, V>> Transform<V> for Rotmat<M> {
#[inline]
fn transform(&self, v: &V) -> V {
self.rotate(v)
}
#[inline]
fn inv_transform(&self, v: &V) -> V {
self.inv_rotate(v)
}
}
impl<N: Clone + Rand + Trigonometric + Num + Algebraic>
Rand for Rotmat<Mat3<N>> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Rotmat<Mat3<N>> {
Rotmat::from_axis_angle(rng.gen())
}
}
impl<M: Dim> Dim for Rotmat<M> {
#[inline]
fn dim(_: Option<Rotmat<M>>) -> uint {
Dim::dim(None::<M>)
}
}
impl<M: One + Zero> One for Rotmat<M> {
#[inline]
fn one() -> Rotmat<M> {
Rotmat { submat: One::one() }
}
}
impl<M: Mul<M, M>> RotmatMulRhs<M, Rotmat<M>> for Rotmat<M> {
#[inline]
fn binop(left: &Rotmat<M>, right: &Rotmat<M>) -> Rotmat<M> {
Rotmat { submat: left.submat * right.submat }
}
}
/*
* Right/Left multiplication implementation for Vec3 and Vec2.
*/
impl<M: Mul<Vec4<N>, Vec4<N>>, N> RotmatMulRhs<M, Vec4<N>> for Vec4<N> {
#[inline]
fn binop(left: &Rotmat<M>, right: &Vec4<N>) -> Vec4<N> {
left.submat * *right
}
}
impl<M: Mul<Vec3<N>, Vec3<N>>, N> RotmatMulRhs<M, Vec3<N>> for Vec3<N> {
#[inline]
fn binop(left: &Rotmat<M>, right: &Vec3<N>) -> Vec3<N> {
left.submat * *right
}
}
impl<M: Mul<Vec2<N>, Vec2<N>>, N> RotmatMulRhs<M, Vec2<N>> for Vec2<N> {
#[inline]
fn binop(left: &Rotmat<M>, right: &Vec2<N>) -> Vec2<N> {
left.submat * *right
}
}
impl<N, M: Vec4MulRhs<N, Vec4<N>>> Vec4MulRhs<N, Vec4<N>> for Rotmat<M> {
#[inline]
fn binop(left: &Vec4<N>, right: &Rotmat<M>) -> Vec4<N> {
*left * right.submat
}
}
impl<N, M: Vec3MulRhs<N, Vec3<N>>> Vec3MulRhs<N, Vec3<N>> for Rotmat<M> {
#[inline]
fn binop(left: &Vec3<N>, right: &Rotmat<M>) -> Vec3<N> {
*left * right.submat
}
}
impl<N, M: Vec2MulRhs<N, Vec2<N>>> Vec2MulRhs<N, Vec2<N>> for Rotmat<M> {
#[inline]
fn binop(left: &Vec2<N>, right: &Rotmat<M>) -> Vec2<N> {
*left * right.submat
}
}
impl<M: Transpose> Inv for Rotmat<M> {
#[inline]
fn inplace_inverse(&mut self) -> bool {
self.transpose();
true
}
#[inline]
fn inverse(&self) -> Option<Rotmat<M>> {
Some(self.transposed())
}
}
impl<M: Transpose>
Transpose for Rotmat<M> {
#[inline]
fn transposed(&self) -> Rotmat<M> {
Rotmat { submat: self.submat.transposed() }
}
#[inline]
fn transpose(&mut self) {
self.submat.transpose()
}
}
impl<M: Row<R>, R> Row<R> for Rotmat<M> {
#[inline]
fn num_rows(&self) -> uint {
self.submat.num_rows()
}
#[inline]
fn row(&self, i: uint) -> R {
self.submat.row(i)
}
#[inline]
fn set_row(&mut self, i: uint, row: R) {
self.submat.set_row(i, row);
}
}
impl<M: Col<C>, C> Col<C> for Rotmat<M> {
#[inline]
fn num_cols(&self) -> uint {
self.submat.num_cols()
}
#[inline]
fn col(&self, i: uint) -> C {
self.submat.col(i)
}
#[inline]
fn set_col(&mut self, i: uint, col: C) {
self.submat.set_col(i, col);
}
}
// we loose the info that we are a rotation matrix
impl<M: ToHomogeneous<M2>, M2> ToHomogeneous<M2> for Rotmat<M> {
#[inline]
fn to_homogeneous(&self) -> M2 {
self.submat.to_homogeneous()
}
}
impl<N: ApproxEq<N>, M: ApproxEq<N>> ApproxEq<N> for Rotmat<M> {
#[inline]
fn approx_epsilon() -> N {
// ApproxEq::<N>::approx_epsilon()
fail!("approx_epsilon is broken since rust revision 8693943676487c01fa09f5f3daf0df6a1f71e24d.")
}
#[inline]
fn approx_eq(&self, other: &Rotmat<M>) -> bool {
self.submat.approx_eq(&other.submat)
}
#[inline]
fn approx_eq_eps(&self, other: &Rotmat<M>, epsilon: &N) -> bool {
self.submat.approx_eq_eps(&other.submat, epsilon)
}
}
impl<M: Absolute<M2>, M2> Absolute<M2> for Rotmat<M> {
#[inline]
fn absolute(&self) -> M2 {
self.submat.absolute()
}
}
impl<N: Signed> AbsoluteRotate<Vec4<N>> for Rotmat<Mat4<N>> {
#[inline]
fn absolute_rotate(&self, v: &Vec4<N>) -> Vec4<N> {
Vec4::new(
self.submat.m11.abs() * v.x +
self.submat.m12.abs() * v.y +
self.submat.m13.abs() * v.z +
self.submat.m14.abs() * v.w,
self.submat.m21.abs() * v.x +
self.submat.m22.abs() * v.y +
self.submat.m23.abs() * v.z +
self.submat.m24.abs() * v.w,
self.submat.m31.abs() * v.x +
self.submat.m32.abs() * v.y +
self.submat.m33.abs() * v.z +
self.submat.m34.abs() * v.w,
self.submat.m41.abs() * v.x +
self.submat.m42.abs() * v.y +
self.submat.m43.abs() * v.z +
self.submat.m44.abs() * v.w)
}
}
impl<N: Signed> AbsoluteRotate<Vec3<N>> for Rotmat<Mat3<N>> {
#[inline]
fn absolute_rotate(&self, v: &Vec3<N>) -> Vec3<N> {
Vec3::new(
self.submat.m11.abs() * v.x + self.submat.m12.abs() * v.y + self.submat.m13.abs() * v.z,
self.submat.m21.abs() * v.x + self.submat.m22.abs() * v.y + self.submat.m23.abs() * v.z,
self.submat.m31.abs() * v.x + self.submat.m32.abs() * v.y + self.submat.m33.abs() * v.z)
}
}
impl<N: Signed> AbsoluteRotate<Vec2<N>> for Rotmat<Mat2<N>> {
#[inline]
fn absolute_rotate(&self, v: &Vec2<N>) -> Vec2<N> {
// the matrix is skew-symetric, so we dont need to compute the absolute value of every
// component.
let m11 = self.submat.m11.abs();
let m12 = self.submat.m12.abs();
let m22 = self.submat.m22.abs();
Vec2::new(m11 * v.x + m12 * v.y, m12 * v.x + m22 * v.y)
}
}

View File

@ -1,394 +0,0 @@
use std::num::{One, Zero};
use std::rand::{Rand, Rng};
use std::cmp::ApproxEq;
use traits::structure::{Dim, Mat, Col};
use traits::operations::{Absolute, Inv, RMul};
use traits::geometry::{Rotation, Rotate, RotationMatrix, Translation, Translate, Transformation,
ToHomogeneous, FromHomogeneous, AbsoluteRotate};
use Ts = traits::geometry::Transform;
use adaptors::rotmat::Rotmat;
use vec::{Vec2, Vec3, Vec2MulRhs, Vec3MulRhs};
use mat::Mat3;
/// Matrix-Vector wrapper used to represent a matrix multiplication followed by a translation.
///
/// Usually, a matrix in homogeneous coordinate is used to be able to apply an affine transform with
/// a translation to a vector. This is weird because it makes a `n`-dimentional transformation be
/// an `n + 1`-matrix. Using the `Transform` wrapper avoid homogeneous coordinates by having the
/// translation separate from the other transformations. This is particularity useful when the
/// underlying transform is a rotation (see `Rotmat`): this makes inversion much faster than
/// inverting the homogeneous matrix itself.
#[deriving(Eq, ToStr, Clone)]
pub struct Transform<V, M> {
priv submat : M,
priv subtrans : V
}
// FIXME: this should be Trasform<V, M>
impl<V, M> Transform<V, M> {
/// Builds a new transform from a matrix and a vector.
#[inline]
pub fn new(trans: V, mat: M) -> Transform<V, M> {
Transform {
submat: mat,
subtrans: trans
}
}
}
/// Trait of object `o` which can be multiplied by a `Transform` `t`: `t * o`.
pub trait TransformMulRhs<V, M, Res> {
/// Multiplies a transformation matrix by `Self`.
fn binop(left: &Transform<V, M>, right: &Self) -> Res;
}
impl<V, M, Rhs: TransformMulRhs<V, M, Res>, Res> Mul<Rhs, Res> for Transform<V, M> {
#[inline(always)]
fn mul(&self, other: &Rhs) -> Res {
TransformMulRhs::binop(self, other)
}
}
impl<V: Clone, M: Clone> Transform<V, M> {
/// Gets a copy of the internal matrix.
#[inline]
pub fn submat(&self) -> M {
self.submat.clone()
}
/// Gets a copy of the internal translation.
#[inline]
pub fn subtrans(&self) -> V {
self.subtrans.clone()
}
}
impl<LV, AV, M: One + RMul<LV> + RotationMatrix<LV, AV, M2>, M2: Mat<LV, LV> + Rotation<AV>>
RotationMatrix<LV, AV, M2> for Transform<LV, M> {
#[inline]
fn to_rot_mat(&self) -> M2 {
self.submat.to_rot_mat()
}
}
impl<N: Clone + Num + Algebraic> Transform<Vec3<N>, Rotmat<Mat3<N>>> {
/// Reorient and translate this transformation such that its local `x` axis points to a given
/// direction. Note that the usually known `look_at` function does the same thing but with the
/// `z` axis. See `look_at_z` for that.
///
/// # Arguments
/// * eye - The new translation of the transformation.
/// * at - The point to look at. `at - eye` is the direction the matrix `x` axis will be
/// aligned with.
/// * 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, eye: &Vec3<N>, at: &Vec3<N>, up: &Vec3<N>) {
self.submat.look_at(&(*at - *eye), up);
self.subtrans = eye.clone();
}
/// Reorient and translate this transformation such that its local `z` axis points to a given
/// direction.
///
/// # Arguments
/// * eye - The new translation of the transformation.
/// * at - The point to look at. `at - eye` is the direction the matrix `x` axis will be
/// aligned with
/// * 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, eye: &Vec3<N>, at: &Vec3<N>, up: &Vec3<N>) {
self.submat.look_at_z(&(*at - *eye), up);
self.subtrans = eye.clone();
}
}
impl<M: Dim, V> Dim for Transform<V, M> {
#[inline]
fn dim(_: Option<Transform<V, M>>) -> uint {
Dim::dim(None::<M>)
}
}
impl<M: One, V: Zero> One for Transform<V, M> {
#[inline]
fn one() -> Transform<V, M> {
Transform {
submat: One::one(), subtrans: Zero::zero()
}
}
}
impl<M: Zero, V: Zero> Zero for Transform<V, M> {
#[inline]
fn zero() -> Transform<V, M> {
Transform {
submat: Zero::zero(), subtrans: Zero::zero()
}
}
#[inline]
fn is_zero(&self) -> bool {
self.submat.is_zero() && self.subtrans.is_zero()
}
}
impl<M: RMul<V> + Mul<M, M>, V: Add<V, V>> TransformMulRhs<V, M, Transform<V, M>> for Transform<V, M> {
#[inline]
fn binop(left: &Transform<V, M>, right: &Transform<V, M>) -> Transform<V, M> {
Transform {
submat: left.submat * right.submat,
subtrans: left.subtrans + left.submat.rmul(&right.subtrans)
}
}
}
impl<N: Clone + Add<N, N>, M: Mul<Vec2<N>, Vec2<N>>>
TransformMulRhs<Vec2<N>, M, Vec2<N>> for Vec2<N> {
#[inline]
fn binop(left: &Transform<Vec2<N>, M>, right: &Vec2<N>) -> Vec2<N> {
left.subtrans + left.submat * *right
}
}
impl<N: Clone + Add<N, N>, M: Mul<Vec3<N>, Vec3<N>>>
TransformMulRhs<Vec3<N>, M, Vec3<N>> for Vec3<N> {
#[inline]
fn binop(left: &Transform<Vec3<N>, M>, right: &Vec3<N>) -> Vec3<N> {
left.subtrans + left.submat * *right
}
}
impl<N: Clone + Add<N, N>, M: Vec2MulRhs<N, Vec2<N>>>
Vec2MulRhs<N, Vec2<N>> for Transform<Vec2<N>, M> {
#[inline]
fn binop(left: &Vec2<N>, right: &Transform<Vec2<N>, M>) -> Vec2<N> {
(left + right.subtrans) * right.submat
}
}
impl<N: Clone + Add<N, N>, M: Vec3MulRhs<N, Vec3<N>>>
Vec3MulRhs<N, Vec3<N>> for Transform<Vec3<N>, M> {
#[inline]
fn binop(left: &Vec3<N>, right: &Transform<Vec3<N>, M>) -> Vec3<N> {
(left + right.subtrans) * right.submat
}
}
impl<M: Clone, V: Translation<V>> Translation<V> for Transform<V, M> {
#[inline]
fn translation(&self) -> V {
self.subtrans.translation()
}
#[inline]
fn inv_translation(&self) -> V {
self.subtrans.inv_translation()
}
#[inline]
fn translate_by(&mut self, t: &V) {
self.subtrans.translate_by(t)
}
#[inline]
fn translated(&self, t: &V) -> Transform<V, M> {
Transform::new(self.subtrans.translated(t), self.submat.clone())
}
#[inline]
fn set_translation(&mut self, t: V) {
self.subtrans.set_translation(t)
}
}
impl<V, M: Translate<V>, _0> Translate<V> for Transform<_0, M> {
#[inline]
fn translate(&self, v: &V) -> V {
self.submat.translate(v)
}
#[inline]
fn inv_translate(&self, v: &V) -> V {
self.submat.inv_translate(v)
}
}
impl<M: Rotation<AV> + RMul<V> + One, V, AV>
Rotation<AV> for Transform<V, M> {
#[inline]
fn rotation(&self) -> AV {
self.submat.rotation()
}
#[inline]
fn inv_rotation(&self) -> AV {
self.submat.inv_rotation()
}
#[inline]
fn rotate_by(&mut self, rot: &AV) {
// FIXME: this does not seem opitmal
let mut delta: M = One::one();
delta.rotate_by(rot);
self.submat.rotate_by(rot);
self.subtrans = delta.rmul(&self.subtrans);
}
#[inline]
fn rotated(&self, rot: &AV) -> Transform<V, M> {
// FIXME: this does not seem opitmal
let _1: M = One::one();
let delta = _1.rotated(rot);
Transform::new(delta.rmul(&self.subtrans), self.submat.rotated(rot))
}
#[inline]
fn set_rotation(&mut self, rot: AV) {
// FIXME: should the translation be changed too?
self.submat.set_rotation(rot)
}
}
impl<V, M: Rotate<V>, _0> Rotate<V> for Transform<_0, M> {
#[inline]
fn rotate(&self, v: &V) -> V {
self.submat.rotate(v)
}
#[inline]
fn inv_rotate(&self, v: &V) -> V {
self.submat.inv_rotate(v)
}
}
impl<M: Inv + RMul<V> + Mul<M, M> + Clone, V: Add<V, V> + Neg<V> + Clone>
Transformation<Transform<V, M>> for Transform<V, M> {
fn transformation(&self) -> Transform<V, M> {
self.clone()
}
fn inv_transformation(&self) -> Transform<V, M> {
// FIXME: fail or return a Some<Transform<V, M>> ?
match self.inverse() {
Some(t) => t,
None => fail!("This transformation was not inversible.")
}
}
fn transform_by(&mut self, other: &Transform<V, M>) {
*self = other * *self
}
fn transformed(&self, t: &Transform<V, M>) -> Transform<V, M> {
t * *self
}
fn set_transformation(&mut self, t: Transform<V, M>) {
*self = t
}
}
impl<M: Ts<V>, V: Add<V, V> + Sub<V, V>>
Ts<V> for Transform<V, M> {
#[inline]
fn transform(&self, v: &V) -> V {
self.submat.transform(v) + self.subtrans
}
#[inline]
fn inv_transform(&self, v: &V) -> V {
self.submat.inv_transform(&(v - self.subtrans))
}
}
impl<M: Inv + RMul<V> + Clone, V: Neg<V> + Clone>
Inv for Transform<V, M> {
#[inline]
fn inplace_inverse(&mut self) -> bool {
if !self.submat.inplace_inverse() {
false
}
else {
self.subtrans = self.submat.rmul(&-self.subtrans);
true
}
}
#[inline]
fn inverse(&self) -> Option<Transform<V, M>> {
let mut res = self.clone();
if res.inplace_inverse() {
Some(res)
}
else {
None
}
}
}
impl<M: ToHomogeneous<M2>, M2: Dim + Col<V2>, V: ToHomogeneous<V2> + Clone, V2>
ToHomogeneous<M2> for Transform<V, M> {
fn to_homogeneous(&self) -> M2 {
let mut res = self.submat.to_homogeneous();
// copy the translation
let dim = Dim::dim(None::<M2>);
res.set_col(dim - 1, self.subtrans.to_homogeneous());
res
}
}
impl<M: Col<V> + Dim, M2: FromHomogeneous<M>, V>
FromHomogeneous<M> for Transform<V, M2> {
fn from(m: &M) -> Transform<V, M2> {
Transform::new(m.col(Dim::dim(None::<M>) - 1), FromHomogeneous::from(m))
}
}
impl<N: ApproxEq<N>, M:ApproxEq<N>, V:ApproxEq<N>>
ApproxEq<N> for Transform<V, M> {
#[inline]
fn approx_epsilon() -> N {
fail!("approx_epsilon is broken since rust revision 8693943676487c01fa09f5f3daf0df6a1f71e24d.")
// ApproxEq::<N>::approx_epsilon()
}
#[inline]
fn approx_eq(&self, other: &Transform<V, M>) -> bool {
self.submat.approx_eq(&other.submat) &&
self.subtrans.approx_eq(&other.subtrans)
}
#[inline]
fn approx_eq_eps(&self, other: &Transform<V, M>, epsilon: &N) -> bool {
self.submat.approx_eq_eps(&other.submat, epsilon) &&
self.subtrans.approx_eq_eps(&other.subtrans, epsilon)
}
}
impl<M: Rand, V: Rand> Rand for Transform<V, M> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Transform<V, M> {
Transform::new(rng.gen(), rng.gen())
}
}
impl<V: Absolute<V2>, M: Absolute<M2>, V2, M2>
Absolute<Transform<V2, M2>> for Transform<V, M> {
#[inline]
fn absolute(&self) -> Transform<V2, M2> {
Transform::new(self.subtrans.absolute(), self.submat.absolute())
}
}
impl<V, M: AbsoluteRotate<V>> AbsoluteRotate<V> for Transform<V, M> {
#[inline]
fn absolute_rotate(&self, v: &V) -> V {
self.submat.absolute_rotate(v)
}
}

View File

@ -1,7 +1,6 @@
use std::rand::random; use std::rand::random;
use extra::test::BenchHarness; use extra::test::BenchHarness;
use mat::*; use na::*;
use vec::*;
macro_rules! bench_mul_mat( macro_rules! bench_mul_mat(
($bh: expr, $t: ty) => { ($bh: expr, $t: ty) => {

View File

@ -1,6 +1,6 @@
use std::rand::random; use std::rand::random;
use extra::test::BenchHarness; use extra::test::BenchHarness;
use vec::*; use na::*;
macro_rules! bench_dot_vec( macro_rules! bench_dot_vec(
($bh: expr, $t: ty) => { ($bh: expr, $t: ty) => {

View File

@ -1,6 +1,92 @@
/*! /*!
# nalgebra
# A n-dimensional linear algebra library. **nalgebra** is a linear algebra library written for Rust targeting:
* general-purpose linear algebra (still misses a lot of features).
* real time computer graphics.
* real time computer physics.
## 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)`.
* You can import the whole prelude, including free functions, using:
```.rust
pub use nalgebra::na::*;
```
* If you dont want to import everything but only every trait:
```.rust
pub use nalgebra::traits::*;
```
* If you dont want to import everything but only every structure:
```.rust
pub use nalgebra::structs::*;
```
Of course, you can still import `nalgebra::na` alone, and get anything you want using the `na`
prefix.
## Features
**nalgebra** is meant to be a general-purpose linear algebra library (but is very far from that),
and keeps an optimized set of tools for computational graphics and physics. Those features include:
* Vectors with static sizes: `Vec0`, `Vec1`, `Vec2`, ..., `Vec6`.
* Square matrices with static sizes: `Mat1`, `Mat2`, ..., `Mat6 `.
* Rotation matrices: `Rot2`, `Rot3`, `Rot4`.
* Isometries: `Iso2`, `Iso3`, `Iso4`.
* Dynamically sized vector: `DVec`.
* Dynamically sized (square or rectangular) matrix: `DMat`.
* A few methods for data analysis: `Cov`, `Mean`.
* Operator overloading using the double trait dispatch
[trick](http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/).
For example, the following work:
```rust
extern mod nalgebra;
use nalgebra::na::{Vec3, Mat3};
fn main() {
let v: Vec3<f64> = Zero::zero();
let m: Mat3<f64> = One::one();
let _ = m * v; // matrix-vector multiplication.
let _ = v * m; // vector-matrix multiplication.
let _ = m * m; // matrix-matrix multiplication.
let _ = v * 2.0; // vector-scalar multiplication.
}
```
* Almost one trait per functionality: useful for generic programming.
## Compilation
You will need the last rust compiler from the master branch.
If you encounter problems, make sure you have the last version before creating an issue.
git clone git://github.com/sebcrozet/nalgebra.git
cd nalgebra
make
You can build the documentation on the `doc` folder using:
```.rust
make doc
```
## **nalgebra** in use
Here are some projects using **nalgebra**.
Feel free to add your project to this list if you happen to use **nalgebra**!
* [nphysics](https://github.com/sebcrozet/nphysics): a real-time physics engine.
* [ncollide](https://github.com/sebcrozet/ncollide): a collision detection library.
* [kiss3d](https://github.com/sebcrozet/kiss3d): a minimalistic graphics engine.
* [frog](https://github.com/natal/frog): a machine learning library.
*/ */
#[link(name = "nalgebra" #[link(name = "nalgebra"
@ -16,34 +102,10 @@
extern mod std; extern mod std;
extern mod extra; extern mod extra;
pub mod dmat; pub mod na;
pub mod dvec; pub mod structs;
pub mod vec; pub mod traits;
pub mod mat;
pub mod types;
/// Wrappers around raw matrices to restrict their behaviour.
pub mod adaptors {
pub mod rotmat;
pub mod transform;
}
/// Traits implemented by matrices and vectors. Re-exported by the `mat` or the `vec` module.
pub mod traits {
pub mod geometry;
pub mod structure;
pub mod operations;
}
// specialization for some 1d, 2d and 3d operations
#[doc(hidden)]
mod spec {
mod identity;
mod mat;
mod vec0;
mod vec;
// mod complex;
}
// mod lower_triangular; // mod lower_triangular;
// mod chol; // mod chol;

549
src/na.rs Normal file
View File

@ -0,0 +1,549 @@
//! **nalgebra** prelude.
pub use traits::{
Absolute,
AbsoluteRotate,
AlgebraicVec,
AlgebraicVecExt,
Basis,
Col,
Cov,
Cross,
CrossMatrix,
Dim,
Dot,
FromHomogeneous,
Indexable,
Inv,
Iterable,
IterableMut,
LMul,
Mat,
MatCast,
Mean,
Norm,
Outer,
RMul,
Rotate, Rotation, RotationMatrix, RotationWithTranslation,
Row,
ScalarAdd, ScalarSub,
ToHomogeneous,
Transform, Transformation,
Translate, Translation,
Transpose,
UniformSphereSample,
Vec,
VecCast,
VecExt
};
pub use structs::{
DMat, DVec,
Iso2, Iso3, Iso4,
Mat1, Mat2, Mat3, Mat4,
Mat5, Mat6,
Rot2, Rot3, Rot4,
Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6
};
//
//
// Geometry
//
//
/*
* Translation<V>
*/
/// Gets the translation applicable by the given object.
///
/// ```rust
/// extern mod nalgebra;
/// use nalgebra::types::{Vec3, Affmat};
/// use nalgebra::na;
///
/// pub main() {
/// let t = Affmat::new_translation3d(1.0, 1.0, 1.0);
/// let trans = na::translation(t);
///
/// assert!(trans == Vec3::new(1.0, 1.0, 1.0));
/// }
/// ```
#[inline(always)]
pub fn translation<V, M: Translation<V>>(m: &M) -> V {
m.translation()
}
/// Gets the inverse translation applicable by the given object.
///
/// ```rust
/// extern mod nalgebra;
/// use nalgebra::types::{Vec3, Affmat};
/// use nalgebra::na;
///
/// pub main() {
/// let t = Affmat::new_translation3d(1.0, 1.0, 1.0);
/// let itrans = na::inv_translation(t);
///
/// assert!(itrans == Vec3::new(-1.0, -1.0, -1.0));
/// }
/// ```
#[inline(always)]
pub fn inv_translation<V, M: Translation<V>>(m: &M) -> V {
m.inv_translation()
}
/// In-place version of `translated`.
#[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)
}
/*
* Translate<V>
*/
/// FIXME
#[inline(always)]
pub fn translate<V, M: Translate<V>>(m: &M, v: &V) -> V {
m.translate(v)
}
/// FIXME
#[inline(always)]
pub fn inv_translate<V, M: Translate<V>>(m: &M, v: &V) -> V {
m.inv_translate(v)
}
/*
* Rotation<V>
*/
/// Gets the rotation applicable by the given object.
///
/// ```rust
/// extern mod nalgebra;
/// use nalgebra::na;
///
/// pub main() {
/// let t = na::rotation3d(1.0, 1.0, 1.0);
///
/// assert!(na::rotation(t) == na::vec3(1.0, 1.0, 1.0));
/// }
/// ```
#[inline(always)]
pub fn rotation<V, M: Rotation<V>>(m: &M) -> V {
m.rotation()
}
/// Gets the rotation applicable by the given object.
///
/// ```rust
/// extern mod nalgebra;
/// use nalgebra::na;
///
/// pub main() {
/// let t = na::rotation3d(1.0, 1.0, 1.0);
///
/// assert!(na::inv_rotation(t) == na::vec3(-1.0, -1.0, -1.0));
/// }
/// ```
#[inline(always)]
pub fn inv_rotation<V, M: Rotation<V>>(m: &M) -> V {
m.inv_rotation()
}
/// FIXME
#[inline(always)]
pub fn rotate_by<V, M: Rotation<V>>(m: &mut M, v: &V) {
m.rotate_by(v)
}
/// FIXME
#[inline(always)]
pub fn rotated<V, M: Rotation<V>>(m: &M, v: &V) -> M {
m.rotated(v)
}
/// FIXME
#[inline(always)]
pub fn set_rotation<V, M: Rotation<V>>(m: &mut M, v: V) {
m.set_rotation(v)
}
/*
* Rotate<V>
*/
/// FIXME
#[inline(always)]
pub fn rotate<V, M: Rotate<V>>(m: &M, v: &V) -> V {
m.rotate(v)
}
/// FIXME
#[inline(always)]
pub fn inv_rotate<V, M: Rotate<V>>(m: &M, v: &V) -> V {
m.inv_rotate(v)
}
/*
* RotationWithTranslation<LV, AV>
*/
/// FIXME
#[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)
}
/// FIXME
#[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)
}
/// FIXME
#[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)
}
/// FIXME
#[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)
}
/*
* RotationMatrix<LV, AV, R>
*/
/// FIXME
#[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()
}
/*
* AbsoluteRotate<V>
*/
/// FIXME
#[inline(always)]
pub fn absolute_rotate<V, M: AbsoluteRotate<V>>(m: &M, v: &V) -> V {
m.absolute_rotate(v)
}
/*
* Transformation<V>
*/
/// FIXME
#[inline(always)]
pub fn transformation<V, M: Transformation<V>>(m: &M) -> V {
m.transformation()
}
/// FIXME
#[inline(always)]
pub fn inv_transformation<V, M: Transformation<V>>(m: &M) -> V {
m.inv_transformation()
}
/// FIXME
#[inline(always)]
pub fn transform_by<V, M: Transformation<V>>(m: &mut M, v: &V) {
m.transform_by(v)
}
/// FIXME
#[inline(always)]
pub fn transformed<V, M: Transformation<V>>(m: &M, v: &V) -> M {
m.transformed(v)
}
/// FIXME
#[inline(always)]
pub fn set_transformation<V, M: Transformation<V>>(m: &mut M, v: V) {
m.set_transformation(v)
}
/*
* Transform<V>
*/
/// FIXME
#[inline(always)]
pub fn transform<V, M: Transform<V>>(m: &M, v: &V) -> V {
m.transform(v)
}
/// FIXME
#[inline(always)]
pub fn inv_transform<V, M: Transform<V>>(m: &M, v: &V) -> V {
m.inv_transform(v)
}
/*
* Dot<N>
*/
/// FIXME
#[inline(always)]
pub fn dot<V: Dot<N>, N>(a: &V, b: &V) -> N {
a.dot(b)
}
/// FIXME
#[inline(always)]
pub fn sub_dot<V: Dot<N>, N>(a: &V, b: &V, c: &V) -> N {
a.sub_dot(b, c)
}
/*
* Norm<N>
*/
/// FIXME
#[inline(always)]
pub fn norm<V: Norm<N>, N: Algebraic>(v: &V) -> N {
v.norm()
}
/// FIXME
#[inline(always)]
pub fn sqnorm<V: Norm<N>, N: Algebraic>(v: &V) -> N {
v.sqnorm()
}
/// FIXME
#[inline(always)]
pub fn normalized<V: Norm<N>, N: Algebraic>(v: &V) -> V {
v.normalized()
}
/// FIXME
#[inline(always)]
pub fn normalize<V: Norm<N>, N: Algebraic>(v: &mut V) -> N {
v.normalize()
}
/*
* Cross<V>
*/
/// FIXME
#[inline(always)]
pub fn cross<LV: Cross<AV>, AV>(a: &LV, b: &LV) -> AV {
a.cross(b)
}
/*
* CrossMatrix<M>
*/
/// FIXME
#[inline(always)]
pub fn cross_matrix<V: CrossMatrix<M>, M>(v: &V) -> M {
v.cross_matrix()
}
/*
* ToHomogeneous<U>
*/
/// FIXME
#[inline(always)]
pub fn to_homogeneous<M: ToHomogeneous<Res>, Res>(m: &M) -> Res {
m.to_homogeneous()
}
/*
* FromHomogeneous<U>
*/
/// FIXME
#[inline(always)]
pub fn from_homogeneous<M, Res: FromHomogeneous<M>>(m: &M) -> Res {
FromHomogeneous::from(m)
}
/*
* UniformSphereSample
*/
/// FIXME
#[inline(always)]
pub fn sample_sphere<V: UniformSphereSample>(f: &fn(V)) {
UniformSphereSample::sample(f)
}
//
//
// Operations
//
//
/*
* Absolute<A>
*/
/// FIXME
#[inline(always)]
pub fn absolute<M: Absolute<Res>, Res>(m: &M) -> Res {
m.absolute()
}
/*
* Inv
*/
/// FIXME
#[inline(always)]
pub fn inverted<M: Inv>(m: &M) -> Option<M> {
m.inverted()
}
/// FIXME
#[inline(always)]
pub fn invert<M: Inv>(m: &mut M) -> bool {
m.invert()
}
/*
* Transpose
*/
/// FIXME
#[inline(always)]
pub fn transposed<M: Transpose>(m: &M) -> M {
m.transposed()
}
/// FIXME
#[inline(always)]
pub fn transpose<M: Transpose>(m: &mut M) {
m.transpose()
}
/*
* Outer<M>
*/
/// FIXME
#[inline(always)]
pub fn outer<V: Outer<M>, M>(a: &V, b: &V) -> M {
a.outer(b)
}
/*
* Cov<M>
*/
/// FIXME
#[inline(always)]
pub fn cov<M: Cov<Res>, Res>(observations: &M) -> Res {
observations.cov()
}
/*
* Mean<N>
*/
/// FIXME
#[inline(always)]
pub fn mean<N, M: Mean<N>>(observations: &M) -> N {
observations.mean()
}
//
//
// Structure
//
//
/*
* MatCast<M>
*/
/// FIXME
#[inline(always)]
pub fn cast_mat<M: MatCast<Res>, Res>(m: M) -> Res {
MatCast::from(m)
}
/*
* VecCast<M>
*/
/// FIXME
#[inline(always)]
pub fn cast_vec<V: VecCast<Res>, Res>(v: V) -> Res {
VecCast::from(v)
}
/*
* Basis
*/
/// FIXME
#[inline(always)]
pub fn canonical_basis<V: Basis>(f: &fn(V) -> bool) {
Basis::canonical_basis(f)
}
/// FIXME
#[inline(always)]
pub fn orthonormal_subspace_basis<V: Basis>(v: &V, f: &fn(V) -> bool) {
v.orthonormal_subspace_basis(f)
}
/*
* Row<R>
*/
/*
* Col<C>
*/
/*
* Dim
*/
/*
* Indexable
*/

27
src/structs/chol.rs Normal file
View File

@ -0,0 +1,27 @@
// use lower_triangular::LowerTriangularMat;
//
// /// Choleski factorization.
// pub trait Chol<N> {
// /// Choleski LL* factorization for a symetric definite positive matrix.
// fn chol(self) -> LowerTriangularMat<N>;
// }
//
// impl<N> Chol<N> for DMat<N> {
// fn chol(self) -> LowerTriangularMat<N> {
// }
// }
//
// impl<N> Chol<N> for LowerTriangularMat<N> {
// fn chol(self) -> LowerTriangularMat<N> {
// }
// }
//
// impl<N> Chol<N> for UpperTriangularMat<N> {
// fn chol(self) -> LowerTriangularMat<N> {
// }
// }
//
// impl<N> Chol<N> for DiagonalMat<N> {
// fn chol(self) -> LowerTriangularMat<N> {
// }
// }

6
src/structs/crout.rs Normal file
View File

@ -0,0 +1,6 @@
use lower_triangular::LowerTriangularMat;
pub trait Crout<N> {
/// Crout LDL* factorization for a symetric definite indefinite matrix.
fn crout(self, &mut DiagonalMat<N>) -> LowerTriangularMat<N>;
}

View File

@ -1,6 +1,6 @@
//! Matrix with dimensions unknown at compile-time. //! Matrix with dimensions unknown at compile-time.
#[doc(hidden)]; // we hide doc to not have to document the $trhs double dispatch trait. #[allow(missing_doc)]; // we hide doc to not have to document the $trhs double dispatch trait.
use std::rand::Rand; use std::rand::Rand;
use std::rand; use std::rand;
@ -8,7 +8,7 @@ use std::num::{One, Zero};
use std::vec; use std::vec;
use std::cmp::ApproxEq; use std::cmp::ApproxEq;
use std::util; use std::util;
use dvec::{DVec, DVecMulRhs}; use structs::dvec::{DVec, DVecMulRhs};
use traits::operations::{Inv, Transpose, Mean, Cov}; use traits::operations::{Inv, Transpose, Mean, Cov};
#[doc(hidden)] #[doc(hidden)]
@ -277,10 +277,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 inverse(&self) -> Option<DMat<N>> { fn inverted(&self) -> Option<DMat<N>> {
let mut res : DMat<N> = self.clone(); let mut res : DMat<N> = self.clone();
if res.inplace_inverse() { if res.invert() {
Some(res) Some(res)
} }
else { else {
@ -288,7 +288,7 @@ Inv for DMat<N> {
} }
} }
fn inplace_inverse(&mut self) -> bool { fn invert(&mut self) -> bool {
assert!(self.nrows == self.ncols); assert!(self.nrows == self.ncols);
let dim = self.nrows; let dim = self.nrows;

View File

@ -1,6 +1,6 @@
//! Vector with dimensions unknown at compile-time. //! Vector with dimensions unknown at compile-time.
#[doc(hidden)]; // we hide doc to not have to document the $trhs double dispatch trait. #[allow(missing_doc)]; // we hide doc to not have to document the $trhs double dispatch trait.
use std::num::{Zero, One, Algebraic}; use std::num::{Zero, One, Algebraic};
use std::rand::Rand; use std::rand::Rand;

115
src/structs/iso.rs Normal file
View File

@ -0,0 +1,115 @@
//! Isometric transformations.
#[allow(missing_doc)];
use std::num::{Zero, One};
use std::rand::{Rand, Rng};
use structs::mat::{Mat3, Mat4, Mat5};
use traits::structure::{Dim, Col};
use traits::operations::{Inv};
use traits::geometry::{RotationMatrix, Rotation, Rotate, AbsoluteRotate, Transform, Transformation,
Translate, Translation, ToHomogeneous};
use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec2MulRhs, Vec3MulRhs, Vec4MulRhs};
use structs::rot::{Rot2, Rot3, Rot4};
mod metal;
mod iso_macros;
/// Two dimensional isometry.
///
/// This is the composition of a rotation followed by a translation.
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
pub struct Iso2<N> {
/// The rotation applicable by this isometry.
rotation: Rot2<N>,
/// The translation applicable by this isometry.
translation: Vec2<N>
}
/// Three dimensional isometry.
///
/// This is the composition of a rotation followed by a translation.
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
pub struct Iso3<N> {
/// The rotation applicable by this isometry.
rotation: Rot3<N>,
/// The translation applicable by this isometry.
translation: Vec3<N>
}
/// Four dimensional isometry.
///
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
pub struct Iso4<N> {
/// The rotation applicable by this isometry.
rotation: Rot4<N>,
/// The translation applicable by this isometry.
translation: Vec4<N>
}
iso_impl!(Iso2, Rot2, Vec2)
double_dispatch_binop_decl_trait!(Iso2, Iso2MulRhs)
mul_redispatch_impl!(Iso2, Iso2MulRhs)
rotation_matrix_impl!(Iso2, Rot2, Vec2, Vec1)
rotation_impl!(Iso2, Rot2, Vec1)
dim_impl!(Iso2, 2)
one_impl!(Iso2)
absolute_rotate_impl!(Iso2, Vec2)
rand_impl!(Iso2)
approx_eq_impl!(Iso2)
to_homogeneous_impl!(Iso2, Mat3)
inv_impl!(Iso2)
transform_impl!(Iso2, Vec2)
transformation_impl!(Iso2)
rotate_impl!(Iso2, Vec2)
translation_impl!(Iso2, Vec2)
translate_impl!(Iso2, Vec2)
iso_mul_iso_impl!(Iso2, Iso2MulRhs)
iso_mul_vec_impl!(Iso2, Vec2, Iso2MulRhs)
vec_mul_iso_impl!(Iso2, Vec2, Vec2MulRhs)
iso_impl!(Iso3, Rot3, Vec3)
double_dispatch_binop_decl_trait!(Iso3, Iso3MulRhs)
mul_redispatch_impl!(Iso3, Iso3MulRhs)
rotation_matrix_impl!(Iso3, Rot3, Vec3, Vec3)
rotation_impl!(Iso3, Rot3, Vec3)
dim_impl!(Iso3, 3)
one_impl!(Iso3)
absolute_rotate_impl!(Iso3, Vec3)
rand_impl!(Iso3)
approx_eq_impl!(Iso3)
to_homogeneous_impl!(Iso3, Mat4)
inv_impl!(Iso3)
transform_impl!(Iso3, Vec3)
transformation_impl!(Iso3)
rotate_impl!(Iso3, Vec3)
translation_impl!(Iso3, Vec3)
translate_impl!(Iso3, Vec3)
iso_mul_iso_impl!(Iso3, Iso3MulRhs)
iso_mul_vec_impl!(Iso3, Vec3, Iso3MulRhs)
vec_mul_iso_impl!(Iso3, Vec3, Vec3MulRhs)
iso_impl!(Iso4, Rot4, Vec4)
double_dispatch_binop_decl_trait!(Iso4, Iso4MulRhs)
mul_redispatch_impl!(Iso4, Iso4MulRhs)
// rotation_matrix_impl!(Iso4, Rot4, Vec4, Vec4)
// rotation_impl!(Iso4, Rot4, Vec4)
dim_impl!(Iso4, 4)
one_impl!(Iso4)
// absolute_rotate_impl!(Iso4, Vec4)
// rand_impl!(Iso4)
approx_eq_impl!(Iso4)
to_homogeneous_impl!(Iso4, Mat5)
inv_impl!(Iso4)
transform_impl!(Iso4, Vec4)
transformation_impl!(Iso4)
// rotate_impl!(Iso4, Vec4)
translation_impl!(Iso4, Vec4)
translate_impl!(Iso4, Vec4)
iso_mul_iso_impl!(Iso4, Iso4MulRhs)
iso_mul_vec_impl!(Iso4, Vec4, Iso4MulRhs)
vec_mul_iso_impl!(Iso4, Vec4, Vec4MulRhs)

319
src/structs/iso_macros.rs Normal file
View File

@ -0,0 +1,319 @@
#[macro_escape];
macro_rules! iso_impl(
($t: ident, $submat: ident, $subvec: ident) => (
impl<N> $t<N> {
/// Creates a new isometry from a rotation matrix and a vector.
#[inline]
pub fn new(translation: $subvec<N>, rotation: $submat<N>) -> $t<N> {
$t {
rotation: rotation,
translation: translation
}
}
}
)
)
macro_rules! rotation_matrix_impl(
($t: ident, $trot: ident, $tlv: ident, $tav: ident) => (
impl<N: NumCast + Algebraic + Trigonometric + Num + Clone>
RotationMatrix<$tlv<N>, $tav<N>, $trot<N>> for $t<N> {
#[inline]
fn to_rot_mat(&self) -> $trot<N> {
self.rotation.clone()
}
}
)
)
macro_rules! dim_impl(
($t: ident, $dim: expr) => (
impl<N> Dim for $t<N> {
#[inline]
fn dim(_: Option<$t<N>>) -> uint {
$dim
}
}
)
)
macro_rules! one_impl(
($t: ident) => (
impl<N: One + Zero + Clone> One for $t<N> {
#[inline]
fn one() -> $t<N> {
$t::new(Zero::zero(), One::one())
}
}
)
)
macro_rules! iso_mul_iso_impl(
($t: ident, $tmul: ident) => (
impl<N: Num + Clone> $tmul<N, $t<N>> for $t<N> {
#[inline]
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
$t::new(left.translation + left.rotation * right.translation, left.rotation * right.rotation)
}
}
)
)
macro_rules! iso_mul_vec_impl(
($t: ident, $tv: ident, $tmul: ident) => (
impl<N: Num + Clone> $tmul<N, $tv<N>> for $tv<N> {
#[inline]
fn binop(left: &$t<N>, right: &$tv<N>) -> $tv<N> {
left.translation + left.rotation * *right
}
}
)
)
macro_rules! vec_mul_iso_impl(
($t: ident, $tv: ident, $tmul: ident) => (
impl<N: Clone + Num> $tmul<N, $tv<N>> for $t<N> {
#[inline]
fn binop(left: &$tv<N>, right: &$t<N>) -> $tv<N> {
(left + right.translation) * right.rotation
}
}
)
)
macro_rules! translation_impl(
($t: ident, $tv: ident) => (
impl<N: Neg<N> + Add<N, N> + Clone> Translation<$tv<N>> for $t<N> {
#[inline]
fn translation(&self) -> $tv<N> {
self.translation.clone()
}
#[inline]
fn inv_translation(&self) -> $tv<N> {
-self.translation
}
#[inline]
fn translate_by(&mut self, t: &$tv<N>) {
self.translation = self.translation + *t
}
#[inline]
fn translated(&self, t: &$tv<N>) -> $t<N> {
$t::new(self.translation + *t, self.rotation.clone())
}
#[inline]
fn set_translation(&mut self, t: $tv<N>) {
self.translation = t
}
}
)
)
macro_rules! translate_impl(
($t: ident, $tv: ident) => (
impl<N: Clone + Add<N, N> + Sub<N, N>> Translate<$tv<N>> for $t<N> {
#[inline]
fn translate(&self, v: &$tv<N>) -> $tv<N> {
v + self.translation
}
#[inline]
fn inv_translate(&self, v: &$tv<N>) -> $tv<N> {
v - self.translation
}
}
)
)
macro_rules! rotation_impl(
($t: ident, $trot: ident, $tav: ident) => (
impl<N: Num + Trigonometric + Algebraic + NumCast + Clone> Rotation<$tav<N>> for $t<N> {
#[inline]
fn rotation(&self) -> $tav<N> {
self.rotation.rotation()
}
#[inline]
fn inv_rotation(&self) -> $tav<N> {
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);
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);
$t::new(delta * self.translation, self.rotation.rotated(rot))
}
#[inline]
fn set_rotation(&mut self, rot: $tav<N>) {
// FIXME: should the translation be changed too?
self.rotation.set_rotation(rot)
}
}
)
)
macro_rules! rotate_impl(
($t: ident, $tv: ident) => (
impl<N: Num + Clone> Rotate<$tv<N>> for $t<N> {
#[inline]
fn rotate(&self, v: &$tv<N>) -> $tv<N> {
self.rotation.rotate(v)
}
#[inline]
fn inv_rotate(&self, v: &$tv<N>) -> $tv<N> {
self.rotation.inv_rotate(v)
}
}
)
)
macro_rules! transformation_impl(
($t: ident) => (
impl<N: Num + Clone> Transformation<$t<N>> for $t<N> {
fn transformation(&self) -> $t<N> {
self.clone()
}
fn inv_transformation(&self) -> $t<N> {
// inversion will never fails
self.inverted().unwrap()
}
fn transform_by(&mut self, other: &$t<N>) {
*self = other * *self
}
fn transformed(&self, t: &$t<N>) -> $t<N> {
t * *self
}
fn set_transformation(&mut self, t: $t<N>) {
*self = t
}
}
)
)
macro_rules! transform_impl(
($t: ident, $tv: ident) => (
impl<N: Num + Clone> Transform<$tv<N>> for $t<N> {
#[inline]
fn transform(&self, v: &$tv<N>) -> $tv<N> {
self.rotation.transform(v) + self.translation
}
#[inline]
fn inv_transform(&self, v: &$tv<N>) -> $tv<N> {
self.rotation.inv_transform(&(v - self.translation))
}
}
)
)
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;
// always succeed
true
}
#[inline]
fn inverted(&self) -> Option<$t<N>> {
let mut res = self.clone();
res.invert();
// always succeed
Some(res)
}
}
)
)
macro_rules! to_homogeneous_impl(
($t: ident, $th: ident) => (
impl<N: One + Zero + Clone> ToHomogeneous<$th<N>> for $t<N> {
fn to_homogeneous(&self) -> $th<N> {
let mut res = self.rotation.to_homogeneous();
// copy the translation
let dim = Dim::dim(None::<$th<N>>);
res.set_col(dim - 1, self.translation.to_homogeneous());
res
}
}
)
)
macro_rules! approx_eq_impl(
($t: ident) => (
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
#[inline]
fn approx_epsilon() -> N {
fail!("approx_epsilon is broken since rust revision 8693943676487c01fa09f5f3daf0df6a1f71e24d.")
// ApproxEq::<N>::approx_epsilon()
}
#[inline]
fn approx_eq(&self, other: &$t<N>) -> bool {
self.rotation.approx_eq(&other.rotation) &&
self.translation.approx_eq(&other.translation)
}
#[inline]
fn approx_eq_eps(&self, other: &$t<N>, epsilon: &N) -> bool {
self.rotation.approx_eq_eps(&other.rotation, epsilon) &&
self.translation.approx_eq_eps(&other.translation, epsilon)
}
}
)
)
macro_rules! rand_impl(
($t: ident) => (
impl<N: Rand + Clone + Trigonometric + Algebraic + Num> Rand for $t<N> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> $t<N> {
$t::new(rng.gen(), rng.gen())
}
}
)
)
macro_rules! absolute_rotate_impl(
($t: ident, $tv: ident) => (
impl<N: Signed> AbsoluteRotate<$tv<N>> for $t<N> {
#[inline]
fn absolute_rotate(&self, v: &$tv<N>) -> $tv<N> {
self.rotation.absolute_rotate(v)
}
}
)
)

View File

@ -0,0 +1,153 @@
use std::rand::Rand;
use std::rand;
use std::num::{One, Zero};
use std::vec;
/// A structure optimized to store lower triangular matrices.
pub struct LowerTriangularMat<N> {
priv dim: uint,
priv mij: ~[N]
}
/// Trait to be implemented by objects which can be left-multiplied by a lower triangular array.
pub trait LowerTriangularMatMulRhs<N, Res> {
/// Apply the muliplicitaion.
fn binop(left: &LowerTriangularMat<N>, right: &Self) -> Res;
}
impl<N, Rhs: LowerTriangularMatMulRhs<N, Res>, Res> Mul<Rhs, Res> for LowerTriangularMat<N> {
#[inline(always)]
fn mul(&self, other: &Rhs) -> Res {
LowerTriangularMatMulRhs::binop(self, other)
}
}
impl<N> LowerTriangularMat<N> {
/// Creates a lower triangular matrix without initializing its arguments.
#[inline]
pub unsafe fn new_uninitialized(dim: uint) -> LowerTriangularMat<N> {
let mut vec = vec::with_capacity(dim * (dim + 1) / 2);
vec::raw::set_len(&mut vec, dim * (dim + 1) / 2);
LowerTriangularMat {
dim: dim,
mij: vec
}
}
}
impl<N: Zero + Clone> LowerTriangularMat<N> {
/// Creates a lower triangular matrix filled with zeros.
#[inline]
pub fn new_zeros(dim: uint) -> LowerTriangularMat<N> {
LowerTriangularMat::from_elem(dim, Zero::zero())
}
/// Tests if every entry of the matrix are exactly zeros.
#[inline]
pub fn is_zero(&self) -> bool {
self.mij.iter().all(|e| e.is_zero())
}
}
impl<N: Rand> LowerTriangularMat<N> {
/// Creates a lower triangular matrix filled with random elements.
#[inline]
pub fn new_random(dim: uint) -> LowerTriangularMat<N> {
LowerTriangularMat::from_fn(dim, |_, _| rand::random())
}
}
impl<N: One + Clone> LowerTriangularMat<N> {
/// Creates a lower triangular matrix filled with ones.
#[inline]
pub fn new_ones(dim: uint) -> LowerTriangularMat<N> {
LowerTriangularMat::from_elem(dim, One::one())
}
}
impl<N: Clone> LowerTriangularMat<N> {
/// Creates a lower triangular matrix filled with a given value.
#[inline]
pub fn from_elem(dim: uint, val: N) -> LowerTriangularMat<N> {
LowerTriangularMat {
dim: dim,
mij: vec::from_elem(dim * (dim + 1) / 2, val)
}
}
}
impl<N> LowerTriangularMat<N> {
/// Creates a lower triangular matrix filled by a function.
#[inline(always)]
pub fn from_fn(dim: uint, f: &fn(uint, uint) -> N) -> LowerTriangularMat<N> {
let mij = do vec::from_fn(dim * (dim + 1) / 2) |i| {
let l = (((1.0f64 + 8.0f64 * i as f64).sqrt() - 1.) / 2.0f64).floor() as uint;
let c = i - l * (l + 1) / 2;
f(l, c)
};
LowerTriangularMat {
dim: dim,
mij: mij
}
}
#[inline]
fn offset(&self, i: uint, j: uint) -> uint {
i * (i + 1) / 2 + j + 1
}
/// Transforms this matrix into an array. This consumes the matrix and is O(1).
#[inline]
pub fn to_array(self) -> ~[N] {
self.mij
}
}
impl<N: Zero + Clone> LowerTriangularMat<N> {
/// Changes the value of a component of the matrix.
/// Fails if the indices point outside of the lower-triangular part of the matrix.
///
/// # Arguments
/// * `row` - 0-based index of the line to be changed
/// * `col` - 0-based index of the column to be changed
#[inline]
pub fn set(&mut self, row: uint, col: uint, val: N) {
assert!(row < self.dim);
assert!(col < self.dim);
assert!(col <= row);
unsafe { self.set_fast(row, col, val) }
}
/// Just like `set` without bounds checking.
#[inline]
pub unsafe fn set_fast(&mut self, row: uint, col: uint, val: N) {
let offset = self.offset(row, col);
*self.mij.unsafe_mut_ref(offset) = val
}
/// Reads the value of a component of the matrix.
/// Fails if the indices point outside of the lower-triangular part of the matrix.
///
/// # Arguments
/// * `row` - 0-based index of the line to be read
/// * `col` - 0-based index of the column to be read
#[inline]
pub fn at(&self, row: uint, col: uint) -> N {
assert!(row < self.dim);
assert!(col < self.dim);
unsafe { self.at_fast(row, col) }
}
/// Just like `at` without bounds checking.
#[inline]
pub unsafe fn at_fast(&self, row: uint, col: uint) -> N {
if col > row {
Zero::zero()
}
vec::raw::get(self.mij, self.offset(row, col))
}
}

View File

@ -6,17 +6,12 @@ use std::cast;
use std::num::{One, Zero}; use std::num::{One, Zero};
use std::cmp::ApproxEq; use std::cmp::ApproxEq;
use std::vec::{VecIterator, VecMutIterator}; use std::vec::{VecIterator, VecMutIterator};
use vec::*; use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, Vec1MulRhs, Vec4MulRhs,
Vec5MulRhs, Vec6MulRhs};
// traits use traits::structure::{MatCast, Row, Col, Iterable, IterableMut, Dim, Indexable};
pub use traits::structure::{Mat, Dim, Indexable, Iterable, IterableMut, MatCast, Row, Col}; use traits::operations::{Absolute, Transpose, Inv, Outer};
pub use traits::operations::{Absolute, ScalarSub, ScalarAdd, Inv, RMul, Transpose, Mean, Cov}; use traits::geometry::{ToHomogeneous, FromHomogeneous};
pub use traits::geometry::{Rotation, RotationMatrix, Rotate, Transformation, Transform,
Translation, Translate, ToHomogeneous, FromHomogeneous,
RotationWithTranslation, AbsoluteRotate};
// structs
pub use dmat::DMat;
mod metal; mod metal;
mod mat_macros; mod mat_macros;
@ -118,7 +113,6 @@ indexable_impl!(Mat1, 1)
mat_mul_mat_impl!(Mat1, Mat1MulRhs, 1) mat_mul_mat_impl!(Mat1, Mat1MulRhs, 1)
mat_mul_vec_impl!(Mat1, Vec1, Mat1MulRhs, 1) mat_mul_vec_impl!(Mat1, Vec1, Mat1MulRhs, 1)
vec_mul_mat_impl!(Mat1, Vec1, Vec1MulRhs, 1) vec_mul_mat_impl!(Mat1, Vec1, Vec1MulRhs, 1)
transform_impl!(Mat1, Vec1)
// (specialized) inv_impl!(Mat1, 1) // (specialized) inv_impl!(Mat1, 1)
transpose_impl!(Mat1, 1) transpose_impl!(Mat1, 1)
approx_eq_impl!(Mat1) approx_eq_impl!(Mat1)
@ -214,7 +208,6 @@ at_fast_impl!(Mat2, 2)
// (specialized) mul_impl!(Mat2, 2) // (specialized) mul_impl!(Mat2, 2)
// (specialized) rmul_impl!(Mat2, Vec2, 2) // (specialized) rmul_impl!(Mat2, Vec2, 2)
// (specialized) lmul_impl!(Mat2, Vec2, 2) // (specialized) lmul_impl!(Mat2, Vec2, 2)
transform_impl!(Mat2, Vec2)
// (specialized) inv_impl!(Mat2, 2) // (specialized) inv_impl!(Mat2, 2)
transpose_impl!(Mat2, 2) transpose_impl!(Mat2, 2)
approx_eq_impl!(Mat2) approx_eq_impl!(Mat2)
@ -324,7 +317,6 @@ at_fast_impl!(Mat3, 3)
// (specialized) mul_impl!(Mat3, 3) // (specialized) mul_impl!(Mat3, 3)
// (specialized) rmul_impl!(Mat3, Vec3, 3) // (specialized) rmul_impl!(Mat3, Vec3, 3)
// (specialized) lmul_impl!(Mat3, Vec3, 3) // (specialized) lmul_impl!(Mat3, Vec3, 3)
transform_impl!(Mat3, Vec3)
// (specialized) inv_impl!(Mat3, 3) // (specialized) inv_impl!(Mat3, 3)
transpose_impl!(Mat3, 3) transpose_impl!(Mat3, 3)
approx_eq_impl!(Mat3) approx_eq_impl!(Mat3)
@ -486,7 +478,6 @@ at_fast_impl!(Mat4, 4)
mat_mul_mat_impl!(Mat4, Mat4MulRhs, 4) mat_mul_mat_impl!(Mat4, Mat4MulRhs, 4)
mat_mul_vec_impl!(Mat4, Vec4, Mat4MulRhs, 4) mat_mul_vec_impl!(Mat4, Vec4, Mat4MulRhs, 4)
vec_mul_mat_impl!(Mat4, Vec4, Vec4MulRhs, 4) vec_mul_mat_impl!(Mat4, Vec4, Vec4MulRhs, 4)
transform_impl!(Mat4, Vec4)
inv_impl!(Mat4, 4) inv_impl!(Mat4, 4)
transpose_impl!(Mat4, 4) transpose_impl!(Mat4, 4)
approx_eq_impl!(Mat4) approx_eq_impl!(Mat4)
@ -664,7 +655,6 @@ at_fast_impl!(Mat5, 5)
mat_mul_mat_impl!(Mat5, Mat5MulRhs, 5) mat_mul_mat_impl!(Mat5, Mat5MulRhs, 5)
mat_mul_vec_impl!(Mat5, Vec5, Mat5MulRhs, 5) mat_mul_vec_impl!(Mat5, Vec5, Mat5MulRhs, 5)
vec_mul_mat_impl!(Mat5, Vec5, Vec5MulRhs, 5) vec_mul_mat_impl!(Mat5, Vec5, Vec5MulRhs, 5)
transform_impl!(Mat5, Vec5)
inv_impl!(Mat5, 5) inv_impl!(Mat5, 5)
transpose_impl!(Mat5, 5) transpose_impl!(Mat5, 5)
approx_eq_impl!(Mat5) approx_eq_impl!(Mat5)
@ -894,7 +884,6 @@ at_fast_impl!(Mat6, 6)
mat_mul_mat_impl!(Mat6, Mat6MulRhs, 6) mat_mul_mat_impl!(Mat6, Mat6MulRhs, 6)
mat_mul_vec_impl!(Mat6, Vec6, Mat6MulRhs, 6) mat_mul_vec_impl!(Mat6, Vec6, Mat6MulRhs, 6)
vec_mul_mat_impl!(Mat6, Vec6, Vec6MulRhs, 6) vec_mul_mat_impl!(Mat6, Vec6, Vec6MulRhs, 6)
transform_impl!(Mat6, Vec6)
inv_impl!(Mat6, 6) inv_impl!(Mat6, 6)
transpose_impl!(Mat6, 6) transpose_impl!(Mat6, 6)
approx_eq_impl!(Mat6) approx_eq_impl!(Mat6)

View File

@ -200,7 +200,7 @@ macro_rules! row_impl(
($t: ident, $tv: ident, $dim: expr) => ( ($t: ident, $tv: ident, $dim: expr) => (
impl<N: Clone + Zero> Row<$tv<N>> for $t<N> { impl<N: Clone + Zero> Row<$tv<N>> for $t<N> {
#[inline] #[inline]
fn num_rows(&self) -> uint { fn nrows(&self) -> uint {
Dim::dim(None::<$t<N>>) Dim::dim(None::<$t<N>>)
} }
@ -229,7 +229,7 @@ macro_rules! col_impl(
($t: ident, $tv: ident, $dim: expr) => ( ($t: ident, $tv: ident, $dim: expr) => (
impl<N: Clone + Zero> Col<$tv<N>> for $t<N> { impl<N: Clone + Zero> Col<$tv<N>> for $t<N> {
#[inline] #[inline]
fn num_cols(&self) -> uint { fn ncols(&self) -> uint {
Dim::dim(None::<$t<N>>) Dim::dim(None::<$t<N>>)
} }
@ -326,35 +326,15 @@ macro_rules! mat_mul_vec_impl(
) )
) )
macro_rules! transform_impl(
($t: ident, $v: ident) => (
impl<N: Clone + Num + Eq>
Transform<$v<N>> for $t<N> {
#[inline]
fn transform(&self, v: &$v<N>) -> $v<N> {
self.rmul(v)
}
#[inline]
fn inv_transform(&self, v: &$v<N>) -> $v<N> {
match self.inverse() {
Some(t) => t.transform(v),
None => fail!("Cannot use inv_transform on a non-inversible matrix.")
}
}
}
)
)
macro_rules! inv_impl( macro_rules! inv_impl(
($t: ident, $dim: expr) => ( ($t: ident, $dim: expr) => (
impl<N: Clone + Eq + Num> impl<N: Clone + Eq + Num>
Inv for $t<N> { Inv for $t<N> {
#[inline] #[inline]
fn inverse(&self) -> Option<$t<N>> { fn inverted(&self) -> Option<$t<N>> {
let mut res : $t<N> = self.clone(); let mut res : $t<N> = self.clone();
if res.inplace_inverse() { if res.invert() {
Some(res) Some(res)
} }
else { else {
@ -362,7 +342,7 @@ macro_rules! inv_impl(
} }
} }
fn inplace_inverse(&mut self) -> bool { fn invert(&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();
@ -528,7 +508,7 @@ macro_rules! from_homogeneous_impl(
macro_rules! outer_impl( macro_rules! outer_impl(
($t: ident, $m: ident) => ( ($t: ident, $m: ident) => (
impl<N: Mul<N, N> + Zero + Clone> Outer<$t<N>, $m<N>> for $t<N> { impl<N: Mul<N, N> + Zero + Clone> Outer<$m<N>> for $t<N> {
#[inline] #[inline]
fn outer(&self, other: &$t<N>) -> $m<N> { fn outer(&self, other: &$t<N>) -> $m<N> {
let mut res: $m<N> = Zero::zero(); let mut res: $m<N> = Zero::zero();

25
src/structs/mod.rs Normal file
View File

@ -0,0 +1,25 @@
//! Data structures and implementations.
pub use self::dmat::DMat;
pub use self::dvec::DVec;
pub use self::vec::{Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6};
pub use self::mat::{Mat1, Mat2, Mat3, Mat4, Mat5, Mat6};
pub use self::rot::{Rot2, Rot3, Rot4};
pub use self::iso::{Iso2, Iso3, Iso4};
pub mod dmat;
pub mod dvec;
pub mod vec;
pub mod mat;
pub mod rot;
pub mod iso;
// specialization for some 1d, 2d and 3d operations
#[doc(hidden)]
mod spec {
mod identity;
mod mat;
mod vec0;
mod vec;
// mod complex;
}

328
src/structs/rot.rs Normal file
View File

@ -0,0 +1,328 @@
//! Rotations matrices.
#[allow(missing_doc)];
use std::num::{Zero, One};
use std::rand::{Rand, Rng};
use traits::geometry::{Rotate, Rotation, AbsoluteRotate, RotationMatrix, Transform, ToHomogeneous,
Norm, Cross};
use traits::structure::{Dim, Indexable, Row, Col};
use traits::operations::{Absolute, Inv, Transpose};
use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec2MulRhs, Vec3MulRhs, Vec4MulRhs};
use structs::mat::{Mat2, Mat3, Mat4, Mat5};
mod metal;
mod rot_macros;
/// Two dimensional rotation matrix.
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
pub struct Rot2<N> {
priv submat: Mat2<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();
Rot2 {
submat: Mat2::new(coa.clone(), -sia, sia.clone(), coa)
}
}
}
impl<N: Trigonometric + Num + Clone>
Rotation<Vec1<N>> for Rot2<N> {
#[inline]
fn rotation(&self) -> Vec1<N> {
Vec1::new((-self.submat.at((0, 1))).atan2(&self.submat.at((0, 0))))
}
#[inline]
fn inv_rotation(&self) -> Vec1<N> {
-self.rotation()
}
#[inline]
fn rotate_by(&mut self, rot: &Vec1<N>) {
*self = self.rotated(rot)
}
#[inline]
fn rotated(&self, rot: &Vec1<N>) -> Rot2<N> {
Rot2::from_angle(rot.x.clone()) * *self
}
#[inline]
fn set_rotation(&mut self, rot: Vec1<N>) {
*self = Rot2::from_angle(rot.x)
}
}
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())
}
}
impl<N: Signed> AbsoluteRotate<Vec2<N>> for Rot2<N> {
#[inline]
fn absolute_rotate(&self, v: &Vec2<N>) -> Vec2<N> {
// the matrix is skew-symetric, so we dont need to compute the absolute value of every
// component.
let m11 = self.submat.m11.abs();
let m12 = self.submat.m12.abs();
let m22 = self.submat.m22.abs();
Vec2::new(m11 * v.x + m12 * v.y, m12 * v.x + m22 * v.y)
}
}
/*
* 3d rotation
*/
/// Three dimensional rotation matrix.
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
pub struct Rot3<N> {
priv submat: Mat3<N>
}
impl<N: Clone + Trigonometric + Num + Algebraic> Rot3<N> {
/// Builds a 3 dimensional rotation matrix from an axis and an angle.
///
/// # 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> {
if axisangle.sqnorm().is_zero() {
One::one()
}
else {
let mut axis = axisangle;
let angle = axis.normalize();
let _1: N = One::one();
let ux = axis.x.clone();
let uy = axis.y.clone();
let uz = axis.z.clone();
let sqx = ux * ux;
let sqy = uy * uy;
let sqz = uz * uz;
let (sin, cos) = angle.sin_cos();
let one_m_cos = _1 - cos;
Rot3 {
submat: Mat3::new(
(sqx + (_1 - sqx) * cos),
(ux * uy * one_m_cos - uz * sin),
(ux * uz * one_m_cos + uy * sin),
(ux * uy * one_m_cos + uz * sin),
(sqy + (_1 - sqy) * cos),
(uy * uz * one_m_cos - ux * sin),
(ux * uz * one_m_cos - uy * sin),
(uy * uz * one_m_cos + ux * sin),
(sqz + (_1 - sqz) * cos))
}
}
}
}
impl<N: Clone + Num + Algebraic> Rot3<N> {
/// Reorient this matrix such that its local `x` axis points to a given point. Note that the
/// usually known `look_at` function does the same thing but with the `z` axis. See `look_at_z`
/// for that.
///
/// # Arguments
/// * at - The point to look at. It is also the direction the matrix `x` axis will be aligned
/// with
/// * 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 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)
}
/// Reorient this matrix such that its local `z` axis points to a given point.
///
/// # Arguments
/// * at - The point to look at. It is also the direction the matrix `y` axis will be aligned
/// with
/// * 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 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)
}
}
impl<N: Clone + Trigonometric + Num + Algebraic + NumCast>
Rotation<Vec3<N>> for Rot3<N> {
#[inline]
fn rotation(&self) -> Vec3<N> {
let angle = ((self.submat.m11 + self.submat.m22 + self.submat.m33 - One::one()) / NumCast::from(2.0)).acos();
if angle != angle {
// FIXME: handle that correctly
Zero::zero()
}
else if angle.is_zero() {
Zero::zero()
}
else {
let m32_m23 = self.submat.m32 - self.submat.m23;
let m13_m31 = self.submat.m13 - self.submat.m31;
let m21_m12 = self.submat.m21 - self.submat.m12;
let denom = (m32_m23 * m32_m23 + m13_m31 * m13_m31 + m21_m12 * m21_m12).sqrt();
if denom.is_zero() {
// XXX: handle that properly
// fail!("Internal error: singularity.")
Zero::zero()
}
else {
let a_d = angle / denom;
Vec3::new(m32_m23 * a_d, m13_m31 * a_d, m21_m12 * a_d)
}
}
}
#[inline]
fn inv_rotation(&self) -> Vec3<N> {
-self.rotation()
}
#[inline]
fn rotate_by(&mut self, rot: &Vec3<N>) {
*self = self.rotated(rot)
}
#[inline]
fn rotated(&self, axisangle: &Vec3<N>) -> Rot3<N> {
Rot3::from_axis_angle(axisangle.clone()) * *self
}
#[inline]
fn set_rotation(&mut self, axisangle: Vec3<N>) {
*self = Rot3::from_axis_angle(axisangle)
}
}
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())
}
}
impl<N: Signed> AbsoluteRotate<Vec3<N>> for Rot3<N> {
#[inline]
fn absolute_rotate(&self, v: &Vec3<N>) -> Vec3<N> {
Vec3::new(
self.submat.m11.abs() * v.x + self.submat.m12.abs() * v.y + self.submat.m13.abs() * v.z,
self.submat.m21.abs() * v.x + self.submat.m22.abs() * v.y + self.submat.m23.abs() * v.z,
self.submat.m31.abs() * v.x + self.submat.m32.abs() * v.y + self.submat.m33.abs() * v.z)
}
}
/// Four dimensional rotation matrix.
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
pub struct Rot4<N> {
priv submat: Mat4<N>
}
impl<N: Signed> AbsoluteRotate<Vec4<N>> for Rot4<N> {
#[inline]
fn absolute_rotate(&self, v: &Vec4<N>) -> Vec4<N> {
Vec4::new(
self.submat.m11.abs() * v.x + self.submat.m12.abs() * v.y +
self.submat.m13.abs() * v.z + self.submat.m14.abs() * v.w,
self.submat.m21.abs() * v.x + self.submat.m22.abs() * v.y +
self.submat.m23.abs() * v.z + self.submat.m24.abs() * v.w,
self.submat.m31.abs() * v.x + self.submat.m32.abs() * v.y +
self.submat.m33.abs() * v.z + self.submat.m34.abs() * v.w,
self.submat.m41.abs() * v.x + self.submat.m42.abs() * v.y +
self.submat.m43.abs() * v.z + self.submat.m44.abs() * v.w)
}
}
/*
* Common implementations.
*/
double_dispatch_binop_decl_trait!(Rot2, Rot2MulRhs)
mul_redispatch_impl!(Rot2, Rot2MulRhs)
submat_impl!(Rot2, Mat2)
rotate_impl!(Rot2, Vec2)
transform_impl!(Rot2, Vec2)
dim_impl!(Rot2, 2)
rot_mul_rot_impl!(Rot2, Rot2MulRhs)
rot_mul_vec_impl!(Rot2, Vec2, Rot2MulRhs)
vec_mul_rot_impl!(Rot2, Vec2, Vec2MulRhs)
one_impl!(Rot2)
rotation_matrix_impl!(Rot2, Vec2, Vec1)
col_impl!(Rot2, Vec2)
row_impl!(Rot2, Vec2)
absolute_impl!(Rot2, Mat2)
to_homogeneous_impl!(Rot2, Mat3)
inv_impl!(Rot2)
transpose_impl!(Rot2)
approx_eq_impl!(Rot2)
double_dispatch_binop_decl_trait!(Rot3, Rot3MulRhs)
mul_redispatch_impl!(Rot3, Rot3MulRhs)
submat_impl!(Rot3, Mat3)
rotate_impl!(Rot3, Vec3)
transform_impl!(Rot3, Vec3)
dim_impl!(Rot3, 3)
rot_mul_rot_impl!(Rot3, Rot3MulRhs)
rot_mul_vec_impl!(Rot3, Vec3, Rot3MulRhs)
vec_mul_rot_impl!(Rot3, Vec3, Vec3MulRhs)
one_impl!(Rot3)
rotation_matrix_impl!(Rot3, Vec3, Vec3)
col_impl!(Rot3, Vec3)
row_impl!(Rot3, Vec3)
absolute_impl!(Rot3, Mat3)
to_homogeneous_impl!(Rot3, Mat4)
inv_impl!(Rot3)
transpose_impl!(Rot3)
approx_eq_impl!(Rot3)
double_dispatch_binop_decl_trait!(Rot4, Rot4MulRhs)
mul_redispatch_impl!(Rot4, Rot4MulRhs)
submat_impl!(Rot4, Mat4)
rotate_impl!(Rot4, Vec4)
transform_impl!(Rot4, Vec4)
dim_impl!(Rot4, 4)
rot_mul_rot_impl!(Rot4, Rot4MulRhs)
rot_mul_vec_impl!(Rot4, Vec4, Rot4MulRhs)
vec_mul_rot_impl!(Rot4, Vec4, Vec4MulRhs)
one_impl!(Rot4)
// rotation_matrix_impl!(Rot4, Vec4, Vec4)
col_impl!(Rot4, Vec4)
row_impl!(Rot4, Vec4)
absolute_impl!(Rot4, Mat4)
to_homogeneous_impl!(Rot4, Mat5)
inv_impl!(Rot4)
transpose_impl!(Rot4)
approx_eq_impl!(Rot4)

231
src/structs/rot_macros.rs Normal file
View File

@ -0,0 +1,231 @@
#[macro_escape];
macro_rules! submat_impl(
($t: ident, $submat: ident) => (
impl<N> $t<N> {
#[inline]
pub fn submat<'r>(&'r self) -> &'r $submat<N> {
&'r self.submat
}
}
)
)
macro_rules! rotate_impl(
($t: ident, $tv: ident) => (
impl<N: Num + Clone> Rotate<$tv<N>> for $t<N> {
#[inline]
fn rotate(&self, v: &$tv<N>) -> $tv<N> {
self * *v
}
#[inline]
fn inv_rotate(&self, v: &$tv<N>) -> $tv<N> {
v * *self
}
}
)
)
macro_rules! transform_impl(
($t: ident, $tv: ident) => (
impl<N: Num + Clone> Transform<$tv<N>> for $t<N> {
#[inline]
fn transform(&self, v: &$tv<N>) -> $tv<N> {
self.rotate(v)
}
#[inline]
fn inv_transform(&self, v: &$tv<N>) -> $tv<N> {
self.inv_rotate(v)
}
}
)
)
macro_rules! dim_impl(
($t: ident, $dim: expr) => (
impl<N> Dim for $t<N> {
#[inline]
fn dim(_: Option<$t<N>>) -> uint {
$dim
}
}
)
)
macro_rules! rotation_matrix_impl(
($t: ident, $tlv: ident, $tav: ident) => (
impl<N: NumCast + Algebraic + Trigonometric + Num + Clone>
RotationMatrix<$tlv<N>, $tav<N>, $t<N>> for $t<N> {
#[inline]
fn to_rot_mat(&self) -> $t<N> {
self.clone()
}
}
)
)
macro_rules! one_impl(
($t: ident) => (
impl<N: One + Zero + Clone> One for $t<N> {
#[inline]
fn one() -> $t<N> {
$t { submat: One::one() }
}
}
)
)
macro_rules! rot_mul_rot_impl(
($t: ident, $mulrhs: ident) => (
impl<N: Num + Clone> $mulrhs<N, $t<N>> for $t<N> {
#[inline]
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
$t { submat: left.submat * right.submat }
}
}
)
)
macro_rules! rot_mul_vec_impl(
($t: ident, $tv: ident, $mulrhs: ident) => (
impl<N: Num + Clone> $mulrhs<N, $tv<N>> for $tv<N> {
#[inline]
fn binop(left: &$t<N>, right: &$tv<N>) -> $tv<N> {
left.submat * *right
}
}
)
)
macro_rules! vec_mul_rot_impl(
($t: ident, $tv: ident, $mulrhs: ident) => (
impl<N: Num + Clone> $mulrhs<N, $tv<N>> for $t<N> {
#[inline]
fn binop(left: &$tv<N>, right: &$t<N>) -> $tv<N> {
*left * right.submat
}
}
)
)
macro_rules! inv_impl(
($t: ident) => (
impl<N: Clone> Inv for $t<N> {
#[inline]
fn invert(&mut self) -> bool {
self.transpose();
// always succeed
true
}
#[inline]
fn inverted(&self) -> Option<$t<N>> {
// always succeed
Some(self.transposed())
}
}
)
)
macro_rules! transpose_impl(
($t: ident) => (
impl<N: Clone> Transpose for $t<N> {
#[inline]
fn transposed(&self) -> $t<N> {
$t { submat: self.submat.transposed() }
}
#[inline]
fn transpose(&mut self) {
self.submat.transpose()
}
}
)
)
macro_rules! row_impl(
($t: ident, $tv: ident) => (
impl<N: Clone + Zero> Row<$tv<N>> for $t<N> {
#[inline]
fn nrows(&self) -> uint {
self.submat.nrows()
}
#[inline]
fn row(&self, i: uint) -> $tv<N> {
self.submat.row(i)
}
#[inline]
fn set_row(&mut self, i: uint, row: $tv<N>) {
self.submat.set_row(i, row);
}
}
)
)
macro_rules! col_impl(
($t: ident, $tv: ident) => (
impl<N: Clone + Zero> Col<$tv<N>> for $t<N> {
#[inline]
fn ncols(&self) -> uint {
self.submat.ncols()
}
#[inline]
fn col(&self, i: uint) -> $tv<N> {
self.submat.col(i)
}
#[inline]
fn set_col(&mut self, i: uint, col: $tv<N>) {
self.submat.set_col(i, col);
}
}
)
)
macro_rules! to_homogeneous_impl(
($t: ident, $tm: ident) => (
impl<N: One + Zero + Clone> ToHomogeneous<$tm<N>> for $t<N> {
#[inline]
fn to_homogeneous(&self) -> $tm<N> {
self.submat.to_homogeneous()
}
}
)
)
macro_rules! approx_eq_impl(
($t: ident) => (
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
#[inline]
fn approx_epsilon() -> N {
// ApproxEq::<N>::approx_epsilon()
fail!("approx_epsilon is broken since rust revision 8693943676487c01fa09f5f3daf0df6a1f71e24d.")
}
#[inline]
fn approx_eq(&self, other: &$t<N>) -> bool {
self.submat.approx_eq(&other.submat)
}
#[inline]
fn approx_eq_eps(&self, other: &$t<N>, epsilon: &N) -> bool {
self.submat.approx_eq_eps(&other.submat, epsilon)
}
}
)
)
macro_rules! absolute_impl(
($t: ident, $tm: ident) => (
impl<N: Signed> Absolute<$tm<N>> for $t<N> {
#[inline]
fn absolute(&self) -> $tm<N> {
self.submat.absolute()
}
}
)
)

110
src/structs/spec/complex.rs Normal file
View File

@ -0,0 +1,110 @@
/// Implement nalgebra traits for complex numbers from `extra::complex::Cmplex`.
use std::num::Zero;
use extra::complex::Cmplx;
use traits::operations::{Absolute, Inv};
use traits::structure::{Dim};
impl<N: Clone + Num> Absolute<Cmplx<N>> for Cmplx<N> {
#[inline]
fn absolute(&self) -> Cmplx<N> {
Cmplx::new(self.re.clone(), self.im.clone())
}
}
impl<N: Clone + Num + NumCast + Zero> Inv for Cmplx<N> {
#[inline]
fn inverse(&self) -> Option<Cmplx<N>> {
if self.is_zero() {
None
}
else {
let _1: N = NumCast::from(1.0);
let divisor = _1 / (self.re * self.re - self.im * self.im);
Some(Cmplx::new(self.re * divisor, -self.im * divisor))
}
}
#[inline]
fn inplace_inverse(&mut self) -> bool {
if self.is_zero() {
false
}
else {
let _1: N = NumCast::from(1.0);
let divisor = _1 / (self.re * self.re - self.im * self.im);
self.re = self.re * divisor;
self.im = -self.im * divisor;
true
}
}
}
impl<N> Dim for Cmplx<N> {
#[inline]
fn dim(unsused_self: Option<Cmplx<N>>) -> uint {
2
}
}
impl<N> Rotation<Vec2<N>> for Cmplx<N> {
#[inline]
fn rotation(&self) -> Vec2<N> {
}
#[inline]
fn inv_rotation(&self) -> Vec2<N> {
-self.rotation();
}
#[inline]
fn rotate_by(&mut self, rotation: &Vec2<N>) {
}
#[inline]
fn rotated(&self, rotation: &Vec2<N>) -> Cmplx<N> {
}
#[inline]
fn set_rotation(&mut self, rotation: Vec2<N>) {
}
}
impl<N> Rotate<Vec2<N>> for Cmplx<N> {
#[inline]
fn rotate(&self, rotation: &V) -> V {
}
#[inline]
fn inv_rotate(&self, rotation: &V) -> V {
}
}
impl<N> RotationMatrix<Vec2<N>, Vec2<N>, Rotmat<Mat2<N>>> for Cmplx<N> {
#[inline]
fn to_rot_mat(&self) -> Rotmat<Mat2<N>> {
}
}
impl<N> Norm<N> for Cmplx<N> {
#[inline]
fn sqnorm(&self) -> N {
}
#[inline]
fn normalized(&self) -> Self {
}
#[inline]
fn normalize(&mut self) -> N {
}
}
impl<N> AbsoluteRotate<V> {
#[inline]
fn absolute_rotate(&elf, v: &V) -> V {
}
}

View File

@ -1,5 +1,5 @@
use std::num::{One, Zero}; use std::num::{One, Zero};
use mat; use structs::mat;
use traits::operations::{Inv, Transpose}; use traits::operations::{Inv, Transpose};
use traits::geometry::{Translation, Translate, Rotation, Rotate, Transformation, Transform}; use traits::geometry::{Translation, Translate, Rotation, Rotate, Transformation, Transform};
@ -11,11 +11,11 @@ impl One for mat::Identity {
} }
impl Inv for mat::Identity { impl Inv for mat::Identity {
fn inverse(&self) -> Option<mat::Identity> { fn inverted(&self) -> Option<mat::Identity> {
Some(mat::Identity::new()) Some(mat::Identity::new())
} }
fn inplace_inverse(&mut self) -> bool { fn invert(&mut self) -> bool {
true true
} }
} }

View File

@ -1,16 +1,18 @@
use std::num::{Zero, One}; use std::num::{Zero, One};
use vec::{Vec2, Vec3, Vec2MulRhs, Vec3MulRhs}; use structs::vec::{Vec2, Vec3, Vec2MulRhs, Vec3MulRhs};
use mat::{Mat1, Mat2, Mat3, Inv, Row, Col, Mat3MulRhs, Mat2MulRhs}; use structs::mat::{Mat1, Mat2, Mat3, Mat3MulRhs, Mat2MulRhs};
use mat; use structs::mat;
use traits::operations::{Inv};
use traits::structure::{Row, Col};
// some specializations: // some specializations:
impl<N: Num + Clone> impl<N: Num + Clone>
Inv for Mat1<N> { Inv for Mat1<N> {
#[inline] #[inline]
fn inverse(&self) -> Option<Mat1<N>> { fn inverted(&self) -> Option<Mat1<N>> {
let mut res : Mat1<N> = self.clone(); let mut res : Mat1<N> = self.clone();
if res.inplace_inverse() { if res.invert() {
Some(res) Some(res)
} }
else { else {
@ -19,7 +21,7 @@ Inv for Mat1<N> {
} }
#[inline] #[inline]
fn inplace_inverse(&mut self) -> bool { fn invert(&mut self) -> bool {
if self.m11.is_zero() { if self.m11.is_zero() {
false false
} }
@ -34,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 inverse(&self) -> Option<Mat2<N>> { fn inverted(&self) -> Option<Mat2<N>> {
let mut res : Mat2<N> = self.clone(); let mut res : Mat2<N> = self.clone();
if res.inplace_inverse() { if res.invert() {
Some(res) Some(res)
} }
else { else {
@ -46,7 +48,7 @@ Inv for Mat2<N> {
} }
#[inline] #[inline]
fn inplace_inverse(&mut self) -> bool { fn invert(&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() {
@ -65,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 inverse(&self) -> Option<Mat3<N>> { fn inverted(&self) -> Option<Mat3<N>> {
let mut res = self.clone(); let mut res = self.clone();
if res.inplace_inverse() { if res.invert() {
Some(res) Some(res)
} }
else { else {
@ -77,7 +79,7 @@ Inv for Mat3<N> {
} }
#[inline] #[inline]
fn inplace_inverse(&mut self) -> bool { fn invert(&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;
@ -111,7 +113,7 @@ Inv for Mat3<N> {
impl<N: Clone> Row<Vec3<N>> for Mat3<N> { impl<N: Clone> Row<Vec3<N>> for Mat3<N> {
#[inline] #[inline]
fn num_rows(&self) -> uint { fn nrows(&self) -> uint {
3 3
} }
@ -151,7 +153,7 @@ impl<N: Clone> Row<Vec3<N>> for Mat3<N> {
impl<N: Clone> Col<Vec3<N>> for Mat3<N> { impl<N: Clone> Col<Vec3<N>> for Mat3<N> {
#[inline] #[inline]
fn num_cols(&self) -> uint { fn ncols(&self) -> uint {
3 3
} }

View File

@ -1,6 +1,8 @@
use std::num::{Zero, One}; use std::num::{Zero, One};
use vec::{Vec1, Vec2, Vec3, Vec4, Norm, VecCast, UniformSphereSample, Cross, CrossMatrix, Basis}; use traits::structure::{VecCast, Row, Basis};
use mat::{Mat3, Row}; use traits::geometry::{Norm, Cross, CrossMatrix, UniformSphereSample};
use structs::vec::{Vec1, Vec2, Vec3, Vec4};
use structs::mat::Mat3;
impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec1<N>> for Vec2<N> { impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec1<N>> for Vec2<N> {
#[inline] #[inline]
@ -39,10 +41,10 @@ impl<N: Neg<N> + Zero + Clone> CrossMatrix<Mat3<N>> for Vec3<N> {
} }
} }
// FIXME: iplement this for all other vectors // FIXME: implement this for all other vectors
impl<N: Clone> Row<Vec1<N>> for Vec2<N> { impl<N: Clone> Row<Vec1<N>> for Vec2<N> {
#[inline] #[inline]
fn num_rows(&self) -> uint { fn nrows(&self) -> uint {
2 2
} }

View File

@ -5,7 +5,7 @@ use std::iter::{Iterator, FromIterator};
use std::cmp::ApproxEq; use std::cmp::ApproxEq;
use traits::structure::{Iterable, IterableMut, Indexable, Basis, Dim}; use traits::structure::{Iterable, IterableMut, Indexable, Basis, Dim};
use traits::geometry::{Translation, Dot, Norm}; use traits::geometry::{Translation, Dot, Norm};
use vec; use structs::vec;
impl<N> vec::Vec0<N> { impl<N> vec::Vec0<N> {
/// Creates a new vector. /// Creates a new vector.

View File

@ -9,16 +9,9 @@ use std::vec::{VecIterator, VecMutIterator};
use std::iter::{Iterator, FromIterator}; use std::iter::{Iterator, FromIterator};
use std::cmp::ApproxEq; use std::cmp::ApproxEq;
use traits::geometry::{Transform, Rotate}; use traits::geometry::{Transform, Rotate, FromHomogeneous, ToHomogeneous, Dot, Norm,
Translation, Translate};
pub use traits::geometry::{FromHomogeneous, ToHomogeneous, Dot, Norm, Cross, CrossMatrix, use traits::structure::{VecCast, Basis, Dim, Indexable, Iterable, IterableMut};
Translation, Translate, UniformSphereSample};
pub use traits::structure::{VecCast, Vec, VecExt, AlgebraicVec, AlgebraicVecExt, Basis, Dim,
Indexable, Iterable, IterableMut};
pub use traits::operations::{Outer, ScalarAdd, ScalarSub};
// structs
pub use dvec::DVec;
mod metal; mod metal;
mod vec_macros; mod vec_macros;

View File

@ -1,16 +1,14 @@
use std::num::{Real, One, abs}; use std::num::{Real, One, abs};
use std::rand::random; use std::rand::random;
use std::cmp::ApproxEq; use std::cmp::ApproxEq;
use vec::*; use na::*;
use mat::*;
use adaptors::rotmat::Rotmat;
macro_rules! test_inv_mat_impl( macro_rules! test_inv_mat_impl(
($t: ty) => ( ($t: ty) => (
do 10000.times { do 10000.times {
let randmat : $t = random(); let randmat : $t = random();
assert!((randmat.inverse().unwrap() * randmat).approx_eq(&One::one())); assert!((randmat.inverted().unwrap() * randmat).approx_eq(&One::one()));
} }
); );
) )
@ -88,7 +86,7 @@ fn test_inv_mat6() {
#[test] #[test]
fn test_rotation2() { fn test_rotation2() {
do 10000.times { do 10000.times {
let randmat: Rotmat<Mat2<f64>> = One::one(); let randmat: Rot2<f64> = One::one();
let ang = &Vec1::new(abs::<f64>(random()) % Real::pi()); let ang = &Vec1::new(abs::<f64>(random()) % Real::pi());
assert!(randmat.rotated(ang).rotation().approx_eq(ang)); assert!(randmat.rotated(ang).rotation().approx_eq(ang));
@ -105,7 +103,7 @@ fn test_index_mat2() {
#[test] #[test]
fn test_inv_rotation3() { fn test_inv_rotation3() {
do 10000.times { do 10000.times {
let randmat: Rotmat<Mat3<f64>> = One::one(); let randmat: Rot3<f64> = One::one();
let dir: Vec3<f64> = random(); let dir: Vec3<f64> = random();
let ang = &(dir.normalized() * (abs::<f64>(random()) % Real::pi())); let ang = &(dir.normalized() * (abs::<f64>(random()) % Real::pi()));
let rot = randmat.rotated(ang); let rot = randmat.rotated(ang);

View File

@ -1,8 +1,7 @@
use std::num::{Zero, One}; use std::num::{Zero, One};
use std::rand::{random}; use std::rand::{random};
use std::cmp::ApproxEq; use std::cmp::ApproxEq;
use vec::*; use na::*;
use mat::*;
macro_rules! test_iterator_impl( macro_rules! test_iterator_impl(
($t: ty, $n: ty) => ( ($t: ty, $n: ty) => (

View File

@ -61,141 +61,6 @@ pub trait Rotate<V> {
fn inv_rotate(&self, v: &V) -> V; fn inv_rotate(&self, v: &V) -> V;
} }
/// Trait of object which represent a transformation, and to which new transformations can
/// be appended.
///
/// A transformation is assumed to be an isometry without reflexion.
pub trait Transformation<M> {
/// Gets the transformation of `self`.
fn transformation(&self) -> 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 `self`.
fn transformed(&self, &M) -> Self;
/// Sets the transformation of `self`.
fn set_transformation(&mut self, M);
}
/// Trait of objects able to transform other objects.
///
/// This is typically implemented by matrices which transform vectors.
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;
}
/// Trait of transformation having a rotation extractable as a rotation matrix. This can typically
/// be implemented by quaternions to convert them to a rotation matrix.
pub trait RotationMatrix<LV, AV, R: Mat<LV, LV> + Rotation<AV>> : Rotation<AV> {
/// Gets the rotation matrix represented by `self`.
fn to_rot_mat(&self) -> R;
}
/// Traits of objects having a dot product.
pub trait Dot<N> {
/// Computes the dot (inner) product of two vectors.
#[inline]
fn dot(&self, &Self) -> N;
/**
* Short-cut to compute the projection of a point on a vector, but without
* computing intermediate vectors.
* The following equation must be verified:
*
* ~~~{.rust}
* a.sub_dot(b, c) == (a - b).dot(c)
* ~~~
*
*/
#[inline]
fn sub_dot(&self, b: &Self, c: &Self) -> N;
}
/// Traits of objects having an euclidian norm.
pub trait Norm<N: Algebraic> {
/// Computes the norm of `self`.
#[inline]
fn norm(&self) -> N {
self.sqnorm().sqrt()
}
/// Computes the squared norm of `self`.
///
/// This is usually faster than computing the norm itself.
#[inline]
fn sqnorm(&self) -> N;
/// Gets the normalized version of `self`.
#[inline]
fn normalized(&self) -> Self;
/// In-place version of `normalized`.
#[inline]
fn normalize(&mut self) -> N;
}
/**
* Trait of elements having a cross product.
*/
pub trait Cross<V> {
/// Computes the cross product between two elements (usually vectors).
fn cross(&self, other: &Self) -> V;
}
/// Traits of objects which can be put in homogeneous coordinates form.
pub trait ToHomogeneous<U> {
/// Gets the homogeneous coordinates form of this object.
fn to_homogeneous(&self) -> U;
}
/// Traits of objects which can be build from an homogeneous coordinate form.
pub trait FromHomogeneous<U> {
/// Builds an object from its homogeneous coordinate form.
///
/// Note that this this is not required that `from` is the inverse of `to_homogeneous`.
/// Typically, `from` will remove some informations unrecoverable by `to_homogeneous`.
fn from(&U) -> Self;
}
/**
* Trait of elements having a cross product operation which can be expressed as a matrix.
*/
pub trait CrossMatrix<M> {
/// The matrix associated to any cross product with this vector. I.e. `v.cross(anything)` =
/// `v.cross_matrix().rmul(anything)`.
fn cross_matrix(&self) -> M;
}
/// Composition of a rotation and an absolute value.
///
/// The operation is accessible using the `RotationMatrix`, `Absolute`, and `RMul` traits, but
/// doing so is not easy in generic code as it can be a cause of type over-parametrization.
pub trait AbsoluteRotate<V> {
/// This is the same as:
///
/// ~~~{.rust}
/// self.rotation_matrix().absolute().rmul(v)
/// ~~~
fn absolute_rotate(&self, v: &V) -> V;
}
/// Trait of vectors able to sample a unit sphere.
///
/// The number of sample must be sufficient to approximate a sphere using a support mapping
/// function.
pub trait UniformSphereSample {
/// Iterate through the samples.
fn sample(&fn(Self));
}
/// Various composition of rotation and translation. /// Various composition of rotation and translation.
/// ///
/// Utilities to make rotations with regard to a point different than the origin. All those /// Utilities to make rotations with regard to a point different than the origin. All those
@ -261,3 +126,138 @@ pub trait RotationWithTranslation<LV: Neg<LV>, AV>: Rotation<AV> + Translation<L
impl<LV: Neg<LV>, AV, M: Rotation<AV> + Translation<LV>> RotationWithTranslation<LV, AV> for M { impl<LV: Neg<LV>, AV, M: Rotation<AV> + Translation<LV>> RotationWithTranslation<LV, AV> for M {
} }
/// Trait of transformation having a rotation extractable as a rotation matrix. This can typically
/// be implemented by quaternions to convert them to a rotation matrix.
pub trait RotationMatrix<LV, AV, M: Mat<LV, LV> + Rotation<AV>> : Rotation<AV> {
/// Gets the rotation matrix represented by `self`.
fn to_rot_mat(&self) -> M;
}
/// Composition of a rotation and an absolute value.
///
/// The operation is accessible using the `RotationMatrix`, `Absolute`, and `RMul` traits, but
/// doing so is not easy in generic code as it can be a cause of type over-parametrization.
pub trait AbsoluteRotate<V> {
/// This is the same as:
///
/// ~~~{.rust}
/// self.rotation_matrix().absolute().rmul(v)
/// ~~~
fn absolute_rotate(&self, v: &V) -> V;
}
/// Trait of object which represent a transformation, and to which new transformations can
/// be appended.
///
/// A transformation is assumed to be an isometry without reflexion.
pub trait Transformation<M> {
/// Gets the transformation of `self`.
fn transformation(&self) -> 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 `self`.
fn transformed(&self, &M) -> Self;
/// Sets the transformation of `self`.
fn set_transformation(&mut self, M);
}
/// Trait of objects able to transform other objects.
///
/// This is typically implemented by matrices which transform vectors.
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;
}
/// Traits of objects having a dot product.
pub trait Dot<N> {
/// Computes the dot (inner) product of two vectors.
#[inline]
fn dot(&self, &Self) -> N;
/**
* Short-cut to compute the projection of a point on a vector, but without
* computing intermediate vectors.
* The following equation must be verified:
*
* ~~~{.rust}
* a.sub_dot(b, c) == (a - b).dot(c)
* ~~~
*
*/
#[inline]
fn sub_dot(&self, b: &Self, c: &Self) -> N;
}
/// Traits of objects having an euclidian norm.
pub trait Norm<N: Algebraic> {
/// Computes the norm of `self`.
#[inline]
fn norm(&self) -> N {
self.sqnorm().sqrt()
}
/// Computes the squared norm of `self`.
///
/// This is usually faster than computing the norm itself.
#[inline]
fn sqnorm(&self) -> N;
/// Gets the normalized version of `self`.
#[inline]
fn normalized(&self) -> Self;
/// In-place version of `normalized`.
#[inline]
fn normalize(&mut self) -> N;
}
/**
* Trait of elements having a cross product.
*/
pub trait Cross<V> {
/// Computes the cross product between two elements (usually vectors).
fn cross(&self, other: &Self) -> V;
}
/**
* Trait of elements having a cross product operation which can be expressed as a matrix.
*/
pub trait CrossMatrix<M> {
/// The matrix associated to any cross product with this vector. I.e. `v.cross(anything)` =
/// `v.cross_matrix().rmul(anything)`.
fn cross_matrix(&self) -> M;
}
/// Traits of objects which can be put in homogeneous coordinates form.
pub trait ToHomogeneous<U> {
/// Gets the homogeneous coordinates form of this object.
fn to_homogeneous(&self) -> U;
}
/// Traits of objects which can be build from an homogeneous coordinate form.
pub trait FromHomogeneous<U> {
/// Builds an object from its homogeneous coordinate form.
///
/// Note that this this is not required that `from` is the inverse of `to_homogeneous`.
/// Typically, `from` will remove some informations unrecoverable by `to_homogeneous`.
fn from(&U) -> Self;
}
/// Trait of vectors able to sample a unit sphere.
///
/// The number of sample must be sufficient to approximate a sphere using a support mapping
/// function.
pub trait UniformSphereSample {
/// Iterate through the samples.
fn sample(&fn(Self));
}

15
src/traits/mod.rs Normal file
View File

@ -0,0 +1,15 @@
//! Mathematical traits.
pub use self::geometry::{AbsoluteRotate, Cross, CrossMatrix, Dot, FromHomogeneous, Norm, Rotate,
Rotation, RotationMatrix, RotationWithTranslation, ToHomogeneous,
Transform, Transformation, Translate, Translation, UniformSphereSample};
pub use self::structure::{AlgebraicVec, AlgebraicVecExt, Basis, Col, Dim, Indexable, Iterable,
IterableMut, Mat, MatCast, Row, Vec, VecCast, VecExt};
pub use self::operations::{Absolute, Cov, Inv, LMul, Mean, Outer, RMul, ScalarAdd, ScalarSub,
Transpose};
pub mod geometry;
pub mod structure;
pub mod operations;

View File

@ -12,9 +12,9 @@ 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 inverse(&self) -> Option<Self>; fn inverted(&self) -> Option<Self>;
/// In-place version of `inverse`. /// In-place version of `inverse`.
fn inplace_inverse(&mut self) -> bool; fn invert(&mut self) -> bool;
} }
/// Trait of objects which can be transposed. /// Trait of objects which can be transposed.
@ -27,9 +27,9 @@ pub trait Transpose {
} }
/// Traits of objects having an outer product. /// Traits of objects having an outer product.
pub trait Outer<V, M> { pub trait Outer<M> {
/// Computes the outer product: `self * other` /// Computes the outer product: `self * other`
fn outer(&self, other: &V) -> M; fn outer(&self, other: &Self) -> M;
} }
/// Trait for computing the covariance of a set of data. /// Trait for computing the covariance of a set of data.

View File

@ -70,38 +70,12 @@ pub trait Basis {
/// Iterates through a basis of the subspace orthogonal to `self`. /// Iterates through a basis of the subspace orthogonal to `self`.
fn orthonormal_subspace_basis(&self, &fn(Self) -> bool); fn orthonormal_subspace_basis(&self, &fn(Self) -> bool);
/// Creates the canonical basis of the space in which this object lives.
fn canonical_basis_list() -> ~[Self] {
let mut res = ~[];
do Basis::canonical_basis |elem| {
res.push(elem);
true
}
res
}
/// Creates a basis of the subspace orthogonal to `self`.
fn orthonormal_subspace_basis_list(&self) -> ~[Self] {
let mut res = ~[];
do self.orthonormal_subspace_basis |elem| {
res.push(elem);
true
}
res
}
} }
/// Trait to access rows of a matrix or a vector. /// Trait to access rows of a matrix or a vector.
pub trait Row<R> { pub trait Row<R> {
/// The number of column of `self`. /// The number of column of `self`.
fn num_rows(&self) -> uint; fn nrows(&self) -> uint;
/// Reads the `i`-th row of `self`. /// Reads the `i`-th row of `self`.
fn row(&self, i: uint) -> R; fn row(&self, i: uint) -> R;
/// Writes the `i`-th row of `self`. /// Writes the `i`-th row of `self`.
@ -114,7 +88,7 @@ pub trait Row<R> {
/// Trait to access columns of a matrix or vector. /// Trait to access columns of a matrix or vector.
pub trait Col<C> { pub trait Col<C> {
/// The number of column of this matrix or vector. /// The number of column of this matrix or vector.
fn num_cols(&self) -> uint; fn ncols(&self) -> uint;
/// Reads the `i`-th column of `self`. /// Reads the `i`-th column of `self`.
fn col(&self, i: uint) -> C; fn col(&self, i: uint) -> C;

View File

@ -1,162 +0,0 @@
//! Useful type aliases.
use vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6};
use mat::{Mat1, Mat2, Mat3, Mat4, Mat5, Mat6};
use adaptors::rotmat::Rotmat;
use adaptors::transform::Transform;
// 1D
/// 1-dimensional `f64`-valued vector.
pub type Vec1f64 = Vec1<f64>;
/// 1-dimensional `f32`-valued vector.
pub type Vec1f32 = Vec1<f32>;
/// 1-dimensional `f64`-valued matrix.
pub type Mat1f64 = Mat1<f64>;
/// 1-dimensional `f32`-valued matrix.
pub type Mat1f32 = Mat1<f32>;
// /// 1-dimensional `f64`-valued rotation matrix.
// pub type Rot1f64 = Rotmat<Mat1<f64>>;
// /// 1-dimensional `f32`-valued rotation matrix.
// pub type Rot1f32 = Rotmat<Mat1<f32>>;
//
// /// 1-dimensional `f64`-valued isometric transform.
// pub type Iso1f64 = Transform<Rot1f64, Vec1f64>;
// /// 1-dimensional `f32`-valued isometric transform.
// pub type Iso1f32 = Transform<Rot1f32, Vec1f32>;
/// 1-dimensional `f64`-valued general transform.
pub type Aff1f64 = Transform<Vec1f64, Mat1f64>;
/// 1-dimensional `f32`-valued general transform.
pub type Aff1f32 = Transform<Vec1f32, Mat1f32>;
// 2D
/// 2-dimensional `f64`-valued vector.
pub type Vec2f64 = Vec2<f64>;
/// 2-dimensional `f32`-valued vector.
pub type Vec2f32 = Vec2<f32>;
/// 2-dimensional `f64`-valued matrix.
pub type Mat2f64 = Mat2<f64>;
/// 2-dimensional `f32`-valued matrix.
pub type Mat2f32 = Mat2<f32>;
/// 2-dimensional `f64`-valued rotation matrix.
pub type Rot2f64 = Rotmat<Mat2<f64>>;
/// 2-dimensional `f32`-valued rotation matrix.
pub type Rot2f32 = Rotmat<Mat2<f32>>;
/// 2-dimensional `f64`-valued isometric transform.
pub type Iso2f64 = Transform<Vec2f64, Rot2f64>;
/// 2-dimensional `f32`-valued isometric transform.
pub type Iso2f32 = Transform<Vec2f32, Rot2f32>;
/// 2-dimensional `f64`-valued general transform.
pub type Aff2f64 = Transform<Vec2f64, Mat2f64>;
/// 2-dimensional `f32`-valued general transform.
pub type Aff2f32 = Transform<Vec2f32, Mat2f32>;
// 3D
/// 3-dimensional `f64`-valued vector.
pub type Vec3f64 = Vec3<f64>;
/// 3-dimensional `f32`-valued vector.
pub type Vec3f32 = Vec3<f32>;
/// 3-dimensional `f64`-valued matrix.
pub type Mat3f64 = Mat3<f64>;
/// 3-dimensional `f32`-valued matrix.
pub type Mat3f32 = Mat3<f32>;
/// 3-dimensional `f64`-valued rotation matrix.
pub type Rot3f64 = Rotmat<Mat3<f64>>;
/// 3-dimensional `f32`-valued rotation matrix.
pub type Rot3f32 = Rotmat<Mat3<f32>>;
/// 3-dimensional `f64`-valued isometric transform.
pub type Iso3f64 = Transform<Vec3f64, Rot3f64>;
/// 3-dimensional `f32`-valued isometric transform.
pub type Iso3f32 = Transform<Vec3f32, Rot3f32>;
/// 3-dimensional `f64`-valued general transform.
pub type Aff3f64 = Transform<Vec3f64, Mat3f64>;
/// 3-dimensional `f32`-valued general transform.
pub type Aff3f32 = Transform<Vec3f32, Mat3f32>;
// 4D
/// 4-dimensional `f64`-valued vector.
pub type Vec4f64 = Vec4<f64>;
/// 4-dimensional `f32`-valued vector.
pub type Vec4f32 = Vec4<f32>;
/// 4-dimensional `f64`-valued matrix.
pub type Mat4f64 = Mat4<f64>;
/// 4-dimensional `f32`-valued matrix.
pub type Mat4f32 = Mat4<f32>;
/// 4-dimensional `f64`-valued rotation matrix.
pub type Rot4f64 = Rotmat<Mat4<f64>>;
/// 4-dimensional `f32`-valued rotation matrix.
pub type Rot4f32 = Rotmat<Mat4<f32>>;
/// 4-dimensional `f64`-valued isometric transform.
pub type Iso4f64 = Transform<Vec4f64, Mat4f64>;
/// 4-dimensional `f32`-valued isometric transform.
pub type Iso4f32 = Transform<Vec4f32, Mat4f32>;
/// 4-dimensional `f64`-valued general transform.
pub type Aff4f64 = Transform<Vec4f64, Mat4f64>;
/// 4-dimensional `f32`-valued general transform.
pub type Aff4f32 = Transform<Vec4f32, Mat4f32>;
// 5D
/// 5-dimensional `f64`-valued vector.
pub type Vec5f64 = Vec5<f64>;
/// 5-dimensional `f32`-valued vector.
pub type Vec5f32 = Vec5<f32>;
/// 5-dimensional `f64`-valued matrix.
pub type Mat5f64 = Mat5<f64>;
/// 5-dimensional `f32`-valued matrix.
pub type Mat5f32 = Mat5<f32>;
// /// 5-dimensional `f64`-valued rotation matrix.
// pub type Rot5f64 = Rotmat<Mat5<f64>>;
// /// 5-dimensional `f32`-valued rotation matrix.
// pub type Rot5f32 = Rotmat<Mat5<f32>>;
//
// /// 5-dimensional `f64`-valued isometric transform.
// pub type Iso5f64 = Transform<Rot5f64, Vec5f64>;
// /// 5-dimensional `f32`-valued isometric transform.
// pub type Iso5f32 = Transform<Rot5f32, Vec5f32>;
/// 5-dimensional `f64`-valued general transform.
pub type Aff5f64 = Transform<Vec5f64, Mat5f64>;
/// 5-dimensional `f32`-valued general transform.
pub type Aff5f32 = Transform<Vec5f32, Mat5f32>;
// 6D
/// 6-dimensional `f64`-valued vector.
pub type Vec6f64 = Vec6<f64>;
/// 6-dimensional `f32`-valued vector.
pub type Vec6f32 = Vec6<f32>;
/// 6-dimensional `f64`-valued matrix.
pub type Mat6f64 = Mat6<f64>;
/// 6-dimensional `f32`-valued matrix.
pub type Mat6f32 = Mat6<f32>;
// /// 6-dimensional `f64`-valued rotation matrix.
// pub type Rot6f64 = Rotmat<Mat6<f64>>;
// /// 6-dimensional `f32`-valued rotation matrix.
// pub type Rot6f32 = Rotmat<Mat6<f32>>;
//
// /// 6-dimensional `f64`-valued isometric transform.
// pub type Iso6f64 = Transform<Rot6f64, Vec6f64>;
// /// 6-dimensional `f32`-valued isometric transform.
// pub type Iso6f32 = Transform<Rot6f32, Vec6f32>;
/// 6-dimensional `f64`-valued general transform.
pub type Aff6f64 = Transform<Vec6f64, Mat6f64>;
/// 6-dimensional `f32`-valued general transform.
pub type Aff6f32 = Transform<Vec6f32, Mat6f32>;