Add matrix adaptors and addapted to the now rust features.

This commit is contained in:
Sébastien Crozet 2013-05-16 21:30:39 +00:00
parent c7059af99d
commit d636fdd346
17 changed files with 437 additions and 189 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.swp
doc

View File

@ -1,5 +1,5 @@
all: all:
rustpkg install rust build src/nalgebra.rc --out-dir lib # rustpkg install
doc: doc:
rust doc src/nalgebra.rc --output-dir doc rust doc src/nalgebra.rc --output-dir doc

112
src/adaptors/rotmat.rs Normal file
View File

@ -0,0 +1,112 @@
use core::num::{One, Zero}; // , Trigonometric};
use traits::workarounds::rlmul::{RMul, LMul};
use traits::workarounds::trigonometric::Trigonometric;
use traits::dim::Dim;
use traits::inv::Inv;
use traits::transpose::Transpose;
use dim2::mat2::Mat2;
use dim3::mat3::Mat3;
use dim3::vec3::Vec3;
// FIXME: use a newtype here?
#[deriving(Eq)]
pub struct Rotmat<M>
{
priv submat: M
}
pub fn Rotmat2<T: Copy + Trigonometric + Neg<T>>(angle: T) -> Rotmat<Mat2<T>>
{
let coa = Trigonometric::cos(angle);
let sia = Trigonometric::sin(angle);
Rotmat
{ submat: Mat2(coa, -sia, sia, coa) }
}
pub fn Rotmat3<T: Copy + Trigonometric + Neg<T> + One + Sub<T, T> + Add<T, T> +
Mul<T, T>>
(axis: &Vec3<T>, angle: T) -> Rotmat<Mat3<T>>
{
let _1 = One::one::<T>();
let ux = axis.x;
let uy = axis.y;
let uz = axis.z;
let sqx = ux * ux;
let sqy = uy * uy;
let sqz = uz * uz;
let cos = Trigonometric::cos(angle);
let one_m_cos = _1 - cos;
let sin = Trigonometric::sin(angle);
Rotmat {
submat: Mat3(
(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<M: Dim> Dim for Rotmat<M>
{
fn dim() -> uint
{ Dim::dim::<M>() }
}
impl<M:Copy + One + Zero> One for Rotmat<M>
{
fn one() -> Rotmat<M>
{ Rotmat { submat: One::one() } }
}
impl<M:Copy + Mul<M, M>> Mul<Rotmat<M>, Rotmat<M>> for Rotmat<M>
{
fn mul(&self, other: &Rotmat<M>) -> Rotmat<M>
{ Rotmat { submat: self.submat.mul(&other.submat) } }
}
impl<V, M: RMul<V>> RMul<V> for Rotmat<M>
{
fn rmul(&self, other: &V) -> V
{ self.submat.rmul(other) }
}
impl<V, M: LMul<V>> LMul<V> for Rotmat<M>
{
fn lmul(&self, other: &V) -> V
{ self.submat.lmul(other) }
}
impl<M:Copy + Transpose>
Inv for Rotmat<M>
{
fn invert(&mut self)
{ self.transpose() }
fn inverse(&self) -> Rotmat<M>
{ self.transposed() }
}
impl<M:Copy + Transpose>
Transpose for Rotmat<M>
{
fn transposed(&self) -> Rotmat<M>
{ Rotmat { submat: self.submat.transposed() } }
fn transpose(&mut self)
{ self.submat.transpose() }
}
impl<M:ToStr> ToStr for Rotmat<M>
{
fn to_str(&self) -> ~str
{ ~"Rotmat {" + " submat: " + self.submat.to_str() + " }" }
}

85
src/adaptors/transform.rs Normal file
View File

@ -0,0 +1,85 @@
use core::num::{One, Zero};
use traits::dim::Dim;
use traits::inv::Inv;
use traits::transpose::Transpose;
use traits::workarounds::rlmul::{RMul, LMul};
pub struct Transform<M, V>
{
submat : M,
subtrans : V
}
pub fn Transform<M: Copy, V: Copy>(mat: &M, trans: &V) -> Transform<M, V>
{ Transform { submat: *mat, subtrans: *trans } }
impl<M:Dim, V> Dim for Transform<M, V>
{
fn dim() -> uint
{ Dim::dim::<M>() }
}
impl<M:Copy + One, V:Copy + Zero> One for Transform<M, V>
{
fn one() -> Transform<M, V>
{ Transform { submat: One::one(), subtrans: Zero::zero() } }
}
impl<M:Copy + Zero, V:Copy + Zero> Zero for Transform<M, V>
{
fn zero() -> Transform<M, V>
{ Transform { submat: Zero::zero(), subtrans: Zero::zero() } }
fn is_zero(&self) -> bool
{ self.submat.is_zero() && self.subtrans.is_zero() }
}
impl<M:Copy + RMul<V> + Mul<M, M>, V:Copy + Add<V, V>>
Mul<Transform<M, V>, Transform<M, V>> for Transform<M, V>
{
fn mul(&self, other: &Transform<M, V>) -> Transform<M, V>
{
Transform { submat: self.submat * other.submat,
subtrans: self.subtrans + self.submat.rmul(&other.subtrans) }
}
}
impl<M: RMul<V>, V> RMul<V> for Transform<M, V>
{
fn rmul(&self, other: &V) -> V
{ self.submat.rmul(other) }
}
impl<M: LMul<V>, V> LMul<V> for Transform<M, V>
{
fn lmul(&self, other: &V) -> V
{ self.submat.lmul(other) }
}
impl<M:Copy + Transpose + Inv + RMul<V>, V:Copy + Neg<V>>
Inv for Transform<M, V>
{
fn invert(&mut self)
{
self.submat.invert();
self.subtrans = self.submat.rmul(&-self.subtrans);
}
fn inverse(&self) -> Transform<M, V>
{
let mut res = *self;
res.invert();
res
}
}
impl<M:ToStr, V:ToStr> ToStr for Transform<M, V>
{
fn to_str(&self) -> ~str
{
~"Transform {" + " submat: " + self.submat.to_str() +
" subtrans: " + self.subtrans.to_str() + " }"
}
}

View File

@ -2,6 +2,7 @@ use core::num::{One, Zero};
use traits::dim::Dim; use traits::dim::Dim;
use traits::inv::Inv; use traits::inv::Inv;
use traits::transpose::Transpose; use traits::transpose::Transpose;
use traits::workarounds::rlmul::{RMul, LMul};
use dim2::vec2::Vec2; use dim2::vec2::Vec2;
#[deriving(Eq)] #[deriving(Eq)]
@ -45,11 +46,11 @@ impl<T:Copy + Zero> Zero for Mat2<T>
_0, _0) _0, _0)
} }
// fn is_zero(&self) -> bool fn is_zero(&self) -> bool
// { {
// self.m11.is_zero() && self.m11.is_zero() && self.m12.is_zero() self.m11.is_zero() && self.m12.is_zero() &&
// && self.m21.is_zero() && self.m21.is_zero() && self.m22.is_zero() self.m21.is_zero() && self.m22.is_zero()
// } }
} }
impl<T:Copy + Mul<T, T> + Add<T, T>> Mul<Mat2<T>, Mat2<T>> for Mat2<T> impl<T:Copy + Mul<T, T> + Add<T, T>> Mul<Mat2<T>, Mat2<T>> for Mat2<T>
@ -64,31 +65,47 @@ impl<T:Copy + Mul<T, T> + Add<T, T>> Mul<Mat2<T>, Mat2<T>> for Mat2<T>
} }
} }
// FIXME: implementation of multiple classes for the same struct fails impl<T:Copy + Add<T, T> + Mul<T, T>> RMul<Vec2<T>> for Mat2<T>
// with "internal compiler error: Asked to compute kind of a type variable".
//
// impl<T:Copy + Mul<T, T> + Add<T, T>> Mul<Vec2<T>, Vec2<T>> for Mat2<T>
// {
// fn mul(&self, v: &Vec2<T>) -> Vec2<T>
// { Vec2(self.m11 * v.x + self.m12 * v.y, self.m21 * v.x + self.m22 * v.y) }
// }
impl<T:Copy + Mul<T, T> + Add<T, T>> Mul<Mat2<T>, Vec2<T>> for Vec2<T>
{ {
fn mul(&self, m: &Mat2<T>) -> Vec2<T> fn rmul(&self, other: &Vec2<T>) -> Vec2<T>
{ Vec2(self.x * m.m11 + self.y * m.m21, self.x * m.m12 + self.y * m.m22) } {
Vec2(
self.m11 * other.x + self.m12 * other.y,
self.m21 * other.x + self.m22 * other.y
)
}
} }
impl<T:Copy + Mul<T, T> + Div<T, T> + Sub<T, T> + Neg<T> + Eq + Zero> impl<T:Copy + Add<T, T> + Mul<T, T>> LMul<Vec2<T>> for Mat2<T>
{
fn lmul(&self, other: &Vec2<T>) -> Vec2<T>
{
Vec2(
self.m11 * other.x + self.m21 * other.y,
self.m12 * other.x + self.m22 * other.y
)
}
}
impl<T:Copy + Mul<T, T> + Quot<T, T> + Sub<T, T> + Neg<T> + Eq + Zero>
Inv for Mat2<T> Inv for Mat2<T>
{ {
fn inv(&self) -> Mat2<T> fn inverse(&self) -> Mat2<T>
{
let mut res : Mat2<T> = *self;
res.invert();
res
}
fn invert(&mut self)
{ {
let det = self.m11 * self.m22 - self.m21 * self.m12; let det = self.m11 * self.m22 - self.m21 * self.m12;
assert!(det != Zero::zero()); assert!(det != Zero::zero());
Mat2(self.m22 / det , -self.m12 / det, *self = Mat2(self.m22 / det , -self.m12 / det,
-self.m21 / det, self.m11 / det) -self.m21 / det, self.m11 / det)
} }
} }

View File

@ -1,92 +0,0 @@
use core::num::{One, Zero};
use traits::workarounds::trigonometric::Trigonometric;
use traits::dim::Dim;
use dim2::mat2::Mat2;
// use dim2::vec2::Vec2;
// FIXME: using a newtype did not compile (due a compiler bug)
// pub type Rotmat2<T> = (Mat2<T>)
#[deriving(Eq)]
pub struct Rotmat2<T>
{
priv submat: Mat2<T>
}
pub fn Rotmat2<T:Copy + Trigonometric + Neg<T>>(angle: T) -> Rotmat2<T>
{
let coa = angle.cos();
let sia = angle.sin();
Rotmat2
{ submat: Mat2(coa, -sia, sia, coa) }
}
impl<T> Dim for Rotmat2<T>
{
fn dim() -> uint
{ 2 }
}
impl<T:Copy + One + Zero> One for Rotmat2<T>
{
fn one() -> Rotmat2<T>
{ Rotmat2 { submat: One::one() } }
}
impl<T:Copy + Mul<T, T> + Add<T, T>> Mul<Rotmat2<T>, Rotmat2<T>> for Rotmat2<T>
{
fn mul(&self, other: &Rotmat2<T>) -> Rotmat2<T>
{ Rotmat2 { submat: self.submat.mul(&other.submat) } }
}
// FIXME: implementation of the same classes for the same struct fails
// with "internal compiler error: Asked to compute kind of a type variable".
//
// impl<T:Copy + Mul<T, T> + Add<T, T>> Mul<Vec2<T>, Vec2<T>> for Rotmat2<T>
// {
// fn mul(&self, v: &Vec2<T>) -> Vec2<T>
// { Vec2(self.m11 * v.x + self.m12 * v.y, self.m21 * v.x + self.m22 * v.y) }
// }
// FIXME: implementation of the same classes for the same struct (here Vec2<T>)
// fails with "internal compiler error: Asked to compute kind of a type
// variable".
//
// impl<T:Copy + Mul<T, T> + Add<T, T>> Mul<Rotmat2<T>, Vec2<T>> for Vec2<T>
// {
// fn mul(&self, m: &Rotmat2<T>) -> Vec2<T>
// { self.mult(&m.submat) }
// }
/*
impl<T:Copy + Mul<T, T> + Div<T, T> + Sub<T, T> + Neg<T> + Eq + Zero>
Inv<T> for Rotmat2<T>
{
fn inv(&self) -> Rotmat2<T>
{
// transpose
Rotmat2(
Mat2(
self.submat.m11, self.submat.m21,
self.submat.m12, self.submat.m22
)
)
}
}
*/
/*
impl<T:ToStr> ToStr for Rotmat2<T>
{
fn to_str(&self) -> ~str
{
~"Rotmat2 {"
+ " m11: " + self.m11.to_str()
+ " m12: " + self.m12.to_str()
+ " m21: " + self.m21.to_str()
+ " m22: " + self.m22.to_str()
+ " }"
}
}
*/

View File

@ -1,8 +1,7 @@
use core::num::Zero; use core::num::{Zero, Algebraic};
use traits::dot::Dot; use traits::dot::Dot;
use traits::dim::Dim; use traits::dim::Dim;
use traits::cross::Cross; use traits::cross::Cross;
use traits::workarounds::sqrt::Sqrt;
#[deriving(Eq)] #[deriving(Eq)]
pub struct Vec2<T> pub struct Vec2<T>
@ -32,7 +31,7 @@ impl<T:Copy + Sub<T,T>> Sub<Vec2<T>, Vec2<T>> for Vec2<T>
{ Vec2(self.x - other.x, self.y - other.y) } { Vec2(self.x - other.x, self.y - other.y) }
} }
impl<T:Copy + Mul<T, T> + Add<T, T> + Sqrt> Dot<T> for Vec2<T> impl<T:Copy + Mul<T, T> + Add<T, T> + Algebraic> Dot<T> for Vec2<T>
{ {
fn dot(&self, other : &Vec2<T>) -> T fn dot(&self, other : &Vec2<T>) -> T
{ self.x * other.x + self.y * other.y } { self.x * other.x + self.y * other.y }
@ -50,6 +49,12 @@ impl<T:Copy + Mul<T, T> + Sub<T, T>> Cross<T> for Vec2<T>
{ self.x * other.y - self.y * other.x } { self.x * other.y - self.y * other.x }
} }
impl<T:Copy + Neg<T>> Neg<Vec2<T>> for Vec2<T>
{
fn neg(&self) -> Vec2<T>
{ Vec2(-self.x, -self.y) }
}
impl<T:Copy + Zero> Zero for Vec2<T> impl<T:Copy + Zero> Zero for Vec2<T>
{ {
fn zero() -> Vec2<T> fn zero() -> Vec2<T>
@ -57,6 +62,9 @@ impl<T:Copy + Zero> Zero for Vec2<T>
let _0 = Zero::zero(); let _0 = Zero::zero();
Vec2(_0, _0) Vec2(_0, _0)
} }
fn is_zero(&self) -> bool
{ self.x.is_zero() && self.y.is_zero() }
} }
impl<T:ToStr> ToStr for Vec2<T> impl<T:ToStr> ToStr for Vec2<T>

View File

@ -1,8 +1,8 @@
use core::num::{One, Zero}; use core::num::{One, Zero};
// use core::rand::{Rand, Rng};
use traits::dim::Dim; use traits::dim::Dim;
use traits::inv::Inv; use traits::inv::Inv;
use traits::transpose::Transpose; use traits::transpose::Transpose;
use traits::workarounds::rlmul::{RMul, LMul};
use dim3::vec3::Vec3; use dim3::vec3::Vec3;
#[deriving(Eq)] #[deriving(Eq)]
@ -51,6 +51,13 @@ impl<T:Copy + Zero> Zero for Mat3<T>
_0, _0, _0, _0, _0, _0,
_0, _0, _0) _0, _0, _0)
} }
fn is_zero(&self) -> bool
{
self.m11.is_zero() && self.m12.is_zero() && self.m13.is_zero() &&
self.m21.is_zero() && self.m22.is_zero() && self.m23.is_zero() &&
self.m31.is_zero() && self.m32.is_zero() && self.m33.is_zero()
}
} }
impl<T:Copy + Mul<T, T> + Add<T, T>> Mul<Mat3<T>, Mat3<T>> for Mat3<T> impl<T:Copy + Mul<T, T> + Add<T, T>> Mul<Mat3<T>, Mat3<T>> for Mat3<T>
@ -73,34 +80,44 @@ impl<T:Copy + Mul<T, T> + Add<T, T>> Mul<Mat3<T>, Mat3<T>> for Mat3<T>
} }
} }
// FIXME: implementation of multiple classes for the same struct fails impl<T:Copy + Add<T, T> + Mul<T, T>> RMul<Vec3<T>> for Mat3<T>
// with "internal compiler error: Asked to compute kind of a type variable".
//
// impl<T:Copy + Mul<T, T> + Add<T, T>> Mul<Vec3<T>, Vec3<T>> for Mat3<T>
// {
// fn mul(&self, m : &Mat3<T>) -> Vec3<T>
// {
// Vec3(self.x * m.m11 + self.y * m.m21 + self.z * m.m31,
// self.x * m.m12 + self.y * m.m22 + self.z * m.m32,
// self.x * m.m13 + self.y * m.m23 + self.z * m.m33)
// }
// }
impl<T:Copy + Mul<T, T> + Add<T, T>> Mul<Mat3<T>, Vec3<T>> for Vec3<T>
{ {
fn mul(&self, m : &Mat3<T>) -> Vec3<T> fn rmul(&self, other: &Vec3<T>) -> Vec3<T>
{ {
Vec3(self.x * m.m11 + self.y * m.m21 + self.z * m.m31, Vec3(
self.x * m.m12 + self.y * m.m22 + self.z * m.m32, self.m11 * other.x + self.m12 * other.y + self.m13 * other.z,
self.x * m.m13 + self.y * m.m23 + self.z * m.m33) self.m21 * other.x + self.m22 * other.y + self.m33 * other.z,
self.m31 * other.x + self.m32 * other.y + self.m33 * other.z
)
} }
} }
impl<T:Copy + Mul<T, T> + Div<T, T> + Sub<T, T> + Add<T, T> + Neg<T> impl<T:Copy + Add<T, T> + Mul<T, T>> LMul<Vec3<T>> for Mat3<T>
{
fn lmul(&self, other: &Vec3<T>) -> Vec3<T>
{
Vec3(
self.m11 * other.x + self.m21 * other.y + self.m31 * other.z,
self.m12 * other.x + self.m22 * other.y + self.m32 * other.z,
self.m13 * other.x + self.m23 * other.y + self.m33 * other.z
)
}
}
impl<T:Copy + Mul<T, T> + Quot<T, T> + Sub<T, T> + Add<T, T> + Neg<T>
+ Eq + Zero> + Eq + Zero>
Inv for Mat3<T> Inv for Mat3<T>
{ {
fn inv(&self) -> Mat3<T> fn inverse(&self) -> Mat3<T>
{
let mut res = *self;
res.invert();
res
}
fn invert(&mut self)
{ {
let minor_m22_m33 = self.m22 * self.m33 - self.m32 * self.m23; let minor_m22_m33 = self.m22 * self.m33 - self.m32 * self.m23;
let minor_m21_m33 = self.m21 * self.m33 - self.m31 * self.m23; let minor_m21_m33 = self.m21 * self.m33 - self.m31 * self.m23;
@ -112,7 +129,7 @@ Inv for Mat3<T>
assert!(det != Zero::zero()); assert!(det != Zero::zero());
Mat3( *self = Mat3(
(minor_m22_m33 / det), (minor_m22_m33 / det),
((self.m13 * self.m32 - self.m33 * self.m12) / det), ((self.m13 * self.m32 - self.m33 * self.m12) / det),
((self.m12 * self.m23 - self.m22 * self.m13) / det), ((self.m12 * self.m23 - self.m22 * self.m13) / det),

View File

@ -1,8 +1,7 @@
use core::num::Zero; use core::num::{Zero, Algebraic};
use traits::dim::Dim; use traits::dim::Dim;
use traits::dot::Dot; use traits::dot::Dot;
use traits::cross::Cross; use traits::cross::Cross;
use traits::workarounds::sqrt::Sqrt;
#[deriving(Eq)] #[deriving(Eq)]
pub struct Vec3<T> pub struct Vec3<T>
@ -33,7 +32,13 @@ impl<T:Copy + Sub<T,T>> Sub<Vec3<T>, Vec3<T>> for Vec3<T>
{ Vec3(self.x - other.x, self.y - other.y, self.z - other.z) } { Vec3(self.x - other.x, self.y - other.y, self.z - other.z) }
} }
impl<T:Copy + Mul<T, T> + Add<T, T> + Sqrt> Dot<T> for Vec3<T> impl<T:Copy + Neg<T>> Neg<Vec3<T>> for Vec3<T>
{
fn neg(&self) -> Vec3<T>
{ Vec3(-self.x, -self.y, -self.z) }
}
impl<T:Copy + Mul<T, T> + Add<T, T> + Algebraic> Dot<T> for Vec3<T>
{ {
fn dot(&self, other : &Vec3<T>) -> T fn dot(&self, other : &Vec3<T>) -> T
{ self.x * other.x + self.y * other.y + self.z * other.z } { self.x * other.x + self.y * other.y + self.z * other.z }
@ -64,6 +69,9 @@ impl<T:Copy + Zero> Zero for Vec3<T>
let _0 = Zero::zero(); let _0 = Zero::zero();
Vec3(_0, _0, _0) Vec3(_0, _0, _0)
} }
fn is_zero(&self) -> bool
{ self.x.is_zero() && self.y.is_zero() && self.z.is_zero() }
} }
impl<T:ToStr> ToStr for Vec3<T> impl<T:ToStr> ToStr for Vec3<T>

View File

@ -12,26 +12,26 @@ pub use dim3::mat3::Mat3;
pub use dim2::vec2::Vec2; pub use dim2::vec2::Vec2;
pub use dim2::mat2::Mat2; pub use dim2::mat2::Mat2;
pub use dim2::rotmat2::Rotmat2;
pub use ndim::nvec::NVec; pub use ndim::nvec::NVec;
pub use ndim::nmat::NMat; pub use ndim::nmat::NMat;
pub use adaptors::rotmat::Rotmat;
pub use adaptors::transform::Transform;
pub use traits::dot::Dot; pub use traits::dot::Dot;
pub use traits::cross::Cross; pub use traits::cross::Cross;
pub use traits::dim::Dim; pub use traits::dim::Dim;
pub use traits::workarounds::sqrt::Sqrt;
pub use traits::workarounds::trigonometric::Trigonometric;
pub use traits::inv::Inv; pub use traits::inv::Inv;
pub use traits::transpose::Transpose; pub use traits::transpose::Transpose;
pub use traits::workarounds::rlmul::{RMul, LMul};
pub use traits::workarounds::trigonometric::Trigonometric;
mod dim2 mod dim2
{ {
mod vec2; mod vec2;
mod mat2; mod mat2;
mod rotmat2;
} }
mod dim3 mod dim3
@ -46,6 +46,12 @@ mod ndim
mod nmat; mod nmat;
} }
mod adaptors
{
mod rotmat;
mod transform;
}
mod traits mod traits
{ {
mod dot; mod dot;
@ -56,7 +62,7 @@ mod traits
mod workarounds mod workarounds
{ {
mod sqrt; mod rlmul;
mod trigonometric; mod trigonometric;
} }
} }

View File

@ -1,9 +1,10 @@
use core::num::{One, Zero}; use core::num::{One, Zero};
use core::vec::{from_elem, swap}; use core::vec::{from_elem, swap, all};
use traits::dim::Dim; use traits::dim::Dim;
use traits::inv::Inv; use traits::inv::Inv;
use traits::transpose::Transpose; use traits::transpose::Transpose;
// use ndim::nvec::NVec; use traits::workarounds::rlmul::{RMul, LMul};
use ndim::nvec::NVec;
// D is a phantom type parameter, used only as a dimensional token. // D is a phantom type parameter, used only as a dimensional token.
// Its allows use to encode the vector dimension at the type-level. // Its allows use to encode the vector dimension at the type-level.
@ -15,6 +16,12 @@ pub struct NMat<D, T>
mij: ~[T] mij: ~[T]
} }
impl<D, T: Clone> Clone for NMat<D, T>
{
fn clone(&self) -> NMat<D, T>
{ NMat{ mij: self.mij.clone() } }
}
impl<D: Dim, T: Copy> NMat<D, T> impl<D: Dim, T: Copy> NMat<D, T>
{ {
fn offset(i: uint, j: uint) -> uint fn offset(i: uint, j: uint) -> uint
@ -59,6 +66,9 @@ impl<D: Dim, T:Copy + Zero> Zero for NMat<D, T>
NMat{ mij: from_elem(dim * dim, Zero::zero()) } NMat{ mij: from_elem(dim * dim, Zero::zero()) }
} }
fn is_zero(&self) -> bool
{ all(self.mij, |e| e.is_zero()) }
} }
impl<D: Dim, T:Copy + Mul<T, T> + Add<T, T> + Zero> impl<D: Dim, T:Copy + Mul<T, T> + Add<T, T> + Zero>
@ -86,13 +96,59 @@ Mul<NMat<D, T>, NMat<D, T>> for NMat<D, T>
} }
} }
impl<D: Dim, T:Copy + Add<T, T> + Mul<T, T> + Zero>
RMul<NVec<D, T>> for NMat<D, T>
{
fn rmul(&self, other: &NVec<D, T>) -> NVec<D, T>
{
let dim = Dim::dim::<D>();
let mut res : NVec<D, T> = Zero::zero();
for uint::range(0u, dim) |i|
{
for uint::range(0u, dim) |j|
{ res.at[i] = res.at[i] + other.at[j] * self[(i, j)]; }
}
res
}
}
impl<D: Dim, T:Copy + Add<T, T> + Mul<T, T> + Zero>
LMul<NVec<D, T>> for NMat<D, T>
{
fn lmul(&self, other: &NVec<D, T>) -> NVec<D, T>
{
let dim = Dim::dim::<D>();
let mut res : NVec<D, T> = Zero::zero();
for uint::range(0u, dim) |i|
{
for uint::range(0u, dim) |j|
{ res.at[i] = res.at[i] + other.at[j] * self[(j, i)]; }
}
res
}
}
impl<D: Dim, impl<D: Dim,
T: Copy + Mul<T, T> + Div<T, T> + Sub<T, T> + Neg<T> + Eq + One + Zero> T: Clone + Copy + Eq + One + Zero +
Mul<T, T> + Quot<T, T> + Sub<T, T> + Neg<T>
>
Inv for NMat<D, T> Inv for NMat<D, T>
{ {
fn inv(&self) -> NMat<D, T> fn inverse(&self) -> NMat<D, T>
{
let mut res : NMat<D, T> = self.clone();
res.invert();
res
}
fn invert(&mut self)
{ {
let mut cpy = copy *self;
let dim = Dim::dim::<D>(); let dim = Dim::dim::<D>();
let mut res = One::one::<NMat<D, T>>(); let mut res = One::one::<NMat<D, T>>();
let _0T = Zero::zero::<T>(); let _0T = Zero::zero::<T>();
@ -111,7 +167,7 @@ Inv for NMat<D, T>
while (n0 != dim) while (n0 != dim)
{ {
if (cpy[(n0, k)] != _0T) if (self[(n0, k)] != _0T)
{ break; } { break; }
n0 += 1; n0 += 1;
@ -124,7 +180,7 @@ Inv for NMat<D, T>
{ {
for uint::range(0u, dim) |j| for uint::range(0u, dim) |j|
{ {
swap(cpy.mij, swap(self.mij,
NMat::offset::<D, T>(n0, j), NMat::offset::<D, T>(n0, j),
NMat::offset::<D, T>(k, j)); NMat::offset::<D, T>(k, j));
swap(res.mij, swap(res.mij,
@ -133,11 +189,11 @@ Inv for NMat<D, T>
} }
} }
let pivot = cpy[(k, k)]; let pivot = self[(k, k)];
for uint::range(k, dim) |j| for uint::range(k, dim) |j|
{ {
cpy.set(k, j, &(cpy[(k, j)] / pivot)); self.set(k, j, &(self[(k, j)] / pivot));
res.set(k, j, &(res[(k, j)] / pivot)); res.set(k, j, &(res[(k, j)] / pivot));
} }
@ -145,18 +201,16 @@ Inv for NMat<D, T>
{ {
if (l != k) if (l != k)
{ {
let normalizer = cpy[(l, k)] / pivot; let normalizer = self[(l, k)] / pivot;
for uint::range(k, dim) |j| for uint::range(k, dim) |j|
{ {
cpy.set(k, j, &(cpy[(l, j)] - cpy[(k, j)] * normalizer)); self.set(k, j, &(self[(l, j)] - self[(k, j)] * normalizer));
res.set(k, j, &(res[(l, j)] - res[(k, j)] * normalizer)); res.set(k, j, &(res[(l, j)] - res[(k, j)] * normalizer));
} }
} }
} }
} }
res
} }
} }

View File

@ -1,8 +1,7 @@
use core::vec::{map2, from_elem}; use core::vec::{map_zip, from_elem, map, all};
use core::num::Zero; use core::num::{Zero, Algebraic};
use traits::dim::Dim; use traits::dim::Dim;
use traits::dot::Dot; use traits::dot::Dot;
use traits::workarounds::sqrt::Sqrt;
// D is a phantom parameter, used only as a dimensional token. // D is a phantom parameter, used only as a dimensional token.
// Its allows use to encode the vector dimension at the type-level. // Its allows use to encode the vector dimension at the type-level.
@ -26,16 +25,23 @@ impl<D: Dim, T> Dim for NVec<D, T>
impl<D, T:Copy + Add<T,T>> Add<NVec<D, T>, NVec<D, T>> for NVec<D, T> impl<D, T:Copy + Add<T,T>> Add<NVec<D, T>, NVec<D, T>> for NVec<D, T>
{ {
fn add(&self, other: &NVec<D, T>) -> NVec<D, T> fn add(&self, other: &NVec<D, T>) -> NVec<D, T>
{ NVec { at: map2(self.at, other.at, | a, b | { *a + *b }) } } { NVec { at: map_zip(self.at, other.at, | a, b | { *a + *b }) } }
} }
impl<D, T:Copy + Sub<T,T>> Sub<NVec<D, T>, NVec<D, T>> for NVec<D, T> impl<D, T:Copy + Sub<T,T>> Sub<NVec<D, T>, NVec<D, T>> for NVec<D, T>
{ {
fn sub(&self, other: &NVec<D, T>) -> NVec<D, T> fn sub(&self, other: &NVec<D, T>) -> NVec<D, T>
{ NVec { at: map2(self.at, other.at, | a, b | *a - *b) } } { NVec { at: map_zip(self.at, other.at, | a, b | *a - *b) } }
} }
impl<D: Dim, T:Copy + Mul<T, T> + Add<T, T> + Sqrt + Zero> Dot<T> for NVec<D, T> impl<D, T:Copy + Neg<T>> Neg<NVec<D, T>> for NVec<D, T>
{
fn neg(&self) -> NVec<D, T>
{ NVec { at: map(self.at, |a| -a) } }
}
impl<D: Dim, T:Copy + Mul<T, T> + Add<T, T> + Algebraic + Zero>
Dot<T> for NVec<D, T>
{ {
fn dot(&self, other: &NVec<D, T>) -> T fn dot(&self, other: &NVec<D, T>) -> T
{ {
@ -70,6 +76,11 @@ impl<D: Dim, T:Copy + Zero> Zero for NVec<D, T>
NVec { at: from_elem(Dim::dim::<D>(), _0) } NVec { at: from_elem(Dim::dim::<D>(), _0) }
} }
fn is_zero(&self) -> bool
{
all(self.at, |e| e.is_zero())
}
} }
impl<D: Dim, T:ToStr> ToStr for NVec<D, T> impl<D: Dim, T:ToStr> ToStr for NVec<D, T>

View File

@ -1,4 +1,5 @@
pub trait Inv pub trait Inv
{ {
fn inv(&self) -> Self; fn inverse(&self) -> Self;
fn invert(&mut self);
} }

View File

@ -0,0 +1,4 @@
This packages contains everything done because current (stable) compiler either
bugs or miss features.
Therefore, keep in mind anything in there will be inevitably removed some days.
So dont rely on them too much.

View File

@ -0,0 +1,18 @@
/** This is a workaround of the fact we cannot implement the same trait
* (with different type parameters) twice for the same type:
* ~~~
* trait Mul<V, V> for M
* trait Mul<V2, V2> for M
* ~~~
*/
pub trait RMul<V>
{
/// Computes self * v
fn rmul(&self, v : &V) -> V;
}
pub trait LMul<V>
{
/// Computes v * self
fn lmul(&self, &V) -> V;
}

View File

@ -1,17 +0,0 @@
// FIXME: this does not seem to exist already
// but it will surely be added someday.
pub trait Sqrt
{
fn sqrt(&self) -> Self;
}
impl Sqrt for f64
{
fn sqrt(&self) -> f64 { f64::sqrt(*self) }
}
impl Sqrt for f32
{
fn sqrt(&self) -> f32 { f32::sqrt(*self) }
}

View File

@ -1,5 +1,19 @@
// Trigonometric is available in core, but compilation fails with internal
// error.
use core::f64::{cos, sin};
pub trait Trigonometric pub trait Trigonometric
{ {
fn sin(&self) -> Self; fn cos(Self) -> Self;
fn cos(&self) -> Self; fn sin(Self) -> Self;
}
impl Trigonometric for f64
{
fn cos(a: f64) -> f64
{ cos(a) }
fn sin(a: f64) -> f64
{ sin(a) }
} }