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.
This commit is contained in:
Sébastien Crozet 2013-09-08 18:20:06 +02:00
parent 37f0b123e0
commit bdf82748dc
12 changed files with 67 additions and 63 deletions

View File

@ -10,7 +10,7 @@ use traits::rotation::{Rotation, Rotate};
use traits::transformation::{Transform}; // FIXME: implement Transformation and Transformable use traits::transformation::{Transform}; // FIXME: implement Transformation and Transformable
use traits::homogeneous::ToHomogeneous; use traits::homogeneous::ToHomogeneous;
use traits::indexable::Indexable; use traits::indexable::Indexable;
use traits::vector::AlgebraicVec; use traits::norm::Norm;
use vec::Vec1; use vec::Vec1;
use mat::{Mat2, Mat3}; use mat::{Mat2, Mat3};
use vec::Vec3; use vec::Vec3;

View File

@ -3,7 +3,6 @@ use std::vec;
use std::vec::{VecIterator, VecMutIterator}; use std::vec::{VecIterator, VecMutIterator};
use std::cmp::ApproxEq; use std::cmp::ApproxEq;
use std::iterator::FromIterator; use std::iterator::FromIterator;
use traits::vector::{Vec, AlgebraicVec};
use traits::iterable::{Iterable, IterableMut}; use traits::iterable::{Iterable, IterableMut};
use traits::translation::Translation; use traits::translation::Translation;
use traits::scalar_op::{ScalarAdd, ScalarSub}; use traits::scalar_op::{ScalarAdd, ScalarSub};

View File

@ -59,6 +59,8 @@ pub mod traits
pub mod homogeneous; pub mod homogeneous;
pub mod vec_cast; pub mod vec_cast;
pub mod mat_cast; pub mod mat_cast;
pub mod norm;
pub mod dot;
} }
#[cfg(test)] #[cfg(test)]

View File

@ -13,7 +13,7 @@ use traits::indexable::Indexable;
#[test] #[test]
use traits::transpose::Transpose; use traits::transpose::Transpose;
#[test] #[test]
use traits::vector::AlgebraicVec; use traits::norm::Norm;
#[test] #[test]
use vec::{Vec1, Vec3}; use vec::{Vec1, Vec3};
#[test] #[test]

View File

@ -13,7 +13,9 @@ use traits::basis::Basis;
#[test] #[test]
use traits::cross::Cross; use traits::cross::Cross;
#[test] #[test]
use traits::vector::{Vec, AlgebraicVec}; use traits::dot::Dot;
#[test]
use traits::norm::Norm;
#[test] #[test]
use traits::iterable::{Iterable, IterableMut}; use traits::iterable::{Iterable, IterableMut};
#[test] #[test]

17
src/traits/dot.rs Normal file
View File

@ -0,0 +1,17 @@
/// Traits of objects having a dot product.
pub trait Dot<N> {
/// 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;
}

23
src/traits/norm.rs Normal file
View File

@ -0,0 +1,23 @@
/// Traits of objects having an euclidian norm.
pub trait Norm<N: Algebraic> {
/// 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;
}

View File

@ -5,62 +5,17 @@ use traits::indexable::Indexable;
use traits::iterable::Iterable; use traits::iterable::Iterable;
use traits::sample::UniformSphereSample; use traits::sample::UniformSphereSample;
use traits::scalar_op::{ScalarAdd, ScalarSub}; 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 // NOTE: cant call that `Vector` because it conflicts with std::Vector
/// Trait grouping most common operations on vectors. /// Trait grouping most common operations on vectors.
pub trait Vec<N>: Dim + Sub<Self, Self> + Add<Self, Self> + Neg<Self> + Zero + Eq + Mul<N, Self> pub trait Vec<N>: Dim + Sub<Self, Self> + Add<Self, Self> + Neg<Self> + Zero + Eq + Mul<N, Self>
+ Div<N, Self> + Div<N, Self> + Dot<N> {
{
/// 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. /// Trait of vector with components implementing the `Algebraic` trait.
pub trait AlgebraicVec<N: Algebraic>: Vec<N> { pub trait AlgebraicVec<N: Algebraic>: Vec<N> + Norm<N> {
/// 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) /// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
@ -74,10 +29,14 @@ pub trait VecExt<N>: Vec<N> + Basis + Indexable<uint, N> + Iterable<N> + Round +
pub trait AlgebraicVecExt<N: Algebraic>: AlgebraicVec<N> + VecExt<N> pub trait AlgebraicVecExt<N: Algebraic>: AlgebraicVec<N> + VecExt<N>
{ } { }
impl<N, V: Dim + Sub<V, V> + Add<V, V> + Neg<V> + Zero + Eq + Mul<N, V> + Div<N, V> + Dot<N>>
Vec<N> for V;
impl<N: Algebraic, V: Vec<N> + Norm<N>> AlgebraicVec<N> for V;
impl<N, impl<N,
V: Vec<N> + Basis + Indexable<uint, N> + Iterable<N> + Round + V: Vec<N> + Basis + Indexable<uint, N> + Iterable<N> + Round +
UniformSphereSample + ScalarAdd<N> + ScalarSub<N> + Bounded + Orderable> UniformSphereSample + ScalarAdd<N> + ScalarSub<N> + Bounded + Orderable>
VecExt<N> for V; VecExt<N> for V;
impl<N: Algebraic, V: AlgebraicVec<N> + VecExt<N>> impl<N: Algebraic, V: AlgebraicVec<N> + VecExt<N>> AlgebraicVecExt<N> for V;
AlgebraicVecExt<N> for V;

View File

@ -20,6 +20,8 @@ pub use traits::sample::UniformSphereSample;
pub use traits::scalar_op::{ScalarAdd, ScalarSub}; pub use traits::scalar_op::{ScalarAdd, ScalarSub};
pub use traits::cross::{Cross, CrossMatrix}; pub use traits::cross::{Cross, CrossMatrix};
pub use traits::outer::Outer; pub use traits::outer::Outer;
pub use traits::dot::Dot;
pub use traits::norm::Norm;
// structs // structs
pub use dvec::DVec; pub use dvec::DVec;

View File

@ -9,7 +9,8 @@ use traits::dim::Dim;
use traits::translation::Translation; use traits::translation::Translation;
use traits::scalar_op::{ScalarAdd, ScalarSub}; use traits::scalar_op::{ScalarAdd, ScalarSub};
use traits::indexable::Indexable; use traits::indexable::Indexable;
use traits::vector::{Vec, AlgebraicVec}; use traits::dot::Dot;
use traits::norm::Norm;
use vec; use vec;
impl<N> vec::Vec0<N> { impl<N> vec::Vec0<N> {
@ -95,7 +96,7 @@ impl<N: Neg<N>> Neg<vec::Vec0<N>> for vec::Vec0<N> {
} }
} }
impl<N: Num + Clone> Vec<N> for vec::Vec0<N> { impl<N: Num + Clone> Dot<N> for vec::Vec0<N> {
#[inline] #[inline]
fn dot(&self, _: &vec::Vec0<N>) -> N { fn dot(&self, _: &vec::Vec0<N>) -> N {
Zero::zero() Zero::zero()
@ -167,7 +168,7 @@ impl<N: Clone + Add<N, N> + Neg<N>> Translation<vec::Vec0<N>> for vec::Vec0<N> {
} }
} }
impl<N: Clone + Num + Algebraic> AlgebraicVec<N> for vec::Vec0<N> { impl<N: Clone + Num + Algebraic> Norm<N> for vec::Vec0<N> {
#[inline] #[inline]
fn sqnorm(&self) -> N { fn sqnorm(&self) -> N {
self.dot(self) self.dot(self)

View File

@ -277,7 +277,7 @@ macro_rules! neg_impl(
macro_rules! dot_impl( macro_rules! dot_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => ( ($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Num + Clone> Vec<N> for $t<N> { impl<N: Num + Clone> Dot<N> for $t<N> {
#[inline] #[inline]
fn dot(&self, other: &$t<N>) -> N { fn dot(&self, other: &$t<N>) -> N {
self.$comp0 * other.$comp0 $(+ self.$compN * other.$compN )* self.$comp0 * other.$comp0 $(+ self.$compN * other.$compN )*
@ -380,7 +380,7 @@ macro_rules! translation_impl(
macro_rules! norm_impl( macro_rules! norm_impl(
($t: ident) => ( ($t: ident) => (
impl<N: Clone + Num + Algebraic> AlgebraicVec<N> for $t<N> { impl<N: Clone + Num + Algebraic> Norm<N> for $t<N> {
#[inline] #[inline]
fn sqnorm(&self) -> N { fn sqnorm(&self) -> N {
self.dot(self) self.dot(self)

View File

@ -1,5 +1,5 @@
use std::num::{Zero, One}; 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}; use mat::{Mat3, Row};
impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec1<N>> for Vec2<N> { impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec1<N>> for Vec2<N> {
@ -84,8 +84,7 @@ impl<N: Clone + One + Zero + Neg<N>> Basis for Vec2<N> {
} }
} }
impl<N: Clone + Ord + Algebraic + Signed> impl<N: Clone + Ord + Algebraic + Signed> Basis for Vec3<N> {
Basis for Vec3<N> {
#[inline(always)] #[inline(always)]
fn canonical_basis(f: &fn(Vec3<N>) -> bool) { fn canonical_basis(f: &fn(Vec3<N>) -> bool) {
if !f(Vec3::new(One::one(), Zero::zero(), Zero::zero())) { return }; if !f(Vec3::new(One::one(), Zero::zero(), Zero::zero())) { return };