From bdf82748dc3d22821c923b9a5810a8af2bc53e0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Sun, 8 Sep 2013 18:20:06 +0200 Subject: [PATCH] Add a `Dot` and a `Norm` trait for vectors having a dot product and a norm. Those methods are not part of the `Vec` and `AlgebraicVec` traits any more. --- src/adaptors/rotmat.rs | 2 +- src/dvec.rs | 1 - src/lib.rs | 2 ++ src/tests/mat.rs | 2 +- src/tests/vec.rs | 4 ++- src/traits/dot.rs | 17 ++++++++++++ src/traits/norm.rs | 23 ++++++++++++++++ src/traits/vector.rs | 61 +++++++----------------------------------- src/vec.rs | 2 ++ src/vec0_spec.rs | 7 ++--- src/vec_macros.rs | 4 +-- src/vec_spec.rs | 5 ++-- 12 files changed, 67 insertions(+), 63 deletions(-) create mode 100644 src/traits/dot.rs create mode 100644 src/traits/norm.rs diff --git a/src/adaptors/rotmat.rs b/src/adaptors/rotmat.rs index d6e8ce43..8e253eb6 100644 --- a/src/adaptors/rotmat.rs +++ b/src/adaptors/rotmat.rs @@ -10,7 +10,7 @@ use traits::rotation::{Rotation, Rotate}; use traits::transformation::{Transform}; // FIXME: implement Transformation and Transformable use traits::homogeneous::ToHomogeneous; use traits::indexable::Indexable; -use traits::vector::AlgebraicVec; +use traits::norm::Norm; use vec::Vec1; use mat::{Mat2, Mat3}; use vec::Vec3; diff --git a/src/dvec.rs b/src/dvec.rs index bbfe1ed1..7a0455b3 100644 --- a/src/dvec.rs +++ b/src/dvec.rs @@ -3,7 +3,6 @@ use std::vec; use std::vec::{VecIterator, VecMutIterator}; use std::cmp::ApproxEq; use std::iterator::FromIterator; -use traits::vector::{Vec, AlgebraicVec}; use traits::iterable::{Iterable, IterableMut}; use traits::translation::Translation; use traits::scalar_op::{ScalarAdd, ScalarSub}; diff --git a/src/lib.rs b/src/lib.rs index 9c705887..00cb94ec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,6 +59,8 @@ pub mod traits pub mod homogeneous; pub mod vec_cast; pub mod mat_cast; + pub mod norm; + pub mod dot; } #[cfg(test)] diff --git a/src/tests/mat.rs b/src/tests/mat.rs index fd595e65..c857fc85 100644 --- a/src/tests/mat.rs +++ b/src/tests/mat.rs @@ -13,7 +13,7 @@ use traits::indexable::Indexable; #[test] use traits::transpose::Transpose; #[test] -use traits::vector::AlgebraicVec; +use traits::norm::Norm; #[test] use vec::{Vec1, Vec3}; #[test] diff --git a/src/tests/vec.rs b/src/tests/vec.rs index a0735dd2..ea9fa4d9 100644 --- a/src/tests/vec.rs +++ b/src/tests/vec.rs @@ -13,7 +13,9 @@ use traits::basis::Basis; #[test] use traits::cross::Cross; #[test] -use traits::vector::{Vec, AlgebraicVec}; +use traits::dot::Dot; +#[test] +use traits::norm::Norm; #[test] use traits::iterable::{Iterable, IterableMut}; #[test] diff --git a/src/traits/dot.rs b/src/traits/dot.rs new file mode 100644 index 00000000..5a4ab653 --- /dev/null +++ b/src/traits/dot.rs @@ -0,0 +1,17 @@ +/// Traits of objects having a dot product. +pub trait Dot { + /// 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; +} diff --git a/src/traits/norm.rs b/src/traits/norm.rs new file mode 100644 index 00000000..7bd863b8 --- /dev/null +++ b/src/traits/norm.rs @@ -0,0 +1,23 @@ +/// Traits of objects having an euclidian norm. +pub trait Norm { + /// 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; + + /// Gets the normalized version of the argument. + #[inline] + fn normalized(&self) -> Self; + + /// In-place version of `normalized`. + #[inline] + fn normalize(&mut self) -> N; +} diff --git a/src/traits/vector.rs b/src/traits/vector.rs index 042a111a..d1a41748 100644 --- a/src/traits/vector.rs +++ b/src/traits/vector.rs @@ -5,62 +5,17 @@ use traits::indexable::Indexable; use traits::iterable::Iterable; use traits::sample::UniformSphereSample; use traits::scalar_op::{ScalarAdd, ScalarSub}; +use traits::dot::Dot; +use traits::norm::Norm; // 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) - } + + Div + Dot { } /// 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 - } +pub trait AlgebraicVec: Vec + Norm { } /// Trait grouping uncommon, low-level and borderline (from the mathematical point of view) @@ -74,10 +29,14 @@ pub trait VecExt: Vec + Basis + Indexable + Iterable + Round + pub trait AlgebraicVecExt: AlgebraicVec + VecExt { } +impl + Add + Neg + Zero + Eq + Mul + Div + Dot> +Vec for V; + +impl + Norm> AlgebraicVec for V; + impl + Basis + Indexable + Iterable + Round + UniformSphereSample + ScalarAdd + ScalarSub + Bounded + Orderable> VecExt for V; -impl + VecExt> -AlgebraicVecExt for V; +impl + VecExt> AlgebraicVecExt for V; diff --git a/src/vec.rs b/src/vec.rs index 389d88b0..228836a0 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -20,6 +20,8 @@ pub use traits::sample::UniformSphereSample; pub use traits::scalar_op::{ScalarAdd, ScalarSub}; pub use traits::cross::{Cross, CrossMatrix}; pub use traits::outer::Outer; +pub use traits::dot::Dot; +pub use traits::norm::Norm; // structs pub use dvec::DVec; diff --git a/src/vec0_spec.rs b/src/vec0_spec.rs index 3181534c..84585ef0 100644 --- a/src/vec0_spec.rs +++ b/src/vec0_spec.rs @@ -9,7 +9,8 @@ use traits::dim::Dim; use traits::translation::Translation; use traits::scalar_op::{ScalarAdd, ScalarSub}; use traits::indexable::Indexable; -use traits::vector::{Vec, AlgebraicVec}; +use traits::dot::Dot; +use traits::norm::Norm; use vec; impl vec::Vec0 { @@ -95,7 +96,7 @@ impl> Neg> for vec::Vec0 { } } -impl Vec for vec::Vec0 { +impl Dot for vec::Vec0 { #[inline] fn dot(&self, _: &vec::Vec0) -> N { Zero::zero() @@ -167,7 +168,7 @@ impl + Neg> Translation> for vec::Vec0 { } } -impl AlgebraicVec for vec::Vec0 { +impl Norm for vec::Vec0 { #[inline] fn sqnorm(&self) -> N { self.dot(self) diff --git a/src/vec_macros.rs b/src/vec_macros.rs index 15022238..3cbb723c 100644 --- a/src/vec_macros.rs +++ b/src/vec_macros.rs @@ -277,7 +277,7 @@ macro_rules! neg_impl( macro_rules! dot_impl( ($t: ident, $comp0: ident $(,$compN: ident)*) => ( - impl Vec for $t { + impl Dot for $t { #[inline] fn dot(&self, other: &$t) -> N { self.$comp0 * other.$comp0 $(+ self.$compN * other.$compN )* @@ -380,7 +380,7 @@ macro_rules! translation_impl( macro_rules! norm_impl( ($t: ident) => ( - impl AlgebraicVec for $t { + impl Norm for $t { #[inline] fn sqnorm(&self) -> N { self.dot(self) diff --git a/src/vec_spec.rs b/src/vec_spec.rs index a509921c..0b4ecf68 100644 --- a/src/vec_spec.rs +++ b/src/vec_spec.rs @@ -1,5 +1,5 @@ use std::num::{Zero, One}; -use vec::{Vec1, Vec2, Vec3, AlgebraicVec, VecCast, UniformSphereSample, Cross, CrossMatrix, Basis}; +use vec::{Vec1, Vec2, Vec3, Norm, VecCast, UniformSphereSample, Cross, CrossMatrix, Basis}; use mat::{Mat3, Row}; impl + Sub> Cross> for Vec2 { @@ -84,8 +84,7 @@ impl> Basis for Vec2 { } } -impl -Basis for Vec3 { +impl Basis for Vec3 { #[inline(always)] fn canonical_basis(f: &fn(Vec3) -> bool) { if !f(Vec3::new(One::one(), Zero::zero(), Zero::zero())) { return };