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
programming language.
**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…),
@ -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`.
* 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`.
* Geometry-specific matrix wrapper to ensure at compile-time some properties: `Rotmat`, `Transform`.
* Most well-known geometric functions.
* 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:
* 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
use nalgebra::vec::*;
use nalgebra::mat::*;
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.
@ -37,21 +70,8 @@ If you encounter problems, make sure you have the last version before creating a
cd nalgebra
make
There is also a light, but existing, documentation for most functionalities. Use `make doc` to
generate it on the `doc` folder.
You can build the documentation on the `doc` folder using:
## nalgebra in use
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.
## 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_).
```.rust
make doc
```

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 extra::test::BenchHarness;
use mat::*;
use vec::*;
use na::*;
macro_rules! bench_mul_mat(
($bh: expr, $t: ty) => {

View File

@ -1,6 +1,6 @@
use std::rand::random;
use extra::test::BenchHarness;
use vec::*;
use na::*;
macro_rules! bench_dot_vec(
($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"
@ -16,34 +102,10 @@
extern mod std;
extern mod extra;
pub mod dmat;
pub mod dvec;
pub mod vec;
pub mod mat;
pub mod types;
pub mod na;
pub mod structs;
pub mod traits;
/// 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 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.
#[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;
@ -8,7 +8,7 @@ use std::num::{One, Zero};
use std::vec;
use std::cmp::ApproxEq;
use std::util;
use dvec::{DVec, DVecMulRhs};
use structs::dvec::{DVec, DVecMulRhs};
use traits::operations::{Inv, Transpose, Mean, Cov};
#[doc(hidden)]
@ -277,10 +277,10 @@ DVecMulRhs<N, DVec<N>> for DMat<N> {
impl<N: Clone + Num>
Inv for DMat<N> {
#[inline]
fn inverse(&self) -> Option<DMat<N>> {
fn inverted(&self) -> Option<DMat<N>> {
let mut res : DMat<N> = self.clone();
if res.inplace_inverse() {
if res.invert() {
Some(res)
}
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);
let dim = self.nrows;

View File

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

View File

@ -200,7 +200,7 @@ macro_rules! row_impl(
($t: ident, $tv: ident, $dim: expr) => (
impl<N: Clone + Zero> Row<$tv<N>> for $t<N> {
#[inline]
fn num_rows(&self) -> uint {
fn nrows(&self) -> uint {
Dim::dim(None::<$t<N>>)
}
@ -229,7 +229,7 @@ macro_rules! col_impl(
($t: ident, $tv: ident, $dim: expr) => (
impl<N: Clone + Zero> Col<$tv<N>> for $t<N> {
#[inline]
fn num_cols(&self) -> uint {
fn ncols(&self) -> uint {
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(
($t: ident, $dim: expr) => (
impl<N: Clone + Eq + Num>
Inv for $t<N> {
#[inline]
fn inverse(&self) -> Option<$t<N>> {
fn inverted(&self) -> Option<$t<N>> {
let mut res : $t<N> = self.clone();
if res.inplace_inverse() {
if res.invert() {
Some(res)
}
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 _0N: N = Zero::zero();
@ -528,7 +508,7 @@ macro_rules! from_homogeneous_impl(
macro_rules! outer_impl(
($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]
fn outer(&self, other: &$t<N>) -> $m<N> {
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 mat;
use structs::mat;
use traits::operations::{Inv, Transpose};
use traits::geometry::{Translation, Translate, Rotation, Rotate, Transformation, Transform};
@ -11,11 +11,11 @@ impl One for mat::Identity {
}
impl Inv for mat::Identity {
fn inverse(&self) -> Option<mat::Identity> {
fn inverted(&self) -> Option<mat::Identity> {
Some(mat::Identity::new())
}
fn inplace_inverse(&mut self) -> bool {
fn invert(&mut self) -> bool {
true
}
}

View File

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

View File

@ -1,6 +1,8 @@
use std::num::{Zero, One};
use vec::{Vec1, Vec2, Vec3, Vec4, Norm, VecCast, UniformSphereSample, Cross, CrossMatrix, Basis};
use mat::{Mat3, Row};
use traits::structure::{VecCast, Row, Basis};
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> {
#[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> {
#[inline]
fn num_rows(&self) -> uint {
fn nrows(&self) -> uint {
2
}

View File

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

View File

@ -9,16 +9,9 @@ use std::vec::{VecIterator, VecMutIterator};
use std::iter::{Iterator, FromIterator};
use std::cmp::ApproxEq;
use traits::geometry::{Transform, Rotate};
pub use traits::geometry::{FromHomogeneous, ToHomogeneous, Dot, Norm, Cross, CrossMatrix,
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;
use traits::geometry::{Transform, Rotate, FromHomogeneous, ToHomogeneous, Dot, Norm,
Translation, Translate};
use traits::structure::{VecCast, Basis, Dim, Indexable, Iterable, IterableMut};
mod metal;
mod vec_macros;

View File

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

View File

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

View File

@ -61,141 +61,6 @@ pub trait Rotate<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.
///
/// 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 {
}
/// 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.
pub trait Inv {
/// Returns the inverse of `self`.
fn inverse(&self) -> Option<Self>;
fn inverted(&self) -> Option<Self>;
/// In-place version of `inverse`.
fn inplace_inverse(&mut self) -> bool;
fn invert(&mut self) -> bool;
}
/// Trait of objects which can be transposed.
@ -27,9 +27,9 @@ pub trait Transpose {
}
/// Traits of objects having an outer product.
pub trait Outer<V, M> {
pub trait Outer<M> {
/// 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.

View File

@ -70,38 +70,12 @@ pub trait Basis {
/// Iterates through a basis of the subspace orthogonal to `self`.
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.
pub trait Row<R> {
/// The number of column of `self`.
fn num_rows(&self) -> uint;
fn nrows(&self) -> uint;
/// Reads the `i`-th row of `self`.
fn row(&self, i: uint) -> R;
/// Writes the `i`-th row of `self`.
@ -114,7 +88,7 @@ pub trait Row<R> {
/// Trait to access columns of a matrix or vector.
pub trait Col<C> {
/// 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`.
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>;