From cd355dfb30cf0eae041fe4ba69a3a79c5703f54c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Fri, 28 Jun 2013 21:03:40 +0000 Subject: [PATCH] Refactor vec{1, 2, 3} implemenation + add some useful traits. --- src/adaptors/rotmat.rs | 67 ++-- src/adaptors/transform.rs | 83 ++-- src/dim1/mat1.rs | 46 +-- src/dim1/vec1.rs | 234 ----------- src/dim2/mat2.rs | 51 +-- src/dim2/vec2.rs | 270 ------------- src/dim3/mat3.rs | 68 ++-- src/dim3/vec3.rs | 300 --------------- src/nalgebra.rc | 8 +- src/ndim/dvec.rs | 37 +- src/ndim/nmat.rs | 41 -- src/ndim/nvec.rs | 87 ++--- src/tests/mat.rs | 45 +-- src/tests/vec.rs | 75 ++-- src/traits/basis.rs | 1 + src/traits/delta_transform.rs | 19 - src/traits/flatten.rs | 34 -- src/traits/iterable.rs | 55 +++ src/traits/rotation.rs | 14 +- src/traits/transformation.rs | 12 +- src/traits/translation.rs | 10 +- src/vec.rs | 705 ++++++++++++++++++++++++++++++++++ 22 files changed, 1070 insertions(+), 1192 deletions(-) delete mode 100644 src/dim1/vec1.rs delete mode 100644 src/dim2/vec2.rs delete mode 100644 src/dim3/vec3.rs delete mode 100644 src/traits/delta_transform.rs delete mode 100644 src/traits/flatten.rs create mode 100644 src/traits/iterable.rs create mode 100644 src/vec.rs diff --git a/src/adaptors/rotmat.rs b/src/adaptors/rotmat.rs index 1cca1e86..59354e9f 100644 --- a/src/adaptors/rotmat.rs +++ b/src/adaptors/rotmat.rs @@ -5,12 +5,12 @@ use traits::rlmul::{RMul, LMul}; use traits::dim::Dim; use traits::inv::Inv; use traits::transpose::Transpose; -use traits::rotation::{Rotation, Rotatable}; -use traits::delta_transform::{DeltaTransform, DeltaTransformVector}; -use dim1::vec1::Vec1; +use traits::rotation::{Rotation, Rotate, Rotatable}; +use traits::transformation::{Transform}; // FIXME: implement Transformation and Transformable +use vec::Vec1; use dim2::mat2::Mat2; use dim3::mat3::Mat3; -use dim3::vec3::{Vec3}; +use vec::Vec3; #[deriving(Eq, ToStr)] pub struct Rotmat @@ -30,9 +30,9 @@ pub fn rotmat3 + One + Sub + Add + (axis: &Vec3, angle: N) -> Rotmat> { let _1 = One::one::(); - let ux = copy axis.x; - let uy = copy axis.y; - let uz = copy axis.z; + let ux = copy axis.at[0]; + let uy = copy axis.at[1]; + let uz = copy axis.at[2]; let sqx = ux * ux; let sqy = uy * uy; let sqz = uz * uz; @@ -61,10 +61,14 @@ Rotation> for Rotmat> { #[inline] fn rotation(&self) -> Vec1 - { Vec1::new(-(self.submat.m12 / self.submat.m11).atan()) } + { Vec1::new([-(self.submat.m12 / self.submat.m11).atan()]) } #[inline] - fn rotate(&mut self, rot: &Vec1) + fn inv_rotation(&self) -> Vec1 + { -self.rotation() } + + #[inline] + fn rotate_by(&mut self, rot: &Vec1) { *self = self.rotated(rot) } } @@ -73,7 +77,7 @@ Rotatable, Rotmat>> for Rotmat> { #[inline] fn rotated(&self, rot: &Vec1) -> Rotmat> - { rotmat2(copy rot.x) * *self } + { rotmat2(copy rot.at[0]) * *self } } impl + Trigonometric + Neg + Mul + Add + Copy + @@ -83,9 +87,14 @@ Rotation<(Vec3, N)> for Rotmat> #[inline] fn rotation(&self) -> (Vec3, N) { fail!("Not yet implemented.") } + #[inline] + + fn inv_rotation(&self) -> (Vec3, N) + { fail!("Not yet implemented.") } + #[inline] - fn rotate(&mut self, rot: &(Vec3, N)) + fn rotate_by(&mut self, rot: &(Vec3, N)) { *self = self.rotated(rot) } } @@ -105,6 +114,28 @@ impl> Rand for Rotmat> { rotmat2(rng.gen()) } } +impl + LMul, V> Rotate for Rotmat +{ + #[inline] + fn rotate(&self, v: &V) -> V + { self.rmul(v) } + + #[inline] + fn inv_rotate(&self, v: &V) -> V + { self.lmul(v) } +} + +impl + LMul, V> Transform for Rotmat +{ + #[inline] + fn transform_vec(&self, v: &V) -> V + { self.rotate(v) } + + #[inline] + fn inv_transform(&self, v: &V) -> V + { self.inv_rotate(v) } +} + impl + One + Sub + Add + Mul> Rand for Rotmat> @@ -149,20 +180,6 @@ impl> LMul for Rotmat { self.submat.lmul(other) } } -impl DeltaTransform for Rotmat -{ - #[inline] - fn delta_transform(&self) -> M - { copy self.submat } -} - -impl, V> DeltaTransformVector for Rotmat -{ - #[inline] - fn delta_transform_vector(&self, v: &V) -> V - { self.submat.rmul(v) } -} - impl Inv for Rotmat { #[inline] diff --git a/src/adaptors/transform.rs b/src/adaptors/transform.rs index 32ba9ecc..cc7de693 100644 --- a/src/adaptors/transform.rs +++ b/src/adaptors/transform.rs @@ -3,11 +3,10 @@ use std::rand::{Rand, Rng, RngUtil}; use std::cmp::ApproxEq; use traits::dim::Dim; use traits::inv::Inv; -use traits::rotation::{Rotation, Rotatable}; -use traits::translation::{Translation, Translatable}; +use traits::rotation::{Rotation, Rotate, Rotatable}; +use traits::translation::{Translation, Translate, Translatable}; +use traits::transformation; use traits::transformation::{Transformation, Transformable}; -use traits::transpose::Transpose; -use traits::delta_transform::{DeltaTransform, DeltaTransformVector}; use traits::rlmul::{RMul, LMul}; #[deriving(Eq, ToStr)] @@ -81,8 +80,23 @@ impl> Translation for Transform { self.subtrans.translation() } #[inline] - fn translate(&mut self, t: &V) - { self.subtrans.translate(t) } + fn inv_translation(&self) -> V + { self.subtrans.inv_translation() } + + #[inline] + fn translate_by(&mut self, t: &V) + { self.subtrans.translate_by(t) } +} + +impl, V, _0> Translate for Transform +{ + #[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, Res: Translation> @@ -103,16 +117,32 @@ Rotation for Transform { self.submat.rotation() } #[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 let mut delta = One::one::(); - delta.rotate(rot); - self.submat.rotate(rot); + delta.rotate_by(rot); + self.submat.rotate_by(rot); self.subtrans = delta.rmul(&self.subtrans); } } +impl, V, _0> Rotate for Transform +{ + #[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 + One, Res: Rotation + RMul, V, @@ -129,15 +159,32 @@ Rotatable> for Transform } } -impl + Mul + Copy, V: Add + Copy> Transformation> for Transform +impl + Mul + Copy, V: Add + Neg + Copy> +Transformation> for Transform { fn transformation(&self) -> Transform { copy *self } + fn inv_transformation(&self) -> Transform + { self.inverse() } + fn transform_by(&mut self, other: &Transform) { *self = other * *self; } } +impl, V: Add + Sub> +transformation::Transform for Transform +{ + #[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. // Should be: Transformable ... impl + Mul, V: Add> @@ -147,21 +194,7 @@ Transformable, Transform> for Transform { t * *self } } -impl DeltaTransform for Transform -{ - #[inline] - fn delta_transform(&self) -> M - { copy self.submat } -} - -impl, V> DeltaTransformVector for Transform -{ - #[inline] - fn delta_transform_vector(&self, v: &V) -> V - { self.submat.rmul(v) } -} - -impl, V: Copy + Neg> +impl, V: Copy + Neg> Inv for Transform { #[inline] diff --git a/src/dim1/mat1.rs b/src/dim1/mat1.rs index dff62629..540a3947 100644 --- a/src/dim1/mat1.rs +++ b/src/dim1/mat1.rs @@ -1,12 +1,13 @@ use std::num::{One, Zero}; use std::rand::{Rand, Rng, RngUtil}; use std::cmp::ApproxEq; +use traits::division_ring::DivisionRing; use traits::dim::Dim; use traits::inv::Inv; use traits::transpose::Transpose; -use traits::flatten::Flatten; +use traits::transformation::Transform; // FIXME: implement Transformable, Transformation use traits::rlmul::{RMul, LMul}; -use dim1::vec1::Vec1; +use vec::Vec1; #[deriving(Eq, ToStr)] pub struct Mat1 @@ -54,21 +55,33 @@ impl + Add> Mul, Mat1> for Mat1 { Mat1::new(self.m11 * other.m11) } } +impl +Transform> for Mat1 +{ + #[inline] + fn transform_vec(&self, v: &Vec1) -> Vec1 + { self.rmul(v) } + + #[inline] + fn inv_transform(&self, v: &Vec1) -> Vec1 + { self.inverse().transform_vec(v) } +} + impl + Mul> RMul> for Mat1 { #[inline] fn rmul(&self, other: &Vec1) -> Vec1 - { Vec1::new(self.m11 * other.x) } + { Vec1::new([self.m11 * other.at[0]]) } } impl + Mul> LMul> for Mat1 { #[inline] fn lmul(&self, other: &Vec1) -> Vec1 - { Vec1::new(self.m11 * other.x) } + { Vec1::new([self.m11 * other.at[0]]) } } -impl + Div + Sub + Neg + Zero + One> +impl Inv for Mat1 { #[inline] @@ -101,7 +114,7 @@ impl Transpose for Mat1 { } } -impl> ApproxEq for Mat1 +impl> ApproxEq for Mat1 { #[inline] fn approx_epsilon() -> N @@ -116,28 +129,9 @@ impl> ApproxEq for Mat1 { self.m11.approx_eq_eps(&other.m11, epsilon) } } -impl Rand for Mat1 +impl Rand for Mat1 { #[inline] fn rand(rng: &mut R) -> Mat1 { Mat1::new(rng.gen()) } } - -impl Flatten for Mat1 -{ - #[inline] - fn flat_size() -> uint - { 1 } - - #[inline] - fn from_flattened(l: &[N], off: uint) -> Mat1 - { 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 } -} diff --git a/src/dim1/vec1.rs b/src/dim1/vec1.rs deleted file mode 100644 index a96a1bb9..00000000 --- a/src/dim1/vec1.rs +++ /dev/null @@ -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 -{ x : N } - -impl Vec1 -{ - #[inline] - pub fn new(x: N) -> Vec1 - { Vec1 {x: x} } -} - -impl Dim for Vec1 -{ - #[inline] - fn dim() -> uint - { 1 } -} - -impl> Add, Vec1> for Vec1 -{ - #[inline] - fn add(&self, other: &Vec1) -> Vec1 - { Vec1::new(self.x + other.x) } -} - -impl> Sub, Vec1> for Vec1 -{ - #[inline] - fn sub(&self, other: &Vec1) -> Vec1 - { Vec1::new(self.x - other.x) } -} - -impl> -ScalarMul for Vec1 -{ - #[inline] - fn scalar_mul(&self, s: &N) -> Vec1 - { Vec1 { x: self.x * *s } } - - #[inline] - fn scalar_mul_inplace(&mut self, s: &N) - { self.x = self.x * *s; } -} - - -impl> -ScalarDiv for Vec1 -{ - #[inline] - fn scalar_div(&self, s: &N) -> Vec1 - { Vec1 { x: self.x / *s } } - - #[inline] - fn scalar_div_inplace(&mut self, s: &N) - { self.x = self.x / *s; } -} - -impl> -ScalarAdd for Vec1 -{ - #[inline] - fn scalar_add(&self, s: &N) -> Vec1 - { Vec1 { x: self.x + *s } } - - #[inline] - fn scalar_add_inplace(&mut self, s: &N) - { self.x = self.x + *s; } -} - -impl> -ScalarSub for Vec1 -{ - #[inline] - fn scalar_sub(&self, s: &N) -> Vec1 - { Vec1 { x: self.x - *s } } - - #[inline] - fn scalar_sub_inplace(&mut self, s: &N) - { self.x = self.x - *s; } -} - -impl> Translation> for Vec1 -{ - #[inline] - fn translation(&self) -> Vec1 - { copy *self } - - #[inline] - fn translate(&mut self, t: &Vec1) - { *self = *self + *t } -} - -impl> Translatable, Vec1> for Vec1 -{ - #[inline] - fn translated(&self, t: &Vec1) -> Vec1 - { self + *t } -} - -impl> Dot for Vec1 -{ - #[inline] - fn dot(&self, other : &Vec1) -> N - { self.x * other.x } -} - -impl + Sub> SubDot for Vec1 -{ - #[inline] - fn sub_dot(&self, a: &Vec1, b: &Vec1) -> N - { (self.x - a.x) * b.x } -} - -impl + Add + Div + Algebraic> -Norm for Vec1 -{ - #[inline] - fn sqnorm(&self) -> N - { self.dot(self) } - - #[inline] - fn norm(&self) -> N - { self.sqnorm().sqrt() } - - #[inline] - fn normalized(&self) -> Vec1 - { Vec1::new(self.x / self.norm()) } - - #[inline] - fn normalize(&mut self) -> N - { - let l = self.norm(); - - self.x = self.x / l; - - l - } -} - -impl> Neg> for Vec1 -{ - #[inline] - fn neg(&self) -> Vec1 - { Vec1::new(-self.x) } -} - -impl Zero for Vec1 -{ - #[inline] - fn zero() -> Vec1 - { - let _0 = Zero::zero(); - Vec1::new(_0) - } - - #[inline] - fn is_zero(&self) -> bool - { self.x.is_zero() } -} - -impl Basis for Vec1 -{ - #[inline] - fn canonical_basis() -> ~[Vec1] - { ~[ Vec1::new(One::one()) ] } // FIXME: this should be static - - #[inline] - fn orthogonal_subspace_basis(&self) -> ~[Vec1] - { ~[] } -} - -impl> ApproxEq for Vec1 -{ - #[inline] - fn approx_epsilon() -> N - { ApproxEq::approx_epsilon::() } - - #[inline] - fn approx_eq(&self, other: &Vec1) -> bool - { self.x.approx_eq(&other.x) } - - #[inline] - fn approx_eq_eps(&self, other: &Vec1, epsilon: &N) -> bool - { self.x.approx_eq_eps(&other.x, epsilon) } -} - -impl Rand for Vec1 -{ - #[inline] - fn rand(rng: &mut R) -> Vec1 - { Vec1::new(rng.gen()) } -} - -impl Flatten for Vec1 -{ - #[inline] - fn flat_size() -> uint - { 1 } - - #[inline] - fn from_flattened(l: &[N], off: uint) -> Vec1 - { 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 Bounded for Vec1 -{ - #[inline] - fn max_value() -> Vec1 - { Vec1::new(Bounded::max_value()) } - - #[inline] - fn min_value() -> Vec1 - { Vec1::new(Bounded::min_value()) } -} diff --git a/src/dim2/mat2.rs b/src/dim2/mat2.rs index 5f46855c..e24eca28 100644 --- a/src/dim2/mat2.rs +++ b/src/dim2/mat2.rs @@ -2,12 +2,13 @@ use std::num::{One, Zero}; use std::rand::{Rand, Rng, RngUtil}; use std::cmp::ApproxEq; use std::util::swap; +use traits::transformation::Transform; +use traits::division_ring::DivisionRing; use traits::dim::Dim; use traits::inv::Inv; use traits::transpose::Transpose; -use traits::flatten::Flatten; use traits::rlmul::{RMul, LMul}; -use dim2::vec2::Vec2; +use vec::Vec2; #[deriving(Eq, ToStr)] pub struct Mat2 @@ -79,14 +80,26 @@ impl + Add> Mul, Mat2> for Mat2 } } +impl +Transform> for Mat2 +{ + #[inline] + fn transform_vec(&self, v: &Vec2) -> Vec2 + { self.rmul(v) } + + #[inline] + fn inv_transform(&self, v: &Vec2) -> Vec2 + { self.inverse().transform_vec(v) } +} + impl + Mul> RMul> for Mat2 { #[inline] fn rmul(&self, other: &Vec2) -> Vec2 { Vec2::new( - self.m11 * other.x + self.m12 * other.y, - self.m21 * other.x + self.m22 * other.y + [ self.m11 * other.at[0] + self.m12 * other.at[1], + self.m21 * other.at[0] + self.m22 * other.at[1] ] ) } } @@ -97,13 +110,13 @@ impl + Mul> LMul> for Mat2 fn lmul(&self, other: &Vec2) -> Vec2 { Vec2::new( - self.m11 * other.x + self.m21 * other.y, - self.m12 * other.x + self.m22 * other.y + [ self.m11 * other.at[0] + self.m21 * other.at[1], + self.m12 * other.at[0] + self.m22 * other.at[1] ] ) } } -impl + Div + Sub + Neg + Zero> +impl Inv for Mat2 { #[inline] @@ -175,27 +188,3 @@ impl Rand for Mat2 fn rand(rng: &mut R) -> Mat2 { Mat2::new(rng.gen(), rng.gen(), rng.gen(), rng.gen()) } } - -impl Flatten for Mat2 -{ - #[inline] - fn flat_size() -> uint - { 4 } - - #[inline] - fn from_flattened(l: &[N], off: uint) -> Mat2 - { 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; - } -} diff --git a/src/dim2/vec2.rs b/src/dim2/vec2.rs deleted file mode 100644 index 6b7c478e..00000000 --- a/src/dim2/vec2.rs +++ /dev/null @@ -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 -{ - x : N, - y : N -} - -impl Vec2 -{ - #[inline] - pub fn new(x: N, y: N) -> Vec2 - { Vec2 {x: x, y: y} } -} - -impl Dim for Vec2 -{ - #[inline] - fn dim() -> uint - { 2 } -} - -impl> Add, Vec2> for Vec2 -{ - #[inline] - fn add(&self, other: &Vec2) -> Vec2 - { Vec2::new(self.x + other.x, self.y + other.y) } -} - -impl> Sub, Vec2> for Vec2 -{ - #[inline] - fn sub(&self, other: &Vec2) -> Vec2 - { Vec2::new(self.x - other.x, self.y - other.y) } -} - -impl> -ScalarMul for Vec2 -{ - #[inline] - fn scalar_mul(&self, s: &N) -> Vec2 - { 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> -ScalarDiv for Vec2 -{ - #[inline] - fn scalar_div(&self, s: &N) -> Vec2 - { 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> -ScalarAdd for Vec2 -{ - #[inline] - fn scalar_add(&self, s: &N) -> Vec2 - { 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> -ScalarSub for Vec2 -{ - #[inline] - fn scalar_sub(&self, s: &N) -> Vec2 - { 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> Translation> for Vec2 -{ - #[inline] - fn translation(&self) -> Vec2 - { copy *self } - - #[inline] - fn translate(&mut self, t: &Vec2) - { *self = *self + *t; } -} - -impl> Translatable, Vec2> for Vec2 -{ - #[inline] - fn translated(&self, t: &Vec2) -> Vec2 - { self + *t } -} - -impl + Add> Dot for Vec2 -{ - #[inline] - fn dot(&self, other : &Vec2) -> N - { self.x * other.x + self.y * other.y } -} - -impl + Add + Sub> SubDot for Vec2 -{ - #[inline] - fn sub_dot(&self, a: &Vec2, b: &Vec2) -> N - { (self.x - a.x) * b.x + (self.y - a.y) * b.y } -} - -impl + Add + Div + Algebraic> -Norm for Vec2 -{ - #[inline] - fn sqnorm(&self) -> N - { self.dot(self) } - - #[inline] - fn norm(&self) -> N - { self.sqnorm().sqrt() } - - #[inline] - fn normalized(&self) -> Vec2 - { - 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 + Sub> Cross> for Vec2 -{ - #[inline] - fn cross(&self, other : &Vec2) -> Vec1 - { Vec1::new(self.x * other.y - self.y * other.x) } -} - -impl> Neg> for Vec2 -{ - #[inline] - fn neg(&self) -> Vec2 - { Vec2::new(-self.x, -self.y) } -} - -impl Zero for Vec2 -{ - #[inline] - fn zero() -> Vec2 - { Vec2::new(Zero::zero(), Zero::zero()) } - - #[inline] - fn is_zero(&self) -> bool - { self.x.is_zero() && self.y.is_zero() } -} - -impl> Basis for Vec2 -{ - #[inline] - fn canonical_basis() -> ~[Vec2] - { - // FIXME: this should be static - ~[ Vec2::new(One::one(), Zero::zero()), - Vec2::new(Zero::zero(), One::one()) ] - } - - #[inline] - fn orthogonal_subspace_basis(&self) -> ~[Vec2] - { ~[ Vec2::new(-self.y, copy self.x) ] } -} - -impl> ApproxEq for Vec2 -{ - #[inline] - fn approx_epsilon() -> N - { ApproxEq::approx_epsilon::() } - - #[inline] - fn approx_eq(&self, other: &Vec2) -> bool - { self.x.approx_eq(&other.x) && self.y.approx_eq(&other.y) } - - #[inline] - fn approx_eq_eps(&self, other: &Vec2, epsilon: &N) -> bool - { - self.x.approx_eq_eps(&other.x, epsilon) && - self.y.approx_eq_eps(&other.y, epsilon) - } -} - -impl Rand for Vec2 -{ - #[inline] - fn rand(rng: &mut R) -> Vec2 - { Vec2::new(rng.gen(), rng.gen()) } -} - -impl Flatten for Vec2 -{ - #[inline] - fn flat_size() -> uint - { 2 } - - #[inline] - fn from_flattened(l: &[N], off: uint) -> Vec2 - { 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 Bounded for Vec2 -{ - #[inline] - fn max_value() -> Vec2 - { Vec2::new(Bounded::max_value(), Bounded::max_value()) } - - #[inline] - fn min_value() -> Vec2 - { Vec2::new(Bounded::min_value(), Bounded::min_value()) } -} diff --git a/src/dim3/mat3.rs b/src/dim3/mat3.rs index 6e105c37..098d0f57 100644 --- a/src/dim3/mat3.rs +++ b/src/dim3/mat3.rs @@ -4,10 +4,11 @@ use std::cmp::ApproxEq; use std::util::swap; use traits::dim::Dim; use traits::inv::Inv; +use traits::transformation::Transform; +use traits::division_ring::DivisionRing; use traits::transpose::Transpose; -use traits::flatten::Flatten; use traits::rlmul::{RMul, LMul}; -use dim3::vec3::Vec3; +use vec::Vec3; #[deriving(Eq, ToStr)] pub struct Mat3 @@ -93,15 +94,27 @@ impl + Add> Mul, Mat3> for Mat3 } } +impl +Transform> for Mat3 +{ + #[inline] + fn transform_vec(&self, v: &Vec3) -> Vec3 + { self.rmul(v) } + + #[inline] + fn inv_transform(&self, v: &Vec3) -> Vec3 + { self.inverse().transform_vec(v) } +} + impl + Mul> RMul> for Mat3 { #[inline] fn rmul(&self, other: &Vec3) -> Vec3 { Vec3::new( - self.m11 * other.x + self.m12 * other.y + self.m13 * other.z, - self.m21 * other.x + self.m22 * other.y + self.m33 * other.z, - self.m31 * other.x + self.m32 * other.y + self.m33 * other.z + [self.m11 * other.at[0] + self.m12 * other.at[1] + self.m13 * other.at[2], + self.m21 * other.at[0] + self.m22 * other.at[1] + self.m33 * other.at[2], + self.m31 * other.at[0] + self.m32 * other.at[1] + self.m33 * other.at[2]] ) } } @@ -112,14 +125,14 @@ impl + Mul> LMul> for Mat3 fn lmul(&self, other: &Vec3) -> Vec3 { Vec3::new( - 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 + [self.m11 * other.at[0] + self.m21 * other.at[1] + self.m31 * other.at[2], + self.m12 * other.at[0] + self.m22 * other.at[1] + self.m32 * other.at[2], + self.m13 * other.at[0] + self.m23 * other.at[1] + self.m33 * other.at[2]] ) } } -impl + Div + Sub + Add + Neg + Zero> +impl Inv for Mat3 { #[inline] @@ -229,40 +242,3 @@ impl Rand for Mat3 rng.gen(), rng.gen(), rng.gen()) } } - -impl Flatten for Mat3 -{ - #[inline] - fn flat_size() -> uint - { 9 } - - #[inline] - fn from_flattened(l: &[N], off: uint) -> Mat3 - { 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; - } -} diff --git a/src/dim3/vec3.rs b/src/dim3/vec3.rs deleted file mode 100644 index d6ded216..00000000 --- a/src/dim3/vec3.rs +++ /dev/null @@ -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 -{ - x : N, - y : N, - z : N -} - -impl Vec3 -{ - #[inline] - pub fn new(x: N, y: N, z: N) -> Vec3 - { Vec3 {x: x, y: y, z: z} } -} - -impl Dim for Vec3 -{ - #[inline] - fn dim() -> uint - { 3 } -} - -impl> Add, Vec3> for Vec3 -{ - #[inline] - fn add(&self, other: &Vec3) -> Vec3 - { Vec3::new(self.x + other.x, self.y + other.y, self.z + other.z) } -} - -impl> Sub, Vec3> for Vec3 -{ - #[inline] - fn sub(&self, other: &Vec3) -> Vec3 - { Vec3::new(self.x - other.x, self.y - other.y, self.z - other.z) } -} - -impl> -ScalarMul for Vec3 -{ - #[inline] - fn scalar_mul(&self, s: &N) -> Vec3 - { 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> -ScalarDiv for Vec3 -{ - #[inline] - fn scalar_div(&self, s: &N) -> Vec3 - { 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> -ScalarAdd for Vec3 -{ - #[inline] - fn scalar_add(&self, s: &N) -> Vec3 - { 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> -ScalarSub for Vec3 -{ - #[inline] - fn scalar_sub(&self, s: &N) -> Vec3 - { 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> Translation> for Vec3 -{ - #[inline] - fn translation(&self) -> Vec3 - { copy *self } - - #[inline] - fn translate(&mut self, t: &Vec3) - { *self = *self + *t; } -} - -impl> Translatable, Vec3> for Vec3 -{ - #[inline] - fn translated(&self, t: &Vec3) -> Vec3 - { self + *t } -} - - - -impl> Neg> for Vec3 -{ - #[inline] - fn neg(&self) -> Vec3 - { Vec3::new(-self.x, -self.y, -self.z) } -} - -impl + Add> Dot for Vec3 -{ - #[inline] - fn dot(&self, other : &Vec3) -> N - { self.x * other.x + self.y * other.y + self.z * other.z } -} - -impl + Add + Sub> SubDot for Vec3 -{ - #[inline] - fn sub_dot(&self, a: &Vec3, b: &Vec3) -> N - { (self.x - a.x) * b.x + (self.y - a.y) * b.y + (self.z - a.z) * b.z } -} - -impl + Add + Div + Algebraic> -Norm for Vec3 -{ - #[inline] - fn sqnorm(&self) -> N - { self.dot(self) } - - #[inline] - fn norm(&self) -> N - { self.sqnorm().sqrt() } - - #[inline] - fn normalized(&self) -> Vec3 - { - 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 + Sub> Cross> for Vec3 -{ - #[inline] - fn cross(&self, other : &Vec3) -> Vec3 - { - 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 Zero for Vec3 -{ - #[inline] - fn zero() -> Vec3 - { 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 + Ord + Mul + Sub + Add + - Div + Algebraic> -Basis for Vec3 -{ - #[inline] - fn canonical_basis() -> ~[Vec3] - { - // 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] - { - 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> ApproxEq for Vec3 -{ - #[inline] - fn approx_epsilon() -> N - { ApproxEq::approx_epsilon::() } - - #[inline] - fn approx_eq(&self, other: &Vec3) -> 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, 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 Rand for Vec3 -{ - #[inline] - fn rand(rng: &mut R) -> Vec3 - { Vec3::new(rng.gen(), rng.gen(), rng.gen()) } -} - -impl Flatten for Vec3 -{ - #[inline] - fn flat_size() -> uint - { 3 } - - #[inline] - fn from_flattened(l: &[N], off: uint) -> Vec3 - { 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 Bounded for Vec3 -{ - #[inline] - fn max_value() -> Vec3 - { Vec3::new(Bounded::max_value(), Bounded::max_value(), Bounded::max_value()) } - - #[inline] - fn min_value() -> Vec3 - { Vec3::new(Bounded::min_value(), Bounded::min_value(), Bounded::min_value()) } -} diff --git a/src/nalgebra.rc b/src/nalgebra.rc index aeb28824..dcaef33b 100644 --- a/src/nalgebra.rc +++ b/src/nalgebra.rc @@ -15,24 +15,23 @@ extern mod std; +pub mod vec; + /// 1-dimensional linear algebra. pub mod dim1 { - pub mod vec1; pub mod mat1; } /// 2-dimensional linear algebra. pub mod dim2 { - pub mod vec2; pub mod mat2; } /// 3-dimensional linear algebra. pub mod dim3 { - pub mod vec3; pub mod mat3; } @@ -55,6 +54,7 @@ pub mod adaptors /// Useful linear-algebra related traits. pub mod traits { + pub mod iterable; pub mod dot; pub mod cross; pub mod inv; @@ -65,12 +65,10 @@ pub mod traits pub mod rotation; pub mod translation; pub mod transformation; - pub mod delta_transform; pub mod vector_space; pub mod ring; pub mod division_ring; pub mod sub_dot; - pub mod flatten; pub mod rlmul; pub mod scalar_op; } diff --git a/src/ndim/dvec.rs b/src/ndim/dvec.rs index 0d2c180e..00b38688 100644 --- a/src/ndim/dvec.rs +++ b/src/ndim/dvec.rs @@ -1,8 +1,10 @@ use std::uint::iterate; use std::num::{Zero, One, Algebraic}; +use std::vec::{VecIterator, VecMutIterator}; use std::vec::{map_zip, map, from_elem}; use std::cmp::ApproxEq; -use std::iterator::IteratorUtil; +use std::iterator::{FromIterator, IteratorUtil}; +use traits::iterable::{Iterable, IterableMut}; use traits::ring::Ring; use traits::division_ring::DivisionRing; use traits::dot::Dot; @@ -25,6 +27,31 @@ pub fn zero_vec_with_dim(dim: uint) -> DVec pub fn is_zero_vec(vec: &DVec) -> bool { vec.at.iter().all(|e| e.is_zero()) } +impl Iterable for DVec +{ + fn iter<'l>(&'l self) -> VecIterator<'l, N> + { self.at.iter() } +} + +impl IterableMut for DVec +{ + fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N> + { self.at.mut_iter() } +} + +impl> FromIterator for DVec +{ + fn from_iterator(param: &mut Iter) -> DVec + { + let mut res = DVec { at: ~[] }; + + for param.advance |e| + { res.at.push(e) } + + res + } +} + // FIXME: is Clone needed? impl> DVec { @@ -196,14 +223,18 @@ ScalarSub for DVec } } -impl> Translation> for DVec +impl + Neg> Translation> for DVec { #[inline] fn translation(&self) -> DVec { self.clone() } #[inline] - fn translate(&mut self, t: &DVec) + fn inv_translation(&self) -> DVec + { -self } + + #[inline] + fn translate_by(&mut self, t: &DVec) { *self = *self + *t; } } diff --git a/src/ndim/nmat.rs b/src/ndim/nmat.rs index 42b6b3d8..998fe510 100644 --- a/src/ndim/nmat.rs +++ b/src/ndim/nmat.rs @@ -6,7 +6,6 @@ use traits::dim::Dim; use traits::inv::Inv; use traits::division_ring::DivisionRing; use traits::transpose::Transpose; -use traits::flatten::Flatten; use traits::rlmul::{RMul, LMul}; use ndim::dmat::{DMat, one_mat_with_dim, zero_mat_with_dim, is_zero_mat}; use ndim::nvec::NVec; @@ -183,43 +182,3 @@ impl Rand for NMat res } } - -impl Flatten for NMat -{ - #[inline] - fn flat_size() -> uint - { Dim::dim::() * Dim::dim::() } - - #[inline] - fn from_flattened(l: &[N], off: uint) -> NMat - { - let dim = Dim::dim::(); - let mut res = Zero::zero::>(); - - for iterate(0u, dim * dim) |i| - { res.mij.mij[i] = copy l[off + i] } - - res - } - - #[inline] - fn flatten(&self) -> ~[N] - { - let dim = Dim::dim::(); - 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::(); - - for iterate(0u, dim * dim) |i| - { l[off + i] = copy self.mij.mij[i] } - } -} diff --git a/src/ndim/nvec.rs b/src/ndim/nvec.rs index 935d0952..57dbfbe3 100644 --- a/src/ndim/nvec.rs +++ b/src/ndim/nvec.rs @@ -1,9 +1,11 @@ use std::uint::iterate; use std::num::{Zero, Algebraic, Bounded}; use std::rand::{Rand, Rng, RngUtil}; -use std::vec::{map}; +use std::vec::{VecIterator, VecMutIterator}; use std::cmp::ApproxEq; +use std::iterator::{IteratorUtil, FromIterator}; use ndim::dvec::{DVec, zero_vec_with_dim, is_zero_vec}; +use traits::iterable::{Iterable, IterableMut}; use traits::basis::Basis; use traits::ring::Ring; use traits::division_ring::DivisionRing; @@ -12,7 +14,6 @@ use traits::dot::Dot; use traits::sub_dot::SubDot; use traits::norm::Norm; use traits::translation::{Translation, Translatable}; -use traits::flatten::Flatten; use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub}; // D is a phantom parameter, used only as a dimensional token. @@ -38,6 +39,35 @@ impl Clone for NVec { NVec{ at: self.at.clone() } } } +impl Iterable for NVec +{ + fn iter<'l>(&'l self) -> VecIterator<'l, N> + { self.at.iter() } +} + +impl IterableMut for NVec +{ + fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N> + { self.at.mut_iter() } +} + +impl> FromIterator for NVec +{ + fn from_iterator(param: &mut Iter) -> NVec + { + let mut res: NVec = Zero::zero(); + let mut i = 0; + + for param.advance |e| + { + res.at.at[i] = e; + i = i + 1; + } + + res + } +} + impl> Add, NVec> for NVec { #[inline] @@ -123,14 +153,19 @@ ScalarSub for NVec { self.at.scalar_sub_inplace(s) } } -impl> Translation> for NVec +impl + Neg> Translation> for NVec { #[inline] fn translation(&self) -> NVec { self.clone() } #[inline] - fn translate(&mut self, t: &NVec) + fn inv_translation(&self) -> NVec + { -self.clone() } + + + #[inline] + fn translate_by(&mut self, t: &NVec) { *self = *self + *t; } } @@ -173,11 +208,11 @@ Basis for NVec { #[inline] fn canonical_basis() -> ~[NVec] - { map(DVec::canonical_basis_with_dim(Dim::dim::()), |&e| NVec { at: e }) } + { DVec::canonical_basis_with_dim(Dim::dim::()).map(|&e| NVec { at: e }) } #[inline] fn orthogonal_subspace_basis(&self) -> ~[NVec] - { 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 @@ -229,46 +264,6 @@ impl Rand for NVec } } -impl Flatten for NVec -{ - #[inline] - fn flat_size() -> uint - { Dim::dim::() } - - #[inline] - fn from_flattened(l: &[N], off: uint) -> NVec - { - let dim = Dim::dim::(); - let mut res = Zero::zero::>(); - - for iterate(0u, dim) |i| - { res.at.at[i] = copy l[off + i] } - - res - } - - #[inline] - fn flatten(&self) -> ~[N] - { - let dim = Dim::dim::(); - 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::(); - - for iterate(0u, dim) |i| - { l[off + i] = copy self.at.at[i] } - } -} - impl + Copy> Bounded for NVec { #[inline] diff --git a/src/tests/mat.rs b/src/tests/mat.rs index ace9df27..b6fd00bf 100644 --- a/src/tests/mat.rs +++ b/src/tests/mat.rs @@ -1,7 +1,5 @@ #[test] -use std::vec; -#[test] -use std::num::{Real, Zero, One, abs}; +use std::num::{Real, One, abs}; #[test] use std::rand::random; #[test] @@ -11,9 +9,7 @@ use traits::inv::Inv; #[test] use traits::rotation::{Rotation, Rotatable}; #[test] -use traits::dim::d7; -#[test] -use dim1::vec1::Vec1; +use vec::Vec1; #[test] use dim1::mat1::Mat1; #[test] @@ -21,11 +17,7 @@ use dim2::mat2::Mat2; #[test] use dim3::mat3::Mat3; #[test] -use ndim::nmat::NMat; -#[test] use adaptors::rotmat::Rotmat; -#[test] -use traits::flatten::Flatten; macro_rules! test_inv_mat_impl( ($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] fn test_inv_mat1() { test_inv_mat_impl!(Mat1); } @@ -70,29 +47,13 @@ fn test_inv_mat3() // fn test_inv_nmat() // { test_inv_mat_impl!(NMat); } -#[test] -fn test_flatten_mat1() -{ test_flatten_impl!(Mat1, f64); } - -#[test] -fn test_flatten_mat2() -{ test_flatten_impl!(Mat2, f64); } - -#[test] -fn test_flatten_mat3() -{ test_flatten_impl!(Mat3, f64); } - -#[test] -fn test_flatten_nmat() -{ test_flatten_impl!(NMat, f64); } - #[test] fn test_rotation2() { for 10000.times { let randmat = One::one::>>(); - let ang = &Vec1::new(abs::(random()) % Real::pi()); + let ang = &Vec1::new([abs::(random()) % Real::pi()]); assert!(randmat.rotated(ang).rotation().approx_eq(ang)); } diff --git a/src/tests/vec.rs b/src/tests/vec.rs index f4393b31..f3602e27 100644 --- a/src/tests/vec.rs +++ b/src/tests/vec.rs @@ -1,6 +1,4 @@ #[test] -use std::vec; -#[test] use std::iterator::IteratorUtil; #[test] use std::num::{Zero, One}; @@ -9,11 +7,7 @@ use std::rand::{random}; #[test] use std::cmp::ApproxEq; #[test] -use dim3::vec3::Vec3; -#[test] -use dim2::vec2::Vec2; -#[test] -use dim1::vec1::Vec1; +use vec::{Vec1, Vec2, Vec3}; #[test] use ndim::nvec::NVec; #[test] @@ -27,10 +21,28 @@ use traits::dot::Dot; #[test] use traits::norm::Norm; #[test] -use traits::flatten::Flatten; +use traits::iterable::{Iterable, IterableMut}; #[test] 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( ($t: ty) => ( 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] fn test_cross_vec3() { @@ -182,22 +179,6 @@ fn test_subspace_basis_vec3() fn test_subspace_basis_nvec() { test_subspace_basis_impl!(NVec); } -#[test] -fn test_flatten_vec1() -{ test_flatten_impl!(Vec1, f64); } - -#[test] -fn test_flatten_vec2() -{ test_flatten_impl!(Vec2, f64); } - -#[test] -fn test_flatten_vec3() -{ test_flatten_impl!(Vec3, f64); } - -#[test] -fn test_flatten_nvec() -{ test_flatten_impl!(NVec, f64); } - #[test] fn test_scalar_op_vec1() { test_scalar_op_impl!(Vec1, f64); } @@ -213,3 +194,19 @@ fn test_scalar_op_vec3() #[test] fn test_scalar_op_nvec() { test_scalar_op_impl!(NVec, f64); } + +#[test] +fn test_iterator_vec1() +{ test_iterator_impl!(Vec1, f64); } + +#[test] +fn test_iterator_vec2() +{ test_iterator_impl!(Vec2, f64); } + +#[test] +fn test_iterator_vec3() +{ test_iterator_impl!(Vec3, f64); } + +#[test] +fn test_iterator_nvec() +{ test_iterator_impl!(NVec, f64); } diff --git a/src/traits/basis.rs b/src/traits/basis.rs index a25cae60..0c360165 100644 --- a/src/traits/basis.rs +++ b/src/traits/basis.rs @@ -2,6 +2,7 @@ pub trait Basis { /// Computes the canonical basis of the space in which this object lives. // FIXME: need type-associated values + // FIXME: this will make allocations… this is bad fn canonical_basis() -> ~[Self]; fn orthogonal_subspace_basis(&self) -> ~[Self]; } diff --git a/src/traits/delta_transform.rs b/src/traits/delta_transform.rs deleted file mode 100644 index 5db90891..00000000 --- a/src/traits/delta_transform.rs +++ /dev/null @@ -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
-{ - /// Extracts the delta transformation associated with this transformation. - fn delta_transform(&self) -> DT; -} - -/** - * Trait of delta-transformations on vectors. - */ -pub trait DeltaTransformVector -{ - /// Applies a delta-transform to a vector. - fn delta_transform_vector(&self, &V) -> V; -} diff --git a/src/traits/flatten.rs b/src/traits/flatten.rs deleted file mode 100644 index b0d78fba..00000000 --- a/src/traits/flatten.rs +++ /dev/null @@ -1,34 +0,0 @@ -/// Trait of objects which can be written as a list of values, and read from -/// that list. -pub trait Flatten -{ - /// 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…)? -} diff --git a/src/traits/iterable.rs b/src/traits/iterable.rs new file mode 100644 index 00000000..930370fa --- /dev/null +++ b/src/traits/iterable.rs @@ -0,0 +1,55 @@ +use std::vec; + +pub trait Iterable +{ + fn iter<'l>(&'l self) -> vec::VecIterator<'l, N>; +} + +pub trait IterableMut +{ + 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> +{ + fn iter(&'self self) -> I; +} + +pub trait IterableMut<'self, N, I: Iterator> +{ + 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 +{ + 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 +{ + fn from_iterator>(&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> + * 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. + * + */ diff --git a/src/traits/rotation.rs b/src/traits/rotation.rs index c8660650..c4a7c69a 100644 --- a/src/traits/rotation.rs +++ b/src/traits/rotation.rs @@ -8,8 +8,10 @@ pub trait Rotation /// Gets the rotation associated with this object. fn rotation(&self) -> V; + fn inv_rotation(&self) -> V; + /// In-place version of `rotated`. - fn rotate(&mut self, &V); + fn rotate_by(&mut self, &V); } pub trait Rotatable> @@ -19,6 +21,12 @@ pub trait Rotatable> fn rotated(&self, &V) -> Res; } +pub trait Rotate +{ + fn rotate(&self, &V) -> V; + fn inv_rotate(&self, &V) -> V; +} + /** * Applies a rotation centered on a specific point. * @@ -35,8 +43,8 @@ pub fn rotate_wrt_point, { let mut res = m.translated(&-center); - res.rotate(ammount); - res.translate(center); + res.rotate_by(ammount); + res.translate_by(center); res } diff --git a/src/traits/transformation.rs b/src/traits/transformation.rs index 62cff98f..2925b557 100644 --- a/src/traits/transformation.rs +++ b/src/traits/transformation.rs @@ -2,11 +2,19 @@ pub trait Transformation { fn transformation(&self) -> M; - // XXX: we must use "transform_by" instead of "transform" because of a - // conflict with some iterator function… + fn inv_transformation(&self) -> M; + fn transform_by(&mut self, &M); } +pub trait Transform +{ + // 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> { fn transformed(&self, &M) -> Res; diff --git a/src/traits/translation.rs b/src/traits/translation.rs index 705f5d3b..5564a2b3 100644 --- a/src/traits/translation.rs +++ b/src/traits/translation.rs @@ -6,8 +6,16 @@ pub trait Translation /// Gets the translation associated with this object. fn translation(&self) -> V; + fn inv_translation(&self) -> V; + /// In-place version of `translate`. - fn translate(&mut self, &V); + fn translate_by(&mut self, &V); +} + +pub trait Translate +{ + fn translate(&self, &V) -> V; + fn inv_translate(&self, &V) -> V; } pub trait Translatable> diff --git a/src/vec.rs b/src/vec.rs new file mode 100644 index 00000000..686cf409 --- /dev/null +++ b/src/vec.rs @@ -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 $t + { + #[inline] + pub fn new(at: [N, ..$dim]) -> $t + { $t { at: at } } + } + ) +) + +macro_rules! new_repeat_impl( + ($t: ident, $param: ident, [ $($elem: ident)|+ ]) => ( + impl $t + { + #[inline] + pub fn new_repeat($param: N) -> $t + { $t{ at: [ $( copy $elem, )+ ] } } + } + ) +) + +macro_rules! iterable_impl( + ($t: ident) => ( + impl Iterable for $t + { + fn iter<'l>(&'l self) -> VecIterator<'l, N> + { self.at.iter() } + } + ) +) + +macro_rules! iterable_mut_impl( + ($t: ident) => ( + impl IterableMut for $t + { + fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N> + { self.at.mut_iter() } + } + ) +) + +macro_rules! eq_impl( + ($t: ident) => ( + impl Eq for $t + { + #[inline] + fn eq(&self, other: &$t) -> bool + { self.at.iter().zip(other.at.iter()).all(|(a, b)| a == b) } + + #[inline] + fn ne(&self, other: &$t) -> bool + { self.at.iter().zip(other.at.iter()).all(|(a, b)| a != b) } + } + ) +) + +macro_rules! dim_impl( + ($t: ident, $dim: expr) => ( + impl Dim for $t + { + #[inline] + fn dim() -> uint + { $dim } + } + ) +) + +// FIXME: add the possibility to specialize that +macro_rules! basis_impl( + ($t: ident, $dim: expr) => ( + impl> Basis for $t + { + pub fn canonical_basis() -> ~[$t] + { + let mut res : ~[$t] = ~[]; + + for iterate(0u, $dim) |i| + { + let mut basis_element : $t = Zero::zero(); + + basis_element.at[i] = One::one(); + + res.push(basis_element); + } + + res + } + + pub fn orthogonal_subspace_basis(&self) -> ~[$t] + { + // compute the basis of the orthogonal subspace using Gram-Schmidt + // orthogonalization algorithm + let mut res : ~[$t] = ~[]; + + for iterate(0u, $dim) |i| + { + let mut basis_element : $t = 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> Add<$t, $t> for $t + { + #[inline] + fn add(&self, other: &$t) -> $t + { + self.at.iter() + .zip(other.at.iter()) + .transform(|(a, b)| { *a + *b }) + .collect() + } + } + ) +) + +macro_rules! sub_impl( + ($t: ident) => ( + impl> Sub<$t, $t> for $t + { + #[inline] + fn sub(&self, other: &$t) -> $t + { + self.at.iter() + .zip(other.at.iter()) + .transform(| (a, b) | { *a - *b }) + .collect() + } + } + ) +) + +macro_rules! neg_impl( + ($t: ident) => ( + impl> Neg<$t> for $t + { + #[inline] + fn neg(&self) -> $t + { self.at.iter().transform(|a| -a).collect() } + } + ) +) + +macro_rules! dot_impl( + ($t: ident, $dim: expr) => ( + impl Dot for $t + { + #[inline] + fn dot(&self, other: &$t) -> N + { + let mut res = Zero::zero::(); + + for iterate(0u, $dim) |i| + { res = res + self.at[i] * other.at[i]; } + + res + } + } + ) +) + +macro_rules! sub_dot_impl( + ($t: ident, $dim: expr) => ( + impl SubDot for $t + { + #[inline] + fn sub_dot(&self, a: &$t, b: &$t) -> N + { + let mut res = Zero::zero::(); + + 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> ScalarMul for $t + { + #[inline] + fn scalar_mul(&self, s: &N) -> $t + { 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> ScalarDiv for $t + { + #[inline] + fn scalar_div(&self, s: &N) -> $t + { 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> ScalarAdd for $t + { + #[inline] + fn scalar_add(&self, s: &N) -> $t + { 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> ScalarSub for $t + { + #[inline] + fn scalar_sub(&self, s: &N) -> $t + { 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 + Neg> Translation<$t> for $t + { + #[inline] + fn translation(&self) -> $t + { copy *self } + + #[inline] + fn inv_translation(&self) -> $t + { -self } + + #[inline] + fn translate_by(&mut self, t: &$t) + { *self = *self + *t; } + } + ) +) + +macro_rules! translatable_impl( + ($t: ident) => ( + impl + Copy> Translatable<$t, $t> for $t + { + #[inline] + fn translated(&self, t: &$t) -> $t + { self + *t } + } + ) +) + +macro_rules! norm_impl( + ($t: ident, $dim: expr) => ( + impl Norm for $t + { + #[inline] + fn sqnorm(&self) -> N + { self.dot(self) } + + #[inline] + fn norm(&self) -> N + { self.sqnorm().sqrt() } + + #[inline] + fn normalized(&self) -> $t + { + let mut res : $t = 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> ApproxEq for $t + { + #[inline] + fn approx_epsilon() -> N + { ApproxEq::approx_epsilon::() } + + #[inline] + fn approx_eq(&self, other: &$t) -> 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, 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 Zero for $t + { + #[inline] + fn zero() -> $t + { $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 Rand for $t + { + #[inline] + fn rand($param: &mut R) -> $t + { $t::new([ $( $elem.gen(), )+ ]) } + } + ) +) + +macro_rules! from_any_iterator_impl( + ($t: ident, $param: ident, [ $($elem: ident)|+ ]) => ( + impl FromAnyIterator for $t + { + fn from_iterator<'l>($param: &mut VecIterator<'l, N>) -> $t + { $t { at: [ $( copy *$elem.next().unwrap(), )+ ] } } + + fn from_mut_iterator<'l>($param: &mut VecMutIterator<'l, N>) -> $t + { $t { at: [ $( copy *$elem.next().unwrap(), )+ ] } } + } + ) +) + +macro_rules! from_iterator_impl( + ($t: ident, $param: ident, [ $($elem: ident)|+ ]) => ( + impl> FromIterator for $t + { + fn from_iterator($param: &mut Iter) -> $t + { $t { at: [ $( $elem.next().unwrap(), )+ ] } } + } + ) +) + +macro_rules! bounded_impl( + ($t: ident) => ( + impl Bounded for $t + { + #[inline] + fn max_value() -> $t + { $t::new_repeat(Bounded::max_value()) } + + #[inline] + fn min_value() -> $t + { $t::new_repeat(Bounded::min_value()) } + } + ) +) + +#[deriving(Ord, ToStr)] +pub struct Vec1 +{ 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 +{ 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 +{ 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 +{ 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 +{ 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 +{ 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 + Sub> Cross> for Vec2 +{ + #[inline] + fn cross(&self, other : &Vec2) -> Vec1 + { Vec1::new([self.at[0] * other.at[1] - self.at[1] * other.at[0]]) } +} + +impl + Sub> Cross> for Vec3 +{ + #[inline] + fn cross(&self, other : &Vec3) -> Vec3 + { + 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 Basis for Vec1 +{ + #[inline] + fn canonical_basis() -> ~[Vec1] + { ~[ Vec1::new([One::one()]) ] } // FIXME: this should be static + + #[inline] + fn orthogonal_subspace_basis(&self) -> ~[Vec1] + { ~[] } +} + +impl> Basis for Vec2 +{ + #[inline] + fn canonical_basis() -> ~[Vec2] + { + // FIXME: this should be static + ~[ Vec2::new([One::one(), Zero::zero()]), + Vec2::new([Zero::zero(), One::one()]) ] + } + + #[inline] + fn orthogonal_subspace_basis(&self) -> ~[Vec2] + { ~[ Vec2::new([-self.at[1], copy self.at[0]]) ] } +} + +impl +Basis for Vec3 +{ + #[inline] + fn canonical_basis() -> ~[Vec3] + { + // 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] + { + 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 ] + } +}