diff --git a/CHANGELOG.md b/CHANGELOG.md index cd5558f9..100ed835 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - `.set_col` -> `.set_column` - `::canonical_basis_with_dim` -> `::canonical_basis_with_dimension` - `::from_elem` -> `::from_element` + - `DiagMut` -> `DiagonalMut` * Added: - Added `.exp()` and `.pow()` for quaternions. diff --git a/Cargo.toml b/Cargo.toml index f1d6f68e..ecfca36f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nalgebra" -version = "0.8.2" +version = "0.9.0" authors = [ "Sébastien Crozet " ] # FIXME: add the contributors. description = "Linear algebra library for computer physics, computer graphics and general low-dimensional linear algebra for Rust." diff --git a/benches/vec.rs b/benches/vec.rs index 6bdd0392..4681dc1f 100644 --- a/benches/vec.rs +++ b/benches/vec.rs @@ -63,6 +63,13 @@ bench_unop!(_bench_vec4_normalize, Vector4, normalize); #[cfg(feature = "generic_sizes")] mod bench_vecn { + extern crate test; + extern crate rand; + extern crate nalgebra as na; + + use rand::{IsaacRng, Rng}; + use test::Bencher; + use std::ops::{Add, Sub, Mul, Div}; use typenum::{U2, U3, U4}; use na::VectorN; diff --git a/src/linalg/decompositions.rs b/src/linalg/decompositions.rs index ed7aea7c..ba839070 100644 --- a/src/linalg/decompositions.rs +++ b/src/linalg/decompositions.rs @@ -1,5 +1,5 @@ use traits::operations::{Transpose, ApproxEq}; -use traits::structure::{ColumnSlice, Eye, Indexable, Diagonal, SquareMatrix, BaseFloat, Cast}; +use traits::structure::{ColumnSlice, Eye, Indexable, SquareMatrix, BaseFloat, Cast}; use traits::geometry::Norm; use std::cmp; use std::ops::{Mul, Add, Sub}; diff --git a/src/structs/common_macros.rs b/src/structs/common_macros.rs new file mode 100644 index 00000000..ac5438ad --- /dev/null +++ b/src/structs/common_macros.rs @@ -0,0 +1,351 @@ +#![macro_use] + +macro_rules! pointwise_mul( + ($t: ident, $($compN: ident),+) => ( + impl> Mul<$t> for $t { + type Output = $t; + + #[inline] + fn mul(self, right: $t) -> $t { + $t::new($(self.$compN * right.$compN),+) + } + } + + impl> MulAssign<$t> for $t { + #[inline] + fn mul_assign(&mut self, right: $t) { + $( self.$compN *= right.$compN; )+ + } + } + ) +); + +macro_rules! pointwise_div( + ($t: ident, $($compN: ident),+) => ( + impl> Div<$t> for $t { + type Output = $t; + + #[inline] + fn div(self, right: $t) -> $t { + $t::new($(self.$compN / right.$compN),+) + } + } + + impl> DivAssign<$t> for $t { + #[inline] + fn div_assign(&mut self, right: $t) { + $( self.$compN /= right.$compN; )+ + } + } + ) +); + +macro_rules! pointwise_add( + ($t: ident, $($compN: ident),+) => ( + impl> Add<$t> for $t { + type Output = $t; + + #[inline] + fn add(self, right: $t) -> $t { + $t::new($(self.$compN + right.$compN),+) + } + } + + impl> AddAssign<$t> for $t { + #[inline] + fn add_assign(&mut self, right: $t) { + $( self.$compN += right.$compN; )+ + } + } + ) +); + + +macro_rules! pointwise_sub( + ($t: ident, $($compN: ident),+) => ( + impl> Sub<$t> for $t { + type Output = $t; + + #[inline] + fn sub(self, right: $t) -> $t { + $t::new($(self.$compN - right.$compN),+) + } + } + + + impl> SubAssign<$t> for $t { + #[inline] + fn sub_assign(&mut self, right: $t) { + $( self.$compN -= right.$compN; )+ + } + } + ) +); + + +macro_rules! pointwise_scalar_mul( + ($t: ident, $($compN: ident),+) => ( + impl> Mul for $t { + type Output = $t; + + #[inline] + fn mul(self, right: N) -> $t { + $t::new($(self.$compN * right),+) + } + } + + impl> MulAssign for $t { + #[inline] + fn mul_assign(&mut self, right: N) { + $( self.$compN *= right; )+ + } + } + + impl Mul<$t> for f32 { + type Output = $t; + + #[inline] + fn mul(self, right: $t) -> $t { + $t::new($(self * right.$compN),+) + } + } + + impl Mul<$t> for f64 { + type Output = $t; + + #[inline] + fn mul(self, right: $t) -> $t { + $t::new($(self * right.$compN),+) + } + } + ) +); + + +macro_rules! pointwise_scalar_div( + ($t: ident, $($compN: ident),+) => ( + impl> Div for $t { + type Output = $t; + + #[inline] + fn div(self, right: N) -> $t { + $t::new($(self.$compN / right),+) + } + } + + impl> DivAssign for $t { + #[inline] + fn div_assign(&mut self, right: N) { + $( self.$compN /= right; )+ + } + } + ) +); + + +macro_rules! pointwise_scalar_add( + ($t: ident, $($compN: ident),+) => ( + impl> Add for $t { + type Output = $t; + + #[inline] + fn add(self, right: N) -> $t { + $t::new($(self.$compN + right),+) + } + } + + impl> AddAssign for $t { + #[inline] + fn add_assign(&mut self, right: N) { + $( self.$compN += right; )+ + } + } + + impl Add<$t> for f32 { + type Output = $t; + + #[inline] + fn add(self, right: $t) -> $t { + $t::new($(self + right.$compN),+) + } + } + + impl Add<$t> for f64 { + type Output = $t; + + #[inline] + fn add(self, right: $t) -> $t { + $t::new($(self + right.$compN),+) + } + } + ) +); + +macro_rules! pointwise_scalar_sub( + ($t: ident, $($compN: ident),+) => ( + impl> Sub for $t { + type Output = $t; + + #[inline] + fn sub(self, right: N) -> $t { + $t::new($(self.$compN - right),+) + } + } + + impl> SubAssign for $t { + #[inline] + fn sub_assign(&mut self, right: N) { + $( self.$compN -= right; )+ + } + } + + impl Sub<$t> for f32 { + type Output = $t; + + #[inline] + fn sub(self, right: $t) -> $t { + $t::new($(self - right.$compN),+) + } + } + + impl Sub<$t> for f64 { + type Output = $t; + + #[inline] + fn sub(self, right: $t) -> $t { + $t::new($(self - right.$compN),+) + } + } + ) +); + +macro_rules! componentwise_neg( + ($t: ident, $($compN: ident),+) => ( + impl + Copy> Neg for $t { + type Output = $t; + + #[inline] + fn neg(self) -> $t { + $t::new($(-self.$compN ),+) + } + } + ) +); + +macro_rules! componentwise_repeat( + ($t: ident, $($compN: ident),+) => ( + impl Repeat for $t { + fn repeat(val: N) -> $t { + $t { + $($compN: val ),+ + } + } + } + ) +); + +macro_rules! componentwise_absolute( + ($t: ident, $($compN: ident),+) => ( + impl> Absolute<$t> for $t { + #[inline] + fn abs(m: &$t) -> $t { + $t::new($(::abs(&m.$compN) ),+) + } + } + ) +); + +macro_rules! componentwise_zero( + ($t: ident, $($compN: ident),+ ) => ( + impl Zero for $t { + #[inline] + fn zero() -> $t { + $t { + $($compN: ::zero() ),+ + } + } + + #[inline] + fn is_zero(&self) -> bool { + $(::is_zero(&self.$compN) )&&+ + } + } + ) +); + +macro_rules! componentwise_one( + ($t: ident, $($compN: ident),+ ) => ( + impl One for $t { + #[inline] + fn one() -> $t { + $t { + $($compN: ::one() ),+ + } + } + } + ) +); + +// Implements Arbitrary by setting each components to Arbitrary::arbitrary. +macro_rules! componentwise_arbitrary( + ($t: ident, $($compN: ident),+ ) => ( + #[cfg(feature="arbitrary")] + impl Arbitrary for $t { + #[inline] + fn arbitrary(g: &mut G) -> $t { + $t { $($compN: Arbitrary::arbitrary(g),)* } + } + } + ) +); + +// Implements Rand by setting each components to Rand::rand. +macro_rules! componentwise_rand( + ($t: ident, $($compN: ident),+ ) => ( + impl Rand for $t { + #[inline] + fn rand(rng: &mut R) -> $t { + $t { $($compN: Rand::rand(rng), )* } + } + } + ) +); + +macro_rules! component_basis_element( + ($t: ident, $($compN: ident),+ ) => ( + /* + * + * Element of the canonical basis. + * + */ + impl $t { + $( + /// Create the element of the canonical basis having this component set to one and + /// all the others set to zero. + #[inline] + pub fn $compN() -> $t { + let mut res: $t = ::zero(); + + res.$compN = ::one(); + + res + } + )+ + } + ) +); + +// A function to create a new element from its component values. +macro_rules! component_new( + ($t: ident, $($compN: ident),+) => ( + impl $t { + /// Creation from component values. + #[inline] + pub fn new($($compN: N ),+) -> $t { + $t { + $($compN: $compN ),+ + } + } + } + ); +); diff --git a/src/structs/dmatrix.rs b/src/structs/dmatrix.rs index 3d6a33d6..81bd9962 100644 --- a/src/structs/dmatrix.rs +++ b/src/structs/dmatrix.rs @@ -9,7 +9,8 @@ use rand::{self, Rand}; use num::{Zero, One}; use structs::dvector::{DVector, DVector1, DVector2, DVector3, DVector4, DVector5, DVector6}; use traits::operations::{ApproxEq, Inverse, Transpose, Mean, Covariance}; -use traits::structure::{Cast, Column, ColumnSlice, Row, RowSlice, Diagonal, DiagMut, Eye, Indexable, Shape, BaseNum}; +use traits::structure::{Cast, Column, ColumnSlice, Row, RowSlice, Diagonal, DiagonalMut, Eye, + Indexable, Shape, BaseNum}; #[cfg(feature="arbitrary")] use quickcheck::{Arbitrary, Gen}; diff --git a/src/structs/dmatrix_macros.rs b/src/structs/dmatrix_macros.rs index ff3e9699..80e99761 100644 --- a/src/structs/dmatrix_macros.rs +++ b/src/structs/dmatrix_macros.rs @@ -858,7 +858,7 @@ macro_rules! dmat_impl( } } - impl DiagMut<$dvector> for $dmatrix { + impl DiagonalMut<$dvector> for $dmatrix { #[inline] fn set_diagonal(&mut self, diagonal: &$dvector) { let smallest_dim = cmp::min(self.nrows, self.ncols); diff --git a/src/structs/isometry.rs b/src/structs/isometry.rs index 0bd8d1c9..9dda562b 100644 --- a/src/structs/isometry.rs +++ b/src/structs/isometry.rs @@ -74,8 +74,8 @@ impl Isometry3 { /// requirement of this parameter is to not be collinear to `target - eye`. #[inline] pub fn look_at_rh(eye: &Point3, target: &Point3, up: &Vector3) -> Isometry3 { - let rotation = Rotation3::look_at_rh(&(*target - *eye), up); - let trans = rotation * (-*eye); + let rotation = Rotation3::look_at_rh(&(*target - *eye), up); + let trans = rotation * (-*eye); Isometry3::new_with_rotation_matrix(trans.to_vector(), rotation) } @@ -92,53 +92,15 @@ impl Isometry3 { /// requirement of this parameter is to not be collinear to `target - eye`. #[inline] pub fn look_at_lh(eye: &Point3, target: &Point3, up: &Vector3) -> Isometry3 { - let rotation = Rotation3::look_at_lh(&(*target - *eye), up); - let trans = rotation * (-*eye); + let rotation = Rotation3::look_at_lh(&(*target - *eye), up); + let trans = rotation * (-*eye); Isometry3::new_with_rotation_matrix(trans.to_vector(), rotation) } } -isometry_impl!(Isometry2, Rotation2, Vector2, Vector1); -rotation_matrix_impl!(Isometry2, Rotation2, Vector2, Vector1); -rotation_impl!(Isometry2, Rotation2, Vector1); +isometry_impl!(Isometry2, Rotation2, Vector2, Vector1, Point2, Matrix3); dim_impl!(Isometry2, 2); -one_impl!(Isometry2); -absolute_rotate_impl!(Isometry2, Vector2); -rand_impl!(Isometry2); -approx_eq_impl!(Isometry2); -to_homogeneous_impl!(Isometry2, Matrix3); -inverse_impl!(Isometry2); -transform_impl!(Isometry2, Point2); -transformation_impl!(Isometry2); -rotate_impl!(Isometry2, Vector2); -translation_impl!(Isometry2, Vector2); -translate_impl!(Isometry2, Point2); -isometry_mul_isometry_impl!(Isometry2); -isometry_mul_rotation_impl!(Isometry2, Rotation2); -isometry_mul_point_impl!(Isometry2, Point2); -isometry_mul_vec_impl!(Isometry2, Vector2); -arbitrary_isometry_impl!(Isometry2); -isometry_display_impl!(Isometry2); -isometry_impl!(Isometry3, Rotation3, Vector3, Vector3); -rotation_matrix_impl!(Isometry3, Rotation3, Vector3, Vector3); -rotation_impl!(Isometry3, Rotation3, Vector3); +isometry_impl!(Isometry3, Rotation3, Vector3, Vector3, Point3, Matrix4); dim_impl!(Isometry3, 3); -one_impl!(Isometry3); -absolute_rotate_impl!(Isometry3, Vector3); -rand_impl!(Isometry3); -approx_eq_impl!(Isometry3); -to_homogeneous_impl!(Isometry3, Matrix4); -inverse_impl!(Isometry3); -transform_impl!(Isometry3, Point3); -transformation_impl!(Isometry3); -rotate_impl!(Isometry3, Vector3); -translation_impl!(Isometry3, Vector3); -translate_impl!(Isometry3, Point3); -isometry_mul_isometry_impl!(Isometry3); -isometry_mul_rotation_impl!(Isometry3, Rotation3); -isometry_mul_point_impl!(Isometry3, Point3); -isometry_mul_vec_impl!(Isometry3, Vector3); -arbitrary_isometry_impl!(Isometry3); -isometry_display_impl!(Isometry3); diff --git a/src/structs/isometry_macros.rs b/src/structs/isometry_macros.rs index 8d9742be..de0aca4f 100644 --- a/src/structs/isometry_macros.rs +++ b/src/structs/isometry_macros.rs @@ -1,68 +1,63 @@ #![macro_use] macro_rules! isometry_impl( - ($t: ident, $submatrix: ident, $subvector: ident, $subrotvector: ident) => ( + ($t: ident, $rotmatrix: ident, $vector: ident, $rotvector: ident, $point: ident, + $homogeneous: ident) => ( impl $t { /// Creates a new isometry from an axis-angle rotation, and a vector. #[inline] - pub fn new(translation: $subvector, rotation: $subrotvector) -> $t { + pub fn new(translation: $vector, rotation: $rotvector) -> $t { $t { - rotation: $submatrix::new(rotation), + rotation: $rotmatrix::new(rotation), translation: translation } } /// Creates a new isometry from a rotation matrix and a vector. #[inline] - pub fn new_with_rotation_matrix(translation: $subvector, rotation: $submatrix) -> $t { + pub fn new_with_rotation_matrix(translation: $vector, rotation: $rotmatrix) -> $t { $t { rotation: rotation, translation: translation } } } - ) -); -macro_rules! rotation_matrix_impl( - ($t: ident, $trotation: ident, $tlv: ident, $tav: ident) => ( + + /* + * + * RotationMatrix + * + */ impl + BaseFloat> - RotationMatrix, $tav> for $t { - type Output = $trotation; + RotationMatrix, $rotvector> for $t { + type Output = $rotmatrix; #[inline] - fn to_rotation_matrix(&self) -> $trotation { + fn to_rotation_matrix(&self) -> $rotmatrix { self.rotation } } - ) -); -macro_rules! dim_impl( - ($t: ident, $dimension: expr) => ( - impl Dimension for $t { - #[inline] - fn dimension(_: Option<$t>) -> usize { - $dimension - } - } - ) -); - -macro_rules! one_impl( - ($t: ident) => ( + /* + * + * One + * + */ impl One for $t { #[inline] fn one() -> $t { $t::new_with_rotation_matrix(::zero(), ::one()) } } - ) -); -macro_rules! isometry_mul_isometry_impl( - ($t: ident) => ( + + /* + * + * Isometry × Isometry + * + */ impl Mul<$t> for $t { type Output = $t; @@ -81,21 +76,23 @@ macro_rules! isometry_mul_isometry_impl( self.rotation *= right.rotation; } } - ) -); -macro_rules! isometry_mul_rotation_impl( - ($t: ident, $rotation: ident) => ( - impl Mul<$rotation> for $t { + + /* + * + * Isometry × Rotation + * + */ + impl Mul<$rotmatrix> for $t { type Output = $t; #[inline] - fn mul(self, right: $rotation) -> $t { + fn mul(self, right: $rotmatrix) -> $t { $t::new_with_rotation_matrix(self.translation, self.rotation * right) } } - impl Mul<$t> for $rotation { + impl Mul<$t> for $rotmatrix { type Output = $t; #[inline] @@ -106,167 +103,181 @@ macro_rules! isometry_mul_rotation_impl( } } - impl MulAssign<$rotation> for $t { + impl MulAssign<$rotmatrix> for $t { #[inline] - fn mul_assign(&mut self, right: $rotation) { + fn mul_assign(&mut self, right: $rotmatrix) { self.rotation *= right } } - ) -); -macro_rules! isometry_mul_point_impl( - ($t: ident, $tv: ident) => ( - impl Mul<$tv> for $t { - type Output = $tv; + + /* + * + * Isometry × Point + * + */ + impl Mul<$point> for $t { + type Output = $point; #[inline] - fn mul(self, right: $tv) -> $tv { + fn mul(self, right: $point) -> $point { self.rotation * right + self.translation } } - ) -); -macro_rules! isometry_mul_vec_impl( - ($t: ident, $tv: ident) => ( - impl Mul<$tv> for $t { - type Output = $tv; + + /* + * + * Isometry × Vector + * + */ + impl Mul<$vector> for $t { + type Output = $vector; #[inline] - fn mul(self, right: $tv) -> $tv { + fn mul(self, right: $vector) -> $vector { self.rotation * right } } - ) -); -macro_rules! translation_impl( - ($t: ident, $tv: ident) => ( - impl Translation<$tv> for $t { + + /* + * + * Translation + * + */ + impl Translation<$vector> for $t { #[inline] - fn translation(&self) -> $tv { + fn translation(&self) -> $vector { self.translation } #[inline] - fn inverse_translation(&self) -> $tv { + fn inverse_translation(&self) -> $vector { -self.translation } #[inline] - fn append_translation_mut(&mut self, t: &$tv) { + fn append_translation_mut(&mut self, t: &$vector) { self.translation = *t + self.translation } #[inline] - fn append_translation(&self, t: &$tv) -> $t { + fn append_translation(&self, t: &$vector) -> $t { $t::new_with_rotation_matrix(*t + self.translation, self.rotation) } #[inline] - fn prepend_translation_mut(&mut self, t: &$tv) { + fn prepend_translation_mut(&mut self, t: &$vector) { self.translation = self.translation + self.rotation * *t } #[inline] - fn prepend_translation(&self, t: &$tv) -> $t { + fn prepend_translation(&self, t: &$vector) -> $t { $t::new_with_rotation_matrix(self.translation + self.rotation * *t, self.rotation) } #[inline] - fn set_translation(&mut self, t: $tv) { + fn set_translation(&mut self, t: $vector) { self.translation = t } } - ) -); -macro_rules! translate_impl( - ($t: ident, $tv: ident) => ( - impl + Sub> Translate<$tv> for $t { + + /* + * + * Translate + * + */ + impl + Sub> Translate<$point> for $t { #[inline] - fn translate(&self, v: &$tv) -> $tv { + fn translate(&self, v: &$point) -> $point { *v + self.translation } #[inline] - fn inverse_translate(&self, v: &$tv) -> $tv { + fn inverse_translate(&self, v: &$point) -> $point { *v - self.translation } } - ) -); -macro_rules! rotation_impl( - ($t: ident, $trotation: ident, $tav: ident) => ( - impl + BaseFloat> Rotation<$tav> for $t { + + /* + * + * Rotation + * + */ + impl + BaseFloat> Rotation<$rotvector> for $t { #[inline] - fn rotation(&self) -> $tav { + fn rotation(&self) -> $rotvector { self.rotation.rotation() } #[inline] - fn inverse_rotation(&self) -> $tav { + fn inverse_rotation(&self) -> $rotvector { self.rotation.inverse_rotation() } #[inline] - fn append_rotation_mut(&mut self, rotation: &$tav) { - let delta = $trotation::new(*rotation); + fn append_rotation_mut(&mut self, rotation: &$rotvector) { + let delta = $rotmatrix::new(*rotation); self.rotation = delta * self.rotation; self.translation = delta * self.translation; } #[inline] - fn append_rotation(&self, rotation: &$tav) -> $t { - let delta = $trotation::new(*rotation); + fn append_rotation(&self, rotation: &$rotvector) -> $t { + let delta = $rotmatrix::new(*rotation); $t::new_with_rotation_matrix(delta * self.translation, delta * self.rotation) } #[inline] - fn prepend_rotation_mut(&mut self, rotation: &$tav) { - let delta = $trotation::new(*rotation); + fn prepend_rotation_mut(&mut self, rotation: &$rotvector) { + let delta = $rotmatrix::new(*rotation); self.rotation = self.rotation * delta; } #[inline] - fn prepend_rotation(&self, rotation: &$tav) -> $t { - let delta = $trotation::new(*rotation); + fn prepend_rotation(&self, rotation: &$rotvector) -> $t { + let delta = $rotmatrix::new(*rotation); $t::new_with_rotation_matrix(self.translation, self.rotation * delta) } #[inline] - fn set_rotation(&mut self, rotation: $tav) { + fn set_rotation(&mut self, rotation: $rotvector) { // FIXME: should the translation be changed too? self.rotation.set_rotation(rotation) } } - ) -); -macro_rules! rotate_impl( - ($t: ident, $tv: ident) => ( - impl Rotate<$tv> for $t { + + /* + * + * Rotate + * + */ + impl Rotate<$vector> for $t { #[inline] - fn rotate(&self, v: &$tv) -> $tv { + fn rotate(&self, v: &$vector) -> $vector { self.rotation.rotate(v) } #[inline] - fn inverse_rotate(&self, v: &$tv) -> $tv { + fn inverse_rotate(&self, v: &$vector) -> $vector { self.rotation.inverse_rotate(v) } } - ) -); -macro_rules! transformation_impl( - ($t: ident) => ( + + /* + * + * Transformation + * + */ impl Transformation<$t> for $t { fn transformation(&self) -> $t { *self @@ -297,27 +308,31 @@ macro_rules! transformation_impl( *self = t } } - ) -); -macro_rules! transform_impl( - ($t: ident, $tp: ident) => ( - impl Transform<$tp> for $t { + + /* + * + * Transform + * + */ + impl Transform<$point> for $t { #[inline] - fn transform(&self, p: &$tp) -> $tp { + fn transform(&self, p: &$point) -> $point { self.rotation.transform(p) + self.translation } #[inline] - fn inverse_transform(&self, p: &$tp) -> $tp { + fn inverse_transform(&self, p: &$point) -> $point { self.rotation.inverse_transform(&(*p - self.translation)) } } - ) -); -macro_rules! inverse_impl( - ($t: ident) => ( + + /* + * + * Inverse + * + */ impl> Inverse for $t { #[inline] fn inverse_mut(&mut self) -> bool { @@ -335,28 +350,32 @@ macro_rules! inverse_impl( Some(res) } } - ) -); -macro_rules! to_homogeneous_impl( - ($t: ident, $th: ident) => ( - impl ToHomogeneous<$th> for $t { - fn to_homogeneous(&self) -> $th { + + /* + * + * ToHomogeneous + * + */ + impl ToHomogeneous<$homogeneous> for $t { + fn to_homogeneous(&self) -> $homogeneous { let mut res = self.rotation.to_homogeneous(); // copy the translation - let dimension = Dimension::dimension(None::<$th>); + let dimension = Dimension::dimension(None::<$homogeneous>); res.set_column(dimension - 1, self.translation.as_point().to_homogeneous().to_vector()); res } } - ) -); -macro_rules! approx_eq_impl( - ($t: ident) => ( + + /* + * + * ApproxEq + * + */ impl> ApproxEq for $t { #[inline] fn approx_epsilon(_: Option<$t>) -> N { @@ -380,33 +399,39 @@ macro_rules! approx_eq_impl( ApproxEq::approx_eq_ulps(&self.translation, &other.translation, ulps) } } - ) -); -macro_rules! rand_impl( - ($t: ident) => ( + + /* + * + * Rand + * + */ impl Rand for $t { #[inline] fn rand(rng: &mut R) -> $t { $t::new(rng.gen(), rng.gen()) } } - ) -); -macro_rules! absolute_rotate_impl( - ($t: ident, $tv: ident) => ( - impl AbsoluteRotate<$tv> for $t { + + /* + * + * AbsoluteRotate + * + */ + impl AbsoluteRotate<$vector> for $t { #[inline] - fn absolute_rotate(&self, v: &$tv) -> $tv { + fn absolute_rotate(&self, v: &$vector) -> $vector { self.rotation.absolute_rotate(v) } } - ) -); -macro_rules! arbitrary_isometry_impl( - ($t: ident) => ( + + /* + * + * Arbitrary + * + */ #[cfg(feature="arbitrary")] impl Arbitrary for $t { fn arbitrary(g: &mut G) -> $t { @@ -416,11 +441,13 @@ macro_rules! arbitrary_isometry_impl( ) } } - ) -); -macro_rules! isometry_display_impl( - ($t: ident) => ( + + /* + * + * Display + * + */ impl fmt::Display for $t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(writeln!(f, "Isometry {{")); @@ -441,3 +468,14 @@ macro_rules! isometry_display_impl( } ) ); + +macro_rules! dim_impl( + ($t: ident, $dimension: expr) => ( + impl Dimension for $t { + #[inline] + fn dimension(_: Option<$t>) -> usize { + $dimension + } + } + ) +); diff --git a/src/structs/matrix.rs b/src/structs/matrix.rs index e52f64e0..7e07c663 100644 --- a/src/structs/matrix.rs +++ b/src/structs/matrix.rs @@ -14,7 +14,7 @@ use structs::point::{Point1, Point4, Point5, Point6}; use structs::dvector::{DVector1, DVector2, DVector3, DVector4, DVector5, DVector6}; use traits::structure::{Cast, Row, Column, Iterable, IterableMut, Dimension, Indexable, Eye, ColumnSlice, - RowSlice, Diagonal, DiagMut, Shape, BaseFloat, BaseNum, Repeat}; + RowSlice, Diagonal, DiagonalMut, Shape, BaseFloat, BaseNum, Repeat}; use traits::operations::{Absolute, Transpose, Inverse, Outer, EigenQR, Mean}; use traits::geometry::{ToHomogeneous, FromHomogeneous, Origin}; use linalg; @@ -50,45 +50,20 @@ pub struct Matrix1 { eye_impl!(Matrix1, 1, m11); -mat_impl!(Matrix1, m11); -repeat_impl!(Matrix1, m11); -conversion_impl!(Matrix1, 1); -mat_cast_impl!(Matrix1, m11); -add_impl!(Matrix1, m11); -sub_impl!(Matrix1, m11); -scalar_add_impl!(Matrix1, m11); -scalar_sub_impl!(Matrix1, m11); -scalar_mul_impl!(Matrix1, m11); -scalar_div_impl!(Matrix1, m11); -absolute_impl!(Matrix1, m11); -zero_impl!(Matrix1, m11); +matrix_impl!(Matrix1, 1, Vector1, DVector1, m11); one_impl!(Matrix1, ::one); -iterable_impl!(Matrix1, 1); -iterable_mut_impl!(Matrix1, 1); -at_fast_impl!(Matrix1, 1); dim_impl!(Matrix1, 1); -indexable_impl!(Matrix1, 1); -index_impl!(Matrix1, 1); mat_mul_mat_impl!(Matrix1, 1); mat_mul_vec_impl!(Matrix1, Vector1, 1, ::zero); vec_mul_mat_impl!(Matrix1, Vector1, 1, ::zero); mat_mul_point_impl!(Matrix1, Point1, 1, Origin::origin); point_mul_mat_impl!(Matrix1, Point1, 1, Origin::origin); // (specialized); inverse_impl!(Matrix1, 1); -transpose_impl!(Matrix1, 1); -approx_eq_impl!(Matrix1); -row_impl!(Matrix1, Vector1, 1); -column_impl!(Matrix1, Vector1, 1); -column_slice_impl!(Matrix1, Vector1, DVector1, 1); -row_slice_impl!(Matrix1, Vector1, DVector1, 1); -diag_impl!(Matrix1, Vector1, 1); to_homogeneous_impl!(Matrix1, Matrix2, 1, 2); from_homogeneous_impl!(Matrix1, Matrix2, 1, 2); -outer_impl!(Vector1, Matrix1); eigen_qr_impl!(Matrix1, Vector1); -arbitrary_impl!(Matrix1, m11); -rand_impl!(Matrix1, m11); -mean_impl!(Matrix1, Vector1, 1); +componentwise_arbitrary!(Matrix1, m11); +componentwise_rand!(Matrix1, m11); mat_display_impl!(Matrix1, 1); /// Square matrix of dimension 2. @@ -101,49 +76,20 @@ pub struct Matrix2 { eye_impl!(Matrix2, 2, m11, m22); -mat_impl!(Matrix2, m11, m12, - m21, m22); -repeat_impl!(Matrix2, m11, m12, - m21, m22); -conversion_impl!(Matrix2, 2); -mat_cast_impl!(Matrix2, m11, m12, - m21, m22); -add_impl!(Matrix2, m11, m12, m21, m22); -sub_impl!(Matrix2, m11, m12, m21, m22); -scalar_add_impl!(Matrix2, m11, m12, m21, m22); -scalar_sub_impl!(Matrix2, m11, m12, m21, m22); -scalar_mul_impl!(Matrix2, m11, m12, m21, m22); -scalar_div_impl!(Matrix2, m11, m12, m21, m22); -absolute_impl!(Matrix2, m11, m12, - m21, m22); -zero_impl!(Matrix2, m11, m12, - m21, m22); +matrix_impl!(Matrix2, 2, Vector2, DVector2, m11, m12, + m21, m22); one_impl!(Matrix2, ::one, ::zero, ::zero, ::one); -iterable_impl!(Matrix2, 2); -iterable_mut_impl!(Matrix2, 2); dim_impl!(Matrix2, 2); -indexable_impl!(Matrix2, 2); -index_impl!(Matrix2, 2); -at_fast_impl!(Matrix2, 2); // (specialized); mul_impl!(Matrix2, 2); // (specialized); rmul_impl!(Matrix2, Vector2, 2); // (specialized); lmul_impl!(Matrix2, Vector2, 2); // (specialized); inverse_impl!(Matrix2, 2); -transpose_impl!(Matrix2, 2); -approx_eq_impl!(Matrix2); -row_impl!(Matrix2, Vector2, 2); -column_impl!(Matrix2, Vector2, 2); -column_slice_impl!(Matrix2, Vector2, DVector2, 2); -row_slice_impl!(Matrix2, Vector2, DVector2, 2); -diag_impl!(Matrix2, Vector2, 2); to_homogeneous_impl!(Matrix2, Matrix3, 2, 3); from_homogeneous_impl!(Matrix2, Matrix3, 2, 3); -outer_impl!(Vector2, Matrix2); eigen_qr_impl!(Matrix2, Vector2); -arbitrary_impl!(Matrix2, m11, m12, m21, m22); -rand_impl!(Matrix2, m11, m12, m21, m22); -mean_impl!(Matrix2, Vector2, 2); +componentwise_arbitrary!(Matrix2, m11, m12, m21, m22); +componentwise_rand!(Matrix2, m11, m12, m21, m22); mat_display_impl!(Matrix2, 2); /// Square matrix of dimension 3. @@ -157,91 +103,30 @@ pub struct Matrix3 { eye_impl!(Matrix3, 3, m11, m22, m33); -mat_impl!(Matrix3, m11, m12, m13, - m21, m22, m23, - m31, m32, m33); -repeat_impl!(Matrix3, m11, m12, m13, - m21, m22, m23, - m31, m32, m33); -conversion_impl!(Matrix3, 3); -mat_cast_impl!(Matrix3, m11, m12, m13, - m21, m22, m23, - m31, m32, m33); -add_impl!(Matrix3, - m11, m12, m13, - m21, m22, m23, - m31, m32, m33 -); -sub_impl!(Matrix3, - m11, m12, m13, - m21, m22, m23, - m31, m32, m33 -); -scalar_add_impl!(Matrix3, - m11, m12, m13, - m21, m22, m23, - m31, m32, m33 -); -scalar_sub_impl!(Matrix3, - m11, m12, m13, - m21, m22, m23, - m31, m32, m33 -); -scalar_mul_impl!(Matrix3, - m11, m12, m13, - m21, m22, m23, - m31, m32, m33 -); -scalar_div_impl!(Matrix3, - m11, m12, m13, - m21, m22, m23, - m31, m32, m33 -); -absolute_impl!(Matrix3, - m11, m12, m13, - m21, m22, m23, - m31, m32, m33 -); -zero_impl!(Matrix3, - m11, m12, m13, - m21, m22, m23, - m31, m32, m33 -); +matrix_impl!(Matrix3, 3, Vector3, DVector3, m11, m12, m13, + m21, m22, m23, + m31, m32, m33); one_impl!(Matrix3, ::one , ::zero, ::zero, ::zero, ::one , ::zero, ::zero, ::zero, ::one); -iterable_impl!(Matrix3, 3); -iterable_mut_impl!(Matrix3, 3); dim_impl!(Matrix3, 3); -indexable_impl!(Matrix3, 3); -index_impl!(Matrix3, 3); -at_fast_impl!(Matrix3, 3); // (specialized); mul_impl!(Matrix3, 3); // (specialized); rmul_impl!(Matrix3, Vector3, 3); // (specialized); lmul_impl!(Matrix3, Vector3, 3); // (specialized); inverse_impl!(Matrix3, 3); -transpose_impl!(Matrix3, 3); -approx_eq_impl!(Matrix3); -// (specialized); row_impl!(Matrix3, Vector3, 3); -// (specialized); column_impl!(Matrix3, Vector3, 3); -column_slice_impl!(Matrix3, Vector3, DVector3, 3); -row_slice_impl!(Matrix3, Vector3, DVector3, 3); -diag_impl!(Matrix3, Vector3, 3); to_homogeneous_impl!(Matrix3, Matrix4, 3, 4); from_homogeneous_impl!(Matrix3, Matrix4, 3, 4); -outer_impl!(Vector3, Matrix3); eigen_qr_impl!(Matrix3, Vector3); -arbitrary_impl!(Matrix3, +componentwise_arbitrary!(Matrix3, m11, m12, m13, m21, m22, m23, m31, m32, m33 ); -rand_impl!(Matrix3, +componentwise_rand!(Matrix3, m11, m12, m13, m21, m22, m23, m31, m32, m33 ); -mean_impl!(Matrix3, Vector3, 3); mat_display_impl!(Matrix3, 3); /// Square matrix of dimension 4. @@ -256,68 +141,7 @@ pub struct Matrix4 { eye_impl!(Matrix4, 4, m11, m22, m33, m44); -mat_impl!(Matrix4, - m11, m12, m13, m14, - m21, m22, m23, m24, - m31, m32, m33, m34, - m41, m42, m43, m44 -); -repeat_impl!(Matrix4, - m11, m12, m13, m14, - m21, m22, m23, m24, - m31, m32, m33, m34, - m41, m42, m43, m44 -); -conversion_impl!(Matrix4, 4); -mat_cast_impl!(Matrix4, - m11, m12, m13, m14, - m21, m22, m23, m24, - m31, m32, m33, m34, - m41, m42, m43, m44 -); -add_impl!(Matrix4, - m11, m12, m13, m14, - m21, m22, m23, m24, - m31, m32, m33, m34, - m41, m42, m43, m44 -); -sub_impl!(Matrix4, - m11, m12, m13, m14, - m21, m22, m23, m24, - m31, m32, m33, m34, - m41, m42, m43, m44 -); -scalar_add_impl!(Matrix4, - m11, m12, m13, m14, - m21, m22, m23, m24, - m31, m32, m33, m34, - m41, m42, m43, m44 -); -scalar_sub_impl!(Matrix4, - m11, m12, m13, m14, - m21, m22, m23, m24, - m31, m32, m33, m34, - m41, m42, m43, m44 -); -scalar_mul_impl!(Matrix4, - m11, m12, m13, m14, - m21, m22, m23, m24, - m31, m32, m33, m34, - m41, m42, m43, m44 -); -scalar_div_impl!(Matrix4, - m11, m12, m13, m14, - m21, m22, m23, m24, - m31, m32, m33, m34, - m41, m42, m43, m44 -); -absolute_impl!(Matrix4, - m11, m12, m13, m14, - m21, m22, m23, m24, - m31, m32, m33, m34, - m41, m42, m43, m44 -); -zero_impl!(Matrix4, +matrix_impl!(Matrix4, 4, Vector4, DVector4, m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, @@ -327,42 +151,28 @@ one_impl!(Matrix4, ::one , ::zero, ::zero, ::zero, ::zero, ::one , ::zero, ::zero, ::zero, ::zero, ::one , ::zero, ::zero, ::zero, ::zero, ::one); -iterable_impl!(Matrix4, 4); -iterable_mut_impl!(Matrix4, 4); dim_impl!(Matrix4, 4); -indexable_impl!(Matrix4, 4); -index_impl!(Matrix4, 4); -at_fast_impl!(Matrix4, 4); mat_mul_mat_impl!(Matrix4, 4); mat_mul_vec_impl!(Matrix4, Vector4, 4, ::zero); vec_mul_mat_impl!(Matrix4, Vector4, 4, ::zero); mat_mul_point_impl!(Matrix4, Point4, 4, Origin::origin); point_mul_mat_impl!(Matrix4, Point4, 4, Origin::origin); inverse_impl!(Matrix4, 4); -transpose_impl!(Matrix4, 4); -approx_eq_impl!(Matrix4); -row_impl!(Matrix4, Vector4, 4); -column_impl!(Matrix4, Vector4, 4); -column_slice_impl!(Matrix4, Vector4, DVector4, 4); -row_slice_impl!(Matrix4, Vector4, DVector4, 4); -diag_impl!(Matrix4, Vector4, 4); to_homogeneous_impl!(Matrix4, Matrix5, 4, 5); from_homogeneous_impl!(Matrix4, Matrix5, 4, 5); -outer_impl!(Vector4, Matrix4); eigen_qr_impl!(Matrix4, Vector4); -arbitrary_impl!(Matrix4, +componentwise_arbitrary!(Matrix4, m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44 ); -rand_impl!(Matrix4, +componentwise_rand!(Matrix4, m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44 ); -mean_impl!(Matrix4, Vector4, 4); mat_display_impl!(Matrix4, 4); /// Square matrix of dimension 5. @@ -378,36 +188,7 @@ pub struct Matrix5 { eye_impl!(Matrix5, 5, m11, m22, m33, m44, m55); -mat_impl!(Matrix5, - m11, m12, m13, m14, m15, - m21, m22, m23, m24, m25, - m31, m32, m33, m34, m35, - m41, m42, m43, m44, m45, - m51, m52, m53, m54, m55 -); -repeat_impl!(Matrix5, - m11, m12, m13, m14, m15, - m21, m22, m23, m24, m25, - m31, m32, m33, m34, m35, - m41, m42, m43, m44, m45, - m51, m52, m53, m54, m55 -); -conversion_impl!(Matrix5, 5); -mat_cast_impl!(Matrix5, - m11, m12, m13, m14, m15, - m21, m22, m23, m24, m25, - m31, m32, m33, m34, m35, - m41, m42, m43, m44, m45, - m51, m52, m53, m54, m55 -); -absolute_impl!(Matrix5, - m11, m12, m13, m14, m15, - m21, m22, m23, m24, m25, - m31, m32, m33, m34, m35, - m41, m42, m43, m44, m45, - m51, m52, m53, m54, m55 -); -zero_impl!(Matrix5, +matrix_impl!(Matrix5, 5, Vector5, DVector5, m11, m12, m13, m14, m15, m21, m22, m23, m24, m25, m31, m32, m33, m34, m35, @@ -421,86 +202,30 @@ one_impl!(Matrix5, ::zero, ::zero, ::zero, ::one , ::zero, ::zero, ::zero, ::zero, ::zero, ::one ); -add_impl!(Matrix5, - m11, m12, m13, m14, m15, - m21, m22, m23, m24, m25, - m31, m32, m33, m34, m35, - m41, m42, m43, m44, m45, - m51, m52, m53, m54, m55 -); -sub_impl!(Matrix5, - m11, m12, m13, m14, m15, - m21, m22, m23, m24, m25, - m31, m32, m33, m34, m35, - m41, m42, m43, m44, m45, - m51, m52, m53, m54, m55 -); -scalar_add_impl!(Matrix5, - m11, m12, m13, m14, m15, - m21, m22, m23, m24, m25, - m31, m32, m33, m34, m35, - m41, m42, m43, m44, m45, - m51, m52, m53, m54, m55 -); -scalar_sub_impl!(Matrix5, - m11, m12, m13, m14, m15, - m21, m22, m23, m24, m25, - m31, m32, m33, m34, m35, - m41, m42, m43, m44, m45, - m51, m52, m53, m54, m55 -); -scalar_mul_impl!(Matrix5, - m11, m12, m13, m14, m15, - m21, m22, m23, m24, m25, - m31, m32, m33, m34, m35, - m41, m42, m43, m44, m45, - m51, m52, m53, m54, m55 -); -scalar_div_impl!(Matrix5, - m11, m12, m13, m14, m15, - m21, m22, m23, m24, m25, - m31, m32, m33, m34, m35, - m41, m42, m43, m44, m45, - m51, m52, m53, m54, m55 -); -iterable_impl!(Matrix5, 5); -iterable_mut_impl!(Matrix5, 5); dim_impl!(Matrix5, 5); -indexable_impl!(Matrix5, 5); -index_impl!(Matrix5, 5); -at_fast_impl!(Matrix5, 5); mat_mul_mat_impl!(Matrix5, 5); mat_mul_vec_impl!(Matrix5, Vector5, 5, ::zero); vec_mul_mat_impl!(Matrix5, Vector5, 5, ::zero); mat_mul_point_impl!(Matrix5, Point5, 5, Origin::origin); point_mul_mat_impl!(Matrix5, Point5, 5, Origin::origin); inverse_impl!(Matrix5, 5); -transpose_impl!(Matrix5, 5); -approx_eq_impl!(Matrix5); -row_impl!(Matrix5, Vector5, 5); -column_impl!(Matrix5, Vector5, 5); -column_slice_impl!(Matrix5, Vector5, DVector5, 5); -row_slice_impl!(Matrix5, Vector5, DVector5, 5); -diag_impl!(Matrix5, Vector5, 5); to_homogeneous_impl!(Matrix5, Matrix6, 5, 6); from_homogeneous_impl!(Matrix5, Matrix6, 5, 6); -outer_impl!(Vector5, Matrix5); eigen_qr_impl!(Matrix5, Vector5); -arbitrary_impl!(Matrix5, +componentwise_arbitrary!(Matrix5, m11, m12, m13, m14, m15, m21, m22, m23, m24, m25, m31, m32, m33, m34, m35, m41, m42, m43, m44, m45, m51, m52, m53, m54, m55 ); -rand_impl!(Matrix5, +componentwise_rand!(Matrix5, m11, m12, m13, m14, m15, m21, m22, m23, m24, m25, m31, m32, m33, m34, m35, m41, m42, m43, m44, m45, m51, m52, m53, m54, m55 ); -mean_impl!(Matrix5, Vector5, 5); mat_display_impl!(Matrix5, 5); /// Square matrix of dimension 6. @@ -517,7 +242,7 @@ pub struct Matrix6 { eye_impl!(Matrix6, 6, m11, m22, m33, m44, m55, m66); -mat_impl!(Matrix6, +matrix_impl!(Matrix6, 6, Vector6, DVector6, m11, m12, m13, m14, m15, m16, m21, m22, m23, m24, m25, m26, m31, m32, m33, m34, m35, m36, @@ -525,78 +250,6 @@ mat_impl!(Matrix6, m51, m52, m53, m54, m55, m56, m61, m62, m63, m64, m65, m66 ); -repeat_impl!(Matrix6, - m11, m12, m13, m14, m15, m16, - m21, m22, m23, m24, m25, m26, - m31, m32, m33, m34, m35, m36, - m41, m42, m43, m44, m45, m46, - m51, m52, m53, m54, m55, m56, - m61, m62, m63, m64, m65, m66 -); -conversion_impl!(Matrix6, 6); -mat_cast_impl!(Matrix6, - m11, m12, m13, m14, m15, m16, - m21, m22, m23, m24, m25, m26, - m31, m32, m33, m34, m35, m36, - m41, m42, m43, m44, m45, m46, - m51, m52, m53, m54, m55, m56, - m61, m62, m63, m64, m65, m66 -); -add_impl!(Matrix6, - m11, m12, m13, m14, m15, m16, - m21, m22, m23, m24, m25, m26, - m31, m32, m33, m34, m35, m36, - m41, m42, m43, m44, m45, m46, - m51, m52, m53, m54, m55, m56, - m61, m62, m63, m64, m65, m66 -); -sub_impl!(Matrix6, - m11, m12, m13, m14, m15, m16, - m21, m22, m23, m24, m25, m26, - m31, m32, m33, m34, m35, m36, - m41, m42, m43, m44, m45, m46, - m51, m52, m53, m54, m55, m56, - m61, m62, m63, m64, m65, m66 -); -scalar_add_impl!(Matrix6, - m11, m12, m13, m14, m15, m16, - m21, m22, m23, m24, m25, m26, - m31, m32, m33, m34, m35, m36, - m41, m42, m43, m44, m45, m46, - m51, m52, m53, m54, m55, m56, - m61, m62, m63, m64, m65, m66 -); -scalar_sub_impl!(Matrix6, - m11, m12, m13, m14, m15, m16, - m21, m22, m23, m24, m25, m26, - m31, m32, m33, m34, m35, m36, - m41, m42, m43, m44, m45, m46, - m51, m52, m53, m54, m55, m56, - m61, m62, m63, m64, m65, m66 -); -scalar_mul_impl!(Matrix6, - m11, m12, m13, m14, m15, m16, - m21, m22, m23, m24, m25, m26, - m31, m32, m33, m34, m35, m36, - m41, m42, m43, m44, m45, m46, - m51, m52, m53, m54, m55, m56, - m61, m62, m63, m64, m65, m66 -); -scalar_div_impl!(Matrix6, - m11, m12, m13, m14, m15, m16, - m21, m22, m23, m24, m25, m26, - m31, m32, m33, m34, m35, m36, - m41, m42, m43, m44, m45, m46, - m51, m52, m53, m54, m55, m56, - m61, m62, m63, m64, m65, m66 -); -absolute_impl!(Matrix6, m11, m12, m13, m14, m15, m16, m21, m22, m23, m24, m25, m26, - m31, m32, m33, m34, m35, m36, m41, m42, m43, m44, m45, m46, m51, m52, m53, m54, m55, m56, - m61, m62, m63, m64, m65, m66); - -zero_impl!(Matrix6, m11, m12, m13, m14, m15, m16, m21, m22, m23, m24, m25, m26, - m31, m32, m33, m34, m35, m36, m41, m42, m43, m44, m45, m46, m51, m52, m53, m54, m55, m56, - m61, m62, m63, m64, m65, m66); one_impl!(Matrix6, ::one , ::zero, ::zero, ::zero, ::zero, ::zero, @@ -606,28 +259,15 @@ one_impl!(Matrix6, ::zero, ::zero, ::zero, ::zero, ::one , ::zero, ::zero, ::zero, ::zero, ::zero, ::zero, ::one ); -iterable_impl!(Matrix6, 6); -iterable_mut_impl!(Matrix6, 6); dim_impl!(Matrix6, 6); -indexable_impl!(Matrix6, 6); -index_impl!(Matrix6, 6); -at_fast_impl!(Matrix6, 6); mat_mul_mat_impl!(Matrix6, 6); mat_mul_vec_impl!(Matrix6, Vector6, 6, ::zero); vec_mul_mat_impl!(Matrix6, Vector6, 6, ::zero); mat_mul_point_impl!(Matrix6, Point6, 6, Origin::origin); point_mul_mat_impl!(Matrix6, Point6, 6, Origin::origin); inverse_impl!(Matrix6, 6); -transpose_impl!(Matrix6, 6); -approx_eq_impl!(Matrix6); -row_impl!(Matrix6, Vector6, 6); -column_impl!(Matrix6, Vector6, 6); -column_slice_impl!(Matrix6, Vector6, DVector6, 6); -row_slice_impl!(Matrix6, Vector6, DVector6, 6); -diag_impl!(Matrix6, Vector6, 6); -outer_impl!(Vector6, Matrix6); eigen_qr_impl!(Matrix6, Vector6); -arbitrary_impl!(Matrix6, +componentwise_arbitrary!(Matrix6, m11, m12, m13, m14, m15, m16, m21, m22, m23, m24, m25, m26, m31, m32, m33, m34, m35, m36, @@ -635,7 +275,7 @@ arbitrary_impl!(Matrix6, m51, m52, m53, m54, m55, m56, m61, m62, m63, m64, m65, m66 ); -rand_impl!(Matrix6, +componentwise_rand!(Matrix6, m11, m12, m13, m14, m15, m16, m21, m22, m23, m24, m25, m26, m31, m32, m33, m34, m35, m36, @@ -643,5 +283,4 @@ rand_impl!(Matrix6, m51, m52, m53, m54, m55, m56, m61, m62, m63, m64, m65, m66 ); -mean_impl!(Matrix6, Vector6, 6); mat_display_impl!(Matrix6, 6); diff --git a/src/structs/matrix_macros.rs b/src/structs/matrix_macros.rs index d5de9ea0..21404076 100644 --- a/src/structs/matrix_macros.rs +++ b/src/structs/matrix_macros.rs @@ -1,20 +1,22 @@ #![macro_use] -macro_rules! mat_impl( - ($t: ident, $($compN: ident),+) => ( - impl $t { - #[inline] - pub fn new($($compN: N ),+) -> $t { - $t { - $($compN: $compN ),+ +macro_rules! matrix_impl( + ($t: ident, $dimension: expr, $vector: ident, $dvector: ident, $($compN: ident),+) => ( + impl $t { + #[inline] + pub fn new($($compN: N ),+) -> $t { + $t { + $($compN: $compN ),+ + } } } - } - ) -); -macro_rules! conversion_impl( - ($t: ident, $dimension: expr) => ( + + /* + * + * Conversions (AsRef, AsMut, From) + * + */ impl AsRef<[[N; $dimension]; $dimension]> for $t { #[inline] fn as_ref(&self) -> &[[N; $dimension]; $dimension] { @@ -58,11 +60,13 @@ macro_rules! conversion_impl( tref.clone() } } - ) -); -macro_rules! at_fast_impl( - ($t: ident, $dimension: expr) => ( + + /* + * + * Unsafe indexing. + * + */ impl $t { #[inline] pub unsafe fn at_fast(&self, (i, j): (usize, usize)) -> N { @@ -76,331 +80,77 @@ macro_rules! at_fast_impl( .get_unchecked_mut(i + j * $dimension)) = val } } - ) -); -macro_rules! mat_cast_impl( - ($t: ident, $($compN: ident),+) => ( + + /* + * + * Cast + * + */ impl> Cast<$t> for $t { #[inline] fn from(v: $t) -> $t { $t::new($(Cast::from(v.$compN)),+) } } - ) -); -macro_rules! add_impl( - ($t: ident, $($compN: ident),+) => ( - impl> Add<$t> for $t { - type Output = $t; + /* + * + * Iterable + * + */ + impl Iterable for $t { #[inline] - fn add(self, right: $t) -> $t { - $t::new($(self.$compN + right.$compN),+) - } - } - - impl> AddAssign<$t> for $t { - #[inline] - fn add_assign(&mut self, right: $t) { - $( self.$compN += right.$compN; )+ - } - } - ) -); - -macro_rules! sub_impl( - ($t: ident, $($compN: ident),+) => ( - impl> Sub<$t> for $t { - type Output = $t; - - #[inline] - fn sub(self, right: $t) -> $t { - $t::new($(self.$compN - right.$compN),+) - } - } - - - impl> SubAssign<$t> for $t { - #[inline] - fn sub_assign(&mut self, right: $t) { - $( self.$compN -= right.$compN; )+ - } - } - ) -); - -macro_rules! mat_mul_scalar_impl( - ($t: ident, $($compN: ident),+) => ( - impl> Mul for N { - type Output = $t; - - #[inline] - fn mul(self, right: N) -> $t { - $t::new($(self.$compN * *right),+) - } - } - - impl> MulAssign for $t { - #[inline] - fn mul_assign(&mut self, right: N) { - $( self.$compN *= *right; )+ - } - } - - impl Mul<$t> for f32 { - type Output = $t; - - #[inline] - fn mul(self, right: $t) -> $t { - $t::new($(self * right.$compN),+) - } - } - - impl Mul<$t> for f64 { - type Output = $t; - - #[inline] - fn mul(self, right: $t) -> $t { - $t::new($(self * right.$compN),+) - } - } - ) -); - -macro_rules! mat_div_scalar_impl( - ($t: ident, $($compN: ident),+) => ( - impl> Div for $t { - type Output = $t; - - #[inline] - fn div(self, right: N) -> $t { - $t::new($(self.$compN / *right),+) - } - } - - impl> DivAssign for $t { - #[inline] - fn div_assign(&mut self, right: N) { - $( self.$compN /= *right; )+ - } - } - ) -); - -macro_rules! mat_add_scalar_impl( - ($t: ident, $($compN: ident),+) => ( - impl> Add for $t { - type Output = $t; - - #[inline] - fn add(self, right: N) -> $t { - $t::new($(self.$compN + *right),+) - } - } - - impl> AddAssign for $t { - #[inline] - fn add_assign(&mut self, right: N) { - $( self.$compN += *right; )+ - } - } - - impl Add<$t> for f32 { - type Output = $t; - - #[inline] - fn add(self, right: $t) -> $t { - $t::new($(self + right.$compN),+) - } - } - - impl Add<$t> for f64 { - type Output = $t; - - #[inline] - fn add(self, right: $t) -> $t { - $t::new($(self + right.$compN),+) - } - } - ) -); - -macro_rules! mat_sub_scalar_impl( - ($t: ident, $($compN: ident),+) => ( - impl> Sub for $t { - type Output = $t; - - #[inline] - fn sub(self, right: &N) -> $t { - $t::new($(self.$compN - *right),+) - } - } - - impl> SubAssign for $t { - #[inline] - fn sub_assign(&mut self, right: N) { - $( self.$compN -= *right; )+ - } - } - - impl Sub for $t { - type Output = $t; - - #[inline] - fn sub(self, right: $t) -> $t { - $t::new($(self - right.$compN),+) - } - } - - impl Sub for $t { - type Output = $t; - - #[inline] - fn sub(self, right: $t) -> $t { - $t::new($(self - right.$compN),+) - } - } - ) -); - - -macro_rules! eye_impl( - ($t: ident, $dimension: expr, $($comp_diagN: ident),+) => ( - impl Eye for $t { - fn new_identity(dimension: usize) -> $t { - assert!(dimension == $dimension); - let mut eye: $t = ::zero(); - $(eye.$comp_diagN = ::one();)+ - eye - } - } - ) -); - -macro_rules! repeat_impl( - ($t: ident, $($compN: ident),+) => ( - impl Repeat for $t { - fn repeat(val: N) -> $t { - $t { - $($compN: val ),+ + fn iter(&self) -> Iter { + unsafe { + mem::transmute::<&$t, &[N; $dimension * $dimension]>(self).iter() } } } - ) -); -macro_rules! absolute_impl( - ($t: ident, $($compN: ident),+) => ( - impl> Absolute<$t> for $t { - #[inline] - fn abs(m: &$t) -> $t { - $t::new($(::abs(&m.$compN) ),+) - } - } - ) -); - -macro_rules! iterable_impl( - ($t: ident, $dimension: expr) => ( - impl Iterable for $t { - #[inline] - fn iter(&self) -> Iter { - unsafe { - mem::transmute::<&$t, &[N; $dimension * $dimension]>(self).iter() - } - } - } - ) -); - -macro_rules! iterable_mut_impl( - ($t: ident, $dimension: expr) => ( - impl IterableMut for $t { - #[inline] - fn iter_mut(& mut self) -> IterMut { - unsafe { - mem::transmute::<&mut $t, &mut [N; $dimension * $dimension]>(self).iter_mut() - } - } - } - ) -); - -macro_rules! one_impl( - ($t: ident, $($valueN: expr),+ ) => ( - impl One for $t { - #[inline] - fn one() -> $t { - $t::new($($valueN() ),+) - } - } - ) -); - -macro_rules! zero_impl( - ($t: ident, $($compN: ident),+ ) => ( - impl Zero for $t { - #[inline] - fn zero() -> $t { - $t { - $($compN: ::zero() ),+ + impl IterableMut for $t { + #[inline] + fn iter_mut(& mut self) -> IterMut { + unsafe { + mem::transmute::<&mut $t, &mut [N; $dimension * $dimension]>(self).iter_mut() + } } } - #[inline] - fn is_zero(&self) -> bool { - $(::is_zero(&self.$compN) )&&+ - } - } - ) -); -macro_rules! dim_impl( - ($t: ident, $dimension: expr) => ( - impl Dimension for $t { - #[inline] - fn dimension(_: Option<$t>) -> usize { - $dimension - } - } - ) -); - -macro_rules! indexable_impl( - ($t: ident, $dimension: expr) => ( - impl Shape<(usize, usize)> for $t { - #[inline] - fn shape(&self) -> (usize, usize) { - ($dimension, $dimension) - } - } - - impl Indexable<(usize, usize), N> for $t { - #[inline] - fn swap(&mut self, (i1, j1): (usize, usize), (i2, j2): (usize, usize)) { - unsafe { - mem::transmute::<&mut $t, &mut [N; $dimension * $dimension]>(self) - .swap(i1 + j1 * $dimension, i2 + j2 * $dimension) + /* + * + * Shape/Indexable/Index + * + */ + impl Shape<(usize, usize)> for $t { + #[inline] + fn shape(&self) -> (usize, usize) { + ($dimension, $dimension) } } - #[inline] - unsafe fn unsafe_at(&self, (i, j): (usize, usize)) -> N { - (*mem::transmute::<&$t, &[N; $dimension * $dimension]>(self).get_unchecked(i + j * $dimension)) + impl Indexable<(usize, usize), N> for $t { + #[inline] + fn swap(&mut self, (i1, j1): (usize, usize), (i2, j2): (usize, usize)) { + unsafe { + mem::transmute::<&mut $t, &mut [N; $dimension * $dimension]>(self) + .swap(i1 + j1 * $dimension, i2 + j2 * $dimension) + } + } + + #[inline] + unsafe fn unsafe_at(&self, (i, j): (usize, usize)) -> N { + (*mem::transmute::<&$t, &[N; $dimension * $dimension]>(self).get_unchecked(i + j * $dimension)) + } + + #[inline] + unsafe fn unsafe_set(&mut self, (i, j): (usize, usize), val: N) { + (*mem::transmute::<&mut $t, &mut [N; $dimension * $dimension]>(self).get_unchecked_mut(i + j * $dimension)) = val + } } - #[inline] - unsafe fn unsafe_set(&mut self, (i, j): (usize, usize), val: N) { - (*mem::transmute::<&mut $t, &mut [N; $dimension * $dimension]>(self).get_unchecked_mut(i + j * $dimension)) = val - } - } - ) -); - -macro_rules! index_impl( - ($t: ident, $dimension: expr) => ( impl Index<(usize, usize)> for $t { type Output = N; @@ -418,96 +168,167 @@ macro_rules! index_impl( } } } - ) -); -macro_rules! column_slice_impl( - ($t: ident, $tv: ident, $slice: ident, $dimension: expr) => ( - impl ColumnSlice<$slice> for $t { - fn column_slice(&self, cid: usize, rstart: usize, rend: usize) -> $slice { + + /* + * + * Row/Column + * + */ + impl Column<$vector> for $t { + #[inline] + fn ncols(&self) -> usize { + Dimension::dimension(None::<$t>) + } + + #[inline] + fn set_column(&mut self, column: usize, v: $vector) { + for (i, e) in v.iter().enumerate() { + self[(i, column)] = *e; + } + } + + #[inline] + fn column(&self, column: usize) -> $vector { + let mut res: $vector = ::zero(); + + for (i, e) in res.iter_mut().enumerate() { + *e = self[(i, column)]; + } + + res + } + } + + impl ColumnSlice<$dvector> for $t { + fn column_slice(&self, cid: usize, rstart: usize, rend: usize) -> $dvector { let column = self.column(cid); - $slice::from_slice(rend - rstart, &column.as_ref()[rstart .. rend]) - } - } - ) -); - -macro_rules! row_impl( - ($t: ident, $tv: ident, $dimension: expr) => ( - impl Row<$tv> for $t { - #[inline] - fn nrows(&self) -> usize { - Dimension::dimension(None::<$t>) - } - - #[inline] - fn set_row(&mut self, row: usize, v: $tv) { - for (i, e) in v.iter().enumerate() { - self[(row, i)] = *e; + $dvector::from_slice(rend - rstart, &column.as_ref()[rstart .. rend]) } } - #[inline] - fn row(&self, row: usize) -> $tv { - let mut res: $tv = ::zero(); - - for (i, e) in res.iter_mut().enumerate() { - *e = self[(row, i)]; + impl Row<$vector> for $t { + #[inline] + fn nrows(&self) -> usize { + Dimension::dimension(None::<$t>) } - res - } - } - ) -); + #[inline] + fn set_row(&mut self, row: usize, v: $vector) { + for (i, e) in v.iter().enumerate() { + self[(row, i)] = *e; + } + } -macro_rules! row_slice_impl( - ($t: ident, $tv: ident, $slice: ident, $dimension: expr) => ( - impl RowSlice<$slice> for $t { - fn row_slice(&self, rid: usize, cstart: usize, cend: usize) -> $slice { + #[inline] + fn row(&self, row: usize) -> $vector { + let mut res: $vector = ::zero(); + + for (i, e) in res.iter_mut().enumerate() { + *e = self[(row, i)]; + } + + res + } + } + + impl RowSlice<$dvector> for $t { + fn row_slice(&self, rid: usize, cstart: usize, cend: usize) -> $dvector { let row = self.row(rid); - $slice::from_slice(cend - cstart, &row.as_ref()[cstart .. cend]) - } - } - ) -); - -macro_rules! column_impl( - ($t: ident, $tv: ident, $dimension: expr) => ( - impl Column<$tv> for $t { - #[inline] - fn ncols(&self) -> usize { - Dimension::dimension(None::<$t>) - } - - #[inline] - fn set_column(&mut self, column: usize, v: $tv) { - for (i, e) in v.iter().enumerate() { - self[(i, column)] = *e; + $dvector::from_slice(cend - cstart, &row.as_ref()[cstart .. cend]) } } - #[inline] - fn column(&self, column: usize) -> $tv { - let mut res: $tv = ::zero(); - for (i, e) in res.iter_mut().enumerate() { - *e = self[(i, column)]; - } - - res - } - } - ) -); - -macro_rules! diag_impl( - ($t: ident, $tv: ident, $dimension: expr) => ( - impl Diagonal<$tv> for $t { + /* + * + * Transpose + * + */ + impl Transpose for $t { #[inline] - fn from_diagonal(diagonal: &$tv) -> $t { + fn transpose(&self) -> $t { + let mut res = *self; + + res.transpose_mut(); + res + } + + #[inline] + fn transpose_mut(&mut self) { + for i in 1 .. $dimension { + for j in 0 .. i { + self.swap((i, j), (j, i)) + } + } + } + } + + + /* + * + * ApproxEq + * + */ + impl> ApproxEq for $t { + #[inline] + fn approx_epsilon(_: Option<$t>) -> N { + ApproxEq::approx_epsilon(None::) + } + + #[inline] + fn approx_ulps(_: Option<$t>) -> u32 { + ApproxEq::approx_ulps(None::) + } + + #[inline] + fn approx_eq_eps(&self, other: &$t, epsilon: &N) -> bool { + let mut zip = self.iter().zip(other.iter()); + zip.all(|(a, b)| ApproxEq::approx_eq_eps(a, b, epsilon)) + } + + #[inline] + fn approx_eq_ulps(&self, other: &$t, ulps: u32) -> bool { + let mut zip = self.iter().zip(other.iter()); + zip.all(|(a, b)| ApproxEq::approx_eq_ulps(a, b, ulps)) + } + } + + + /* + * + * Mean + * + */ + impl + Clone> Mean<$vector> for $t { + fn mean(&self) -> $vector { + let mut res: $vector = ::zero(); + let normalizer: N = Cast::from(1.0f64 / $dimension as f64); + + for i in 0 .. $dimension { + for j in 0 .. $dimension { + unsafe { + let acc = res.unsafe_at(j) + self.unsafe_at((i, j)) * normalizer; + res.unsafe_set(j, acc); + } + } + } + + res + } + } + + + /* + * + * Diagonal + * + */ + impl Diagonal<$vector> for $t { + #[inline] + fn from_diagonal(diagonal: &$vector) -> $t { let mut res: $t = ::zero(); res.set_diagonal(diagonal); @@ -516,8 +337,8 @@ macro_rules! diag_impl( } #[inline] - fn diagonal(&self) -> $tv { - let mut diagonal: $tv = ::zero(); + fn diagonal(&self) -> $vector { + let mut diagonal: $vector = ::zero(); for i in 0 .. $dimension { unsafe { diagonal.unsafe_set(i, self.unsafe_at((i, i))) } @@ -527,17 +348,61 @@ macro_rules! diag_impl( } } - impl DiagMut<$tv> for $t { + impl DiagonalMut<$vector> for $t { #[inline] - fn set_diagonal(&mut self, diagonal: &$tv) { + fn set_diagonal(&mut self, diagonal: &$vector) { for i in 0 .. $dimension { unsafe { self.unsafe_set((i, i), diagonal.unsafe_at(i)) } } } } + + + /* + * + * Outer + * + */ + impl + Zero> Outer for $vector { + type OuterProductType = $t; + + #[inline] + fn outer(&self, other: &$vector) -> $t { + let mut res: $t = ::zero(); + + for i in 0 .. ::dimension::<$vector>() { + for j in 0 .. ::dimension::<$vector>() { + res[(i, j)] = self[i] * other[j] + } + } + res + } + } + + /* + * + * Componentwise unary operations. + * + */ + componentwise_repeat!($t, $($compN),+); + componentwise_absolute!($t, $($compN),+); + componentwise_zero!($t, $($compN),+); + + /* + * + * Pointwise binary operations. + * + */ + pointwise_add!($t, $($compN),+); + pointwise_sub!($t, $($compN),+); + pointwise_scalar_add!($t, $($compN),+); + pointwise_scalar_sub!($t, $($compN),+); + pointwise_scalar_div!($t, $($compN),+); + pointwise_scalar_mul!($t, $($compN),+); ) ); + macro_rules! mat_mul_mat_impl( ($t: ident, $dimension: expr) => ( impl Mul<$t> for $t { @@ -727,56 +592,6 @@ macro_rules! inverse_impl( ) ); -macro_rules! transpose_impl( - ($t: ident, $dimension: expr) => ( - impl Transpose for $t { - #[inline] - fn transpose(&self) -> $t { - let mut res = *self; - - res.transpose_mut(); - res - } - - #[inline] - fn transpose_mut(&mut self) { - for i in 1 .. $dimension { - for j in 0 .. i { - self.swap((i, j), (j, i)) - } - } - } - } - ) -); - -macro_rules! approx_eq_impl( - ($t: ident) => ( - impl> ApproxEq for $t { - #[inline] - fn approx_epsilon(_: Option<$t>) -> N { - ApproxEq::approx_epsilon(None::) - } - - #[inline] - fn approx_ulps(_: Option<$t>) -> u32 { - ApproxEq::approx_ulps(None::) - } - - #[inline] - fn approx_eq_eps(&self, other: &$t, epsilon: &N) -> bool { - let mut zip = self.iter().zip(other.iter()); - zip.all(|(a, b)| ApproxEq::approx_eq_eps(a, b, epsilon)) - } - - #[inline] - fn approx_eq_ulps(&self, other: &$t, ulps: u32) -> bool { - let mut zip = self.iter().zip(other.iter()); - zip.all(|(a, b)| ApproxEq::approx_eq_ulps(a, b, ulps)) - } - } - ) -); macro_rules! to_homogeneous_impl( ($t: ident, $t2: ident, $dimension: expr, $dim2: expr) => ( @@ -785,8 +600,8 @@ macro_rules! to_homogeneous_impl( fn to_homogeneous(&self) -> $t2 { let mut res: $t2 = ::one(); - for i in 0..$dimension { - for j in 0..$dimension { + for i in 0 .. $dimension { + for j in 0 .. $dimension { res[(i, j)] = self[(i, j)] } } @@ -804,8 +619,8 @@ macro_rules! from_homogeneous_impl( fn from(m: &$t2) -> $t { let mut res: $t = ::one(); - for i in 0..$dimension { - for j in 0..$dimension { + for i in 0 .. $dimension { + for j in 0 .. $dimension { res[(i, j)] = m[(i, j)] } } @@ -819,25 +634,6 @@ macro_rules! from_homogeneous_impl( ) ); -macro_rules! outer_impl( - ($t: ident, $m: ident) => ( - impl + Zero> Outer for $t { - type OuterProductType = $m; - - #[inline] - fn outer(&self, other: &$t) -> $m { - let mut res: $m = ::zero(); - - for i in 0 .. ::dimension::<$t>() { - for j in 0 .. ::dimension::<$t>() { - res[(i, j)] = self[i] * other[j] - } - } - res - } - } - ) -); macro_rules! eigen_qr_impl( ($t: ident, $v: ident) => ( @@ -851,27 +647,6 @@ macro_rules! eigen_qr_impl( ); -macro_rules! mean_impl( - ($t: ident, $v: ident, $dimension: expr) => ( - impl + Clone> Mean<$v> for $t { - fn mean(&self) -> $v { - let mut res: $v = ::zero(); - let normalizer: N = Cast::from(1.0f64 / $dimension as f64); - - for i in 0 .. $dimension { - for j in 0 .. $dimension { - unsafe { - let acc = res.unsafe_at(j) + self.unsafe_at((i, j)) * normalizer; - res.unsafe_set(j, acc); - } - } - } - - res - } - } - ) -); macro_rules! mat_display_impl( ($t: ident, $dimension: expr) => ( @@ -925,3 +700,39 @@ macro_rules! mat_display_impl( } ) ); + +macro_rules! one_impl( + ($t: ident, $($valueN: expr),+ ) => ( + impl One for $t { + #[inline] + fn one() -> $t { + $t::new($($valueN() ),+) + } + } + ) +); + +macro_rules! eye_impl( + ($t: ident, $dimension: expr, $($comp_diagN: ident),+) => ( + impl Eye for $t { + fn new_identity(dimension: usize) -> $t { + assert!(dimension == $dimension); + let mut eye: $t = ::zero(); + $(eye.$comp_diagN = ::one();)+ + eye + } + } + ) +); + + +macro_rules! dim_impl( + ($t: ident, $dimension: expr) => ( + impl Dimension for $t { + #[inline] + fn dimension(_: Option<$t>) -> usize { + $dimension + } + } + ) +); diff --git a/src/structs/mod.rs b/src/structs/mod.rs index 5eae0cbf..c443782a 100644 --- a/src/structs/mod.rs +++ b/src/structs/mod.rs @@ -15,6 +15,7 @@ pub use self::quaternion::{Quaternion, UnitQuaternion}; #[cfg(feature="generic_sizes")] pub use self::vectorn::VectorN; +mod common_macros; mod dmatrix_macros; mod dmatrix; mod vectorn_macros; diff --git a/src/structs/point.rs b/src/structs/point.rs index 442e1ab3..699d7aaa 100644 --- a/src/structs/point.rs +++ b/src/structs/point.rs @@ -27,38 +27,9 @@ pub struct Point1 { pub x: N } -new_impl!(Point1, x); -origin_impl!(Point1, x); -pord_impl!(Point1, x,); -scalar_mul_impl!(Point1, x); -scalar_div_impl!(Point1, x); -scalar_add_impl!(Point1, x); -scalar_sub_impl!(Point1, x); -vec_cast_impl!(Point1, x); -conversion_impl!(Point1, 1); -index_impl!(Point1); -indexable_impl!(Point1, 1); -at_fast_impl!(Point1, 1); -repeat_impl!(Point1, val, x); -dim_impl!(Point1, 1); -container_impl!(Point1); -point_as_vec_impl!(Point1, Vector1, x); -point_sub_impl!(Point1, Vector1); -neg_impl!(Point1, x); -point_add_vec_impl!(Point1, Vector1, x); -point_sub_vec_impl!(Point1, Vector1, x); -approx_eq_impl!(Point1, x); +point_impl!(Point1, Vector1, Point2, y | x); +vectorlike_impl!(Point1, 1, x); from_iterator_impl!(Point1, iterator); -bounded_impl!(Point1, x); -axpy_impl!(Point1, x); -iterable_impl!(Point1, 1); -iterable_mut_impl!(Point1, 1); -point_to_homogeneous_impl!(Point1, Point2, y, x); -point_from_homogeneous_impl!(Point1, Point2, y, x); -num_float_point_impl!(Point1, Vector1); -arbitrary_point_impl!(Point1, x); -rand_impl!(Point1, x); -point_display_impl!(Point1); /// Point of dimension 2. /// @@ -73,38 +44,9 @@ pub struct Point2 { pub y: N } -new_impl!(Point2, x, y); -origin_impl!(Point2, x, y); -pord_impl!(Point2, x, y); -scalar_mul_impl!(Point2, x, y); -scalar_div_impl!(Point2, x, y); -scalar_add_impl!(Point2, x, y); -scalar_sub_impl!(Point2, x, y); -vec_cast_impl!(Point2, x, y); -conversion_impl!(Point2, 2); -index_impl!(Point2); -indexable_impl!(Point2, 2); -at_fast_impl!(Point2, 2); -repeat_impl!(Point2, val, x, y); -dim_impl!(Point2, 2); -container_impl!(Point2); -point_as_vec_impl!(Point2, Vector2, x, y); -point_sub_impl!(Point2, Vector2); -neg_impl!(Point2, x, y); -point_add_vec_impl!(Point2, Vector2, x, y); -point_sub_vec_impl!(Point2, Vector2, x, y); -approx_eq_impl!(Point2, x, y); +point_impl!(Point2, Vector2, Point3, z | x, y); +vectorlike_impl!(Point2, 2, x, y); from_iterator_impl!(Point2, iterator, iterator); -bounded_impl!(Point2, x, y); -axpy_impl!(Point2, x, y); -iterable_impl!(Point2, 2); -iterable_mut_impl!(Point2, 2); -point_to_homogeneous_impl!(Point2, Point3, z, x, y); -point_from_homogeneous_impl!(Point2, Point3, z, x, y); -num_float_point_impl!(Point2, Vector2); -arbitrary_point_impl!(Point2, x, y); -rand_impl!(Point2, x, y); -point_display_impl!(Point2); /// Point of dimension 3. /// @@ -121,38 +63,9 @@ pub struct Point3 { pub z: N } -new_impl!(Point3, x, y, z); -origin_impl!(Point3, x, y, z); -pord_impl!(Point3, x, y, z); -scalar_mul_impl!(Point3, x, y, z); -scalar_div_impl!(Point3, x, y, z); -scalar_add_impl!(Point3, x, y, z); -scalar_sub_impl!(Point3, x, y, z); -vec_cast_impl!(Point3, x, y, z); -conversion_impl!(Point3, 3); -index_impl!(Point3); -indexable_impl!(Point3, 3); -at_fast_impl!(Point3, 3); -repeat_impl!(Point3, val, x, y, z); -dim_impl!(Point3, 3); -container_impl!(Point3); -point_as_vec_impl!(Point3, Vector3, x, y, z); -point_sub_impl!(Point3, Vector3); -neg_impl!(Point3, x, y, z); -point_add_vec_impl!(Point3, Vector3, x, y, z); -point_sub_vec_impl!(Point3, Vector3, x, y, z); -approx_eq_impl!(Point3, x, y, z); +point_impl!(Point3, Vector3, Point4, w | x, y, z); +vectorlike_impl!(Point3, 3, x, y, z); from_iterator_impl!(Point3, iterator, iterator, iterator); -bounded_impl!(Point3, x, y, z); -axpy_impl!(Point3, x, y, z); -iterable_impl!(Point3, 3); -iterable_mut_impl!(Point3, 3); -point_to_homogeneous_impl!(Point3, Point4, w, x, y, z); -point_from_homogeneous_impl!(Point3, Point4, w, x, y, z); -num_float_point_impl!(Point3, Vector3); -arbitrary_point_impl!(Point3, x, y, z); -rand_impl!(Point3, x, y, z); -point_display_impl!(Point3); /// Point of dimension 4. /// @@ -171,38 +84,9 @@ pub struct Point4 { pub w: N } -new_impl!(Point4, x, y, z, w); -origin_impl!(Point4, x, y, z, w); -pord_impl!(Point4, x, y, z, w); -scalar_mul_impl!(Point4, x, y, z, w); -scalar_div_impl!(Point4, x, y, z, w); -scalar_add_impl!(Point4, x, y, z, w); -scalar_sub_impl!(Point4, x, y, z, w); -vec_cast_impl!(Point4, x, y, z, w); -conversion_impl!(Point4, 4); -index_impl!(Point4); -indexable_impl!(Point4, 4); -at_fast_impl!(Point4, 4); -repeat_impl!(Point4, val, x, y, z, w); -dim_impl!(Point4, 4); -container_impl!(Point4); -point_as_vec_impl!(Point4, Vector4, x, y, z, w); -point_sub_impl!(Point4, Vector4); -neg_impl!(Point4, x, y, z, w); -point_add_vec_impl!(Point4, Vector4, x, y, z, w); -point_sub_vec_impl!(Point4, Vector4, x, y, z, w); -approx_eq_impl!(Point4, x, y, z, w); +point_impl!(Point4, Vector4, Point5, a | x, y, z, w); +vectorlike_impl!(Point4, 4, x, y, z, w); from_iterator_impl!(Point4, iterator, iterator, iterator, iterator); -bounded_impl!(Point4, x, y, z, w); -axpy_impl!(Point4, x, y, z, w); -iterable_impl!(Point4, 4); -iterable_mut_impl!(Point4, 4); -point_to_homogeneous_impl!(Point4, Point5, a, x, y, z, w); -point_from_homogeneous_impl!(Point4, Point5, a, x, y, z, w); -num_float_point_impl!(Point4, Vector4); -arbitrary_point_impl!(Point4, x, y, z, w); -rand_impl!(Point4, x, y, z, w); -point_display_impl!(Point4); /// Point of dimension 5. /// @@ -223,38 +107,9 @@ pub struct Point5 { pub a: N } -new_impl!(Point5, x, y, z, w, a); -origin_impl!(Point5, x, y, z, w, a); -pord_impl!(Point5, x, y, z, w, a); -scalar_mul_impl!(Point5, x, y, z, w, a); -scalar_div_impl!(Point5, x, y, z, w, a); -scalar_add_impl!(Point5, x, y, z, w, a); -scalar_sub_impl!(Point5, x, y, z, w, a); -vec_cast_impl!(Point5, x, y, z, w, a); -conversion_impl!(Point5, 5); -index_impl!(Point5); -indexable_impl!(Point5, 5); -at_fast_impl!(Point5, 5); -repeat_impl!(Point5, val, x, y, z, w, a); -dim_impl!(Point5, 5); -container_impl!(Point5); -point_as_vec_impl!(Point5, Vector5, x, y, z, w, a); -point_sub_impl!(Point5, Vector5); -neg_impl!(Point5, x, y, z, w, a); -point_add_vec_impl!(Point5, Vector5, x, y, z, w, a); -point_sub_vec_impl!(Point5, Vector5, x, y, z, w, a); -approx_eq_impl!(Point5, x, y, z, w, a); +point_impl!(Point5, Vector5, Point6, b | x, y, z, w, a); +vectorlike_impl!(Point5, 5, x, y, z, w, a); from_iterator_impl!(Point5, iterator, iterator, iterator, iterator, iterator); -bounded_impl!(Point5, x, y, z, w, a); -axpy_impl!(Point5, x, y, z, w, a); -iterable_impl!(Point5, 5); -iterable_mut_impl!(Point5, 5); -point_to_homogeneous_impl!(Point5, Point6, b, x, y, z, w, a); -point_from_homogeneous_impl!(Point5, Point6, b, x, y, z, w, a); -num_float_point_impl!(Point5, Vector5); -arbitrary_point_impl!(Point5, x, y, z, w, a); -rand_impl!(Point5, x, y, z, w, a); -point_display_impl!(Point5); /// Point of dimension 6. /// @@ -277,33 +132,6 @@ pub struct Point6 { pub b: N } -new_impl!(Point6, x, y, z, w, a, b); -origin_impl!(Point6, x, y, z, w, a, b); -pord_impl!(Point6, x, y, z, w, a, b); -scalar_mul_impl!(Point6, x, y, z, w, a, b); -scalar_div_impl!(Point6, x, y, z, w, a, b); -scalar_add_impl!(Point6, x, y, z, w, a, b); -scalar_sub_impl!(Point6, x, y, z, w, a, b); -vec_cast_impl!(Point6, x, y, z, w, a, b); -conversion_impl!(Point6, 6); -index_impl!(Point6); -indexable_impl!(Point6, 6); -at_fast_impl!(Point6, 6); -repeat_impl!(Point6, val, x, y, z, w, a, b); -dim_impl!(Point6, 6); -container_impl!(Point6); -point_as_vec_impl!(Point6, Vector6, x, y, z, w, a, b); -point_sub_impl!(Point6, Vector6); -neg_impl!(Point6, x, y, z, w, a, b); -point_add_vec_impl!(Point6, Vector6, x, y, z, w, a, b); -point_sub_vec_impl!(Point6, Vector6, x, y, z, w, a, b); -approx_eq_impl!(Point6, x, y, z, w, a, b); +point_impl!(Point6, Vector6 | x, y, z, w, a, b); +vectorlike_impl!(Point6, 6, x, y, z, w, a, b); from_iterator_impl!(Point6, iterator, iterator, iterator, iterator, iterator, iterator); -bounded_impl!(Point6, x, y, z, w, a, b); -axpy_impl!(Point6, x, y, z, w, a, b); -iterable_impl!(Point6, 6); -iterable_mut_impl!(Point6, 6); -num_float_point_impl!(Point6, Vector6); -arbitrary_point_impl!(Point6, x, y, z, w, a, b); -rand_impl!(Point6, x, y, z, w, a, b); -point_display_impl!(Point6); diff --git a/src/structs/point_macros.rs b/src/structs/point_macros.rs index d55cde10..077255cb 100644 --- a/src/structs/point_macros.rs +++ b/src/structs/point_macros.rs @@ -1,7 +1,13 @@ #![macro_use] -macro_rules! origin_impl( - ($t: ident, $($compN: ident),+) => ( +macro_rules! point_impl( + ($t: ident, $tv: ident | $($compN: ident),+) => ( + + /* + * + * Origin. + * + */ impl Origin for $t { #[inline] fn origin() -> $t { @@ -15,11 +21,13 @@ macro_rules! origin_impl( $(self.$compN.is_zero() )&&+ } } - ) -); -macro_rules! point_sub_impl( - ($t: ident, $tv: ident) => ( + + /* + * + * Point - Point + * + */ impl> Sub<$t> for $t { type Output = $tv; @@ -28,11 +36,13 @@ macro_rules! point_sub_impl( *self.as_vector() - *right.as_vector() } } - ) -); -macro_rules! point_add_vec_impl( - ($t: ident, $tv: ident, $($compN: ident),+) => ( + + /* + * + * Point + Vector + * + */ impl> Add<$tv> for $t { type Output = $t; @@ -48,11 +58,13 @@ macro_rules! point_add_vec_impl( $( self.$compN += right.$compN; )+ } } - ) -); -macro_rules! point_sub_vec_impl( - ($t: ident, $tv: ident, $($compN: ident),+) => ( + + /* + * + * Point - Vector + * + */ impl> Sub<$tv> for $t { type Output = $t; @@ -68,11 +80,14 @@ macro_rules! point_sub_vec_impl( $( self.$compN -= right.$compN; )+ } } - ) -); -macro_rules! point_as_vec_impl( - ($t: ident, $tv: ident, $($compN: ident),+) => ( + + + /* + * + * Point as vector. + * + */ impl $t { /// Converts this point to its associated vector. #[inline] @@ -114,40 +129,14 @@ macro_rules! point_as_vec_impl( self.set_coords(v) } } - ) -); -macro_rules! point_to_homogeneous_impl( - ($t: ident, $t2: ident, $extra: ident, $($compN: ident),+) => ( - impl ToHomogeneous<$t2> for $t { - fn to_homogeneous(&self) -> $t2 { - let mut res: $t2 = Origin::origin(); - $( res.$compN = self.$compN; )+ - res.$extra = ::one(); - res - } - } - ) -); - -macro_rules! point_from_homogeneous_impl( - ($t: ident, $t2: ident, $extra: ident, $($compN: ident),+) => ( - impl + One + Zero> FromHomogeneous<$t2> for $t { - fn from(v: &$t2) -> $t { - let mut res: $t = Origin::origin(); - - $( res.$compN = v.$compN / v.$extra; )+ - - res - } - } - ) -); - -macro_rules! num_float_point_impl( - ($t: ident, $tv: ident) => ( + /* + * + * NumPoint / FloatPoint + * + */ impl NumPoint for $t where N: BaseNum { } @@ -155,25 +144,13 @@ macro_rules! num_float_point_impl( impl FloatPoint for $t where N: BaseFloat + ApproxEq { } - ) -); -macro_rules! arbitrary_point_impl( - ($t: ident, $($compN: ident),*) => ( - #[cfg(feature="arbitrary")] - impl Arbitrary for $t { - #[inline] - fn arbitrary(g: &mut G) -> $t { - $t { - $($compN: Arbitrary::arbitrary(g),)* - } - } - } - ) -); -macro_rules! point_display_impl( - ($t: ident) => ( + /* + * + * Display + * + */ impl fmt::Display for $t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // FIXME: differenciate them from vectors ? @@ -190,5 +167,34 @@ macro_rules! point_display_impl( write!(f, ")") } } + ); + ($t: ident, $tv: ident, $th: ident, $comp_extra: ident | $($compN: ident),+) => ( + point_impl!($t, $tv | $($compN),+); + + /* + * + * ToHomogeneous / FromHomogeneous + * + */ + impl ToHomogeneous<$th> for $t { + fn to_homogeneous(&self) -> $th { + let mut res: $th = Origin::origin(); + + $( res.$compN = self.$compN; )+ + res.$comp_extra = ::one(); + + res + } + } + + impl + One + Zero> FromHomogeneous<$th> for $t { + fn from(v: &$th) -> $t { + let mut res: $t = Origin::origin(); + + $( res.$compN = v.$compN / v.$comp_extra; )+ + + res + } + } ) ); diff --git a/src/structs/quaternion.rs b/src/structs/quaternion.rs index 5cdbd7d1..78b87d1e 100644 --- a/src/structs/quaternion.rs +++ b/src/structs/quaternion.rs @@ -32,17 +32,6 @@ pub struct Quaternion { } impl Quaternion { - /// Creates a new quaternion from its components. - #[inline] - pub fn new(w: N, i: N, j: N, k: N) -> Quaternion { - Quaternion { - w: w, - i: i, - j: j, - k: k - } - } - /// The vector part `(i, j, k)` of this quaternion. #[inline] pub fn vector(&self) -> &Vector3 { @@ -176,9 +165,6 @@ impl fmt::Display for Quaternion { } } -rand_impl!(Quaternion, w, i, j, k); - - /// A unit quaternion that can represent a 3D rotation. #[repr(C)] #[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)] @@ -557,6 +543,18 @@ impl fmt::Display for UnitQuaternion { } } +/* + * + * Dimension + * + */ +impl Dimension for UnitQuaternion { + #[inline] + fn dimension(_: Option>) -> usize { + 3 + } +} + #[cfg(feature="arbitrary")] impl Arbitrary for UnitQuaternion { fn arbitrary(g: &mut G) -> UnitQuaternion { @@ -592,45 +590,15 @@ impl Quaternion { } } -impl Zero for Quaternion where T: Zero { - fn zero() -> Self { - Quaternion::new(::zero(), ::zero(), ::zero(), ::zero()) - } - - fn is_zero(&self) -> bool { - self.w.is_zero() && self.i.is_zero() && self.j.is_zero() && self.k.is_zero() - } -} - impl One for Quaternion where T: Copy + One + Zero + Sub + Add { fn one() -> Self { Quaternion::new(T::one(), T::zero(), T::zero(), T::zero()) } } -pord_impl!(Quaternion, w, i, j, k); -vec_axis_impl!(Quaternion, w, i, j, k); -vec_cast_impl!(Quaternion, w, i, j, k); -conversion_impl!(Quaternion, 4); -index_impl!(Quaternion); -indexable_impl!(Quaternion, 4); -at_fast_impl!(Quaternion, 4); -repeat_impl!(Quaternion, val, w, i, j, k); -dim_impl!(Quaternion, 3); -container_impl!(Quaternion); -add_impl!(Quaternion, w, i, j, k); -sub_impl!(Quaternion, w, i, j, k); -scalar_add_impl!(Quaternion, w, i, j, k); -scalar_sub_impl!(Quaternion, w, i, j, k); -scalar_mul_impl!(Quaternion, w, i, j, k); -scalar_div_impl!(Quaternion, w, i, j, k); -neg_impl!(Quaternion, w, i, j, k); -approx_eq_impl!(Quaternion, w, i, j, k); +componentwise_zero!(Quaternion, w, i, j, k); +component_basis_element!(Quaternion, w, i, j, k); +pointwise_add!(Quaternion, w, i, j, k); +pointwise_sub!(Quaternion, w, i, j, k); from_iterator_impl!(Quaternion, iterator, iterator, iterator, iterator); -bounded_impl!(Quaternion, w, i, j, k); -axpy_impl!(Quaternion, w, i, j, k); -iterable_impl!(Quaternion, 4); -iterable_mut_impl!(Quaternion, 4); -arbitrary_impl!(Quaternion, w, i, j, k); - -dim_impl!(UnitQuaternion, 3); +vectorlike_impl!(Quaternion, 4, w, i, j, k); diff --git a/src/structs/rotation.rs b/src/structs/rotation.rs index 94276c7a..0bcf940f 100644 --- a/src/structs/rotation.rs +++ b/src/structs/rotation.rs @@ -105,13 +105,6 @@ impl AbsoluteRotate> for Rotation2 { } } -#[cfg(feature="arbitrary")] -impl Arbitrary for Rotation2 { - fn arbitrary(g: &mut G) -> Rotation2 { - Rotation2::new(Arbitrary::arbitrary(g)) - } -} - /* * 3d rotation @@ -343,60 +336,13 @@ impl AbsoluteRotate> for Rotation3 { } } -#[cfg(feature="arbitrary")] -impl Arbitrary for Rotation3 { - fn arbitrary(g: &mut G) -> Rotation3 { - Rotation3::new(Arbitrary::arbitrary(g)) - } -} - /* * Common implementations. */ -submat_impl!(Rotation2, Matrix2); -rotate_impl!(Rotation2, Vector2, Point2); -transform_impl!(Rotation2, Vector2, Point2); +rotation_impl!(Rotation2, Matrix2, Vector2, Vector1, Point2, Matrix3); dim_impl!(Rotation2, 2); -rotation_mul_rotation_impl!(Rotation2); -rotation_mul_vec_impl!(Rotation2, Vector2); -vec_mul_rotation_impl!(Rotation2, Vector2); -rotation_mul_point_impl!(Rotation2, Point2); -point_mul_rotation_impl!(Rotation2, Point2); -one_impl!(Rotation2); -eye_impl!(Rotation2); -rotation_matrix_impl!(Rotation2, Vector2, Vector1); -column_impl!(Rotation2, Vector2); -row_impl!(Rotation2, Vector2); -index_impl!(Rotation2); -absolute_impl!(Rotation2, Matrix2); -to_homogeneous_impl!(Rotation2, Matrix3); -inverse_impl!(Rotation2); -transpose_impl!(Rotation2); -approx_eq_impl!(Rotation2); -diag_impl!(Rotation2, Vector2); -rotation_display_impl!(Rotation2); -submat_impl!(Rotation3, Matrix3); -rotate_impl!(Rotation3, Vector3, Point3); -transform_impl!(Rotation3, Vector3, Point3); +rotation_impl!(Rotation3, Matrix3, Vector3, Vector3, Point3, Matrix4); dim_impl!(Rotation3, 3); -rotation_mul_rotation_impl!(Rotation3); -rotation_mul_vec_impl!(Rotation3, Vector3); -vec_mul_rotation_impl!(Rotation3, Vector3); -rotation_mul_point_impl!(Rotation3, Point3); -point_mul_rotation_impl!(Rotation3, Point3); -one_impl!(Rotation3); -eye_impl!(Rotation3); -rotation_matrix_impl!(Rotation3, Vector3, Vector3); -column_impl!(Rotation3, Vector3); -row_impl!(Rotation3, Vector3); -index_impl!(Rotation3); -absolute_impl!(Rotation3, Matrix3); -to_homogeneous_impl!(Rotation3, Matrix4); -inverse_impl!(Rotation3); -transpose_impl!(Rotation3); -approx_eq_impl!(Rotation3); -diag_impl!(Rotation3, Vector3); -rotation_display_impl!(Rotation3); diff --git a/src/structs/rotation_macros.rs b/src/structs/rotation_macros.rs index 22cb90de..22307968 100644 --- a/src/structs/rotation_macros.rs +++ b/src/structs/rotation_macros.rs @@ -1,7 +1,7 @@ #![macro_use] -macro_rules! submat_impl( - ($t: ident, $submatrix: ident) => ( +macro_rules! rotation_impl( + ($t: ident, $submatrix: ident, $vector: ident, $rotvector: ident, $point: ident, $homogeneous: ident) => ( impl $t { /// This rotation's underlying matrix. #[inline] @@ -9,79 +9,75 @@ macro_rules! submat_impl( &self.submatrix } } - ) -); -macro_rules! rotate_impl( - ($t: ident, $tv: ident, $tp: ident) => ( - impl Rotate<$tv> for $t { + + /* + * + * Rotate Vector and Point + * + */ + impl Rotate<$vector> for $t { #[inline] - fn rotate(&self, v: &$tv) -> $tv { + fn rotate(&self, v: &$vector) -> $vector { *self * *v } #[inline] - fn inverse_rotate(&self, v: &$tv) -> $tv { + fn inverse_rotate(&self, v: &$vector) -> $vector { *v * *self } } - impl Rotate<$tp> for $t { + impl Rotate<$point> for $t { #[inline] - fn rotate(&self, p: &$tp) -> $tp { + fn rotate(&self, p: &$point) -> $point { *self * *p } #[inline] - fn inverse_rotate(&self, p: &$tp) -> $tp { + fn inverse_rotate(&self, p: &$point) -> $point { *p * *self } } - ) -); -macro_rules! transform_impl( - ($t: ident, $tv: ident, $tp: ident) => ( - impl Transform<$tv> for $t { + + /* + * + * Transform Vector and Point + * + */ + impl Transform<$vector> for $t { #[inline] - fn transform(&self, v: &$tv) -> $tv { + fn transform(&self, v: &$vector) -> $vector { self.rotate(v) } #[inline] - fn inverse_transform(&self, v: &$tv) -> $tv { + fn inverse_transform(&self, v: &$vector) -> $vector { self.inverse_rotate(v) } } - impl Transform<$tp> for $t { + impl Transform<$point> for $t { #[inline] - fn transform(&self, p: &$tp) -> $tp { + fn transform(&self, p: &$point) -> $point { self.rotate(p) } #[inline] - fn inverse_transform(&self, p: &$tp) -> $tp { + fn inverse_transform(&self, p: &$point) -> $point { self.inverse_rotate(p) } } - ) -); -macro_rules! dim_impl( - ($t: ident, $dimension: expr) => ( - impl Dimension for $t { - #[inline] - fn dimension(_: Option<$t>) -> usize { - $dimension - } - } - ) -); -macro_rules! rotation_matrix_impl( - ($t: ident, $tlv: ident, $tav: ident) => ( - impl + BaseFloat> RotationMatrix, $tav> for $t { + + /* + * + * Rotation Matrix + * + */ + impl + BaseFloat> RotationMatrix, $rotvector> for $t { type Output = $t; #[inline] @@ -89,22 +85,26 @@ macro_rules! rotation_matrix_impl( self.clone() } } - ) -); -macro_rules! one_impl( - ($t: ident) => ( + + /* + * + * One + * + */ impl One for $t { #[inline] fn one() -> $t { $t { submatrix: ::one() } } } - ) -); -macro_rules! eye_impl( - ($t: ident) => ( + + /* + * + * Eye + * + */ impl Eye for $t { #[inline] fn new_identity(dimension: usize) -> $t { @@ -116,27 +116,31 @@ macro_rules! eye_impl( } } } - ) -); -macro_rules! diag_impl( - ($t: ident, $tv: ident) => ( - impl Diagonal<$tv> for $t { + + /* + * + * Diagonal + * + */ + impl Diagonal<$vector> for $t { #[inline] - fn from_diagonal(diagonal: &$tv) -> $t { + fn from_diagonal(diagonal: &$vector) -> $t { $t { submatrix: Diagonal::from_diagonal(diagonal) } } #[inline] - fn diagonal(&self) -> $tv { + fn diagonal(&self) -> $vector { self.submatrix.diagonal() } } - ) -); -macro_rules! rotation_mul_rotation_impl( - ($t: ident) => ( + + /* + * + * Rotation * Rotation + * + */ impl Mul<$t> for $t { type Output = $t; @@ -152,56 +156,75 @@ macro_rules! rotation_mul_rotation_impl( self.submatrix *= right.submatrix } } - ) -); -macro_rules! rotation_mul_vec_impl( - ($t: ident, $tv: ident) => ( - impl Mul<$tv> for $t { - type Output = $tv; + + /* + * + * Rotation * Vector + * + */ + impl Mul<$vector> for $t { + type Output = $vector; #[inline] - fn mul(self, right: $tv) -> $tv { + fn mul(self, right: $vector) -> $vector { self.submatrix * right } } - ) -); -macro_rules! rotation_mul_point_impl( - ($t: ident, $tv: ident) => ( - rotation_mul_vec_impl!($t, $tv); - ) -); - -macro_rules! vec_mul_rotation_impl( - ($t: ident, $tv: ident) => ( - impl Mul<$t> for $tv { - type Output = $tv; + impl Mul<$t> for $vector { + type Output = $vector; #[inline] - fn mul(self, right: $t) -> $tv { + fn mul(self, right: $t) -> $vector { self * right.submatrix } } - impl MulAssign<$t> for $tv { + impl MulAssign<$t> for $vector { #[inline] fn mul_assign(&mut self, right: $t) { *self *= right.submatrix } } - ) -); -macro_rules! point_mul_rotation_impl( - ($t: ident, $tv: ident) => ( - vec_mul_rotation_impl!($t, $tv); - ) -); -macro_rules! inverse_impl( - ($t: ident) => ( + /* + * + * Rotation * Point + * + */ + impl Mul<$point> for $t { + type Output = $point; + + #[inline] + fn mul(self, right: $point) -> $point { + self.submatrix * right + } + } + + impl Mul<$t> for $point { + type Output = $point; + + #[inline] + fn mul(self, right: $t) -> $point { + self * right.submatrix + } + } + + impl MulAssign<$t> for $point { + #[inline] + fn mul_assign(&mut self, right: $t) { + *self *= right.submatrix + } + } + + + /* + * + * Inverse + * + */ impl Inverse for $t { #[inline] fn inverse_mut(&mut self) -> bool { @@ -217,11 +240,13 @@ macro_rules! inverse_impl( Some(self.transpose()) } } - ) -); -macro_rules! transpose_impl( - ($t: ident) => ( + + /* + * + * Transpose + * + */ impl Transpose for $t { #[inline] fn transpose(&self) -> $t { @@ -233,51 +258,57 @@ macro_rules! transpose_impl( self.submatrix.transpose_mut() } } - ) -); -macro_rules! row_impl( - ($t: ident, $tv: ident) => ( - impl Row<$tv> for $t { + + /* + * + * Row + * + */ + impl Row<$vector> for $t { #[inline] fn nrows(&self) -> usize { self.submatrix.nrows() } #[inline] - fn row(&self, i: usize) -> $tv { + fn row(&self, i: usize) -> $vector { self.submatrix.row(i) } #[inline] - fn set_row(&mut self, i: usize, row: $tv) { + fn set_row(&mut self, i: usize, row: $vector) { self.submatrix.set_row(i, row); } } - ) -); -macro_rules! column_impl( - ($t: ident, $tv: ident) => ( - impl Column<$tv> for $t { + + /* + * + * Column + * + */ + impl Column<$vector> for $t { #[inline] fn ncols(&self) -> usize { self.submatrix.ncols() } #[inline] - fn column(&self, i: usize) -> $tv { + fn column(&self, i: usize) -> $vector { self.submatrix.column(i) } #[inline] - fn set_column(&mut self, i: usize, column: $tv) { + fn set_column(&mut self, i: usize, column: $vector) { self.submatrix.set_column(i, column); } } - ) -); -macro_rules! index_impl( - ($t: ident) => ( + + /* + * + * Index + * + */ impl Index<(usize, usize)> for $t { type Output = N; @@ -285,22 +316,26 @@ macro_rules! index_impl( &self.submatrix[i] } } - ) -); -macro_rules! to_homogeneous_impl( - ($t: ident, $tm: ident) => ( - impl ToHomogeneous<$tm> for $t { + + /* + * + * ToHomogeneous + * + */ + impl ToHomogeneous<$homogeneous> for $t { #[inline] - fn to_homogeneous(&self) -> $tm { + fn to_homogeneous(&self) -> $homogeneous { self.submatrix.to_homogeneous() } } - ) -); -macro_rules! approx_eq_impl( - ($t: ident) => ( + + /* + * + * ApproxEq + * + */ impl> ApproxEq for $t { #[inline] fn approx_epsilon(_: Option<$t>) -> N { @@ -327,22 +362,27 @@ macro_rules! approx_eq_impl( ApproxEq::approx_eq_ulps(&self.submatrix, &other.submatrix, ulps) } } - ) -); -macro_rules! absolute_impl( - ($t: ident, $tm: ident) => ( - impl> Absolute<$tm> for $t { + + /* + * + * Absolute + * + */ + impl> Absolute<$submatrix> for $t { #[inline] - fn abs(m: &$t) -> $tm { + fn abs(m: &$t) -> $submatrix { Absolute::abs(&m.submatrix) } } - ) -); -macro_rules! rotation_display_impl( - ($t: ident) => ( + + + /* + * + * Display + * + */ impl fmt::Display for $t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let precision = f.precision().unwrap_or(3); @@ -352,5 +392,29 @@ macro_rules! rotation_display_impl( writeln!(f, "}}") } } + + + /* + * + * Arbitrary + * + */ + #[cfg(feature="arbitrary")] + impl Arbitrary for $t { + fn arbitrary(g: &mut G) -> $t { + $t::new(Arbitrary::arbitrary(g)) + } + } + ) +); + +macro_rules! dim_impl( + ($t: ident, $dimension: expr) => ( + impl Dimension for $t { + #[inline] + fn dimension(_: Option<$t>) -> usize { + $dimension + } + } ) ); diff --git a/src/structs/similarity.rs b/src/structs/similarity.rs index 1fb6eb1d..f0dbef03 100644 --- a/src/structs/similarity.rs +++ b/src/structs/similarity.rs @@ -6,7 +6,7 @@ use num::One; use structs::matrix::{Matrix3, Matrix4}; use traits::structure::{Dimension, Column, BaseFloat, BaseNum}; use traits::operations::{Inverse, ApproxEq}; -use traits::geometry::{Rotation, Transform, Transformation, Translation, ToHomogeneous}; +use traits::geometry::{Transform, Transformation, ToHomogeneous}; use structs::vector::{Vector1, Vector2, Vector3}; use structs::point::{Point2, Point3}; @@ -49,38 +49,9 @@ pub struct Similarity3 { pub isometry: Isometry3 } -sim_impl!(Similarity2, Isometry2, Rotation2, Vector2, Vector1); -dim_impl!(Similarity2, 2); -sim_scale_impl!(Similarity2); -sim_one_impl!(Similarity2); -sim_mul_sim_impl!(Similarity2); -sim_mul_isometry_impl!(Similarity2, Isometry2); -sim_mul_rotation_impl!(Similarity2, Rotation2); -sim_mul_point_vec_impl!(Similarity2, Point2); -sim_mul_point_vec_impl!(Similarity2, Vector2); -transformation_impl!(Similarity2); -sim_transform_impl!(Similarity2, Point2); -sim_inverse_impl!(Similarity2); -sim_to_homogeneous_impl!(Similarity2, Matrix3); -sim_approx_eq_impl!(Similarity2); -sim_rand_impl!(Similarity2); -sim_arbitrary_impl!(Similarity2); -sim_display_impl!(Similarity2); -sim_impl!(Similarity3, Isometry3, Rotation3, Vector3, Vector3); +similarity_impl!(Similarity2, Isometry2, Rotation2, Vector2, Vector1, Point2, Matrix3); +dim_impl!(Similarity2, 2); + +similarity_impl!(Similarity3, Isometry3, Rotation3, Vector3, Vector3, Point3, Matrix4); dim_impl!(Similarity3, 3); -sim_scale_impl!(Similarity3); -sim_one_impl!(Similarity3); -sim_mul_sim_impl!(Similarity3); -sim_mul_isometry_impl!(Similarity3, Isometry3); -sim_mul_rotation_impl!(Similarity3, Rotation3); -sim_mul_point_vec_impl!(Similarity3, Point3); -sim_mul_point_vec_impl!(Similarity3, Vector3); -transformation_impl!(Similarity3); -sim_transform_impl!(Similarity3, Point3); -sim_inverse_impl!(Similarity3); -sim_to_homogeneous_impl!(Similarity3, Matrix4); -sim_approx_eq_impl!(Similarity3); -sim_rand_impl!(Similarity3); -sim_arbitrary_impl!(Similarity3); -sim_display_impl!(Similarity3); diff --git a/src/structs/similarity_macros.rs b/src/structs/similarity_macros.rs index 8bac2e62..845e3d6e 100644 --- a/src/structs/similarity_macros.rs +++ b/src/structs/similarity_macros.rs @@ -1,13 +1,22 @@ #![macro_use] -macro_rules! sim_impl( - ($t: ident, $isometry: ident, $rotation_matrix: ident, $subvector: ident, $subrotvector: ident) => ( +macro_rules! similarity_impl( + ($t: ident, + $isometry: ident, $rotation_matrix: ident, + $vector: ident, $rotvector: ident, + $point: ident, + $homogeneous_matrix: ident) => ( impl $t { + /* + * + * Constructors. + * + */ /// Creates a new similarity transformation from a vector, an axis-angle rotation, and a scale factor. /// /// The scale factor may be negative but not zero. #[inline] - pub fn new(translation: $subvector, rotation: $subrotvector, scale: N) -> $t { + pub fn new(translation: $vector, rotation: $rotvector, scale: N) -> $t { assert!(!scale.is_zero(), "A similarity transformation scale factor cannot be zero."); $t { @@ -20,7 +29,7 @@ macro_rules! sim_impl( /// /// The scale factor may be negative but not zero. #[inline] - pub fn new_with_rotation_matrix(translation: $subvector, rotation: $rotation_matrix, scale: N) -> $t { + pub fn new_with_rotation_matrix(translation: $vector, rotation: $rotation_matrix, scale: N) -> $t { assert!(!scale.is_zero(), "A similarity transformation scale factor cannot be zero."); $t { @@ -41,13 +50,12 @@ macro_rules! sim_impl( isometry: isometry } } - } - ) -); -macro_rules! sim_scale_impl( - ($t: ident) => ( - impl $t { + /* + * + * Methods related to scaling. + * + */ /// The scale factor of this similarity transformation. #[inline] pub fn scale(&self) -> N { @@ -96,22 +104,61 @@ macro_rules! sim_scale_impl( self.scale = s } } - ) -); -macro_rules! sim_one_impl( - ($t: ident) => ( + /* + * + * One Impl. + * + */ impl One for $t { #[inline] fn one() -> $t { $t::new_with_isometry(::one(), ::one()) } } - ) -); -macro_rules! sim_mul_sim_impl( - ($t: ident) => ( + + /* + * + * Transformation + * + */ + impl Transformation<$t> for $t { + fn transformation(&self) -> $t { + *self + } + + fn inverse_transformation(&self) -> $t { + // inversion will never fails + Inverse::inverse(self).unwrap() + } + + fn append_transformation_mut(&mut self, t: &$t) { + *self = *t * *self + } + + fn append_transformation(&self, t: &$t) -> $t { + *t * *self + } + + fn prepend_transformation_mut(&mut self, t: &$t) { + *self = *self * *t + } + + fn prepend_transformation(&self, t: &$t) -> $t { + *self * *t + } + + fn set_transformation(&mut self, t: $t) { + *self = t + } + } + + /* + * + * Similarity × Similarity + * + */ impl Mul<$t> for $t { type Output = $t; @@ -132,16 +179,18 @@ macro_rules! sim_mul_sim_impl( self.scale *= right.scale; } } - ) -); -macro_rules! sim_mul_isometry_impl( - ($t: ident, $ti: ident) => ( - impl Mul<$ti> for $t { + + /* + * + * Similarity × Isometry + * + */ + impl Mul<$isometry> for $t { type Output = $t; #[inline] - fn mul(self, right: $ti) -> $t { + fn mul(self, right: $isometry) -> $t { $t::new_with_rotation_matrix( self.isometry.translation + self.isometry.rotation * (right.translation * self.scale), self.isometry.rotation * right.rotation, @@ -149,15 +198,15 @@ macro_rules! sim_mul_isometry_impl( } } - impl MulAssign<$ti> for $t { + impl MulAssign<$isometry> for $t { #[inline] - fn mul_assign(&mut self, right: $ti) { + fn mul_assign(&mut self, right: $isometry) { self.isometry.translation += self.isometry.rotation * (right.translation * self.scale); self.isometry.rotation *= right.rotation; } } - impl Mul<$t> for $ti { + impl Mul<$t> for $isometry { type Output = $t; #[inline] @@ -168,16 +217,17 @@ macro_rules! sim_mul_isometry_impl( right.scale) } } - ) -); -macro_rules! sim_mul_rotation_impl( - ($t: ident, $tr: ident) => ( - impl Mul<$tr> for $t { + /* + * + * Similarity × Rotation + * + */ + impl Mul<$rotation_matrix> for $t { type Output = $t; #[inline] - fn mul(self, right: $tr) -> $t { + fn mul(self, right: $rotation_matrix) -> $t { $t::new_with_rotation_matrix( self.isometry.translation, self.isometry.rotation * right, @@ -185,14 +235,14 @@ macro_rules! sim_mul_rotation_impl( } } - impl MulAssign<$tr> for $t { + impl MulAssign<$rotation_matrix> for $t { #[inline] - fn mul_assign(&mut self, right: $tr) { + fn mul_assign(&mut self, right: $rotation_matrix) { self.isometry.rotation *= right; } } - impl Mul<$t> for $tr { + impl Mul<$t> for $rotation_matrix { type Output = $t; #[inline] @@ -203,44 +253,56 @@ macro_rules! sim_mul_rotation_impl( right.scale) } } - ) -); -macro_rules! sim_mul_point_vec_impl( - ($t: ident, $tv: ident) => ( - impl Mul<$tv> for $t { - type Output = $tv; + /* + * + * Similarity × { Point, Vector } + * + */ + impl Mul<$vector> for $t { + type Output = $vector; #[inline] - fn mul(self, right: $tv) -> $tv { + fn mul(self, right: $vector) -> $vector { self.isometry * (right * self.scale) } } + impl Mul<$point> for $t { + type Output = $point; + + #[inline] + fn mul(self, right: $point) -> $point { + self.isometry * (right * self.scale) + } + } // NOTE: there is no viable pre-multiplication definition because of the translation // component. - ) -); -macro_rules! sim_transform_impl( - ($t: ident, $tp: ident) => ( - impl Transform<$tp> for $t { + /* + * + * Similarity × Point + * + */ + impl Transform<$point> for $t { #[inline] - fn transform(&self, p: &$tp) -> $tp { + fn transform(&self, p: &$point) -> $point { self.isometry.transform(&(*p * self.scale)) } #[inline] - fn inverse_transform(&self, p: &$tp) -> $tp { + fn inverse_transform(&self, p: &$point) -> $point { self.isometry.inverse_transform(p) / self.scale } } - ) -); -macro_rules! sim_inverse_impl( - ($t: ident) => ( + + /* + * + * Inverse + * + */ impl> Inverse for $t { #[inline] fn inverse_mut(&mut self) -> bool { @@ -263,28 +325,32 @@ macro_rules! sim_inverse_impl( Some(res) } } - ) -); -macro_rules! sim_to_homogeneous_impl( - ($t: ident, $th: ident) => ( - impl ToHomogeneous<$th> for $t { - fn to_homogeneous(&self) -> $th { + + /* + * + * ToHomogeneous + * + */ + impl ToHomogeneous<$homogeneous_matrix> for $t { + fn to_homogeneous(&self) -> $homogeneous_matrix { let mut res = (*self.isometry.rotation.submatrix() * self.scale).to_homogeneous(); // copy the translation - let dimension = Dimension::dimension(None::<$th>); + let dimension = Dimension::dimension(None::<$homogeneous_matrix>); res.set_column(dimension - 1, self.isometry.translation.as_point().to_homogeneous().to_vector()); res } } - ) -); -macro_rules! sim_approx_eq_impl( - ($t: ident) => ( + + /* + * + * ApproxEq + * + */ impl> ApproxEq for $t { #[inline] fn approx_epsilon(_: Option<$t>) -> N { @@ -308,11 +374,13 @@ macro_rules! sim_approx_eq_impl( ApproxEq::approx_eq_ulps(&self.isometry, &other.isometry, ulps) } } - ) -); -macro_rules! sim_rand_impl( - ($t: ident) => ( + + /* + * + * Rand + * + */ impl Rand for $t { #[inline] fn rand(rng: &mut R) -> $t { @@ -324,11 +392,13 @@ macro_rules! sim_rand_impl( $t::new_with_isometry(rng.gen(), scale) } } - ) -); -macro_rules! sim_arbitrary_impl( - ($t: ident) => ( + + /* + * + * Arbitrary + * + */ #[cfg(feature="arbitrary")] impl Arbitrary for $t { fn arbitrary(g: &mut G) -> $t { @@ -338,11 +408,13 @@ macro_rules! sim_arbitrary_impl( ) } } - ) -); -macro_rules! sim_display_impl( - ($t: ident) => ( + + /* + * + * Display + * + */ impl fmt::Display for $t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(writeln!(f, "Similarity transformation {{")); diff --git a/src/structs/specializations/matrix.rs b/src/structs/specializations/matrix.rs index c1a1d964..27868e7b 100644 --- a/src/structs/specializations/matrix.rs +++ b/src/structs/specializations/matrix.rs @@ -3,7 +3,7 @@ use structs::vector::{Vector2, Vector3}; use structs::point::{Point2, Point3}; use structs::matrix::{Matrix1, Matrix2, Matrix3}; use traits::operations::{Inverse, Determinant, ApproxEq}; -use traits::structure::{Row, Column, BaseNum}; +use traits::structure::BaseNum; // some specializations: impl> Inverse for Matrix1 { @@ -129,85 +129,6 @@ impl Determinant for Matrix3 { } } -impl Row> for Matrix3 { - #[inline] - fn nrows(&self) -> usize { - 3 - } - - #[inline] - fn row(&self, i: usize) -> Vector3 { - match i { - 0 => Vector3::new(self.m11, self.m12, self.m13), - 1 => Vector3::new(self.m21, self.m22, self.m23), - 2 => Vector3::new(self.m31, self.m32, self.m33), - _ => panic!(format!("Index out of range: 3d matrices do not have {} rows.", i)) - } - } - - #[inline] - fn set_row(&mut self, i: usize, r: Vector3) { - match i { - 0 => { - self.m11 = r.x; - self.m12 = r.y; - self.m13 = r.z; - }, - 1 => { - self.m21 = r.x; - self.m22 = r.y; - self.m23 = r.z; - }, - 2 => { - self.m31 = r.x; - self.m32 = r.y; - self.m33 = r.z; - }, - _ => panic!(format!("Index out of range: 3d matrices do not have {} rows.", i)) - - } - } -} - -impl Column> for Matrix3 { - #[inline] - fn ncols(&self) -> usize { - 3 - } - - #[inline] - fn column(&self, i: usize) -> Vector3 { - match i { - 0 => Vector3::new(self.m11, self.m21, self.m31), - 1 => Vector3::new(self.m12, self.m22, self.m32), - 2 => Vector3::new(self.m13, self.m23, self.m33), - _ => panic!(format!("Index out of range: 3d matrices do not have {} cols.", i)) - } - } - - #[inline] - fn set_column(&mut self, i: usize, r: Vector3) { - match i { - 0 => { - self.m11 = r.x; - self.m21 = r.y; - self.m31 = r.z; - }, - 1 => { - self.m12 = r.x; - self.m22 = r.y; - self.m32 = r.z; - }, - 2 => { - self.m13 = r.x; - self.m23 = r.y; - self.m33 = r.z; - }, - _ => panic!(format!("Index out of range: 3d matrices do not have {} cols.", i)) - - } - } -} impl + Add> Mul> for Matrix3 { type Output = Matrix3; diff --git a/src/structs/vector.rs b/src/structs/vector.rs index f18ac8e4..45ac1646 100644 --- a/src/structs/vector.rs +++ b/src/structs/vector.rs @@ -29,50 +29,14 @@ pub struct Vector1 { pub x: N } -new_impl!(Vector1, x); -pord_impl!(Vector1, x,); -vec_axis_impl!(Vector1, x); -vec_cast_impl!(Vector1, x); -conversion_impl!(Vector1, 1); -index_impl!(Vector1); -indexable_impl!(Vector1, 1); -at_fast_impl!(Vector1, 1); -repeat_impl!(Vector1, val, x); -dim_impl!(Vector1, 1); -container_impl!(Vector1); -// (specialized); basis_impl!(Vector1, 1); -add_impl!(Vector1, x); -sub_impl!(Vector1, x); -mul_impl!(Vector1, x); -div_impl!(Vector1, x); -scalar_add_impl!(Vector1, x); -scalar_sub_impl!(Vector1, x); -scalar_mul_impl!(Vector1, x); -scalar_div_impl!(Vector1, x); -neg_impl!(Vector1, x); -dot_impl!(Vector1, x); -translation_impl!(Vector1); -norm_impl!(Vector1, x); -approx_eq_impl!(Vector1, x); -zero_one_impl!(Vector1, x); +vector_impl!(Vector1, Point1, x); +vectorlike_impl!(Vector1, 1, x); from_iterator_impl!(Vector1, iterator); -bounded_impl!(Vector1, x); -axpy_impl!(Vector1, x); -iterable_impl!(Vector1, 1); -iterable_mut_impl!(Vector1, 1); +// (specialized); basis_impl!(Vector1, 1); vec_to_homogeneous_impl!(Vector1, Vector2, y, x); vec_from_homogeneous_impl!(Vector1, Vector2, y, x); -translate_impl!(Vector1, Point1); -rotate_impl!(Vector1); -rotate_impl!(Point1); -transform_impl!(Vector1, Point1); -vec_as_point_impl!(Vector1, Point1, x); -num_float_vec_impl!(Vector1); -absolute_vec_impl!(Vector1, x); -arbitrary_impl!(Vector1, x); -rand_impl!(Vector1, x); -mean_impl!(Vector1); -vec_display_impl!(Vector1); + + /// Vector of dimension 2. /// @@ -87,50 +51,14 @@ pub struct Vector2 { pub y: N } -new_impl!(Vector2, x, y); -pord_impl!(Vector2, x, y); -vec_axis_impl!(Vector2, x, y); -vec_cast_impl!(Vector2, x, y); -conversion_impl!(Vector2, 2); -index_impl!(Vector2); -indexable_impl!(Vector2, 2); -at_fast_impl!(Vector2, 2); -repeat_impl!(Vector2, val, x, y); -dim_impl!(Vector2, 2); -container_impl!(Vector2); -// (specialized); basis_impl!(Vector2, 1); -add_impl!(Vector2, x, y); -sub_impl!(Vector2, x, y); -mul_impl!(Vector2, x, y); -div_impl!(Vector2, x, y); -scalar_add_impl!(Vector2, x, y); -scalar_sub_impl!(Vector2, x, y); -scalar_mul_impl!(Vector2, x, y); -scalar_div_impl!(Vector2, x, y); -neg_impl!(Vector2, x, y); -dot_impl!(Vector2, x, y); -translation_impl!(Vector2); -norm_impl!(Vector2, x, y); -approx_eq_impl!(Vector2, x, y); -zero_one_impl!(Vector2, x, y); +vector_impl!(Vector2, Point2, x, y); +vectorlike_impl!(Vector2, 2, x, y); from_iterator_impl!(Vector2, iterator, iterator); -bounded_impl!(Vector2, x, y); -axpy_impl!(Vector2, x, y); -iterable_impl!(Vector2, 2); -iterable_mut_impl!(Vector2, 2); +// (specialized); basis_impl!(Vector2, 1); vec_to_homogeneous_impl!(Vector2, Vector3, z, x, y); vec_from_homogeneous_impl!(Vector2, Vector3, z, x, y); -translate_impl!(Vector2, Point2); -rotate_impl!(Vector2); -rotate_impl!(Point2); -transform_impl!(Vector2, Point2); -vec_as_point_impl!(Vector2, Point2, x, y); -num_float_vec_impl!(Vector2); -absolute_vec_impl!(Vector2, x, y); -arbitrary_impl!(Vector2, x, y); -rand_impl!(Vector2, x, y); -mean_impl!(Vector2); -vec_display_impl!(Vector2); + + /// Vector of dimension 3. /// @@ -147,50 +75,12 @@ pub struct Vector3 { pub z: N } -new_impl!(Vector3, x, y, z); -pord_impl!(Vector3, x, y, z); -vec_axis_impl!(Vector3, x, y, z); -vec_cast_impl!(Vector3, x, y, z); -conversion_impl!(Vector3, 3); -index_impl!(Vector3); -indexable_impl!(Vector3, 3); -at_fast_impl!(Vector3, 3); -repeat_impl!(Vector3, val, x, y, z); -dim_impl!(Vector3, 3); -container_impl!(Vector3); -// (specialized); basis_impl!(Vector3, 1); -add_impl!(Vector3, x, y, z); -sub_impl!(Vector3, x, y, z); -mul_impl!(Vector3, x, y, z); -div_impl!(Vector3, x, y, z); -scalar_add_impl!(Vector3, x, y, z); -scalar_sub_impl!(Vector3, x, y, z); -scalar_mul_impl!(Vector3, x, y, z); -scalar_div_impl!(Vector3, x, y, z); -neg_impl!(Vector3, x, y, z); -dot_impl!(Vector3, x, y, z); -translation_impl!(Vector3); -norm_impl!(Vector3, x, y ,z); -approx_eq_impl!(Vector3, x, y, z); -zero_one_impl!(Vector3, x, y, z); +vector_impl!(Vector3, Point3, x, y, z); +vectorlike_impl!(Vector3, 3, x, y, z); from_iterator_impl!(Vector3, iterator, iterator, iterator); -bounded_impl!(Vector3, x, y, z); -axpy_impl!(Vector3, x, y, z); -iterable_impl!(Vector3, 3); -iterable_mut_impl!(Vector3, 3); +// (specialized); basis_impl!(Vector3, 1); vec_to_homogeneous_impl!(Vector3, Vector4, w, x, y, z); vec_from_homogeneous_impl!(Vector3, Vector4, w, x, y, z); -translate_impl!(Vector3, Point3); -rotate_impl!(Vector3); -rotate_impl!(Point3); -transform_impl!(Vector3, Point3); -vec_as_point_impl!(Vector3, Point3, x, y, z); -num_float_vec_impl!(Vector3); -absolute_vec_impl!(Vector3, x, y, z); -arbitrary_impl!(Vector3, x, y, z); -rand_impl!(Vector3, x, y, z); -mean_impl!(Vector3); -vec_display_impl!(Vector3); /// Vector of dimension 4. @@ -210,50 +100,14 @@ pub struct Vector4 { pub w: N } -new_impl!(Vector4, x, y, z, w); -pord_impl!(Vector4, x, y, z, w); -vec_axis_impl!(Vector4, x, y, z, w); -vec_cast_impl!(Vector4, x, y, z, w); -conversion_impl!(Vector4, 4); -index_impl!(Vector4); -indexable_impl!(Vector4, 4); -at_fast_impl!(Vector4, 4); -repeat_impl!(Vector4, val, x, y, z, w); -dim_impl!(Vector4, 4); -container_impl!(Vector4); -basis_impl!(Vector4, 4); -add_impl!(Vector4, x, y, z, w); -sub_impl!(Vector4, x, y, z, w); -mul_impl!(Vector4, x, y, z, w); -div_impl!(Vector4, x, y, z, w); -scalar_add_impl!(Vector4, x, y, z, w); -scalar_sub_impl!(Vector4, x, y, z, w); -scalar_mul_impl!(Vector4, x, y, z, w); -scalar_div_impl!(Vector4, x, y, z, w); -neg_impl!(Vector4, x, y, z, w); -dot_impl!(Vector4, x, y, z, w); -translation_impl!(Vector4); -norm_impl!(Vector4, x, y, z, w); -approx_eq_impl!(Vector4, x, y, z, w); -zero_one_impl!(Vector4, x, y, z, w); +vector_impl!(Vector4, Point4, x, y, z, w); +vectorlike_impl!(Vector4, 4, x, y, z, w); from_iterator_impl!(Vector4, iterator, iterator, iterator, iterator); -bounded_impl!(Vector4, x, y, z, w); -axpy_impl!(Vector4, x, y, z, w); -iterable_impl!(Vector4, 4); -iterable_mut_impl!(Vector4, 4); +basis_impl!(Vector4, 4); vec_to_homogeneous_impl!(Vector4, Vector5, a, x, y, z, w); vec_from_homogeneous_impl!(Vector4, Vector5, a, x, y, z, w); -translate_impl!(Vector4, Point4); -rotate_impl!(Vector4); -rotate_impl!(Point4); -transform_impl!(Vector4, Point4); -vec_as_point_impl!(Vector4, Point4, x, y, z, w); -num_float_vec_impl!(Vector4); -absolute_vec_impl!(Vector4, x, y, z, w); -arbitrary_impl!(Vector4, x, y, z, w); -rand_impl!(Vector4, x, y, z, w); -mean_impl!(Vector4); -vec_display_impl!(Vector4); + + /// Vector of dimension 5. /// @@ -274,50 +128,13 @@ pub struct Vector5 { pub a: N } -new_impl!(Vector5, x, y, z, w, a); -pord_impl!(Vector5, x, y, z, w, a); -vec_axis_impl!(Vector5, x, y, z, w, a); -vec_cast_impl!(Vector5, x, y, z, w, a); -conversion_impl!(Vector5, 5); -index_impl!(Vector5); -indexable_impl!(Vector5, 5); -at_fast_impl!(Vector5, 5); -repeat_impl!(Vector5, val, x, y, z, w, a); -dim_impl!(Vector5, 5); -container_impl!(Vector5); -basis_impl!(Vector5, 5); -add_impl!(Vector5, x, y, z, w, a); -sub_impl!(Vector5, x, y, z, w, a); -mul_impl!(Vector5, x, y, z, w, a); -div_impl!(Vector5, x, y, z, w, a); -scalar_add_impl!(Vector5, x, y, z, w, a); -scalar_sub_impl!(Vector5, x, y, z, w, a); -scalar_mul_impl!(Vector5, x, y, z, w, a); -scalar_div_impl!(Vector5, x, y, z, w, a); -neg_impl!(Vector5, x, y, z, w, a); -dot_impl!(Vector5, x, y, z, w, a); -translation_impl!(Vector5); -norm_impl!(Vector5, x, y, z, w, a); -approx_eq_impl!(Vector5, x, y, z, w, a); -zero_one_impl!(Vector5, x, y, z, w, a); +vector_impl!(Vector5, Point5, x, y, z, w, a); +vectorlike_impl!(Vector5, 5, x, y, z, w, a); from_iterator_impl!(Vector5, iterator, iterator, iterator, iterator, iterator); -bounded_impl!(Vector5, x, y, z, w, a); -axpy_impl!(Vector5, x, y, z, w, a); -iterable_impl!(Vector5, 5); -iterable_mut_impl!(Vector5, 5); +basis_impl!(Vector5, 5); vec_to_homogeneous_impl!(Vector5, Vector6, b, x, y, z, w, a); vec_from_homogeneous_impl!(Vector5, Vector6, b, x, y, z, w, a); -translate_impl!(Vector5, Point5); -rotate_impl!(Vector5); -rotate_impl!(Point5); -transform_impl!(Vector5, Point5); -vec_as_point_impl!(Vector5, Point5, x, y, z, w, a); -num_float_vec_impl!(Vector5); -absolute_vec_impl!(Vector5, x, y, z, w, a); -arbitrary_impl!(Vector5, x, y, z, w, a); -rand_impl!(Vector5, x, y, z, w, a); -mean_impl!(Vector5); -vec_display_impl!(Vector5); + /// Vector of dimension 6. /// @@ -340,45 +157,8 @@ pub struct Vector6 { pub b: N } -new_impl!(Vector6, x, y, z, w, a, b); -pord_impl!(Vector6, x, y, z, w, a, b); -vec_axis_impl!(Vector6, x, y, z, w, a, b); -vec_cast_impl!(Vector6, x, y, z, w, a, b); -conversion_impl!(Vector6, 6); -index_impl!(Vector6); -indexable_impl!(Vector6, 6); -at_fast_impl!(Vector6, 6); -repeat_impl!(Vector6, val, x, y, z, w, a, b); -dim_impl!(Vector6, 6); -container_impl!(Vector6); -basis_impl!(Vector6, 6); -add_impl!(Vector6, x, y, z, w, a, b); -sub_impl!(Vector6, x, y, z, w, a, b); -mul_impl!(Vector6, x, y, z, w, a, b); -div_impl!(Vector6, x, y, z, w, a, b); -scalar_add_impl!(Vector6, x, y, z, w, a, b); -scalar_sub_impl!(Vector6, x, y, z, w, a, b); -scalar_mul_impl!(Vector6, x, y, z, w, a, b); -scalar_div_impl!(Vector6, x, y, z, w, a, b); -neg_impl!(Vector6, x, y, z, w, a, b); -dot_impl!(Vector6, x, y, z, w, a, b); -translation_impl!(Vector6); -norm_impl!(Vector6, x, y, z, w, a, b); -approx_eq_impl!(Vector6, x, y, z, w, a, b); -zero_one_impl!(Vector6, x, y, z, w, a, b); +vector_impl!(Vector6, Point6, x, y, z, w, a, b); +vectorlike_impl!(Vector6, 6, x, y, z, w, a, b); from_iterator_impl!(Vector6, iterator, iterator, iterator, iterator, iterator, iterator); -bounded_impl!(Vector6, x, y, z, w, a, b); -axpy_impl!(Vector6, x, y, z, w, a, b); -iterable_impl!(Vector6, 6); -iterable_mut_impl!(Vector6, 6); -translate_impl!(Vector6, Point6); -rotate_impl!(Vector6); -rotate_impl!(Point6); -transform_impl!(Vector6, Point6); -vec_as_point_impl!(Vector6, Point6, x, y, z, w, a, b); -num_float_vec_impl!(Vector6); -absolute_vec_impl!(Vector6, x, y, z, w, a, b); -arbitrary_impl!(Vector6, x, y, z, w, a, b); -rand_impl!(Vector6, x, y, z, w, a, b); -mean_impl!(Vector6); -vec_display_impl!(Vector6); + +basis_impl!(Vector6, 6); diff --git a/src/structs/vector_macros.rs b/src/structs/vector_macros.rs index 8deb71c9..5cdd2cda 100644 --- a/src/structs/vector_macros.rs +++ b/src/structs/vector_macros.rs @@ -1,21 +1,139 @@ #![macro_use] -macro_rules! new_impl( - ($t: ident, $($compN: ident),+) => ( - impl $t { - /// Creates a new vector. +macro_rules! vectorlike_impl( + ($t: ident, $dimension: expr, $($compN: ident),+) => ( + componentwise_neg!($t, $($compN),+); + componentwise_repeat!($t, $($compN),+); + componentwise_arbitrary!($t, $($compN),+); + componentwise_rand!($t, $($compN),+); + pointwise_scalar_add!($t, $($compN),+); + pointwise_scalar_sub!($t, $($compN),+); + pointwise_scalar_mul!($t, $($compN),+); + pointwise_scalar_div!($t, $($compN),+); + component_new!($t, $($compN),+); + partial_order_impl!($t, $($compN),+); + + + /* + * + * Cast between inner scalar type. + * + */ + impl> Cast<$t> for $t { #[inline] - pub fn new($($compN: N ),+) -> $t { + fn from(v: $t) -> $t { + $t::new($(Cast::from(v.$compN)),+) + } + } + + + /* + * + * ApproxEq + * + */ + impl> ApproxEq for $t { + #[inline] + fn approx_epsilon(_: Option<$t>) -> N { + ApproxEq::approx_epsilon(None::) + } + + #[inline] + fn approx_ulps(_: Option<$t>) -> u32 { + ApproxEq::approx_ulps(None::) + } + + #[inline] + fn approx_eq(&self, other: &$t) -> bool { + $(ApproxEq::approx_eq(&self.$compN, &other.$compN))&&+ + } + + #[inline] + fn approx_eq_eps(&self, other: &$t, eps: &N) -> bool { + $(ApproxEq::approx_eq_eps(&self.$compN, &other.$compN, eps))&&+ + } + + #[inline] + fn approx_eq_ulps(&self, other: &$t, ulps: u32) -> bool { + $(ApproxEq::approx_eq_ulps(&self.$compN, &other.$compN, ulps))&&+ + } + } + + + /* + * + * Unsafe indexing. + * + */ + impl $t { + /// Unsafe read access to a vector element by index. + #[inline] + pub unsafe fn at_fast(&self, i: usize) -> N { + (*self.as_ref().get_unchecked(i)) + } + + /// Unsafe write access to a vector element by index. + #[inline] + pub unsafe fn set_fast(&mut self, i: usize, val: N) { + (*self.as_mut().get_unchecked_mut(i)) = val + } + } + + + /* + * + * Axpy + * + */ + impl> Axpy for $t { + #[inline] + fn axpy(&mut self, a: &N, x: &$t) { + $( self.$compN.axpy(a, &x.$compN); )+ + } + } + + + /* + * + * Bounded + * + */ + impl Bounded for $t { + #[inline] + fn max_value() -> $t { $t { - $($compN: $compN ),+ + $($compN: Bounded::max_value() ),+ + } + } + + #[inline] + fn min_value() -> $t { + $t { + $($compN: Bounded::min_value() ),+ } } } - ); -); -macro_rules! conversion_impl( - ($t: ident, $dimension: expr) => ( + + /* + * + * Container + * + */ + impl $t { + /// The dimension of this entity. + #[inline] + pub fn len(&self) -> usize { + Dimension::dimension(None::<$t>) + } + } + + + /* + * + * Conversions from/to slices + * + */ impl AsRef<[N; $dimension]> for $t { #[inline] fn as_ref(&self) -> &[N; $dimension] { @@ -59,133 +177,26 @@ macro_rules! conversion_impl( vref.clone() } } - ) -); -macro_rules! at_fast_impl( - ($t: ident, $dimension: expr) => ( - impl $t { - /// Unsafe read access to a vector element by index. - #[inline] - pub unsafe fn at_fast(&self, i: usize) -> N { - (*self.as_ref().get_unchecked(i)) - } - /// Unsafe write access to a vector element by index. + /* + * + * Dimension + * + */ + impl Dimension for $t { #[inline] - pub unsafe fn set_fast(&mut self, i: usize, val: N) { - (*self.as_mut().get_unchecked_mut(i)) = val + fn dimension(_: Option<$t>) -> usize { + $dimension } } - ) -); -// FIXME: N should be bounded by Ord instead of BaseFloat… -// However, f32/f64 does not implement Ord… -macro_rules! pord_impl( - ($t: ident, $comp0: ident, $($compN: ident),*) => ( - impl PartialOrder for $t { - #[inline] - fn inf(&self, other: &$t) -> $t { - $t::new(self.$comp0.min(other.$comp0) - $(, self.$compN.min(other.$compN))*) - } - #[inline] - fn sup(&self, other: &$t) -> $t { - $t::new(self.$comp0.max(other.$comp0) - $(, self.$compN.max(other.$compN))*) - } - - #[inline] - #[allow(unused_mut)] // otherwise there will be a warning for is_eq or Vector1. - fn partial_cmp(&self, other: &$t) -> PartialOrdering { - let is_lt = self.$comp0 < other.$comp0; - let mut is_eq = self.$comp0 == other.$comp0; - - if is_lt { // < - $( - if self.$compN > other.$compN { - return PartialOrdering::NotComparable - } - )* - - PartialOrdering::PartialLess - } - else { // >= - $( - if self.$compN < other.$compN { - return PartialOrdering::NotComparable - } - else if self.$compN > other.$compN { - is_eq = false; - } - - )* - - if is_eq { - PartialOrdering::PartialEqual - } - else { - PartialOrdering::PartialGreater - } - } - } - - #[inline] - fn partial_lt(&self, other: &$t) -> bool { - self.$comp0 < other.$comp0 $(&& self.$compN < other.$compN)* - } - - #[inline] - fn partial_le(&self, other: &$t) -> bool { - self.$comp0 <= other.$comp0 $(&& self.$compN <= other.$compN)* - } - - #[inline] - fn partial_gt(&self, other: &$t) -> bool { - self.$comp0 > other.$comp0 $(&& self.$compN > other.$compN)* - } - - #[inline] - fn partial_ge(&self, other: &$t) -> bool { - self.$comp0 >= other.$comp0 $(&& self.$compN >= other.$compN)* - } - } - ) -); - -macro_rules! vec_axis_impl( - ($t: ident, $($compN: ident),+) => ( - impl $t { - $( - /// Create a unit vector with its `$compN` component equal to 1.0. - #[inline] - pub fn $compN() -> $t { - let mut res: $t = ::zero(); - - res.$compN = ::one(); - - res - } - )+ - } - ) -); - -macro_rules! vec_cast_impl( - ($t: ident, $($compN: ident),+) => ( - impl> Cast<$t> for $t { - #[inline] - fn from(v: $t) -> $t { - $t::new($(Cast::from(v.$compN)),+) - } - } - ) -); - -macro_rules! indexable_impl( - ($t: ident, $dimension: expr) => ( + /* + * + * Indexable + * + */ impl Shape for $t { #[inline] fn shape(&self) -> usize { @@ -211,11 +222,13 @@ macro_rules! indexable_impl( (*mem::transmute::<&mut $t, &mut [N; $dimension]>(self).get_unchecked_mut(i)) = val } } - ) -); -macro_rules! index_impl( - ($t: ident) => ( + + /* + * + * Index + * + */ impl Index for $t where [N]: Index { type Output = <[N] as Index>::Output; @@ -229,25 +242,13 @@ macro_rules! index_impl( &mut self.as_mut()[i] } } - ) -); -macro_rules! repeat_impl( - ($t: ident, $param: ident, $($compN: ident),+) => ( - impl Repeat for $t { - /// Creates a new vector with all its components equal to a given value. - #[inline] - fn repeat($param: N) -> $t { - $t{ - $($compN: $param ),+ - } - } - } - ) -); -macro_rules! iterable_impl( - ($t: ident, $dimension: expr) => ( + /* + * + * Iterable + * + */ impl Iterable for $t { #[inline] fn iter(&self) -> Iter { @@ -256,11 +257,7 @@ macro_rules! iterable_impl( } } } - ) -); -macro_rules! iterable_mut_impl( - ($t: ident, $dimension: expr) => ( impl IterableMut for $t { #[inline] fn iter_mut(&mut self) -> IterMut { @@ -272,28 +269,242 @@ macro_rules! iterable_mut_impl( ) ); -macro_rules! dim_impl( - ($t: ident, $dimension: expr) => ( - impl Dimension for $t { +macro_rules! vector_impl( + ($t: ident, $tp: ident, $($compN: ident),+) => ( + pointwise_add!($t, $($compN),+); + pointwise_sub!($t, $($compN),+); + pointwise_mul!($t, $($compN),+); + pointwise_div!($t, $($compN),+); + componentwise_zero!($t, $($compN),+); + componentwise_one!($t, $($compN),+); + componentwise_absolute!($t, $($compN),+); + component_basis_element!($t, $($compN),+); + + + /* + * + * Dot product + * + */ + impl Dot for $t { #[inline] - fn dimension(_: Option<$t>) -> usize { - $dimension + fn dot(&self, other: &$t) -> N { + add!($(self.$compN * other.$compN ),+) + } + } + + + /* + * + * Norm + * + */ + impl Norm for $t { + #[inline] + fn norm_squared(&self) -> N { + Dot::dot(self, self) + } + + #[inline] + fn normalize(&self) -> $t { + let mut res : $t = *self; + let _ = res.normalize_mut(); + res + } + + #[inline] + fn normalize_mut(&mut self) -> N { + let l = Norm::norm(self); + + $(self.$compN = self.$compN / l;)* + + l + } + } + + + /* + * + * Translation + * + */ + impl + Neg> Translation<$t> for $t { + #[inline] + fn translation(&self) -> $t { + *self + } + + #[inline] + fn inverse_translation(&self) -> $t { + -*self + } + + #[inline] + fn append_translation_mut(&mut self, t: &$t) { + *self = *t + *self; + } + + #[inline] + fn append_translation(&self, t: &$t) -> $t { + *t + *self + } + + #[inline] + fn prepend_translation_mut(&mut self, t: &$t) { + *self = *self + *t; + } + + #[inline] + fn prepend_translation(&self, t: &$t) -> $t { + *self + *t + } + + #[inline] + fn set_translation(&mut self, t: $t) { + *self = t + } + } + + + + /* + * + * Translate + * + */ + impl + Sub> Translate<$tp> for $t { + fn translate(&self, other: &$tp) -> $tp { + *other + *self + } + + fn inverse_translate(&self, other: &$tp) -> $tp { + *other - *self + } + } + + + /* + * + * Rotate + * + */ + impl Rotate for $t { + fn rotate(&self, other: &O) -> O { + *other + } + + fn inverse_rotate(&self, other: &O) -> O { + *other + } + } + + impl Rotate for $tp { + fn rotate(&self, other: &O) -> O { + *other + } + + fn inverse_rotate(&self, other: &O) -> O { + *other + } + } + + + + /* + * + * Transform + * + */ + impl + Sub> Transform<$tp> for $t { + fn transform(&self, other: &$tp) -> $tp { + self.translate(other) + } + + fn inverse_transform(&self, other: &$tp) -> $tp { + self.inverse_translate(other) + } + } + + + + /* + * + * Conversion to point. + * + */ + impl $t { + /// Converts this vector to a point. + #[inline] + pub fn to_point(self) -> $tp { + $tp::new( + $(self.$compN),+ + ) + } + + /// Reinterprets this vector as a point. + #[inline] + pub fn as_point(&self) -> &$tp { + unsafe { + mem::transmute(self) + } + } + } + + + /* + * + * NumVector / FloatVector + * + */ + impl NumVector for $t + where N: BaseNum { + } + + impl FloatVector for $t + where N: BaseFloat + ApproxEq { + } + + + + /* + * + * Mean + * + */ + impl> Mean for $t { + #[inline] + fn mean(&self) -> N { + let normalizer = ::cast(1.0f64 / self.len() as f64); + self.iter().fold(::zero(), |acc, x| acc + *x * normalizer) + } + } + + + /* + * + * Display + * + */ + impl fmt::Display for $t { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "(")); + + let mut it = self.iter(); + + let precision = f.precision().unwrap_or(8); + + try!(write!(f, "{:.*}", precision, *it.next().unwrap())); + + for comp in it { + try!(write!(f, ", {:.*}", precision, *comp)); + } + + write!(f, ")") } } ) ); -macro_rules! container_impl( - ($t: ident) => ( - impl $t { - /// The dimension of this entity. - #[inline] - pub fn len(&self) -> usize { - Dimension::dimension(None::<$t>) - } - } - ) -); macro_rules! basis_impl( ($t: ident, $dimension: expr) => ( @@ -359,243 +570,6 @@ macro_rules! basis_impl( ) ); -macro_rules! axpy_impl( - ($t: ident, $($compN: ident),+) => ( - impl> Axpy for $t { - #[inline] - fn axpy(&mut self, a: &N, x: &$t) { - $( self.$compN.axpy(a, &x.$compN); )+ - } - } - ) -); - -macro_rules! add_impl( - ($t: ident, $($compN: ident),+) => ( - impl> Add<$t> for $t { - type Output = $t; - - #[inline] - fn add(self, right: $t) -> $t { - $t::new($(self.$compN + right.$compN),+) - } - } - - impl> AddAssign<$t> for $t { - #[inline] - fn add_assign(&mut self, right: $t) { - $( self.$compN += right.$compN; )+ - } - } - ) -); - -macro_rules! scalar_add_impl( - ($t: ident, $($compN: ident),+) => ( - // $t against scalar - impl> Add for $t { - type Output = $t; - - #[inline] - fn add(self, right: N) -> $t { - $t::new($(self.$compN + right),+) - } - } - - impl> AddAssign for $t { - #[inline] - fn add_assign(&mut self, right: N) { - $( self.$compN += right; )+ - } - } - - impl Add<$t> for f32 { - type Output = $t; - - #[inline] - fn add(self, right: $t) -> $t { - $t::new($(self + right.$compN),+) - } - } - - impl Add<$t> for f64 { - type Output = $t; - - #[inline] - fn add(self, right: $t) -> $t { - $t::new($(self + right.$compN),+) - } - } - ) -); - -macro_rules! sub_impl( - ($t: ident, $($compN: ident),+) => ( - impl> Sub<$t> for $t { - type Output = $t; - - #[inline] - fn sub(self, right: $t) -> $t { - $t::new($(self.$compN - right.$compN),+) - } - } - - impl> SubAssign<$t> for $t { - #[inline] - fn sub_assign(&mut self, right: $t) { - $( self.$compN -= right.$compN; )+ - } - } - ) -); - -macro_rules! scalar_sub_impl( - ($t: ident, $($compN: ident),+) => ( - impl> Sub for $t { - type Output = $t; - - #[inline] - fn sub(self, right: N) -> $t { - $t::new($(self.$compN - right),+) - } - } - - impl> SubAssign for $t { - #[inline] - fn sub_assign(&mut self, right: N) { - $( self.$compN -= right; )+ - } - } - - impl Sub<$t> for f32 { - type Output = $t; - - #[inline] - fn sub(self, right: $t) -> $t { - $t::new($(self - right.$compN),+) - } - } - - impl Sub<$t> for f64 { - type Output = $t; - - #[inline] - fn sub(self, right: $t) -> $t { - $t::new($(self - right.$compN),+) - } - } - ) -); - -macro_rules! mul_impl( - ($t: ident, $($compN: ident),+) => ( - impl> Mul<$t> for $t { - type Output = $t; - #[inline] - fn mul(self, right: $t) -> $t { - $t::new($(self.$compN * right.$compN),+) - } - } - - impl> MulAssign<$t> for $t { - #[inline] - fn mul_assign(&mut self, right: $t) { - $( self.$compN *= right.$compN; )+ - } - } - ) -); - -macro_rules! scalar_mul_impl( - ($t: ident, $($compN: ident),+) => ( - impl> Mul for $t { - type Output = $t; - - #[inline] - fn mul(self, right: N) -> $t { - $t::new($(self.$compN * right),+) - } - } - - impl> MulAssign for $t { - #[inline] - fn mul_assign(&mut self, right: N) { - $( self.$compN *= right; )+ - } - } - - impl Mul<$t> for f32 { - type Output = $t; - - #[inline] - fn mul(self, right: $t) -> $t { - $t::new($(self * right.$compN),+) - } - } - - impl Mul<$t> for f64 { - type Output = $t; - - #[inline] - fn mul(self, right: $t) -> $t { - $t::new($(self * right.$compN),+) - } - } - ) -); - -macro_rules! div_impl( - ($t: ident, $($compN: ident),+) => ( - impl> Div<$t> for $t { - type Output = $t; - - #[inline] - fn div(self, right: $t) -> $t { - $t::new($(self.$compN / right.$compN),+) - } - } - - impl> DivAssign<$t> for $t { - #[inline] - fn div_assign(&mut self, right: $t) { - $( self.$compN /= right.$compN; )+ - } - } - ) -); - -macro_rules! scalar_div_impl( - ($t: ident, $($compN: ident),+) => ( - impl> Div for $t { - type Output = $t; - - #[inline] - fn div(self, right: N) -> $t { - $t::new($(self.$compN / right),+) - } - } - - impl> DivAssign for $t { - #[inline] - fn div_assign(&mut self, right: N) { - $( self.$compN /= right; )+ - } - } - ) -); - -macro_rules! neg_impl( - ($t: ident, $($compN: ident),+) => ( - impl + Copy> Neg for $t { - type Output = $t; - - #[inline] - fn neg(self) -> $t { - $t::new($(-self.$compN ),+) - } - } - ) -); macro_rules! add ( // base case @@ -609,143 +583,6 @@ macro_rules! add ( } ); -macro_rules! dot_impl( - ($t: ident, $($compN: ident),+) => ( - impl Dot for $t { - #[inline] - fn dot(&self, other: &$t) -> N { - add!($(self.$compN * other.$compN ),+) - } - } - ) -); - -macro_rules! translation_impl( - ($t: ident) => ( - impl + Neg> Translation<$t> for $t { - #[inline] - fn translation(&self) -> $t { - *self - } - - #[inline] - fn inverse_translation(&self) -> $t { - -*self - } - - #[inline] - fn append_translation_mut(&mut self, t: &$t) { - *self = *t + *self; - } - - #[inline] - fn append_translation(&self, t: &$t) -> $t { - *t + *self - } - - #[inline] - fn prepend_translation_mut(&mut self, t: &$t) { - *self = *self + *t; - } - - #[inline] - fn prepend_translation(&self, t: &$t) -> $t { - *self + *t - } - - #[inline] - fn set_translation(&mut self, t: $t) { - *self = t - } - } - ) -); - -macro_rules! norm_impl( - ($t: ident, $($compN: ident),+) => ( - impl Norm for $t { - #[inline] - fn norm_squared(&self) -> N { - Dot::dot(self, self) - } - - #[inline] - fn normalize(&self) -> $t { - let mut res : $t = *self; - let _ = res.normalize_mut(); - res - } - - #[inline] - fn normalize_mut(&mut self) -> N { - let l = Norm::norm(self); - - $(self.$compN = self.$compN / l;)* - - l - } - } - ) -); - -macro_rules! approx_eq_impl( - ($t: ident, $($compN: ident),+) => ( - impl> ApproxEq for $t { - #[inline] - fn approx_epsilon(_: Option<$t>) -> N { - ApproxEq::approx_epsilon(None::) - } - - #[inline] - fn approx_ulps(_: Option<$t>) -> u32 { - ApproxEq::approx_ulps(None::) - } - - #[inline] - fn approx_eq(&self, other: &$t) -> bool { - $(ApproxEq::approx_eq(&self.$compN, &other.$compN))&&+ - } - - #[inline] - fn approx_eq_eps(&self, other: &$t, eps: &N) -> bool { - $(ApproxEq::approx_eq_eps(&self.$compN, &other.$compN, eps))&&+ - } - - #[inline] - fn approx_eq_ulps(&self, other: &$t, ulps: u32) -> bool { - $(ApproxEq::approx_eq_ulps(&self.$compN, &other.$compN, ulps))&&+ - } - } - ) -); - -macro_rules! zero_one_impl( - ($t: ident, $($compN: ident),+) => ( - impl One for $t - where N: Copy + One + Sub + Add { - #[inline] - fn one() -> $t { - $t { - $($compN: ::one() ),+ - } - } - } - - impl Zero for $t { - #[inline] - fn zero() -> $t { - $t { - $($compN: ::zero() ),+ - } - } - - #[inline] - fn is_zero(&self) -> bool { - $(self.$compN.is_zero() )&&+ - } - } - ) -); macro_rules! from_iterator_impl( ($t: ident, $param0: ident) => ( @@ -769,26 +606,6 @@ macro_rules! from_iterator_impl( ) ); -macro_rules! bounded_impl( - ($t: ident, $($compN: ident),+) => ( - impl Bounded for $t { - #[inline] - fn max_value() -> $t { - $t { - $($compN: Bounded::max_value() ),+ - } - } - - #[inline] - fn min_value() -> $t { - $t { - $($compN: Bounded::min_value() ),+ - } - } - } - ) -); - macro_rules! vec_to_homogeneous_impl( ($t: ident, $t2: ident, $extra: ident, $($compN: ident),+) => ( impl ToHomogeneous<$t2> for $t { @@ -817,145 +634,79 @@ macro_rules! vec_from_homogeneous_impl( ) ); -macro_rules! translate_impl( - ($tv: ident, $t: ident) => ( - impl + Sub> Translate<$t> for $tv { - fn translate(&self, other: &$t) -> $t { - *other + *self - } - fn inverse_translate(&self, other: &$t) -> $t { - *other - *self - } - } - ) -); - -macro_rules! rotate_impl( - ($t: ident) => ( - impl Rotate for $t { - fn rotate(&self, other: &O) -> O { - *other - } - - fn inverse_rotate(&self, other: &O) -> O { - *other - } - } - ) -); - -macro_rules! transform_impl( - ($tv: ident, $t: ident) => ( - impl + Sub> Transform<$t> for $tv { - fn transform(&self, other: &$t) -> $t { - self.translate(other) - } - - fn inverse_transform(&self, other: &$t) -> $t { - self.inverse_translate(other) - } - } - ) -); - -macro_rules! vec_as_point_impl( - ($tv: ident, $t: ident, $($compN: ident),+) => ( - impl $tv { - /// Converts this vector to a point. +// We need to keep this on a separate macro to retrieve the first component nam. +macro_rules! partial_order_impl( + ($t: ident, $comp0: ident $(, $compN: ident)*) => ( + /* + * + * PartialOrder + * + */ + impl PartialOrder for $t { #[inline] - pub fn to_point(self) -> $t { - $t::new( - $(self.$compN),+ - ) + fn inf(&self, other: &$t) -> $t { + $t::new(self.$comp0.min(other.$comp0), $(self.$compN.min(other.$compN)),*) } - /// Reinterprets this vector as a point. #[inline] - pub fn as_point(&self) -> &$t { - unsafe { - mem::transmute(self) + fn sup(&self, other: &$t) -> $t { + $t::new(self.$comp0.max(other.$comp0), $(self.$compN.max(other.$compN)),*) + } + + #[inline] + #[allow(unused_mut)] // otherwise there will be a warning for is_eq or Vector1. + fn partial_cmp(&self, other: &$t) -> PartialOrdering { + let is_lt = self.$comp0 < other.$comp0; + let mut is_eq = self.$comp0 == other.$comp0; + + if is_lt { // < + $( + if self.$compN > other.$compN { + return PartialOrdering::NotComparable + } + )* + + PartialOrdering::PartialLess + } + else { // >= + $( + if self.$compN < other.$compN { + return PartialOrdering::NotComparable + } + else if self.$compN > other.$compN { + is_eq = false; + } + + )* + + if is_eq { + PartialOrdering::PartialEqual + } + else { + PartialOrdering::PartialGreater + } } } - } - ) -); -macro_rules! num_float_vec_impl( - ($t: ident) => ( - impl NumVector for $t - where N: BaseNum { - } - - impl FloatVector for $t - where N: BaseFloat + ApproxEq { - } - ) -); - -macro_rules! absolute_vec_impl( - ($t: ident, $($compN: ident),+) => ( - impl> Absolute<$t> for $t { - #[inline] - fn abs(m: &$t) -> $t { - $t::new($(::abs(&m.$compN) ),+) - } - } - ) -); - -macro_rules! arbitrary_impl( - ($t: ident, $($compN: ident),*) => ( - #[cfg(feature="arbitrary")] - impl Arbitrary for $t { #[inline] - fn arbitrary(g: &mut G) -> $t { - $t { $($compN: Arbitrary::arbitrary(g),)* } + fn partial_lt(&self, other: &$t) -> bool { + self.$comp0 < other.$comp0 $(&& self.$compN < other.$compN)* } - } - ) -); -macro_rules! rand_impl( - ($t: ident, $($compN: ident),*) => ( - impl Rand for $t { #[inline] - fn rand(rng: &mut R) -> $t { - $t { $($compN: Rand::rand(rng), )* } + fn partial_le(&self, other: &$t) -> bool { + self.$comp0 <= other.$comp0 $(&& self.$compN <= other.$compN)* } - } - ) -); -macro_rules! mean_impl( - ($t: ident) => ( - impl> Mean for $t { #[inline] - fn mean(&self) -> N { - let normalizer = ::cast(1.0f64 / self.len() as f64); - self.iter().fold(::zero(), |acc, x| acc + *x * normalizer) - } - } - ) -); - -macro_rules! vec_display_impl( - ($t: ident) => ( - impl fmt::Display for $t { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "(")); - - let mut it = self.iter(); - - let precision = f.precision().unwrap_or(8); - - try!(write!(f, "{:.*}", precision, *it.next().unwrap())); - - for comp in it { - try!(write!(f, ", {:.*}", precision, *comp)); - } - - write!(f, ")") + fn partial_gt(&self, other: &$t) -> bool { + self.$comp0 > other.$comp0 $(&& self.$compN > other.$compN)* + } + + #[inline] + fn partial_ge(&self, other: &$t) -> bool { + self.$comp0 >= other.$comp0 $(&& self.$compN >= other.$compN)* } } ) diff --git a/src/traits/mod.rs b/src/traits/mod.rs index ea31e696..ccf756bf 100644 --- a/src/traits/mod.rs +++ b/src/traits/mod.rs @@ -7,7 +7,7 @@ pub use traits::geometry::{AbsoluteRotate, Cross, CrossMatrix, Dot, FromHomogene pub use traits::structure::{FloatVector, FloatPoint, Basis, Cast, Column, Dimension, Indexable, Iterable, IterableMut, Matrix, SquareMatrix, Row, NumVector, NumPoint, PointAsVector, ColumnSlice, - RowSlice, Diagonal, DiagMut, Eye, Repeat, Shape, BaseFloat, BaseNum, + RowSlice, Diagonal, DiagonalMut, Eye, Repeat, Shape, BaseFloat, BaseNum, Bounded}; pub use traits::operations::{Absolute, ApproxEq, Axpy, Covariance, Determinant, Inverse, Mean, Outer, PartialOrder, Transpose, diff --git a/src/traits/operations.rs b/src/traits/operations.rs index 07bba122..48f80be9 100644 --- a/src/traits/operations.rs +++ b/src/traits/operations.rs @@ -1,7 +1,7 @@ //! Low level operations on vectors and matrices. use std::mem; -use num::{Float, Signed}; +use num::Signed; use std::ops::Mul; use std::cmp::Ordering; use traits::structure::SquareMatrix; diff --git a/src/traits/structure.rs b/src/traits/structure.rs index cf1a8295..96c38b3b 100644 --- a/src/traits/structure.rs +++ b/src/traits/structure.rs @@ -176,7 +176,7 @@ pub trait Diagonal { } /// Trait to set the diagonal of square matrices. -pub trait DiagMut: Diagonal { +pub trait DiagonalMut: Diagonal { /// Sets the diagonal of this matrix. fn set_diagonal(&mut self, diagonal: &V); }