Refactor vec{1, 2, 3} implemenation + add some useful traits.

This commit is contained in:
Sébastien Crozet 2013-06-28 21:03:40 +00:00
parent 8abcdeeedc
commit cd355dfb30
22 changed files with 1070 additions and 1192 deletions

View File

@ -5,12 +5,12 @@ use traits::rlmul::{RMul, LMul};
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::rotation::{Rotation, Rotatable}; use traits::rotation::{Rotation, Rotate, Rotatable};
use traits::delta_transform::{DeltaTransform, DeltaTransformVector}; use traits::transformation::{Transform}; // FIXME: implement Transformation and Transformable
use dim1::vec1::Vec1; use vec::Vec1;
use dim2::mat2::Mat2; use dim2::mat2::Mat2;
use dim3::mat3::Mat3; use dim3::mat3::Mat3;
use dim3::vec3::{Vec3}; use vec::Vec3;
#[deriving(Eq, ToStr)] #[deriving(Eq, ToStr)]
pub struct Rotmat<M> pub struct Rotmat<M>
@ -30,9 +30,9 @@ pub fn rotmat3<N: Copy + Trigonometric + Neg<N> + One + Sub<N, N> + Add<N, N> +
(axis: &Vec3<N>, angle: N) -> Rotmat<Mat3<N>> (axis: &Vec3<N>, angle: N) -> Rotmat<Mat3<N>>
{ {
let _1 = One::one::<N>(); let _1 = One::one::<N>();
let ux = copy axis.x; let ux = copy axis.at[0];
let uy = copy axis.y; let uy = copy axis.at[1];
let uz = copy axis.z; let uz = copy axis.at[2];
let sqx = ux * ux; let sqx = ux * ux;
let sqy = uy * uy; let sqy = uy * uy;
let sqz = uz * uz; let sqz = uz * uz;
@ -61,10 +61,14 @@ Rotation<Vec1<N>> for Rotmat<Mat2<N>>
{ {
#[inline] #[inline]
fn rotation(&self) -> Vec1<N> fn rotation(&self) -> Vec1<N>
{ Vec1::new(-(self.submat.m12 / self.submat.m11).atan()) } { Vec1::new([-(self.submat.m12 / self.submat.m11).atan()]) }
#[inline] #[inline]
fn rotate(&mut self, rot: &Vec1<N>) fn inv_rotation(&self) -> Vec1<N>
{ -self.rotation() }
#[inline]
fn rotate_by(&mut self, rot: &Vec1<N>)
{ *self = self.rotated(rot) } { *self = self.rotated(rot) }
} }
@ -73,7 +77,7 @@ Rotatable<Vec1<N>, Rotmat<Mat2<N>>> for Rotmat<Mat2<N>>
{ {
#[inline] #[inline]
fn rotated(&self, rot: &Vec1<N>) -> Rotmat<Mat2<N>> fn rotated(&self, rot: &Vec1<N>) -> Rotmat<Mat2<N>>
{ rotmat2(copy rot.x) * *self } { rotmat2(copy rot.at[0]) * *self }
} }
impl<N: Div<N, N> + Trigonometric + Neg<N> + Mul<N, N> + Add<N, N> + Copy + impl<N: Div<N, N> + Trigonometric + Neg<N> + Mul<N, N> + Add<N, N> + Copy +
@ -83,9 +87,14 @@ Rotation<(Vec3<N>, N)> for Rotmat<Mat3<N>>
#[inline] #[inline]
fn rotation(&self) -> (Vec3<N>, N) fn rotation(&self) -> (Vec3<N>, N)
{ fail!("Not yet implemented.") } { fail!("Not yet implemented.") }
#[inline]
fn inv_rotation(&self) -> (Vec3<N>, N)
{ fail!("Not yet implemented.") }
#[inline] #[inline]
fn rotate(&mut self, rot: &(Vec3<N>, N)) fn rotate_by(&mut self, rot: &(Vec3<N>, N))
{ *self = self.rotated(rot) } { *self = self.rotated(rot) }
} }
@ -105,6 +114,28 @@ impl<N: Copy + Rand + Trigonometric + Neg<N>> Rand for Rotmat<Mat2<N>>
{ rotmat2(rng.gen()) } { rotmat2(rng.gen()) }
} }
impl<M: RMul<V> + LMul<V>, V> Rotate<V> for Rotmat<M>
{
#[inline]
fn rotate(&self, v: &V) -> V
{ self.rmul(v) }
#[inline]
fn inv_rotate(&self, v: &V) -> V
{ self.lmul(v) }
}
impl<M: RMul<V> + LMul<V>, V> Transform<V> for Rotmat<M>
{
#[inline]
fn transform_vec(&self, v: &V) -> V
{ self.rotate(v) }
#[inline]
fn inv_transform(&self, v: &V) -> V
{ self.inv_rotate(v) }
}
impl<N: Copy + Rand + Trigonometric + Neg<N> + One + Sub<N, N> + Add<N, N> + impl<N: Copy + Rand + Trigonometric + Neg<N> + One + Sub<N, N> + Add<N, N> +
Mul<N, N>> Mul<N, N>>
Rand for Rotmat<Mat3<N>> Rand for Rotmat<Mat3<N>>
@ -149,20 +180,6 @@ impl<V, M: LMul<V>> LMul<V> for Rotmat<M>
{ self.submat.lmul(other) } { self.submat.lmul(other) }
} }
impl<M: Copy> DeltaTransform<M> for Rotmat<M>
{
#[inline]
fn delta_transform(&self) -> M
{ copy self.submat }
}
impl<M: RMul<V>, V> DeltaTransformVector<V> for Rotmat<M>
{
#[inline]
fn delta_transform_vector(&self, v: &V) -> V
{ self.submat.rmul(v) }
}
impl<M: Transpose> Inv for Rotmat<M> impl<M: Transpose> Inv for Rotmat<M>
{ {
#[inline] #[inline]

View File

@ -3,11 +3,10 @@ use std::rand::{Rand, Rng, RngUtil};
use std::cmp::ApproxEq; use std::cmp::ApproxEq;
use traits::dim::Dim; use traits::dim::Dim;
use traits::inv::Inv; use traits::inv::Inv;
use traits::rotation::{Rotation, Rotatable}; use traits::rotation::{Rotation, Rotate, Rotatable};
use traits::translation::{Translation, Translatable}; use traits::translation::{Translation, Translate, Translatable};
use traits::transformation;
use traits::transformation::{Transformation, Transformable}; use traits::transformation::{Transformation, Transformable};
use traits::transpose::Transpose;
use traits::delta_transform::{DeltaTransform, DeltaTransformVector};
use traits::rlmul::{RMul, LMul}; use traits::rlmul::{RMul, LMul};
#[deriving(Eq, ToStr)] #[deriving(Eq, ToStr)]
@ -81,8 +80,23 @@ impl<M, V: Translation<V>> Translation<V> for Transform<M, V>
{ self.subtrans.translation() } { self.subtrans.translation() }
#[inline] #[inline]
fn translate(&mut self, t: &V) fn inv_translation(&self) -> V
{ self.subtrans.translate(t) } { self.subtrans.inv_translation() }
#[inline]
fn translate_by(&mut self, t: &V)
{ self.subtrans.translate_by(t) }
}
impl<M: Translate<V>, V, _0> Translate<V> for Transform<M, _0>
{
#[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: Copy, V: Translatable<V, Res>, Res: Translation<V>> impl<M: Copy, V: Translatable<V, Res>, Res: Translation<V>>
@ -103,16 +117,32 @@ Rotation<AV> for Transform<M, V>
{ self.submat.rotation() } { self.submat.rotation() }
#[inline] #[inline]
fn rotate(&mut self, rot: &AV) fn inv_rotation(&self) -> AV
{ self.submat.inv_rotation() }
#[inline]
fn rotate_by(&mut self, rot: &AV)
{ {
// FIXME: this does not seem opitmal // FIXME: this does not seem opitmal
let mut delta = One::one::<M>(); let mut delta = One::one::<M>();
delta.rotate(rot); delta.rotate_by(rot);
self.submat.rotate(rot); self.submat.rotate_by(rot);
self.subtrans = delta.rmul(&self.subtrans); self.subtrans = delta.rmul(&self.subtrans);
} }
} }
impl<M: Rotate<V>, V, _0> Rotate<V> for Transform<M, _0>
{
#[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: Rotatable<AV, Res> + One, impl<M: Rotatable<AV, Res> + One,
Res: Rotation<AV> + RMul<V>, Res: Rotation<AV> + RMul<V>,
V, V,
@ -129,15 +159,32 @@ Rotatable<AV, Transform<Res, V>> for Transform<M, V>
} }
} }
impl<M: RMul<V> + Mul<M, M> + Copy, V: Add<V, V> + Copy> Transformation<Transform<M, V>> for Transform<M, V> impl<M: Inv + RMul<V> + Mul<M, M> + Copy, V: Add<V, V> + Neg<V> + Copy>
Transformation<Transform<M, V>> for Transform<M, V>
{ {
fn transformation(&self) -> Transform<M, V> fn transformation(&self) -> Transform<M, V>
{ copy *self } { copy *self }
fn inv_transformation(&self) -> Transform<M, V>
{ self.inverse() }
fn transform_by(&mut self, other: &Transform<M, V>) fn transform_by(&mut self, other: &Transform<M, V>)
{ *self = other * *self; } { *self = other * *self; }
} }
impl<M: transformation::Transform<V>, V: Add<V, V> + Sub<V, V>>
transformation::Transform<V> for Transform<M, V>
{
#[inline]
fn transform_vec(&self, v: &V) -> V
{ self.submat.transform_vec(v) + self.subtrans }
#[inline]
fn inv_transform(&self, v: &V) -> V
{ self.submat.inv_transform(&(v - self.subtrans)) }
}
// FIXME: constraints are too restrictive. // FIXME: constraints are too restrictive.
// Should be: Transformable<M2, // Transform<Res, V> ... // Should be: Transformable<M2, // Transform<Res, V> ...
impl<M: RMul<V> + Mul<M, M>, V: Add<V, V>> impl<M: RMul<V> + Mul<M, M>, V: Add<V, V>>
@ -147,21 +194,7 @@ Transformable<Transform<M, V>, Transform<M, V>> for Transform<M, V>
{ t * *self } { t * *self }
} }
impl<M: Copy, V> DeltaTransform<M> for Transform<M, V> impl<M: Copy + Inv + RMul<V>, V: Copy + Neg<V>>
{
#[inline]
fn delta_transform(&self) -> M
{ copy self.submat }
}
impl<M: RMul<V>, V> DeltaTransformVector<V> for Transform<M, V>
{
#[inline]
fn delta_transform_vector(&self, v: &V) -> V
{ self.submat.rmul(v) }
}
impl<M:Copy + Transpose + Inv + RMul<V>, V: Copy + Neg<V>>
Inv for Transform<M, V> Inv for Transform<M, V>
{ {
#[inline] #[inline]

View File

@ -1,12 +1,13 @@
use std::num::{One, Zero}; use std::num::{One, Zero};
use std::rand::{Rand, Rng, RngUtil}; use std::rand::{Rand, Rng, RngUtil};
use std::cmp::ApproxEq; use std::cmp::ApproxEq;
use traits::division_ring::DivisionRing;
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::flatten::Flatten; use traits::transformation::Transform; // FIXME: implement Transformable, Transformation
use traits::rlmul::{RMul, LMul}; use traits::rlmul::{RMul, LMul};
use dim1::vec1::Vec1; use vec::Vec1;
#[deriving(Eq, ToStr)] #[deriving(Eq, ToStr)]
pub struct Mat1<N> pub struct Mat1<N>
@ -54,21 +55,33 @@ impl<N: Mul<N, N> + Add<N, N>> Mul<Mat1<N>, Mat1<N>> for Mat1<N>
{ Mat1::new(self.m11 * other.m11) } { Mat1::new(self.m11 * other.m11) }
} }
impl<N: Copy + DivisionRing>
Transform<Vec1<N>> for Mat1<N>
{
#[inline]
fn transform_vec(&self, v: &Vec1<N>) -> Vec1<N>
{ self.rmul(v) }
#[inline]
fn inv_transform(&self, v: &Vec1<N>) -> Vec1<N>
{ self.inverse().transform_vec(v) }
}
impl<N: Add<N, N> + Mul<N, N>> RMul<Vec1<N>> for Mat1<N> impl<N: Add<N, N> + Mul<N, N>> RMul<Vec1<N>> for Mat1<N>
{ {
#[inline] #[inline]
fn rmul(&self, other: &Vec1<N>) -> Vec1<N> fn rmul(&self, other: &Vec1<N>) -> Vec1<N>
{ Vec1::new(self.m11 * other.x) } { Vec1::new([self.m11 * other.at[0]]) }
} }
impl<N: Add<N, N> + Mul<N, N>> LMul<Vec1<N>> for Mat1<N> impl<N: Add<N, N> + Mul<N, N>> LMul<Vec1<N>> for Mat1<N>
{ {
#[inline] #[inline]
fn lmul(&self, other: &Vec1<N>) -> Vec1<N> fn lmul(&self, other: &Vec1<N>) -> Vec1<N>
{ Vec1::new(self.m11 * other.x) } { Vec1::new([self.m11 * other.at[0]]) }
} }
impl<N:Copy + Mul<N, N> + Div<N, N> + Sub<N, N> + Neg<N> + Zero + One> impl<N: Copy + DivisionRing>
Inv for Mat1<N> Inv for Mat1<N>
{ {
#[inline] #[inline]
@ -101,7 +114,7 @@ impl<N: Copy> Transpose for Mat1<N>
{ } { }
} }
impl<N:ApproxEq<N>> ApproxEq<N> for Mat1<N> impl<N: ApproxEq<N>> ApproxEq<N> for Mat1<N>
{ {
#[inline] #[inline]
fn approx_epsilon() -> N fn approx_epsilon() -> N
@ -116,28 +129,9 @@ impl<N:ApproxEq<N>> ApproxEq<N> for Mat1<N>
{ self.m11.approx_eq_eps(&other.m11, epsilon) } { self.m11.approx_eq_eps(&other.m11, epsilon) }
} }
impl<N: Rand > Rand for Mat1<N> impl<N: Rand> Rand for Mat1<N>
{ {
#[inline] #[inline]
fn rand<R: Rng>(rng: &mut R) -> Mat1<N> fn rand<R: Rng>(rng: &mut R) -> Mat1<N>
{ Mat1::new(rng.gen()) } { Mat1::new(rng.gen()) }
} }
impl<N: Copy> Flatten<N> for Mat1<N>
{
#[inline]
fn flat_size() -> uint
{ 1 }
#[inline]
fn from_flattened(l: &[N], off: uint) -> Mat1<N>
{ Mat1::new(copy l[off]) }
#[inline]
fn flatten(&self) -> ~[N]
{ ~[ copy self.m11 ] }
#[inline]
fn flatten_to(&self, l: &mut [N], off: uint)
{ l[off] = copy self.m11 }
}

View File

@ -1,234 +0,0 @@
use std::num::{Zero, One, Algebraic, Bounded};
use std::rand::{Rand, Rng, RngUtil};
use std::cmp::ApproxEq;
use traits::basis::Basis;
use traits::dim::Dim;
use traits::dot::Dot;
use traits::norm::Norm;
use traits::translation::{Translation, Translatable};
use traits::sub_dot::SubDot;
use traits::flatten::Flatten;
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
#[deriving(Eq, Ord, ToStr)]
pub struct Vec1<N>
{ x : N }
impl<N> Vec1<N>
{
#[inline]
pub fn new(x: N) -> Vec1<N>
{ Vec1 {x: x} }
}
impl<N> Dim for Vec1<N>
{
#[inline]
fn dim() -> uint
{ 1 }
}
impl<N: Add<N, N>> Add<Vec1<N>, Vec1<N>> for Vec1<N>
{
#[inline]
fn add(&self, other: &Vec1<N>) -> Vec1<N>
{ Vec1::new(self.x + other.x) }
}
impl<N: Sub<N, N>> Sub<Vec1<N>, Vec1<N>> for Vec1<N>
{
#[inline]
fn sub(&self, other: &Vec1<N>) -> Vec1<N>
{ Vec1::new(self.x - other.x) }
}
impl<N: Mul<N, N>>
ScalarMul<N> for Vec1<N>
{
#[inline]
fn scalar_mul(&self, s: &N) -> Vec1<N>
{ Vec1 { x: self.x * *s } }
#[inline]
fn scalar_mul_inplace(&mut self, s: &N)
{ self.x = self.x * *s; }
}
impl<N: Div<N, N>>
ScalarDiv<N> for Vec1<N>
{
#[inline]
fn scalar_div(&self, s: &N) -> Vec1<N>
{ Vec1 { x: self.x / *s } }
#[inline]
fn scalar_div_inplace(&mut self, s: &N)
{ self.x = self.x / *s; }
}
impl<N: Add<N, N>>
ScalarAdd<N> for Vec1<N>
{
#[inline]
fn scalar_add(&self, s: &N) -> Vec1<N>
{ Vec1 { x: self.x + *s } }
#[inline]
fn scalar_add_inplace(&mut self, s: &N)
{ self.x = self.x + *s; }
}
impl<N: Sub<N, N>>
ScalarSub<N> for Vec1<N>
{
#[inline]
fn scalar_sub(&self, s: &N) -> Vec1<N>
{ Vec1 { x: self.x - *s } }
#[inline]
fn scalar_sub_inplace(&mut self, s: &N)
{ self.x = self.x - *s; }
}
impl<N: Copy + Add<N, N>> Translation<Vec1<N>> for Vec1<N>
{
#[inline]
fn translation(&self) -> Vec1<N>
{ copy *self }
#[inline]
fn translate(&mut self, t: &Vec1<N>)
{ *self = *self + *t }
}
impl<N: Add<N, N>> Translatable<Vec1<N>, Vec1<N>> for Vec1<N>
{
#[inline]
fn translated(&self, t: &Vec1<N>) -> Vec1<N>
{ self + *t }
}
impl<N: Mul<N, N>> Dot<N> for Vec1<N>
{
#[inline]
fn dot(&self, other : &Vec1<N>) -> N
{ self.x * other.x }
}
impl<N: Mul<N, N> + Sub<N, N>> SubDot<N> for Vec1<N>
{
#[inline]
fn sub_dot(&self, a: &Vec1<N>, b: &Vec1<N>) -> N
{ (self.x - a.x) * b.x }
}
impl<N: Mul<N, N> + Add<N, N> + Div<N, N> + Algebraic>
Norm<N> for Vec1<N>
{
#[inline]
fn sqnorm(&self) -> N
{ self.dot(self) }
#[inline]
fn norm(&self) -> N
{ self.sqnorm().sqrt() }
#[inline]
fn normalized(&self) -> Vec1<N>
{ Vec1::new(self.x / self.norm()) }
#[inline]
fn normalize(&mut self) -> N
{
let l = self.norm();
self.x = self.x / l;
l
}
}
impl<N: Neg<N>> Neg<Vec1<N>> for Vec1<N>
{
#[inline]
fn neg(&self) -> Vec1<N>
{ Vec1::new(-self.x) }
}
impl<N: Zero> Zero for Vec1<N>
{
#[inline]
fn zero() -> Vec1<N>
{
let _0 = Zero::zero();
Vec1::new(_0)
}
#[inline]
fn is_zero(&self) -> bool
{ self.x.is_zero() }
}
impl<N: One> Basis for Vec1<N>
{
#[inline]
fn canonical_basis() -> ~[Vec1<N>]
{ ~[ Vec1::new(One::one()) ] } // FIXME: this should be static
#[inline]
fn orthogonal_subspace_basis(&self) -> ~[Vec1<N>]
{ ~[] }
}
impl<N:ApproxEq<N>> ApproxEq<N> for Vec1<N>
{
#[inline]
fn approx_epsilon() -> N
{ ApproxEq::approx_epsilon::<N, N>() }
#[inline]
fn approx_eq(&self, other: &Vec1<N>) -> bool
{ self.x.approx_eq(&other.x) }
#[inline]
fn approx_eq_eps(&self, other: &Vec1<N>, epsilon: &N) -> bool
{ self.x.approx_eq_eps(&other.x, epsilon) }
}
impl<N: Rand> Rand for Vec1<N>
{
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Vec1<N>
{ Vec1::new(rng.gen()) }
}
impl<N: Copy> Flatten<N> for Vec1<N>
{
#[inline]
fn flat_size() -> uint
{ 1 }
#[inline]
fn from_flattened(l: &[N], off: uint) -> Vec1<N>
{ Vec1::new(copy l[off]) }
#[inline]
fn flatten(&self) -> ~[N]
{ ~[ copy self.x ] }
#[inline]
fn flatten_to(&self, l: &mut [N], off: uint)
{ l[off] = copy self.x }
}
impl<N: Bounded> Bounded for Vec1<N>
{
#[inline]
fn max_value() -> Vec1<N>
{ Vec1::new(Bounded::max_value()) }
#[inline]
fn min_value() -> Vec1<N>
{ Vec1::new(Bounded::min_value()) }
}

View File

@ -2,12 +2,13 @@ use std::num::{One, Zero};
use std::rand::{Rand, Rng, RngUtil}; use std::rand::{Rand, Rng, RngUtil};
use std::cmp::ApproxEq; use std::cmp::ApproxEq;
use std::util::swap; use std::util::swap;
use traits::transformation::Transform;
use traits::division_ring::DivisionRing;
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::flatten::Flatten;
use traits::rlmul::{RMul, LMul}; use traits::rlmul::{RMul, LMul};
use dim2::vec2::Vec2; use vec::Vec2;
#[deriving(Eq, ToStr)] #[deriving(Eq, ToStr)]
pub struct Mat2<N> pub struct Mat2<N>
@ -79,14 +80,26 @@ impl<N: Mul<N, N> + Add<N, N>> Mul<Mat2<N>, Mat2<N>> for Mat2<N>
} }
} }
impl<N: Copy + DivisionRing>
Transform<Vec2<N>> for Mat2<N>
{
#[inline]
fn transform_vec(&self, v: &Vec2<N>) -> Vec2<N>
{ self.rmul(v) }
#[inline]
fn inv_transform(&self, v: &Vec2<N>) -> Vec2<N>
{ self.inverse().transform_vec(v) }
}
impl<N: Add<N, N> + Mul<N, N>> RMul<Vec2<N>> for Mat2<N> impl<N: Add<N, N> + Mul<N, N>> RMul<Vec2<N>> for Mat2<N>
{ {
#[inline] #[inline]
fn rmul(&self, other: &Vec2<N>) -> Vec2<N> fn rmul(&self, other: &Vec2<N>) -> Vec2<N>
{ {
Vec2::new( Vec2::new(
self.m11 * other.x + self.m12 * other.y, [ self.m11 * other.at[0] + self.m12 * other.at[1],
self.m21 * other.x + self.m22 * other.y self.m21 * other.at[0] + self.m22 * other.at[1] ]
) )
} }
} }
@ -97,13 +110,13 @@ impl<N: Add<N, N> + Mul<N, N>> LMul<Vec2<N>> for Mat2<N>
fn lmul(&self, other: &Vec2<N>) -> Vec2<N> fn lmul(&self, other: &Vec2<N>) -> Vec2<N>
{ {
Vec2::new( Vec2::new(
self.m11 * other.x + self.m21 * other.y, [ self.m11 * other.at[0] + self.m21 * other.at[1],
self.m12 * other.x + self.m22 * other.y self.m12 * other.at[0] + self.m22 * other.at[1] ]
) )
} }
} }
impl<N:Copy + Mul<N, N> + Div<N, N> + Sub<N, N> + Neg<N> + Zero> impl<N: Copy + DivisionRing>
Inv for Mat2<N> Inv for Mat2<N>
{ {
#[inline] #[inline]
@ -175,27 +188,3 @@ impl<N: Rand> Rand for Mat2<N>
fn rand<R: Rng>(rng: &mut R) -> Mat2<N> fn rand<R: Rng>(rng: &mut R) -> Mat2<N>
{ Mat2::new(rng.gen(), rng.gen(), rng.gen(), rng.gen()) } { Mat2::new(rng.gen(), rng.gen(), rng.gen(), rng.gen()) }
} }
impl<N: Copy> Flatten<N> for Mat2<N>
{
#[inline]
fn flat_size() -> uint
{ 4 }
#[inline]
fn from_flattened(l: &[N], off: uint) -> Mat2<N>
{ Mat2::new(copy l[off], copy l[off + 1], copy l[off + 2], copy l[off + 3]) }
#[inline]
fn flatten(&self) -> ~[N]
{ ~[ copy self.m11, copy self.m12, copy self.m21, copy self.m22 ] }
#[inline]
fn flatten_to(&self, l: &mut [N], off: uint)
{
l[off] = copy self.m11;
l[off + 1] = copy self.m12;
l[off + 2] = copy self.m21;
l[off + 3] = copy self.m22;
}
}

View File

@ -1,270 +0,0 @@
use std::num::{Zero, One, Algebraic, Bounded};
use std::rand::{Rand, Rng, RngUtil};
use dim1::vec1::Vec1;
use std::cmp::ApproxEq;
use traits::basis::Basis;
use traits::cross::Cross;
use traits::dim::Dim;
use traits::dot::Dot;
use traits::sub_dot::SubDot;
use traits::norm::Norm;
use traits::flatten::Flatten;
use traits::translation::{Translation, Translatable};
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
#[deriving(Eq, Ord, ToStr)]
pub struct Vec2<N>
{
x : N,
y : N
}
impl<N> Vec2<N>
{
#[inline]
pub fn new(x: N, y: N) -> Vec2<N>
{ Vec2 {x: x, y: y} }
}
impl<N> Dim for Vec2<N>
{
#[inline]
fn dim() -> uint
{ 2 }
}
impl<N: Add<N,N>> Add<Vec2<N>, Vec2<N>> for Vec2<N>
{
#[inline]
fn add(&self, other: &Vec2<N>) -> Vec2<N>
{ Vec2::new(self.x + other.x, self.y + other.y) }
}
impl<N: Sub<N,N>> Sub<Vec2<N>, Vec2<N>> for Vec2<N>
{
#[inline]
fn sub(&self, other: &Vec2<N>) -> Vec2<N>
{ Vec2::new(self.x - other.x, self.y - other.y) }
}
impl<N: Mul<N, N>>
ScalarMul<N> for Vec2<N>
{
#[inline]
fn scalar_mul(&self, s: &N) -> Vec2<N>
{ Vec2 { x: self.x * *s, y: self.y * *s } }
#[inline]
fn scalar_mul_inplace(&mut self, s: &N)
{
self.x = self.x * *s;
self.y = self.y * *s;
}
}
impl<N: Div<N, N>>
ScalarDiv<N> for Vec2<N>
{
#[inline]
fn scalar_div(&self, s: &N) -> Vec2<N>
{ Vec2 { x: self.x / *s, y: self.y / *s } }
#[inline]
fn scalar_div_inplace(&mut self, s: &N)
{
self.x = self.x / *s;
self.y = self.y / *s;
}
}
impl<N: Add<N, N>>
ScalarAdd<N> for Vec2<N>
{
#[inline]
fn scalar_add(&self, s: &N) -> Vec2<N>
{ Vec2 { x: self.x + *s, y: self.y + *s } }
#[inline]
fn scalar_add_inplace(&mut self, s: &N)
{
self.x = self.x + *s;
self.y = self.y + *s;
}
}
impl<N: Sub<N, N>>
ScalarSub<N> for Vec2<N>
{
#[inline]
fn scalar_sub(&self, s: &N) -> Vec2<N>
{ Vec2 { x: self.x - *s, y: self.y - *s } }
#[inline]
fn scalar_sub_inplace(&mut self, s: &N)
{
self.x = self.x - *s;
self.y = self.y - *s;
}
}
impl<N: Copy + Add<N, N>> Translation<Vec2<N>> for Vec2<N>
{
#[inline]
fn translation(&self) -> Vec2<N>
{ copy *self }
#[inline]
fn translate(&mut self, t: &Vec2<N>)
{ *self = *self + *t; }
}
impl<N: Add<N, N>> Translatable<Vec2<N>, Vec2<N>> for Vec2<N>
{
#[inline]
fn translated(&self, t: &Vec2<N>) -> Vec2<N>
{ self + *t }
}
impl<N: Mul<N, N> + Add<N, N>> Dot<N> for Vec2<N>
{
#[inline]
fn dot(&self, other : &Vec2<N>) -> N
{ self.x * other.x + self.y * other.y }
}
impl<N: Mul<N, N> + Add<N, N> + Sub<N, N>> SubDot<N> for Vec2<N>
{
#[inline]
fn sub_dot(&self, a: &Vec2<N>, b: &Vec2<N>) -> N
{ (self.x - a.x) * b.x + (self.y - a.y) * b.y }
}
impl<N: Mul<N, N> + Add<N, N> + Div<N, N> + Algebraic>
Norm<N> for Vec2<N>
{
#[inline]
fn sqnorm(&self) -> N
{ self.dot(self) }
#[inline]
fn norm(&self) -> N
{ self.sqnorm().sqrt() }
#[inline]
fn normalized(&self) -> Vec2<N>
{
let l = self.norm();
Vec2::new(self.x / l, self.y / l)
}
#[inline]
fn normalize(&mut self) -> N
{
let l = self.norm();
self.x = self.x / l;
self.y = self.y / l;
l
}
}
impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec1<N>> for Vec2<N>
{
#[inline]
fn cross(&self, other : &Vec2<N>) -> Vec1<N>
{ Vec1::new(self.x * other.y - self.y * other.x) }
}
impl<N: Neg<N>> Neg<Vec2<N>> for Vec2<N>
{
#[inline]
fn neg(&self) -> Vec2<N>
{ Vec2::new(-self.x, -self.y) }
}
impl<N: Zero> Zero for Vec2<N>
{
#[inline]
fn zero() -> Vec2<N>
{ Vec2::new(Zero::zero(), Zero::zero()) }
#[inline]
fn is_zero(&self) -> bool
{ self.x.is_zero() && self.y.is_zero() }
}
impl<N: Copy + One + Zero + Neg<N>> Basis for Vec2<N>
{
#[inline]
fn canonical_basis() -> ~[Vec2<N>]
{
// FIXME: this should be static
~[ Vec2::new(One::one(), Zero::zero()),
Vec2::new(Zero::zero(), One::one()) ]
}
#[inline]
fn orthogonal_subspace_basis(&self) -> ~[Vec2<N>]
{ ~[ Vec2::new(-self.y, copy self.x) ] }
}
impl<N:ApproxEq<N>> ApproxEq<N> for Vec2<N>
{
#[inline]
fn approx_epsilon() -> N
{ ApproxEq::approx_epsilon::<N, N>() }
#[inline]
fn approx_eq(&self, other: &Vec2<N>) -> bool
{ self.x.approx_eq(&other.x) && self.y.approx_eq(&other.y) }
#[inline]
fn approx_eq_eps(&self, other: &Vec2<N>, epsilon: &N) -> bool
{
self.x.approx_eq_eps(&other.x, epsilon) &&
self.y.approx_eq_eps(&other.y, epsilon)
}
}
impl<N:Rand> Rand for Vec2<N>
{
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Vec2<N>
{ Vec2::new(rng.gen(), rng.gen()) }
}
impl<N: Copy> Flatten<N> for Vec2<N>
{
#[inline]
fn flat_size() -> uint
{ 2 }
#[inline]
fn from_flattened(l: &[N], off: uint) -> Vec2<N>
{ Vec2::new(copy l[off], copy l[off + 1]) }
#[inline]
fn flatten(&self) -> ~[N]
{ ~[ copy self.x, copy self.y ] }
#[inline]
fn flatten_to(&self, l: &mut [N], off: uint)
{
l[off] = copy self.x;
l[off + 1] = copy self.y;
}
}
impl<N: Bounded> Bounded for Vec2<N>
{
#[inline]
fn max_value() -> Vec2<N>
{ Vec2::new(Bounded::max_value(), Bounded::max_value()) }
#[inline]
fn min_value() -> Vec2<N>
{ Vec2::new(Bounded::min_value(), Bounded::min_value()) }
}

View File

@ -4,10 +4,11 @@ use std::cmp::ApproxEq;
use std::util::swap; use std::util::swap;
use traits::dim::Dim; use traits::dim::Dim;
use traits::inv::Inv; use traits::inv::Inv;
use traits::transformation::Transform;
use traits::division_ring::DivisionRing;
use traits::transpose::Transpose; use traits::transpose::Transpose;
use traits::flatten::Flatten;
use traits::rlmul::{RMul, LMul}; use traits::rlmul::{RMul, LMul};
use dim3::vec3::Vec3; use vec::Vec3;
#[deriving(Eq, ToStr)] #[deriving(Eq, ToStr)]
pub struct Mat3<N> pub struct Mat3<N>
@ -93,15 +94,27 @@ impl<N: Mul<N, N> + Add<N, N>> Mul<Mat3<N>, Mat3<N>> for Mat3<N>
} }
} }
impl<N: Copy + DivisionRing>
Transform<Vec3<N>> for Mat3<N>
{
#[inline]
fn transform_vec(&self, v: &Vec3<N>) -> Vec3<N>
{ self.rmul(v) }
#[inline]
fn inv_transform(&self, v: &Vec3<N>) -> Vec3<N>
{ self.inverse().transform_vec(v) }
}
impl<N: Add<N, N> + Mul<N, N>> RMul<Vec3<N>> for Mat3<N> impl<N: Add<N, N> + Mul<N, N>> RMul<Vec3<N>> for Mat3<N>
{ {
#[inline] #[inline]
fn rmul(&self, other: &Vec3<N>) -> Vec3<N> fn rmul(&self, other: &Vec3<N>) -> Vec3<N>
{ {
Vec3::new( Vec3::new(
self.m11 * other.x + self.m12 * other.y + self.m13 * other.z, [self.m11 * other.at[0] + self.m12 * other.at[1] + self.m13 * other.at[2],
self.m21 * other.x + self.m22 * other.y + self.m33 * other.z, self.m21 * other.at[0] + self.m22 * other.at[1] + self.m33 * other.at[2],
self.m31 * other.x + self.m32 * other.y + self.m33 * other.z self.m31 * other.at[0] + self.m32 * other.at[1] + self.m33 * other.at[2]]
) )
} }
} }
@ -112,14 +125,14 @@ impl<N: Add<N, N> + Mul<N, N>> LMul<Vec3<N>> for Mat3<N>
fn lmul(&self, other: &Vec3<N>) -> Vec3<N> fn lmul(&self, other: &Vec3<N>) -> Vec3<N>
{ {
Vec3::new( Vec3::new(
self.m11 * other.x + self.m21 * other.y + self.m31 * other.z, [self.m11 * other.at[0] + self.m21 * other.at[1] + self.m31 * other.at[2],
self.m12 * other.x + self.m22 * other.y + self.m32 * other.z, self.m12 * other.at[0] + self.m22 * other.at[1] + self.m32 * other.at[2],
self.m13 * other.x + self.m23 * other.y + self.m33 * other.z self.m13 * other.at[0] + self.m23 * other.at[1] + self.m33 * other.at[2]]
) )
} }
} }
impl<N:Copy + Mul<N, N> + Div<N, N> + Sub<N, N> + Add<N, N> + Neg<N> + Zero> impl<N: Copy + DivisionRing>
Inv for Mat3<N> Inv for Mat3<N>
{ {
#[inline] #[inline]
@ -229,40 +242,3 @@ impl<N: Rand> Rand for Mat3<N>
rng.gen(), rng.gen(), rng.gen()) rng.gen(), rng.gen(), rng.gen())
} }
} }
impl<N: Copy> Flatten<N> for Mat3<N>
{
#[inline]
fn flat_size() -> uint
{ 9 }
#[inline]
fn from_flattened(l: &[N], off: uint) -> Mat3<N>
{ Mat3::new(copy l[off + 0], copy l[off + 1], copy l[off + 2],
copy l[off + 3], copy l[off + 4], copy l[off + 5],
copy l[off + 6], copy l[off + 7], copy l[off + 8]) }
#[inline]
fn flatten(&self) -> ~[N]
{
~[
copy self.m11, copy self.m12, copy self.m13,
copy self.m21, copy self.m22, copy self.m23,
copy self.m31, copy self.m32, copy self.m33
]
}
#[inline]
fn flatten_to(&self, l: &mut [N], off: uint)
{
l[off + 0] = copy self.m11;
l[off + 1] = copy self.m12;
l[off + 2] = copy self.m13;
l[off + 3] = copy self.m21;
l[off + 4] = copy self.m22;
l[off + 5] = copy self.m23;
l[off + 6] = copy self.m31;
l[off + 7] = copy self.m32;
l[off + 8] = copy self.m33;
}
}

View File

@ -1,300 +0,0 @@
use std::num::{Zero, One, Algebraic, abs, Bounded};
use std::rand::{Rand, Rng, RngUtil};
use std::cmp::ApproxEq;
use traits::basis::Basis;
use traits::cross::Cross;
use traits::dim::Dim;
use traits::dot::Dot;
use traits::sub_dot::SubDot;
use traits::norm::Norm;
use traits::flatten::Flatten;
use traits::translation::{Translation, Translatable};
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
#[deriving(Eq, Ord, ToStr)]
pub struct Vec3<N>
{
x : N,
y : N,
z : N
}
impl<N> Vec3<N>
{
#[inline]
pub fn new(x: N, y: N, z: N) -> Vec3<N>
{ Vec3 {x: x, y: y, z: z} }
}
impl<N> Dim for Vec3<N>
{
#[inline]
fn dim() -> uint
{ 3 }
}
impl<N: Add<N,N>> Add<Vec3<N>, Vec3<N>> for Vec3<N>
{
#[inline]
fn add(&self, other: &Vec3<N>) -> Vec3<N>
{ Vec3::new(self.x + other.x, self.y + other.y, self.z + other.z) }
}
impl<N: Sub<N,N>> Sub<Vec3<N>, Vec3<N>> for Vec3<N>
{
#[inline]
fn sub(&self, other: &Vec3<N>) -> Vec3<N>
{ Vec3::new(self.x - other.x, self.y - other.y, self.z - other.z) }
}
impl<N: Mul<N, N>>
ScalarMul<N> for Vec3<N>
{
#[inline]
fn scalar_mul(&self, s: &N) -> Vec3<N>
{ Vec3 { x: self.x * *s, y: self.y * *s, z: self.z * *s } }
#[inline]
fn scalar_mul_inplace(&mut self, s: &N)
{
self.x = self.x * *s;
self.y = self.y * *s;
self.z = self.z * *s;
}
}
impl<N: Div<N, N>>
ScalarDiv<N> for Vec3<N>
{
#[inline]
fn scalar_div(&self, s: &N) -> Vec3<N>
{ Vec3 { x: self.x / *s, y: self.y / *s, z: self.z / *s } }
#[inline]
fn scalar_div_inplace(&mut self, s: &N)
{
self.x = self.x / *s;
self.y = self.y / *s;
self.z = self.z / *s;
}
}
impl<N: Add<N, N>>
ScalarAdd<N> for Vec3<N>
{
#[inline]
fn scalar_add(&self, s: &N) -> Vec3<N>
{ Vec3 { x: self.x + *s, y: self.y + *s, z: self.z + *s } }
#[inline]
fn scalar_add_inplace(&mut self, s: &N)
{
self.x = self.x + *s;
self.y = self.y + *s;
self.z = self.z + *s;
}
}
impl<N: Sub<N, N>>
ScalarSub<N> for Vec3<N>
{
#[inline]
fn scalar_sub(&self, s: &N) -> Vec3<N>
{ Vec3 { x: self.x - *s, y: self.y - *s, z: self.z - *s } }
#[inline]
fn scalar_sub_inplace(&mut self, s: &N)
{
self.x = self.x - *s;
self.y = self.y - *s;
self.z = self.z - *s;
}
}
impl<N: Copy + Add<N, N>> Translation<Vec3<N>> for Vec3<N>
{
#[inline]
fn translation(&self) -> Vec3<N>
{ copy *self }
#[inline]
fn translate(&mut self, t: &Vec3<N>)
{ *self = *self + *t; }
}
impl<N: Add<N, N>> Translatable<Vec3<N>, Vec3<N>> for Vec3<N>
{
#[inline]
fn translated(&self, t: &Vec3<N>) -> Vec3<N>
{ self + *t }
}
impl<N: Neg<N>> Neg<Vec3<N>> for Vec3<N>
{
#[inline]
fn neg(&self) -> Vec3<N>
{ Vec3::new(-self.x, -self.y, -self.z) }
}
impl<N: Mul<N, N> + Add<N, N>> Dot<N> for Vec3<N>
{
#[inline]
fn dot(&self, other : &Vec3<N>) -> N
{ self.x * other.x + self.y * other.y + self.z * other.z }
}
impl<N: Mul<N, N> + Add<N, N> + Sub<N, N>> SubDot<N> for Vec3<N>
{
#[inline]
fn sub_dot(&self, a: &Vec3<N>, b: &Vec3<N>) -> N
{ (self.x - a.x) * b.x + (self.y - a.y) * b.y + (self.z - a.z) * b.z }
}
impl<N: Mul<N, N> + Add<N, N> + Div<N, N> + Algebraic>
Norm<N> for Vec3<N>
{
#[inline]
fn sqnorm(&self) -> N
{ self.dot(self) }
#[inline]
fn norm(&self) -> N
{ self.sqnorm().sqrt() }
#[inline]
fn normalized(&self) -> Vec3<N>
{
let l = self.norm();
Vec3::new(self.x / l, self.y / l, self.z / l)
}
#[inline]
fn normalize(&mut self) -> N
{
let l = self.norm();
self.x = self.x / l;
self.y = self.y / l;
self.z = self.z / l;
l
}
}
impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec3<N>> for Vec3<N>
{
#[inline]
fn cross(&self, other : &Vec3<N>) -> Vec3<N>
{
Vec3::new(
self.y * other.z - self.z * other.y,
self.z * other.x - self.x * other.z,
self.x * other.y - self.y * other.x
)
}
}
impl<N: Zero> Zero for Vec3<N>
{
#[inline]
fn zero() -> Vec3<N>
{ Vec3::new(Zero::zero(), Zero::zero(), Zero::zero()) }
#[inline]
fn is_zero(&self) -> bool
{ self.x.is_zero() && self.y.is_zero() && self.z.is_zero() }
}
impl<N: Copy + One + Zero + Neg<N> + Ord + Mul<N, N> + Sub<N, N> + Add<N, N> +
Div<N, N> + Algebraic>
Basis for Vec3<N>
{
#[inline]
fn canonical_basis() -> ~[Vec3<N>]
{
// FIXME: this should be static
~[ Vec3::new(One::one(), Zero::zero(), Zero::zero()),
Vec3::new(Zero::zero(), One::one(), Zero::zero()),
Vec3::new(Zero::zero(), Zero::zero(), One::one()) ]
}
#[inline]
fn orthogonal_subspace_basis(&self) -> ~[Vec3<N>]
{
let a =
if abs(copy self.x) > abs(copy self.y)
{ Vec3::new(copy self.z, Zero::zero(), -copy self.x).normalized() }
else
{ Vec3::new(Zero::zero(), -self.z, copy self.y).normalized() };
~[ a.cross(self), a ]
}
}
impl<N:ApproxEq<N>> ApproxEq<N> for Vec3<N>
{
#[inline]
fn approx_epsilon() -> N
{ ApproxEq::approx_epsilon::<N, N>() }
#[inline]
fn approx_eq(&self, other: &Vec3<N>) -> bool
{
self.x.approx_eq(&other.x) &&
self.y.approx_eq(&other.y) &&
self.z.approx_eq(&other.z)
}
#[inline]
fn approx_eq_eps(&self, other: &Vec3<N>, epsilon: &N) -> bool
{
self.x.approx_eq_eps(&other.x, epsilon) &&
self.y.approx_eq_eps(&other.y, epsilon) &&
self.z.approx_eq_eps(&other.z, epsilon)
}
}
impl<N: Rand> Rand for Vec3<N>
{
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Vec3<N>
{ Vec3::new(rng.gen(), rng.gen(), rng.gen()) }
}
impl<N: Copy> Flatten<N> for Vec3<N>
{
#[inline]
fn flat_size() -> uint
{ 3 }
#[inline]
fn from_flattened(l: &[N], off: uint) -> Vec3<N>
{ Vec3::new(copy l[off], copy l[off + 1], copy l[off + 2]) }
#[inline]
fn flatten(&self) -> ~[N]
{ ~[ copy self.x, copy self.y, copy self.z ] }
#[inline]
fn flatten_to(&self, l: &mut [N], off: uint)
{
l[off] = copy self.x;
l[off + 1] = copy self.y;
l[off + 2] = copy self.z;
}
}
impl<N: Bounded> Bounded for Vec3<N>
{
#[inline]
fn max_value() -> Vec3<N>
{ Vec3::new(Bounded::max_value(), Bounded::max_value(), Bounded::max_value()) }
#[inline]
fn min_value() -> Vec3<N>
{ Vec3::new(Bounded::min_value(), Bounded::min_value(), Bounded::min_value()) }
}

View File

@ -15,24 +15,23 @@
extern mod std; extern mod std;
pub mod vec;
/// 1-dimensional linear algebra. /// 1-dimensional linear algebra.
pub mod dim1 pub mod dim1
{ {
pub mod vec1;
pub mod mat1; pub mod mat1;
} }
/// 2-dimensional linear algebra. /// 2-dimensional linear algebra.
pub mod dim2 pub mod dim2
{ {
pub mod vec2;
pub mod mat2; pub mod mat2;
} }
/// 3-dimensional linear algebra. /// 3-dimensional linear algebra.
pub mod dim3 pub mod dim3
{ {
pub mod vec3;
pub mod mat3; pub mod mat3;
} }
@ -55,6 +54,7 @@ pub mod adaptors
/// Useful linear-algebra related traits. /// Useful linear-algebra related traits.
pub mod traits pub mod traits
{ {
pub mod iterable;
pub mod dot; pub mod dot;
pub mod cross; pub mod cross;
pub mod inv; pub mod inv;
@ -65,12 +65,10 @@ pub mod traits
pub mod rotation; pub mod rotation;
pub mod translation; pub mod translation;
pub mod transformation; pub mod transformation;
pub mod delta_transform;
pub mod vector_space; pub mod vector_space;
pub mod ring; pub mod ring;
pub mod division_ring; pub mod division_ring;
pub mod sub_dot; pub mod sub_dot;
pub mod flatten;
pub mod rlmul; pub mod rlmul;
pub mod scalar_op; pub mod scalar_op;
} }

View File

@ -1,8 +1,10 @@
use std::uint::iterate; use std::uint::iterate;
use std::num::{Zero, One, Algebraic}; use std::num::{Zero, One, Algebraic};
use std::vec::{VecIterator, VecMutIterator};
use std::vec::{map_zip, map, from_elem}; use std::vec::{map_zip, map, from_elem};
use std::cmp::ApproxEq; use std::cmp::ApproxEq;
use std::iterator::IteratorUtil; use std::iterator::{FromIterator, IteratorUtil};
use traits::iterable::{Iterable, IterableMut};
use traits::ring::Ring; use traits::ring::Ring;
use traits::division_ring::DivisionRing; use traits::division_ring::DivisionRing;
use traits::dot::Dot; use traits::dot::Dot;
@ -25,6 +27,31 @@ pub fn zero_vec_with_dim<N: Zero + Copy>(dim: uint) -> DVec<N>
pub fn is_zero_vec<N: Zero>(vec: &DVec<N>) -> bool pub fn is_zero_vec<N: Zero>(vec: &DVec<N>) -> bool
{ vec.at.iter().all(|e| e.is_zero()) } { vec.at.iter().all(|e| e.is_zero()) }
impl<N> Iterable<N> for DVec<N>
{
fn iter<'l>(&'l self) -> VecIterator<'l, N>
{ self.at.iter() }
}
impl<N> IterableMut<N> for DVec<N>
{
fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N>
{ self.at.mut_iter() }
}
impl<N, Iter: Iterator<N>> FromIterator<N, Iter> for DVec<N>
{
fn from_iterator(param: &mut Iter) -> DVec<N>
{
let mut res = DVec { at: ~[] };
for param.advance |e|
{ res.at.push(e) }
res
}
}
// FIXME: is Clone needed? // FIXME: is Clone needed?
impl<N: Copy + DivisionRing + Algebraic + Clone + ApproxEq<N>> DVec<N> impl<N: Copy + DivisionRing + Algebraic + Clone + ApproxEq<N>> DVec<N>
{ {
@ -196,14 +223,18 @@ ScalarSub<N> for DVec<N>
} }
} }
impl<N: Clone + Copy + Add<N, N>> Translation<DVec<N>> for DVec<N> impl<N: Clone + Copy + Add<N, N> + Neg<N>> Translation<DVec<N>> for DVec<N>
{ {
#[inline] #[inline]
fn translation(&self) -> DVec<N> fn translation(&self) -> DVec<N>
{ self.clone() } { self.clone() }
#[inline] #[inline]
fn translate(&mut self, t: &DVec<N>) fn inv_translation(&self) -> DVec<N>
{ -self }
#[inline]
fn translate_by(&mut self, t: &DVec<N>)
{ *self = *self + *t; } { *self = *self + *t; }
} }

View File

@ -6,7 +6,6 @@ use traits::dim::Dim;
use traits::inv::Inv; use traits::inv::Inv;
use traits::division_ring::DivisionRing; use traits::division_ring::DivisionRing;
use traits::transpose::Transpose; use traits::transpose::Transpose;
use traits::flatten::Flatten;
use traits::rlmul::{RMul, LMul}; use traits::rlmul::{RMul, LMul};
use ndim::dmat::{DMat, one_mat_with_dim, zero_mat_with_dim, is_zero_mat}; use ndim::dmat::{DMat, one_mat_with_dim, zero_mat_with_dim, is_zero_mat};
use ndim::nvec::NVec; use ndim::nvec::NVec;
@ -183,43 +182,3 @@ impl<D: Dim, N: Rand + Zero + Copy> Rand for NMat<D, N>
res res
} }
} }
impl<D: Dim, N: Zero + Copy> Flatten<N> for NMat<D, N>
{
#[inline]
fn flat_size() -> uint
{ Dim::dim::<D>() * Dim::dim::<D>() }
#[inline]
fn from_flattened(l: &[N], off: uint) -> NMat<D, N>
{
let dim = Dim::dim::<D>();
let mut res = Zero::zero::<NMat<D, N>>();
for iterate(0u, dim * dim) |i|
{ res.mij.mij[i] = copy l[off + i] }
res
}
#[inline]
fn flatten(&self) -> ~[N]
{
let dim = Dim::dim::<D>();
let mut res = ~[];
for iterate(0u, dim * dim) |i|
{ res.push(copy self.mij.mij[i]) }
res
}
#[inline]
fn flatten_to(&self, l: &mut [N], off: uint)
{
let dim = Dim::dim::<D>();
for iterate(0u, dim * dim) |i|
{ l[off + i] = copy self.mij.mij[i] }
}
}

View File

@ -1,9 +1,11 @@
use std::uint::iterate; use std::uint::iterate;
use std::num::{Zero, Algebraic, Bounded}; use std::num::{Zero, Algebraic, Bounded};
use std::rand::{Rand, Rng, RngUtil}; use std::rand::{Rand, Rng, RngUtil};
use std::vec::{map}; use std::vec::{VecIterator, VecMutIterator};
use std::cmp::ApproxEq; use std::cmp::ApproxEq;
use std::iterator::{IteratorUtil, FromIterator};
use ndim::dvec::{DVec, zero_vec_with_dim, is_zero_vec}; use ndim::dvec::{DVec, zero_vec_with_dim, is_zero_vec};
use traits::iterable::{Iterable, IterableMut};
use traits::basis::Basis; use traits::basis::Basis;
use traits::ring::Ring; use traits::ring::Ring;
use traits::division_ring::DivisionRing; use traits::division_ring::DivisionRing;
@ -12,7 +14,6 @@ use traits::dot::Dot;
use traits::sub_dot::SubDot; use traits::sub_dot::SubDot;
use traits::norm::Norm; use traits::norm::Norm;
use traits::translation::{Translation, Translatable}; use traits::translation::{Translation, Translatable};
use traits::flatten::Flatten;
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub}; use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
// D is a phantom parameter, used only as a dimensional token. // D is a phantom parameter, used only as a dimensional token.
@ -38,6 +39,35 @@ impl<D, N: Clone> Clone for NVec<D, N>
{ NVec{ at: self.at.clone() } } { NVec{ at: self.at.clone() } }
} }
impl<D, N> Iterable<N> for NVec<D, N>
{
fn iter<'l>(&'l self) -> VecIterator<'l, N>
{ self.at.iter() }
}
impl<D, N> IterableMut<N> for NVec<D, N>
{
fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N>
{ self.at.mut_iter() }
}
impl<D: Dim, N: Zero + Copy, Iter: Iterator<N>> FromIterator<N, Iter> for NVec<D, N>
{
fn from_iterator(param: &mut Iter) -> NVec<D, N>
{
let mut res: NVec<D, N> = Zero::zero();
let mut i = 0;
for param.advance |e|
{
res.at.at[i] = e;
i = i + 1;
}
res
}
}
impl<D, N: Copy + Add<N,N>> Add<NVec<D, N>, NVec<D, N>> for NVec<D, N> impl<D, N: Copy + Add<N,N>> Add<NVec<D, N>, NVec<D, N>> for NVec<D, N>
{ {
#[inline] #[inline]
@ -123,14 +153,19 @@ ScalarSub<N> for NVec<D, N>
{ self.at.scalar_sub_inplace(s) } { self.at.scalar_sub_inplace(s) }
} }
impl<D: Dim, N: Clone + Copy + Add<N, N>> Translation<NVec<D, N>> for NVec<D, N> impl<D: Dim, N: Clone + Copy + Add<N, N> + Neg<N>> Translation<NVec<D, N>> for NVec<D, N>
{ {
#[inline] #[inline]
fn translation(&self) -> NVec<D, N> fn translation(&self) -> NVec<D, N>
{ self.clone() } { self.clone() }
#[inline] #[inline]
fn translate(&mut self, t: &NVec<D, N>) fn inv_translation(&self) -> NVec<D, N>
{ -self.clone() }
#[inline]
fn translate_by(&mut self, t: &NVec<D, N>)
{ *self = *self + *t; } { *self = *self + *t; }
} }
@ -173,11 +208,11 @@ Basis for NVec<D, N>
{ {
#[inline] #[inline]
fn canonical_basis() -> ~[NVec<D, N>] fn canonical_basis() -> ~[NVec<D, N>]
{ map(DVec::canonical_basis_with_dim(Dim::dim::<D>()), |&e| NVec { at: e }) } { DVec::canonical_basis_with_dim(Dim::dim::<D>()).map(|&e| NVec { at: e }) }
#[inline] #[inline]
fn orthogonal_subspace_basis(&self) -> ~[NVec<D, N>] fn orthogonal_subspace_basis(&self) -> ~[NVec<D, N>]
{ map(self.at.orthogonal_subspace_basis(), |&e| NVec { at: e }) } { self.at.orthogonal_subspace_basis().map(|&e| NVec { at: e }) }
} }
// FIXME: I dont really know how te generalize the cross product int // FIXME: I dont really know how te generalize the cross product int
@ -229,46 +264,6 @@ impl<D: Dim, N: Rand + Zero + Copy> Rand for NVec<D, N>
} }
} }
impl<D: Dim, N: Zero + Copy> Flatten<N> for NVec<D, N>
{
#[inline]
fn flat_size() -> uint
{ Dim::dim::<D>() }
#[inline]
fn from_flattened(l: &[N], off: uint) -> NVec<D, N>
{
let dim = Dim::dim::<D>();
let mut res = Zero::zero::<NVec<D, N>>();
for iterate(0u, dim) |i|
{ res.at.at[i] = copy l[off + i] }
res
}
#[inline]
fn flatten(&self) -> ~[N]
{
let dim = Dim::dim::<D>();
let mut res = ~[];
for iterate(0u, dim) |i|
{ res.push(copy self.at.at[i]) }
res
}
#[inline]
fn flatten_to(&self, l: &mut [N], off: uint)
{
let dim = Dim::dim::<D>();
for iterate(0u, dim) |i|
{ l[off + i] = copy self.at.at[i] }
}
}
impl<D: Dim, N: Bounded + Zero + Add<N, N> + Copy> Bounded for NVec<D, N> impl<D: Dim, N: Bounded + Zero + Add<N, N> + Copy> Bounded for NVec<D, N>
{ {
#[inline] #[inline]

View File

@ -1,7 +1,5 @@
#[test] #[test]
use std::vec; use std::num::{Real, One, abs};
#[test]
use std::num::{Real, Zero, One, abs};
#[test] #[test]
use std::rand::random; use std::rand::random;
#[test] #[test]
@ -11,9 +9,7 @@ use traits::inv::Inv;
#[test] #[test]
use traits::rotation::{Rotation, Rotatable}; use traits::rotation::{Rotation, Rotatable};
#[test] #[test]
use traits::dim::d7; use vec::Vec1;
#[test]
use dim1::vec1::Vec1;
#[test] #[test]
use dim1::mat1::Mat1; use dim1::mat1::Mat1;
#[test] #[test]
@ -21,11 +17,7 @@ use dim2::mat2::Mat2;
#[test] #[test]
use dim3::mat3::Mat3; use dim3::mat3::Mat3;
#[test] #[test]
use ndim::nmat::NMat;
#[test]
use adaptors::rotmat::Rotmat; use adaptors::rotmat::Rotmat;
#[test]
use traits::flatten::Flatten;
macro_rules! test_inv_mat_impl( macro_rules! test_inv_mat_impl(
($t: ty) => ( ($t: ty) => (
@ -38,21 +30,6 @@ macro_rules! test_inv_mat_impl(
); );
) )
macro_rules! test_flatten_impl(
($t: ty, $n: ty) => (
for 10000.times
{
let v: $t = random();
let mut l: ~[$n] = vec::from_elem(42 + Flatten::flat_size::<$n, $t>(), Zero::zero::<$n>());
v.flatten_to(l, 42);
assert!(Flatten::from_flattened::<$n, $t>(v.flatten(), 0) == v);
assert!(Flatten::from_flattened::<$n, $t>(l, 42) == v);
}
)
)
#[test] #[test]
fn test_inv_mat1() fn test_inv_mat1()
{ test_inv_mat_impl!(Mat1<f64>); } { test_inv_mat_impl!(Mat1<f64>); }
@ -70,29 +47,13 @@ fn test_inv_mat3()
// fn test_inv_nmat() // fn test_inv_nmat()
// { test_inv_mat_impl!(NMat<d7, f64>); } // { test_inv_mat_impl!(NMat<d7, f64>); }
#[test]
fn test_flatten_mat1()
{ test_flatten_impl!(Mat1<f64>, f64); }
#[test]
fn test_flatten_mat2()
{ test_flatten_impl!(Mat2<f64>, f64); }
#[test]
fn test_flatten_mat3()
{ test_flatten_impl!(Mat3<f64>, f64); }
#[test]
fn test_flatten_nmat()
{ test_flatten_impl!(NMat<d7, f64>, f64); }
#[test] #[test]
fn test_rotation2() fn test_rotation2()
{ {
for 10000.times for 10000.times
{ {
let randmat = One::one::<Rotmat<Mat2<f64>>>(); let randmat = One::one::<Rotmat<Mat2<f64>>>();
let ang = &Vec1::new(abs::<f64>(random()) % Real::pi()); let ang = &Vec1::new([abs::<f64>(random()) % Real::pi()]);
assert!(randmat.rotated(ang).rotation().approx_eq(ang)); assert!(randmat.rotated(ang).rotation().approx_eq(ang));
} }

View File

@ -1,6 +1,4 @@
#[test] #[test]
use std::vec;
#[test]
use std::iterator::IteratorUtil; use std::iterator::IteratorUtil;
#[test] #[test]
use std::num::{Zero, One}; use std::num::{Zero, One};
@ -9,11 +7,7 @@ use std::rand::{random};
#[test] #[test]
use std::cmp::ApproxEq; use std::cmp::ApproxEq;
#[test] #[test]
use dim3::vec3::Vec3; use vec::{Vec1, Vec2, Vec3};
#[test]
use dim2::vec2::Vec2;
#[test]
use dim1::vec1::Vec1;
#[test] #[test]
use ndim::nvec::NVec; use ndim::nvec::NVec;
#[test] #[test]
@ -27,10 +21,28 @@ use traits::dot::Dot;
#[test] #[test]
use traits::norm::Norm; use traits::norm::Norm;
#[test] #[test]
use traits::flatten::Flatten; use traits::iterable::{Iterable, IterableMut};
#[test] #[test]
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub}; use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
macro_rules! test_iterator_impl(
($t: ty, $n: ty) => (
for 10000.times
{
let v: $t = random();
let mut mv: $t = copy v;
let n: $n = random();
let nv: $t = v.iter().transform(|e| e * n).collect();
for mv.mut_iter().advance |e|
{ *e = *e * n }
assert!(nv == mv && nv == v.scalar_mul(&n));
}
)
)
macro_rules! test_commut_dot_impl( macro_rules! test_commut_dot_impl(
($t: ty) => ( ($t: ty) => (
for 10000.times for 10000.times
@ -105,21 +117,6 @@ macro_rules! test_subspace_basis_impl(
); );
) )
macro_rules! test_flatten_impl(
($t: ty, $n: ty) => (
for 10000.times
{
let v: $t = random();
let mut l: ~[$n] = vec::from_elem(42 + Flatten::flat_size::<$n, $t>(), Zero::zero::<$n>());
v.flatten_to(l, 42);
assert!(Flatten::from_flattened::<$n, $t>(v.flatten(), 0) == v);
assert!(Flatten::from_flattened::<$n, $t>(l, 42) == v);
}
)
)
#[test] #[test]
fn test_cross_vec3() fn test_cross_vec3()
{ {
@ -182,22 +179,6 @@ fn test_subspace_basis_vec3()
fn test_subspace_basis_nvec() fn test_subspace_basis_nvec()
{ test_subspace_basis_impl!(NVec<d7, f64>); } { test_subspace_basis_impl!(NVec<d7, f64>); }
#[test]
fn test_flatten_vec1()
{ test_flatten_impl!(Vec1<f64>, f64); }
#[test]
fn test_flatten_vec2()
{ test_flatten_impl!(Vec2<f64>, f64); }
#[test]
fn test_flatten_vec3()
{ test_flatten_impl!(Vec3<f64>, f64); }
#[test]
fn test_flatten_nvec()
{ test_flatten_impl!(NVec<d7, f64>, f64); }
#[test] #[test]
fn test_scalar_op_vec1() fn test_scalar_op_vec1()
{ test_scalar_op_impl!(Vec1<f64>, f64); } { test_scalar_op_impl!(Vec1<f64>, f64); }
@ -213,3 +194,19 @@ fn test_scalar_op_vec3()
#[test] #[test]
fn test_scalar_op_nvec() fn test_scalar_op_nvec()
{ test_scalar_op_impl!(NVec<d7, f64>, f64); } { test_scalar_op_impl!(NVec<d7, f64>, f64); }
#[test]
fn test_iterator_vec1()
{ test_iterator_impl!(Vec1<f64>, f64); }
#[test]
fn test_iterator_vec2()
{ test_iterator_impl!(Vec2<f64>, f64); }
#[test]
fn test_iterator_vec3()
{ test_iterator_impl!(Vec3<f64>, f64); }
#[test]
fn test_iterator_nvec()
{ test_iterator_impl!(NVec<d7, f64>, f64); }

View File

@ -2,6 +2,7 @@ pub trait Basis
{ {
/// Computes the canonical basis of the space in which this object lives. /// Computes the canonical basis of the space in which this object lives.
// FIXME: need type-associated values // FIXME: need type-associated values
// FIXME: this will make allocations… this is bad
fn canonical_basis() -> ~[Self]; fn canonical_basis() -> ~[Self];
fn orthogonal_subspace_basis(&self) -> ~[Self]; fn orthogonal_subspace_basis(&self) -> ~[Self];
} }

View File

@ -1,19 +0,0 @@
/**
* A delta-transformation is the generalization of rotation. A delta transform
* can apply any transformation to the object without translating it.
* In partilular, 0 is neutral wrt. the delta-transform.
*/
pub trait DeltaTransform<DT>
{
/// Extracts the delta transformation associated with this transformation.
fn delta_transform(&self) -> DT;
}
/**
* Trait of delta-transformations on vectors.
*/
pub trait DeltaTransformVector<V>
{
/// Applies a delta-transform to a vector.
fn delta_transform_vector(&self, &V) -> V;
}

View File

@ -1,34 +0,0 @@
/// Trait of objects which can be written as a list of values, and read from
/// that list.
pub trait Flatten<N>
{
/// The number of elements needed to flatten this object.
fn flat_size() -> uint;
/**
* Creates a new object from its flattened version. Its flattened version is
* a continuous list of values. It is assumet that `flat_size` elements will
* be read.
*
* - `l`: list from which the flat version must be read.
* - `off`: index from which (included) the flat version read must begin.
* It is assumed that the caller gives a valid input.
*/
fn from_flattened(l: &[N], off: uint) -> Self; // FIXME: keep (vector + index) or use an iterator?
/**
* Creates a flattened version of `self`. The result vector must be of size
* `flat_size`.
*/
fn flatten(&self) -> ~[N];
/**
* Creates a flattened version of `self` on a vector. It is assumed that
* `flat_size` elements will be written contiguously.
*
* - `l`: list to which the flat version must be written.
* - `off`: index from which (included) the flat version write must begin.
* It is assumed that the caller allocated a long enough list.
*/
fn flatten_to(&self, l: &mut [N], off: uint); // FIXME: keep (vector + index) or use an iterator (to a mutable value…)?
}

55
src/traits/iterable.rs Normal file
View File

@ -0,0 +1,55 @@
use std::vec;
pub trait Iterable<N>
{
fn iter<'l>(&'l self) -> vec::VecIterator<'l, N>;
}
pub trait IterableMut<N>
{
fn mut_iter<'l>(&'l mut self) -> vec::VecMutIterator<'l, N>;
}
/*
* FIXME: the prevous traits are only workarounds.
* It should be something like:
pub trait Iterable<'self, N, I: Iterator<N>>
{
fn iter(&'self self) -> I;
}
pub trait IterableMut<'self, N, I: Iterator<N>>
{
fn mut_iter(&'self self) -> I;
}
* but this gives an ICE =(
* For now, we oblige the iterator to be one specific type which works with
* everything on this lib.
*/
pub trait FromAnyIterator<N>
{
fn from_iterator<'l>(&mut vec::VecIterator<'l, N>) -> Self;
fn from_mut_iterator<'l>(&mut vec::VecMutIterator<'l, N>) -> Self;
}
/*
* FIXME: the previous trait is only a workaround.
* It should be something like:
pub trait FromAnyIterator<N>
{
fn from_iterator<I: Iterator<N>>(&mut I) -> Self;
}
* but this gives a wierd error message (the compile seems to mistake N with
* I).
* For now, we oblige the iterator to be one specific type which works with
* everything on this lib.
*
* Note that we dont use the standard std::iterator::FromIterator<N, I: Iterator<N>>
* because it is too hard to work with on generic code (as a type bound)
* because we have to name explicitly the type of the iterator.
*
*/

View File

@ -8,8 +8,10 @@ pub trait Rotation<V>
/// Gets the rotation associated with this object. /// Gets the rotation associated with this object.
fn rotation(&self) -> V; fn rotation(&self) -> V;
fn inv_rotation(&self) -> V;
/// In-place version of `rotated`. /// In-place version of `rotated`.
fn rotate(&mut self, &V); fn rotate_by(&mut self, &V);
} }
pub trait Rotatable<V, Res: Rotation<V>> pub trait Rotatable<V, Res: Rotation<V>>
@ -19,6 +21,12 @@ pub trait Rotatable<V, Res: Rotation<V>>
fn rotated(&self, &V) -> Res; fn rotated(&self, &V) -> Res;
} }
pub trait Rotate<V>
{
fn rotate(&self, &V) -> V;
fn inv_rotate(&self, &V) -> V;
}
/** /**
* Applies a rotation centered on a specific point. * Applies a rotation centered on a specific point.
* *
@ -35,8 +43,8 @@ pub fn rotate_wrt_point<M: Translatable<LV, M2>,
{ {
let mut res = m.translated(&-center); let mut res = m.translated(&-center);
res.rotate(ammount); res.rotate_by(ammount);
res.translate(center); res.translate_by(center);
res res
} }

View File

@ -2,11 +2,19 @@ pub trait Transformation<M>
{ {
fn transformation(&self) -> M; fn transformation(&self) -> M;
// XXX: we must use "transform_by" instead of "transform" because of a fn inv_transformation(&self) -> M;
// conflict with some iterator function…
fn transform_by(&mut self, &M); fn transform_by(&mut self, &M);
} }
pub trait Transform<V>
{
// XXX: sadly we cannot call this `transform` as it conflicts with the
// iterators' `transform` function (which seems always exist).
fn transform_vec(&self, &V) -> V;
fn inv_transform(&self, &V) -> V;
}
pub trait Transformable<M, Res: Transformation<M>> pub trait Transformable<M, Res: Transformation<M>>
{ {
fn transformed(&self, &M) -> Res; fn transformed(&self, &M) -> Res;

View File

@ -6,8 +6,16 @@ pub trait Translation<V>
/// Gets the translation associated with this object. /// Gets the translation associated with this object.
fn translation(&self) -> V; fn translation(&self) -> V;
fn inv_translation(&self) -> V;
/// In-place version of `translate`. /// In-place version of `translate`.
fn translate(&mut self, &V); fn translate_by(&mut self, &V);
}
pub trait Translate<V>
{
fn translate(&self, &V) -> V;
fn inv_translate(&self, &V) -> V;
} }
pub trait Translatable<V, Res: Translation<V>> pub trait Translatable<V, Res: Translation<V>>

705
src/vec.rs Normal file
View File

@ -0,0 +1,705 @@
use std::num::{abs, Zero, One, Algebraic, Bounded};
use std::rand::{Rand, Rng, RngUtil};
use std::vec::{VecIterator, VecMutIterator};
use std::iterator::{Iterator, FromIterator};
use std::cmp::ApproxEq;
use traits::iterable::{Iterable, IterableMut, FromAnyIterator};
use traits::basis::Basis;
use traits::cross::Cross;
use traits::dim::Dim;
use traits::dot::Dot;
use traits::sub_dot::SubDot;
use traits::norm::Norm;
use traits::translation::{Translation, Translatable};
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
use std::uint::iterate;
use std::iterator::IteratorUtil;
use traits::ring::Ring;
use traits::division_ring::DivisionRing;
// FIXME: is there a way to split this file:
// one file for macros
// another file for macro calls and specializations
// ?
macro_rules! new_impl(
($t: ident, $dim: expr) => (
impl<N> $t<N>
{
#[inline]
pub fn new(at: [N, ..$dim]) -> $t<N>
{ $t { at: at } }
}
)
)
macro_rules! new_repeat_impl(
($t: ident, $param: ident, [ $($elem: ident)|+ ]) => (
impl<N: Copy> $t<N>
{
#[inline]
pub fn new_repeat($param: N) -> $t<N>
{ $t{ at: [ $( copy $elem, )+ ] } }
}
)
)
macro_rules! iterable_impl(
($t: ident) => (
impl<N> Iterable<N> for $t<N>
{
fn iter<'l>(&'l self) -> VecIterator<'l, N>
{ self.at.iter() }
}
)
)
macro_rules! iterable_mut_impl(
($t: ident) => (
impl<N> IterableMut<N> for $t<N>
{
fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N>
{ self.at.mut_iter() }
}
)
)
macro_rules! eq_impl(
($t: ident) => (
impl<N: Eq> Eq for $t<N>
{
#[inline]
fn eq(&self, other: &$t<N>) -> bool
{ self.at.iter().zip(other.at.iter()).all(|(a, b)| a == b) }
#[inline]
fn ne(&self, other: &$t<N>) -> bool
{ self.at.iter().zip(other.at.iter()).all(|(a, b)| a != b) }
}
)
)
macro_rules! dim_impl(
($t: ident, $dim: expr) => (
impl<N> Dim for $t<N>
{
#[inline]
fn dim() -> uint
{ $dim }
}
)
)
// FIXME: add the possibility to specialize that
macro_rules! basis_impl(
($t: ident, $dim: expr) => (
impl<N: Copy + DivisionRing + Algebraic + ApproxEq<N>> Basis for $t<N>
{
pub fn canonical_basis() -> ~[$t<N>]
{
let mut res : ~[$t<N>] = ~[];
for iterate(0u, $dim) |i|
{
let mut basis_element : $t<N> = Zero::zero();
basis_element.at[i] = One::one();
res.push(basis_element);
}
res
}
pub fn orthogonal_subspace_basis(&self) -> ~[$t<N>]
{
// compute the basis of the orthogonal subspace using Gram-Schmidt
// orthogonalization algorithm
let mut res : ~[$t<N>] = ~[];
for iterate(0u, $dim) |i|
{
let mut basis_element : $t<N> = Zero::zero();
basis_element.at[i] = One::one();
if res.len() == $dim - 1
{ break; }
let mut elt = copy basis_element;
elt = elt - self.scalar_mul(&basis_element.dot(self));
for res.iter().advance |v|
{ elt = elt - v.scalar_mul(&elt.dot(v)) };
if !elt.sqnorm().approx_eq(&Zero::zero())
{ res.push(elt.normalized()); }
}
res
}
}
)
)
macro_rules! add_impl(
($t: ident) => (
impl<N: Copy + Add<N,N>> Add<$t<N>, $t<N>> for $t<N>
{
#[inline]
fn add(&self, other: &$t<N>) -> $t<N>
{
self.at.iter()
.zip(other.at.iter())
.transform(|(a, b)| { *a + *b })
.collect()
}
}
)
)
macro_rules! sub_impl(
($t: ident) => (
impl<N: Copy + Sub<N,N>> Sub<$t<N>, $t<N>> for $t<N>
{
#[inline]
fn sub(&self, other: &$t<N>) -> $t<N>
{
self.at.iter()
.zip(other.at.iter())
.transform(| (a, b) | { *a - *b })
.collect()
}
}
)
)
macro_rules! neg_impl(
($t: ident) => (
impl<N: Neg<N>> Neg<$t<N>> for $t<N>
{
#[inline]
fn neg(&self) -> $t<N>
{ self.at.iter().transform(|a| -a).collect() }
}
)
)
macro_rules! dot_impl(
($t: ident, $dim: expr) => (
impl<N: Ring> Dot<N> for $t<N>
{
#[inline]
fn dot(&self, other: &$t<N>) -> N
{
let mut res = Zero::zero::<N>();
for iterate(0u, $dim) |i|
{ res = res + self.at[i] * other.at[i]; }
res
}
}
)
)
macro_rules! sub_dot_impl(
($t: ident, $dim: expr) => (
impl<N: Ring> SubDot<N> for $t<N>
{
#[inline]
fn sub_dot(&self, a: &$t<N>, b: &$t<N>) -> N
{
let mut res = Zero::zero::<N>();
for iterate(0u, $dim) |i|
{ res = res + (self.at[i] - a.at[i]) * b.at[i]; }
res
}
}
)
)
macro_rules! scalar_mul_impl(
($t: ident, $dim: expr) => (
impl<N: Mul<N, N>> ScalarMul<N> for $t<N>
{
#[inline]
fn scalar_mul(&self, s: &N) -> $t<N>
{ self.at.iter().transform(|a| a * *s).collect() }
#[inline]
fn scalar_mul_inplace(&mut self, s: &N)
{
for iterate(0u, $dim) |i|
{ self.at[i] = self.at[i] * *s; }
}
}
)
)
macro_rules! scalar_div_impl(
($t: ident, $dim: expr) => (
impl<N: Div<N, N>> ScalarDiv<N> for $t<N>
{
#[inline]
fn scalar_div(&self, s: &N) -> $t<N>
{ self.at.iter().transform(|a| a / *s).collect() }
#[inline]
fn scalar_div_inplace(&mut self, s: &N)
{
for iterate(0u, $dim) |i|
{ self.at[i] = self.at[i] / *s; }
}
}
)
)
macro_rules! scalar_add_impl(
($t: ident, $dim: expr) => (
impl<N: Add<N, N>> ScalarAdd<N> for $t<N>
{
#[inline]
fn scalar_add(&self, s: &N) -> $t<N>
{ self.at.iter().transform(|a| a + *s).collect() }
#[inline]
fn scalar_add_inplace(&mut self, s: &N)
{
for iterate(0u, $dim) |i|
{ self.at[i] = self.at[i] + *s; }
}
}
)
)
macro_rules! scalar_sub_impl(
($t: ident, $dim: expr) => (
impl<N: Sub<N, N>> ScalarSub<N> for $t<N>
{
#[inline]
fn scalar_sub(&self, s: &N) -> $t<N>
{ self.at.iter().transform(|a| a - *s).collect() }
#[inline]
fn scalar_sub_inplace(&mut self, s: &N)
{
for iterate(0u, $dim) |i|
{ self.at[i] = self.at[i] - *s; }
}
}
)
)
macro_rules! translation_impl(
($t: ident) => (
impl<N: Copy + Add<N, N> + Neg<N>> Translation<$t<N>> for $t<N>
{
#[inline]
fn translation(&self) -> $t<N>
{ copy *self }
#[inline]
fn inv_translation(&self) -> $t<N>
{ -self }
#[inline]
fn translate_by(&mut self, t: &$t<N>)
{ *self = *self + *t; }
}
)
)
macro_rules! translatable_impl(
($t: ident) => (
impl<N: Add<N, N> + Copy> Translatable<$t<N>, $t<N>> for $t<N>
{
#[inline]
fn translated(&self, t: &$t<N>) -> $t<N>
{ self + *t }
}
)
)
macro_rules! norm_impl(
($t: ident, $dim: expr) => (
impl<N: Copy + DivisionRing + Algebraic> Norm<N> for $t<N>
{
#[inline]
fn sqnorm(&self) -> N
{ self.dot(self) }
#[inline]
fn norm(&self) -> N
{ self.sqnorm().sqrt() }
#[inline]
fn normalized(&self) -> $t<N>
{
let mut res : $t<N> = copy *self;
res.normalize();
res
}
#[inline]
fn normalize(&mut self) -> N
{
let l = self.norm();
for iterate(0u, $dim) |i|
{ self.at[i] = self.at[i] / l; }
l
}
}
)
)
macro_rules! approx_eq_impl(
($t: ident) => (
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N>
{
#[inline]
fn approx_epsilon() -> N
{ ApproxEq::approx_epsilon::<N, N>() }
#[inline]
fn approx_eq(&self, other: &$t<N>) -> bool
{
let mut zip = self.at.iter().zip(other.at.iter());
do zip.all |(a, b)| { a.approx_eq(b) }
}
#[inline]
fn approx_eq_eps(&self, other: &$t<N>, epsilon: &N) -> bool
{
let mut zip = self.at.iter().zip(other.at.iter());
do zip.all |(a, b)| { a.approx_eq_eps(b, epsilon) }
}
}
)
)
macro_rules! zero_impl(
($t: ident) => (
impl<N: Copy + Zero> Zero for $t<N>
{
#[inline]
fn zero() -> $t<N>
{ $t::new_repeat(Zero::zero()) }
#[inline]
fn is_zero(&self) -> bool
{ self.at.iter().all(|e| e.is_zero()) }
}
)
)
macro_rules! rand_impl(
($t: ident, $param: ident, [ $($elem: ident)|+ ]) => (
impl<N: Rand> Rand for $t<N>
{
#[inline]
fn rand<R: Rng>($param: &mut R) -> $t<N>
{ $t::new([ $( $elem.gen(), )+ ]) }
}
)
)
macro_rules! from_any_iterator_impl(
($t: ident, $param: ident, [ $($elem: ident)|+ ]) => (
impl<N: Copy> FromAnyIterator<N> for $t<N>
{
fn from_iterator<'l>($param: &mut VecIterator<'l, N>) -> $t<N>
{ $t { at: [ $( copy *$elem.next().unwrap(), )+ ] } }
fn from_mut_iterator<'l>($param: &mut VecMutIterator<'l, N>) -> $t<N>
{ $t { at: [ $( copy *$elem.next().unwrap(), )+ ] } }
}
)
)
macro_rules! from_iterator_impl(
($t: ident, $param: ident, [ $($elem: ident)|+ ]) => (
impl<N, Iter: Iterator<N>> FromIterator<N, Iter> for $t<N>
{
fn from_iterator($param: &mut Iter) -> $t<N>
{ $t { at: [ $( $elem.next().unwrap(), )+ ] } }
}
)
)
macro_rules! bounded_impl(
($t: ident) => (
impl<N: Bounded + Copy> Bounded for $t<N>
{
#[inline]
fn max_value() -> $t<N>
{ $t::new_repeat(Bounded::max_value()) }
#[inline]
fn min_value() -> $t<N>
{ $t::new_repeat(Bounded::min_value()) }
}
)
)
#[deriving(Ord, ToStr)]
pub struct Vec1<N>
{ at: [N, ..1] }
new_impl!(Vec1, 1)
new_repeat_impl!(Vec1, elem, [elem])
dim_impl!(Vec1, 1)
eq_impl!(Vec1)
// (specialized) basis_impl!(Vec1, 1)
add_impl!(Vec1)
sub_impl!(Vec1)
neg_impl!(Vec1)
dot_impl!(Vec1, 1)
sub_dot_impl!(Vec1, 1)
scalar_mul_impl!(Vec1, 1)
scalar_div_impl!(Vec1, 1)
scalar_add_impl!(Vec1, 1)
scalar_sub_impl!(Vec1, 1)
translation_impl!(Vec1)
translatable_impl!(Vec1)
norm_impl!(Vec1, 1)
approx_eq_impl!(Vec1)
zero_impl!(Vec1)
rand_impl!(Vec1, rng, [rng])
from_iterator_impl!(Vec1, iterator, [iterator])
from_any_iterator_impl!(Vec1, iterator, [iterator])
bounded_impl!(Vec1)
iterable_impl!(Vec1)
iterable_mut_impl!(Vec1)
#[deriving(Ord, ToStr)]
pub struct Vec2<N>
{ at: [N, ..2] }
new_impl!(Vec2, 2)
new_repeat_impl!(Vec2, elem, [elem | elem])
dim_impl!(Vec2, 2)
eq_impl!(Vec2)
// (specialized) basis_impl!(Vec2, 2)
add_impl!(Vec2)
sub_impl!(Vec2)
neg_impl!(Vec2)
dot_impl!(Vec2, 2)
sub_dot_impl!(Vec2, 2)
scalar_mul_impl!(Vec2, 2)
scalar_div_impl!(Vec2, 2)
scalar_add_impl!(Vec2, 2)
scalar_sub_impl!(Vec2, 2)
translation_impl!(Vec2)
translatable_impl!(Vec2)
norm_impl!(Vec2, 2)
approx_eq_impl!(Vec2)
zero_impl!(Vec2)
rand_impl!(Vec2, rng, [rng | rng])
from_iterator_impl!(Vec2, iterator, [iterator | iterator])
from_any_iterator_impl!(Vec2, iterator, [iterator | iterator])
bounded_impl!(Vec2)
iterable_impl!(Vec2)
iterable_mut_impl!(Vec2)
#[deriving(Ord, ToStr)]
pub struct Vec3<N>
{ at: [N, ..3] }
new_impl!(Vec3, 3)
new_repeat_impl!(Vec3, elem, [elem | elem | elem])
dim_impl!(Vec3, 3)
eq_impl!(Vec3)
// (specialized) basis_impl!(Vec3, 3)
add_impl!(Vec3)
sub_impl!(Vec3)
neg_impl!(Vec3)
dot_impl!(Vec3, 3)
sub_dot_impl!(Vec3, 3)
scalar_mul_impl!(Vec3, 3)
scalar_div_impl!(Vec3, 3)
scalar_add_impl!(Vec3, 3)
scalar_sub_impl!(Vec3, 3)
translation_impl!(Vec3)
translatable_impl!(Vec3)
norm_impl!(Vec3, 3)
approx_eq_impl!(Vec3)
zero_impl!(Vec3)
rand_impl!(Vec3, rng, [rng | rng | rng])
from_iterator_impl!(Vec3, iterator, [iterator | iterator | iterator])
from_any_iterator_impl!(Vec3, iterator, [iterator | iterator | iterator])
bounded_impl!(Vec3)
iterable_impl!(Vec3)
iterable_mut_impl!(Vec3)
#[deriving(Ord, ToStr)]
pub struct Vec4<N>
{ at: [N, ..4] }
new_impl!(Vec4, 4)
new_repeat_impl!(Vec4, elem, [elem | elem | elem | elem])
dim_impl!(Vec4, 4)
eq_impl!(Vec4)
basis_impl!(Vec4, 4)
add_impl!(Vec4)
sub_impl!(Vec4)
neg_impl!(Vec4)
dot_impl!(Vec4, 4)
sub_dot_impl!(Vec4, 4)
scalar_mul_impl!(Vec4, 4)
scalar_div_impl!(Vec4, 4)
scalar_add_impl!(Vec4, 4)
scalar_sub_impl!(Vec4, 4)
translation_impl!(Vec4)
translatable_impl!(Vec4)
norm_impl!(Vec4, 4)
approx_eq_impl!(Vec4)
zero_impl!(Vec4)
rand_impl!(Vec4, rng, [rng | rng | rng | rng])
from_iterator_impl!(Vec4, iterator, [iterator | iterator | iterator | iterator])
from_any_iterator_impl!(Vec4, iterator, [iterator | iterator | iterator | iterator])
bounded_impl!(Vec4)
iterable_impl!(Vec4)
iterable_mut_impl!(Vec4)
#[deriving(Ord, ToStr)]
pub struct Vec5<N>
{ at: [N, ..5] }
new_impl!(Vec5, 5)
new_repeat_impl!(Vec5, elem, [elem | elem | elem | elem | elem])
dim_impl!(Vec5, 5)
eq_impl!(Vec5)
basis_impl!(Vec5, 5)
add_impl!(Vec5)
sub_impl!(Vec5)
neg_impl!(Vec5)
dot_impl!(Vec5, 5)
sub_dot_impl!(Vec5, 5)
scalar_mul_impl!(Vec5, 5)
scalar_div_impl!(Vec5, 5)
scalar_add_impl!(Vec5, 5)
scalar_sub_impl!(Vec5, 5)
translation_impl!(Vec5)
translatable_impl!(Vec5)
norm_impl!(Vec5, 5)
approx_eq_impl!(Vec5)
zero_impl!(Vec5)
rand_impl!(Vec5, rng, [rng | rng | rng | rng | rng])
from_iterator_impl!(Vec5, iterator, [iterator | iterator | iterator | iterator | iterator])
from_any_iterator_impl!(Vec5, iterator, [iterator | iterator | iterator | iterator | iterator])
bounded_impl!(Vec5)
iterable_impl!(Vec5)
iterable_mut_impl!(Vec5)
#[deriving(Ord, ToStr)]
pub struct Vec6<N>
{ at: [N, ..6] }
new_impl!(Vec6, 6)
new_repeat_impl!(Vec6, elem, [elem | elem | elem | elem | elem | elem])
dim_impl!(Vec6, 6)
eq_impl!(Vec6)
basis_impl!(Vec6, 6)
add_impl!(Vec6)
sub_impl!(Vec6)
neg_impl!(Vec6)
dot_impl!(Vec6, 6)
sub_dot_impl!(Vec6, 6)
scalar_mul_impl!(Vec6, 6)
scalar_div_impl!(Vec6, 6)
scalar_add_impl!(Vec6, 6)
scalar_sub_impl!(Vec6, 6)
translation_impl!(Vec6)
translatable_impl!(Vec6)
norm_impl!(Vec6, 6)
approx_eq_impl!(Vec6)
zero_impl!(Vec6)
rand_impl!(Vec6, rng, [rng | rng | rng | rng | rng | rng])
from_iterator_impl!(Vec6, iterator, [iterator | iterator | iterator | iterator | iterator | iterator])
from_any_iterator_impl!(Vec6, iterator, [iterator | iterator | iterator | iterator | iterator | iterator])
bounded_impl!(Vec6)
iterable_impl!(Vec6)
iterable_mut_impl!(Vec6)
impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec1<N>> for Vec2<N>
{
#[inline]
fn cross(&self, other : &Vec2<N>) -> Vec1<N>
{ Vec1::new([self.at[0] * other.at[1] - self.at[1] * other.at[0]]) }
}
impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec3<N>> for Vec3<N>
{
#[inline]
fn cross(&self, other : &Vec3<N>) -> Vec3<N>
{
Vec3::new(
[self.at[1] * other.at[2] - self.at[2] * other.at[1],
self.at[2] * other.at[0] - self.at[0] * other.at[2],
self.at[0] * other.at[1] - self.at[1] * other.at[0]]
)
}
}
impl<N: One> Basis for Vec1<N>
{
#[inline]
fn canonical_basis() -> ~[Vec1<N>]
{ ~[ Vec1::new([One::one()]) ] } // FIXME: this should be static
#[inline]
fn orthogonal_subspace_basis(&self) -> ~[Vec1<N>]
{ ~[] }
}
impl<N: Copy + One + Zero + Neg<N>> Basis for Vec2<N>
{
#[inline]
fn canonical_basis() -> ~[Vec2<N>]
{
// FIXME: this should be static
~[ Vec2::new([One::one(), Zero::zero()]),
Vec2::new([Zero::zero(), One::one()]) ]
}
#[inline]
fn orthogonal_subspace_basis(&self) -> ~[Vec2<N>]
{ ~[ Vec2::new([-self.at[1], copy self.at[0]]) ] }
}
impl<N: Copy + DivisionRing + Ord + Algebraic>
Basis for Vec3<N>
{
#[inline]
fn canonical_basis() -> ~[Vec3<N>]
{
// FIXME: this should be static
~[ Vec3::new([One::one(), Zero::zero(), Zero::zero()]),
Vec3::new([Zero::zero(), One::one(), Zero::zero()]),
Vec3::new([Zero::zero(), Zero::zero(), One::one()]) ]
}
#[inline]
fn orthogonal_subspace_basis(&self) -> ~[Vec3<N>]
{
let a =
if abs(copy self.at[0]) > abs(copy self.at[1])
{ Vec3::new([copy self.at[2], Zero::zero(), -copy self.at[0]]).normalized() }
else
{ Vec3::new([Zero::zero(), -self.at[2], copy self.at[1]]).normalized() };
~[ a.cross(self), a ]
}
}