From 347883caa19e6ac578b275123da412208fa71868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Sun, 18 Aug 2013 18:33:25 +0200 Subject: [PATCH] Rework of the traits for Vectors. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The goal is to make traits less fine-grained for vectors, and reduce the amount of `use`. - Scalar{Mul, Div} are removed, replaced by Mul and Div, - Ring and DivisionRing are removed. Use Num instead. - VectorSpace, Dot, and Norm are removed, replaced by the new, higher-level traits. Add four traits: - Vec: common operations on vectors. Replaces VectorSpace and Dot. - AlgebraicVec: Vec + the old Norm trait. - VecExt: Vec + every other traits vectors implement. - AlgebraicVecExt: AlgebraicVec + VecExt. --- src/adaptors/rotmat.rs | 17 ++++---- src/adaptors/transform.rs | 3 +- src/dmat.rs | 3 +- src/dvec.rs | 41 +++++-------------- src/mat.rs | 3 +- src/mat_macros.rs | 32 +++++---------- src/mat_spec.rs | 7 ++-- src/nalgebra.rc | 6 +-- src/tests/mat.rs | 8 ++-- src/tests/vec.rs | 16 ++++---- src/traits/dot.rs | 8 ---- src/traits/norm.rs | 19 --------- src/traits/ring.rs | 22 ---------- src/traits/sample.rs | 5 +-- src/traits/scalar_op.rs | 22 ---------- src/traits/sub_dot.rs | 14 ------- src/traits/vector.rs | 83 ++++++++++++++++++++++++++++++++++++++ src/traits/vector_space.rs | 13 ------ src/vec.rs | 24 ++--------- src/vec0_spec.rs | 33 +++++---------- src/vec_macros.rs | 40 +++++------------- src/vec_spec.rs | 32 +++++---------- 22 files changed, 166 insertions(+), 285 deletions(-) delete mode 100644 src/traits/dot.rs delete mode 100644 src/traits/norm.rs delete mode 100644 src/traits/ring.rs delete mode 100644 src/traits/sub_dot.rs create mode 100644 src/traits/vector.rs delete mode 100644 src/traits/vector_space.rs diff --git a/src/adaptors/rotmat.rs b/src/adaptors/rotmat.rs index a1085727..5a5c242b 100644 --- a/src/adaptors/rotmat.rs +++ b/src/adaptors/rotmat.rs @@ -1,7 +1,6 @@ use std::num::{One, Zero}; use std::rand::{Rand, Rng, RngUtil}; use std::cmp::ApproxEq; -use traits::ring::DivisionRing; use traits::rlmul::{RMul, LMul}; use traits::cross::Cross; use traits::dim::Dim; @@ -11,7 +10,7 @@ use traits::rotation::{Rotation, Rotate, Rotatable}; use traits::transformation::{Transform}; // FIXME: implement Transformation and Transformable use traits::homogeneous::ToHomogeneous; use traits::indexable::Indexable; -use traits::norm::Norm; +use traits::vector::AlgebraicVec; use vec::Vec1; use mat::{Mat2, Mat3}; use vec::Vec3; @@ -42,7 +41,7 @@ impl> Rotmat> { } } -impl Rotmat> { +impl Rotmat> { /// Builds a 3 dimensional rotation matrix from an axis and an angle. /// /// # Arguments @@ -83,7 +82,7 @@ impl Rotmat> { } } -impl Rotmat> { +impl Rotmat> { /// Reorient this matrix such that its local `x` axis points to a given point. Note that the /// usually known `look_at` function does the same thing but with the `z` axis. See `look_at_z` /// for that. @@ -121,7 +120,7 @@ impl Rotmat> { } } -impl +impl Rotation> for Rotmat> { #[inline] fn rotation(&self) -> Vec1 { @@ -139,7 +138,7 @@ Rotation> for Rotmat> { } } -impl +impl Rotatable, Rotmat>> for Rotmat> { #[inline] fn rotated(&self, rot: &Vec1) -> Rotmat> { @@ -147,7 +146,7 @@ Rotatable, Rotmat>> for Rotmat> { } } -impl +impl Rotation> for Rotmat> { #[inline] fn rotation(&self) -> Vec3 { @@ -166,7 +165,7 @@ Rotation> for Rotmat> { } } -impl +impl Rotatable, Rotmat>> for Rotmat> { #[inline] fn rotated(&self, axisangle: &Vec3) -> Rotmat> { @@ -205,7 +204,7 @@ impl + LMul, V> Transform for Rotmat { } } -impl +impl Rand for Rotmat> { #[inline] fn rand(rng: &mut R) -> Rotmat> { diff --git a/src/adaptors/transform.rs b/src/adaptors/transform.rs index 78df3a11..afa13ff5 100644 --- a/src/adaptors/transform.rs +++ b/src/adaptors/transform.rs @@ -3,7 +3,6 @@ use std::rand::{Rand, Rng, RngUtil}; use std::cmp::ApproxEq; use traits::dim::Dim; use traits::inv::Inv; -use traits::ring::DivisionRing; use traits::rotation::{Rotation, Rotate, Rotatable}; use traits::translation::{Translation, Translate, Translatable}; use Ts = traits::transformation::Transform; @@ -53,7 +52,7 @@ impl Transform { } } -impl Transform>, Vec3> { +impl Transform>, Vec3> { /// Reorient and translate this transformation such that its local `x` axis points to a given /// direction. Note that the usually known `look_at` function does the same thing but with the /// `z` axis. See `look_at_z` for that. diff --git a/src/dmat.rs b/src/dmat.rs index b60dd88a..56a1d427 100644 --- a/src/dmat.rs +++ b/src/dmat.rs @@ -2,7 +2,6 @@ use std::num::{One, Zero}; use std::vec::from_elem; use std::cmp::ApproxEq; use traits::inv::Inv; -use traits::ring::DivisionRing; use traits::transpose::Transpose; use traits::rlmul::{RMul, LMul}; use dvec::{DVec, zero_vec_with_dim}; @@ -145,7 +144,7 @@ LMul> for DMat { } } -impl +impl Inv for DMat { #[inline] fn inverse(&self) -> Option> { diff --git a/src/dvec.rs b/src/dvec.rs index ca7b4be5..1b6c49ff 100644 --- a/src/dvec.rs +++ b/src/dvec.rs @@ -3,13 +3,10 @@ use std::vec::{VecIterator, VecMutIterator}; use std::vec::from_elem; use std::cmp::ApproxEq; use std::iterator::FromIterator; +use traits::vector::{Vec, AlgebraicVec}; use traits::iterable::{Iterable, IterableMut}; -use traits::ring::{Ring, DivisionRing}; -use traits::dot::Dot; -use traits::sub_dot::SubDot; -use traits::norm::Norm; use traits::translation::{Translation, Translatable}; -use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub}; +use traits::scalar_op::{ScalarAdd, ScalarSub}; /// Vector with a dimension unknown at compile-time. #[deriving(Eq, ToStr, Clone)] @@ -57,7 +54,7 @@ impl FromIterator for DVec { } } -impl> DVec { +impl> DVec { /// Computes the canonical basis for the given dimension. A canonical basis is a set of /// vectors, mutually orthogonal, with all its component equal to 0.0 exept one which is equal /// to 1.0. @@ -94,10 +91,10 @@ impl> DVec { let mut elt = basis_element.clone(); - elt = elt - self.scalar_mul(&basis_element.dot(self)); + elt = elt - self * basis_element.dot(self); for v in res.iter() { - elt = elt - v.scalar_mul(&elt.dot(v)) + elt = elt - v * elt.dot(v) }; if !elt.sqnorm().approx_eq(&Zero::zero()) { @@ -138,7 +135,7 @@ impl> Neg> for DVec { } } -impl Dot for DVec { +impl DVec { #[inline] fn dot(&self, other: &DVec) -> N { assert!(self.at.len() == other.at.len()); @@ -151,9 +148,7 @@ impl Dot for DVec { res } -} -impl SubDot for DVec { #[inline] fn sub_dot(&self, a: &DVec, b: &DVec) -> N { let mut res = Zero::zero::(); @@ -166,33 +161,19 @@ impl SubDot for DVec { } } -impl> ScalarMul for DVec { +impl> Mul> for DVec { #[inline] - fn scalar_mul(&self, s: &N) -> DVec { + fn mul(&self, s: &N) -> DVec { DVec { at: self.at.iter().map(|a| a * *s).collect() } } - - #[inline] - fn scalar_mul_inplace(&mut self, s: &N) { - for i in range(0u, self.at.len()) { - self.at[i] = self.at[i] * *s; - } - } } -impl> ScalarDiv for DVec { +impl> Div> for DVec { #[inline] - fn scalar_div(&self, s: &N) -> DVec { + fn div(&self, s: &N) -> DVec { DVec { at: self.at.iter().map(|a| a / *s).collect() } } - - #[inline] - fn scalar_div_inplace(&mut self, s: &N) { - for i in range(0u, self.at.len()) { - self.at[i] = self.at[i] / *s; - } - } } impl> ScalarAdd for DVec { @@ -247,7 +228,7 @@ impl + Neg + Clone> Translatable, DVec> for DVec { } } -impl Norm for DVec { +impl DVec { #[inline] fn sqnorm(&self) -> N { self.dot(self) diff --git a/src/mat.rs b/src/mat.rs index d9291c5f..847b6a4c 100644 --- a/src/mat.rs +++ b/src/mat.rs @@ -6,7 +6,6 @@ use std::cmp::ApproxEq; use std::vec::{VecIterator, VecMutIterator}; use vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6}; use traits::dim::Dim; -use traits::ring::{Ring, DivisionRing}; use traits::inv::Inv; use traits::transpose::Transpose; use traits::rlmul::{RMul, LMul}; @@ -16,7 +15,7 @@ use traits::indexable::Indexable; use traits::column::Column; use traits::iterable::{Iterable, IterableMut}; use traits::outer::Outer; -use traits::scalar_op::{ScalarMul, ScalarAdd, ScalarDiv, ScalarSub}; +use traits::scalar_op::{ScalarAdd, ScalarSub}; pub use traits::mat_cast::*; pub use traits::column::*; diff --git a/src/mat_macros.rs b/src/mat_macros.rs index bfd84bb8..e58d5d1c 100644 --- a/src/mat_macros.rs +++ b/src/mat_macros.rs @@ -49,34 +49,24 @@ macro_rules! sub_impl( macro_rules! scalar_mul_impl( ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl> ScalarMul for $t { + impl> $t { #[inline] - fn scalar_mul(&self, other: &N) -> $t { + /// Scalar multiplication of each component of this matrix by a scalar. + pub fn scalar_mul(&self, other: &N) -> $t { $t::new(self.$comp0 * *other $(, self.$compN * *other )*) } - - #[inline] - fn scalar_mul_inplace(&mut self, other: &N) { - self.$comp0 = self.$comp0 * *other; - $(self.$compN = self.$compN * *other; )* - } } ) ) macro_rules! scalar_div_impl( ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl> ScalarDiv for $t { + impl> $t { #[inline] - fn scalar_div(&self, other: &N) -> $t { + /// Scalar division of each component of this matrix by a scalar. + pub fn scalar_div(&self, other: &N) -> $t { $t::new(self.$comp0 / *other $(, self.$compN / *other )*) } - - #[inline] - fn scalar_div_inplace(&mut self, other: &N) { - self.$comp0 = self.$comp0 / *other; - $(self.$compN = self.$compN / *other; )* - } } ) ) @@ -226,7 +216,7 @@ macro_rules! column_impl( macro_rules! mul_impl( ($t: ident, $dim: expr) => ( - impl Mul<$t, $t> for $t { + impl Mul<$t, $t> for $t { #[inline] fn mul(&self, other: &$t) -> $t { let mut res: $t = Zero::zero(); @@ -251,7 +241,7 @@ macro_rules! mul_impl( macro_rules! rmul_impl( ($t: ident, $v: ident, $dim: expr) => ( - impl RMul<$v> for $t { + impl RMul<$v> for $t { #[inline] fn rmul(&self, other: &$v) -> $v { let mut res : $v = Zero::zero(); @@ -271,7 +261,7 @@ macro_rules! rmul_impl( macro_rules! lmul_impl( ($t: ident, $v: ident, $dim: expr) => ( - impl LMul<$v> for $t { + impl LMul<$v> for $t { #[inline] fn lmul(&self, other: &$v) -> $v { let mut res : $v = Zero::zero(); @@ -291,7 +281,7 @@ macro_rules! lmul_impl( macro_rules! transform_impl( ($t: ident, $v: ident) => ( - impl + impl Transform<$v> for $t { #[inline] fn transform(&self, v: &$v) -> $v { @@ -311,7 +301,7 @@ macro_rules! transform_impl( macro_rules! inv_impl( ($t: ident, $dim: expr) => ( - impl + impl Inv for $t { #[inline] fn inverse(&self) -> Option<$t> { diff --git a/src/mat_spec.rs b/src/mat_spec.rs index d0c629ea..ae1748e9 100644 --- a/src/mat_spec.rs +++ b/src/mat_spec.rs @@ -1,10 +1,9 @@ use std::num::{Zero, One}; use mat::{Mat1, Mat2, Mat3}; -use traits::ring::DivisionRing; use traits::inv::Inv; // some specializations: -impl +impl Inv for Mat1 { #[inline] fn inverse(&self) -> Option> { @@ -30,7 +29,7 @@ Inv for Mat1 { } } -impl +impl Inv for Mat2 { #[inline] fn inverse(&self) -> Option> { @@ -61,7 +60,7 @@ Inv for Mat2 { } } -impl +impl Inv for Mat3 { #[inline] fn inverse(&self) -> Option> { diff --git a/src/nalgebra.rc b/src/nalgebra.rc index 83bb6088..7454a396 100644 --- a/src/nalgebra.rc +++ b/src/nalgebra.rc @@ -47,24 +47,20 @@ pub mod types; // FIXME: it would be better to hide all those from the outside! pub mod traits { + pub mod vector; pub mod sample; pub mod indexable; pub mod column; pub mod iterable; - pub mod dot; pub mod outer; pub mod cross; pub mod inv; pub mod transpose; pub mod dim; pub mod basis; - pub mod norm; pub mod rotation; pub mod translation; pub mod transformation; - pub mod vector_space; - pub mod ring; - pub mod sub_dot; pub mod rlmul; pub mod scalar_op; pub mod homogeneous; diff --git a/src/tests/mat.rs b/src/tests/mat.rs index 7cdb6dcd..97317abc 100644 --- a/src/tests/mat.rs +++ b/src/tests/mat.rs @@ -5,10 +5,6 @@ use std::rand::random; #[test] use std::cmp::ApproxEq; #[test] -use traits::norm::Norm; -#[test] -use traits::scalar_op::ScalarMul; -#[test] use traits::inv::Inv; #[test] use traits::rotation::{Rotation, Rotatable}; @@ -17,6 +13,8 @@ use traits::indexable::Indexable; #[test] use traits::transpose::Transpose; #[test] +use traits::vector::AlgebraicVec; +#[test] use vec::{Vec1, Vec3}; #[test] use mat::{Mat1, Mat2, Mat3, Mat4, Mat5, Mat6}; @@ -125,7 +123,7 @@ fn test_inv_rotation3() { do 10000.times { let randmat = One::one::>>(); let dir: Vec3 = random(); - let ang = &dir.normalized().scalar_mul(&(abs::(random()) % Real::pi())); + let ang = &(dir.normalized() * (abs::(random()) % Real::pi())); let rot = randmat.rotated(ang); assert!((rot.transposed() * rot).approx_eq(&One::one())); diff --git a/src/tests/vec.rs b/src/tests/vec.rs index 740cd0c2..0d290e17 100644 --- a/src/tests/vec.rs +++ b/src/tests/vec.rs @@ -13,13 +13,11 @@ use traits::basis::Basis; #[test] use traits::cross::Cross; #[test] -use traits::dot::Dot; -#[test] -use traits::norm::Norm; +use traits::vector::{Vec, AlgebraicVec}; #[test] use traits::iterable::{Iterable, IterableMut}; #[test] -use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub}; +use traits::scalar_op::{ScalarAdd, ScalarSub}; #[test] use traits::outer::Outer; @@ -36,7 +34,7 @@ macro_rules! test_iterator_impl( *e = *e * n } - assert!(nv == mv && nv == v.scalar_mul(&n)); + assert!(nv == mv && nv == v * n); } ) ) @@ -58,8 +56,8 @@ macro_rules! test_scalar_op_impl( let v1 : $t = random(); let n : $n = random(); - assert!(v1.scalar_mul(&n).scalar_div(&n).approx_eq(&v1)); - assert!(v1.scalar_div(&n).scalar_mul(&n).approx_eq(&v1)); + assert!(((v1 * n) / n).approx_eq(&v1)); + assert!(((v1 / n) * n).approx_eq(&v1)); assert!(v1.scalar_sub(&n).scalar_add(&n).approx_eq(&v1)); assert!(v1.scalar_add(&n).scalar_sub(&n).approx_eq(&v1)); @@ -67,8 +65,8 @@ macro_rules! test_scalar_op_impl( let v0 : $t = v1.clone(); let n : $n = random(); - v1.scalar_mul_inplace(&n); - v1.scalar_div_inplace(&n); + v1 = v1 * n; + v1 = v1 / n; assert!(v1.approx_eq(&v0)); } diff --git a/src/traits/dot.rs b/src/traits/dot.rs deleted file mode 100644 index 2cb41047..00000000 --- a/src/traits/dot.rs +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Trait of objects having a dot product (also called inner product). - */ -pub trait Dot -{ - /// Computes the dot (inner) product of two objects. - fn dot(&self, &Self) -> N; -} diff --git a/src/traits/norm.rs b/src/traits/norm.rs deleted file mode 100644 index e7c47f80..00000000 --- a/src/traits/norm.rs +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Trait of objects having a L² norm and which can be normalized. - */ -pub trait Norm { - /// Computes the norm a an object. - fn norm(&self) -> N; - - /** - * Computes the squared norm of an object. Usually faster than computing the - * norm itself. - */ - fn sqnorm(&self) -> N; - - /// Gets the normalized version of the argument. - fn normalized(&self) -> Self; - - /// In-place version of `normalized`. - fn normalize(&mut self) -> N; -} diff --git a/src/traits/ring.rs b/src/traits/ring.rs deleted file mode 100644 index 95eece7e..00000000 --- a/src/traits/ring.rs +++ /dev/null @@ -1,22 +0,0 @@ -use std::num::{One, Zero}; - -/** - * Trait of elements of a ring. A rings is an algebraic structure, the - * elements of which have all the common numeric operation but the division: - * addition, subtraction, multiplication and distinct elements (`One` and - * `Zero`) respectively neutral and absorbant wrt the multiplication. - */ -pub trait Ring : -Sub + Add + Neg + Mul + One + Zero { } - -impl + Add + Neg + Mul + One + Zero> -Ring for N; - -/** - * Trait of elements of a division ring. A division ring is an algebraic - * structure like a ring, but with the division operator. - */ -pub trait DivisionRing : Ring + Div -{ } - -impl> DivisionRing for N; diff --git a/src/traits/sample.rs b/src/traits/sample.rs index e44e0cad..cdd4d993 100644 --- a/src/traits/sample.rs +++ b/src/traits/sample.rs @@ -2,8 +2,5 @@ /// approximate a sphere using support mapping functions. pub trait UniformSphereSample { /// Iterate throught the samples. - fn sample(&fn(&'static Self)); - - /// Gets the list of all samples. - fn sample_list() -> &[Self]; + fn sample(&fn(Self)); } diff --git a/src/traits/scalar_op.rs b/src/traits/scalar_op.rs index f2f2f9a5..10c103f3 100644 --- a/src/traits/scalar_op.rs +++ b/src/traits/scalar_op.rs @@ -1,25 +1,3 @@ -/** - * Trait of objects having a multiplication with a scalar. - */ -pub trait ScalarMul { - /// Gets the result of a multiplication by a scalar. - fn scalar_mul(&self, &N) -> Self; - - /// In-place version of `scalar_mul`. - fn scalar_mul_inplace(&mut self, &N); -} - -/** - * Trait of objects having a division with a scalar. - */ -pub trait ScalarDiv { - /// Gets the result of a division by a scalar. - fn scalar_div(&self, &N) -> Self; - - /// In-place version of `scalar_div`. - fn scalar_div_inplace(&mut self, &N); -} - /** * Trait of objects having an addition with a scalar. */ diff --git a/src/traits/sub_dot.rs b/src/traits/sub_dot.rs deleted file mode 100644 index 1452addc..00000000 --- a/src/traits/sub_dot.rs +++ /dev/null @@ -1,14 +0,0 @@ -use traits::dot::Dot; - -/// Traits of objects with a subtract and a dot product. Exists only for optimization purpose. -pub trait SubDot : Sub + Dot { - /** - * Short-cut to compute the projection of a point on a vector, but without - * computing intermediate vectors. - * This must be equivalent to: - * - * (a - b).dot(c) - * - */ - fn sub_dot(&self, b: &Self, c: &Self) -> N; -} diff --git a/src/traits/vector.rs b/src/traits/vector.rs new file mode 100644 index 00000000..3b3bcbf1 --- /dev/null +++ b/src/traits/vector.rs @@ -0,0 +1,83 @@ +use std::num::Zero; +use traits::dim::Dim; +use traits::basis::Basis; +use traits::indexable::Indexable; +use traits::iterable::Iterable; +use traits::sample::UniformSphereSample; +use traits::scalar_op::{ScalarAdd, ScalarSub}; + +// NOTE: cant call that `Vector` because it conflicts with std::Vector +/// Trait grouping most common operations on vectors. +pub trait Vec: Dim + Sub + Add + Neg + Zero + Eq + Mul + + Div +{ + /// Computes the dot (inner) product of two vectors. + #[inline] + fn dot(&self, &Self) -> N; + + /** + * Short-cut to compute the projection of a point on a vector, but without + * computing intermediate vectors. + * This must be equivalent to: + * + * (a - b).dot(c) + * + */ + #[inline] + fn sub_dot(&self, b: &Self, c: &Self) -> N { + (*self - *b).dot(c) + } +} + +/// Trait of vector with components implementing the `Algebraic` trait. +pub trait AlgebraicVec: Vec { + /// Computes the norm a an object. + #[inline] + fn norm(&self) -> N { + self.sqnorm().sqrt() + } + + /** + * Computes the squared norm of an object. Usually faster than computing the + * norm itself. + */ + #[inline] + fn sqnorm(&self) -> N { + self.dot(self) + } + + /// Gets the normalized version of the argument. + #[inline] + fn normalized(&self) -> Self { + self / self.norm() + } + + /// In-place version of `normalized`. + #[inline] + fn normalize(&mut self) -> N { + let norm = self.norm(); + + *self = *self / norm; + + norm + } +} + +/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view) +/// operations on vectors. +pub trait VecExt: Vec + Basis + Indexable + Iterable + Round + + UniformSphereSample + ScalarAdd + ScalarSub + Bounded + Orderable +{ } + +/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view) +/// operations on vectors. +pub trait AlgebraicVecExt: AlgebraicVec + VecExt +{ } + +impl + Basis + Indexable + Iterable + Round + + UniformSphereSample + ScalarAdd + ScalarSub + Bounded + Orderable> +VecExt for V; + +impl + VecExt> +AlgebraicVecExt for V; diff --git a/src/traits/vector_space.rs b/src/traits/vector_space.rs deleted file mode 100644 index 31738079..00000000 --- a/src/traits/vector_space.rs +++ /dev/null @@ -1,13 +0,0 @@ -use std::num::Zero; -use traits::ring::DivisionRing; -use traits::scalar_op::{ScalarMul, ScalarDiv}; - -/// Trait of elements of a vector space. A vector space is an algebraic -/// structure, the elements of which have addition, substraction, negation, -/// scalar multiplication (the scalar being a element of a `DivisionRing`), and -/// has a distinct element (`Zero`) neutral wrt the addition. -pub trait VectorSpace -: Sub + Add + Neg + Zero + ScalarMul + ScalarDiv { } - -impl + Add + Neg + Zero + ScalarMul + ScalarDiv, - N: DivisionRing> VectorSpace for V; diff --git a/src/vec.rs b/src/vec.rs index 585b2b7d..c6e556fe 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -7,22 +7,12 @@ use std::cmp::ApproxEq; use traits::basis::Basis; use traits::dim::Dim; use traits::translation::{Translation, Translatable}; -use traits::ring::{Ring, DivisionRing}; use traits::homogeneous::{FromHomogeneous, ToHomogeneous}; use traits::indexable::Indexable; - -pub use traits::vec_cast::*; -pub use traits::basis::*; -pub use traits::cross::*; -pub use traits::outer::*; -pub use traits::dot::*; -pub use traits::indexable::*; -pub use traits::iterable::*; -pub use traits::norm::*; -pub use traits::sample::*; -pub use traits::sub_dot::*; -pub use traits::vector_space::*; -pub use traits::scalar_op::*; +use traits::scalar_op::{ScalarAdd, ScalarSub}; +use traits::iterable::{Iterable, IterableMut}; +use traits::vec_cast::VecCast; +use traits::vector::{Vec, AlgebraicVec}; mod vec_macros; @@ -50,7 +40,6 @@ add_impl!(Vec1, x) sub_impl!(Vec1, x) neg_impl!(Vec1, x) dot_impl!(Vec1, x) -sub_dot_impl!(Vec1, x) scalar_mul_impl!(Vec1, x) scalar_div_impl!(Vec1, x) scalar_add_impl!(Vec1, x) @@ -90,7 +79,6 @@ add_impl!(Vec2, x, y) sub_impl!(Vec2, x, y) neg_impl!(Vec2, x, y) dot_impl!(Vec2, x, y) -sub_dot_impl!(Vec2, x, y) scalar_mul_impl!(Vec2, x, y) scalar_div_impl!(Vec2, x, y) scalar_add_impl!(Vec2, x, y) @@ -132,7 +120,6 @@ add_impl!(Vec3, x, y, z) sub_impl!(Vec3, x, y, z) neg_impl!(Vec3, x, y, z) dot_impl!(Vec3, x, y, z) -sub_dot_impl!(Vec3, x, y, z) scalar_mul_impl!(Vec3, x, y, z) scalar_div_impl!(Vec3, x, y, z) scalar_add_impl!(Vec3, x, y, z) @@ -176,7 +163,6 @@ add_impl!(Vec4, x, y, z, w) sub_impl!(Vec4, x, y, z, w) neg_impl!(Vec4, x, y, z, w) dot_impl!(Vec4, x, y, z, w) -sub_dot_impl!(Vec4, x, y, z, w) scalar_mul_impl!(Vec4, x, y, z, w) scalar_div_impl!(Vec4, x, y, z, w) scalar_add_impl!(Vec4, x, y, z, w) @@ -222,7 +208,6 @@ add_impl!(Vec5, x, y, z, w, a) sub_impl!(Vec5, x, y, z, w, a) neg_impl!(Vec5, x, y, z, w, a) dot_impl!(Vec5, x, y, z, w, a) -sub_dot_impl!(Vec5, x, y, z, w, a) scalar_mul_impl!(Vec5, x, y, z, w, a) scalar_div_impl!(Vec5, x, y, z, w, a) scalar_add_impl!(Vec5, x, y, z, w, a) @@ -270,7 +255,6 @@ add_impl!(Vec6, x, y, z, w, a, b) sub_impl!(Vec6, x, y, z, w, a, b) neg_impl!(Vec6, x, y, z, w, a, b) dot_impl!(Vec6, x, y, z, w, a, b) -sub_dot_impl!(Vec6, x, y, z, w, a, b) scalar_mul_impl!(Vec6, x, y, z, w, a, b) scalar_div_impl!(Vec6, x, y, z, w, a, b) scalar_add_impl!(Vec6, x, y, z, w, a, b) diff --git a/src/vec0_spec.rs b/src/vec0_spec.rs index c7a4270c..72c564a3 100644 --- a/src/vec0_spec.rs +++ b/src/vec0_spec.rs @@ -6,13 +6,10 @@ use std::cmp::ApproxEq; use traits::iterable::{Iterable, IterableMut}; use traits::basis::Basis; use traits::dim::Dim; -use traits::dot::Dot; -use traits::sub_dot::SubDot; -use traits::norm::Norm; use traits::translation::{Translation, Translatable}; -use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub}; -use traits::ring::{Ring, DivisionRing}; +use traits::scalar_op::{ScalarAdd, ScalarSub}; use traits::indexable::Indexable; +use traits::vector::{Vec, AlgebraicVec}; use vec; impl vec::Vec0 { @@ -69,7 +66,7 @@ impl Dim for vec::Vec0 { } } -impl> Basis for vec::Vec0 { +impl> Basis for vec::Vec0 { #[inline(always)] fn canonical_basis(_: &fn(vec::Vec0) -> bool) { } @@ -98,38 +95,30 @@ impl> Neg> for vec::Vec0 { } } -impl Dot for vec::Vec0 { +impl Vec for vec::Vec0 { #[inline] fn dot(&self, _: &vec::Vec0) -> N { Zero::zero() - } -} + } -impl SubDot for vec::Vec0 { #[inline] fn sub_dot(&self, _: &vec::Vec0, _: &vec::Vec0) -> N { Zero::zero() } } -impl> ScalarMul for vec::Vec0 { +impl> Mul> for vec::Vec0 { #[inline] - fn scalar_mul(&self, _: &N) -> vec::Vec0 { + fn mul(&self, _: &N) -> vec::Vec0 { vec::Vec0 } - - #[inline] - fn scalar_mul_inplace(&mut self, _: &N) { } } -impl> ScalarDiv for vec::Vec0 { +impl> Div> for vec::Vec0 { #[inline] - fn scalar_div(&self, _: &N) -> vec::Vec0 { + fn div(&self, _: &N) -> vec::Vec0 { vec::Vec0 } - - #[inline] - fn scalar_div_inplace(&mut self, _: &N) { } } impl> ScalarAdd for vec::Vec0 { @@ -176,7 +165,7 @@ impl + Neg + Clone> Translatable, vec::Vec0> for } } -impl Norm for vec::Vec0 { +impl AlgebraicVec for vec::Vec0 { #[inline] fn sqnorm(&self) -> N { self.dot(self) @@ -200,7 +189,7 @@ impl Norm for vec::Vec0 { fn normalize(&mut self) -> N { let l = self.norm(); - self.scalar_div_inplace(&l); + *self = *self / l; l } diff --git a/src/vec_macros.rs b/src/vec_macros.rs index be956974..668d8b47 100644 --- a/src/vec_macros.rs +++ b/src/vec_macros.rs @@ -183,7 +183,7 @@ macro_rules! dim_impl( macro_rules! basis_impl( ($t: ident, $dim: expr) => ( - impl> Basis for $t { + impl> Basis for $t { #[inline] fn canonical_basis(f: &fn($t) -> bool) { for i in range(0u, $dim) { @@ -212,10 +212,10 @@ macro_rules! basis_impl( let mut elt = basis_element.clone(); - elt = elt - self.scalar_mul(&basis_element.dot(self)); + elt = elt - *self * basis_element.dot(self); for v in basis.iter() { - elt = elt - v.scalar_mul(&elt.dot(v)) + elt = elt - v * elt.dot(v) }; if !elt.sqnorm().approx_eq(&Zero::zero()) { @@ -266,18 +266,12 @@ macro_rules! neg_impl( macro_rules! dot_impl( ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl Dot for $t { + impl Vec for $t { #[inline] fn dot(&self, other: &$t) -> N { self.$comp0 * other.$comp0 $(+ self.$compN * other.$compN )* } - } - ) -) -macro_rules! sub_dot_impl( - ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl SubDot for $t { #[inline] fn sub_dot(&self, a: &$t, b: &$t) -> N { (self.$comp0 - a.$comp0) * b.$comp0 $(+ (self.$compN - a.$compN) * b.$compN )* @@ -288,34 +282,22 @@ macro_rules! sub_dot_impl( macro_rules! scalar_mul_impl( ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl> ScalarMul for $t { + impl> Mul> for $t { #[inline] - fn scalar_mul(&self, s: &N) -> $t { + fn mul(&self, s: &N) -> $t { $t::new(self.$comp0 * *s $(, self.$compN * *s)*) } - - #[inline] - fn scalar_mul_inplace(&mut self, s: &N) { - self.$comp0 = self.$comp0 * *s; - $(self.$compN = self.$compN * *s;)* - } } ) ) macro_rules! scalar_div_impl( ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl> ScalarDiv for $t { + impl> Div> for $t { #[inline] - fn scalar_div(&self, s: &N) -> $t { + fn div(&self, s: &N) -> $t { $t::new(self.$comp0 / *s $(, self.$compN / *s)*) } - - #[inline] - fn scalar_div_inplace(&mut self, s: &N) { - self.$comp0 = self.$comp0 / *s; - $(self.$compN = self.$compN / *s;)* - } } ) ) @@ -388,7 +370,7 @@ macro_rules! translatable_impl( macro_rules! norm_impl( ($t: ident) => ( - impl Norm for $t { + impl AlgebraicVec for $t { #[inline] fn sqnorm(&self) -> N { self.dot(self) @@ -412,7 +394,7 @@ macro_rules! norm_impl( fn normalize(&mut self) -> N { let l = self.norm(); - self.scalar_div_inplace(&l); + *self = *self / l; l } @@ -529,7 +511,7 @@ macro_rules! from_homogeneous_impl( res.$comp0 = v.$comp0.clone(); $( res.$compN = v.$compN.clone(); )* - res.scalar_div(&v.$extra); + res = res / v.$extra; res } diff --git a/src/vec_spec.rs b/src/vec_spec.rs index 1289c009..a35c1b4e 100644 --- a/src/vec_spec.rs +++ b/src/vec_spec.rs @@ -1,9 +1,9 @@ use std::num::{Zero, One}; use traits::basis::Basis; use traits::cross::Cross; -use traits::ring::DivisionRing; -use traits::norm::Norm; use traits::sample::UniformSphereSample; +use traits::vec_cast::VecCast; +use traits::vector::{AlgebraicVec}; use vec::{Vec1, Vec2, Vec3}; impl + Sub> Cross> for Vec2 { @@ -47,7 +47,7 @@ impl> Basis for Vec2 { } } -impl +impl Basis for Vec3 { #[inline(always)] fn canonical_basis(f: &fn(Vec3) -> bool) { @@ -142,34 +142,20 @@ static SAMPLES_3_F64: [Vec3, ..42] = [ Vec3 { x: 0.162456 , y: 0.499995 , z: 0.850654 } ]; -impl UniformSphereSample for Vec2 { +impl UniformSphereSample for Vec2 { #[inline(always)] - fn sample(f: &fn(&'static Vec2)) { + fn sample(f: &fn(Vec2)) { for sample in SAMPLES_2_F64.iter() { - f(sample) + f(VecCast::from(*sample)) } } - - #[inline] - fn sample_list() -> &[Vec2] { - let res: &[Vec2] = SAMPLES_2_F64; - - res - } } -impl UniformSphereSample for Vec3 { +impl UniformSphereSample for Vec3 { #[inline(always)] - fn sample(f: &fn(&'static Vec3)) { + fn sample(f: &fn(Vec3)) { for sample in SAMPLES_3_F64.iter() { - f(sample) + f(VecCast::from(*sample)) } } - - #[inline] - fn sample_list() -> &[Vec3] { - let res: &[Vec3] = SAMPLES_3_F64; - - res - } }