Move the dot method onto EuclideanVector

The Vector and EuclideanVector traits roughly line up with the concept of vector spaces and inner spaces respectively. It makes more sense to group `dot` with the other methods that depend on it.
This commit is contained in:
Brendan Zabarauskas 2016-04-04 19:45:54 +10:00
parent 84c2c0ff8a
commit 2cd6f402df
3 changed files with 37 additions and 15 deletions

View file

@ -22,7 +22,7 @@ use matrix::{Matrix2, Matrix3};
use num::BaseFloat; use num::BaseFloat;
use point::{Point, Point2, Point3}; use point::{Point, Point2, Point3};
use quaternion::Quaternion; use quaternion::Quaternion;
use vector::{Vector, Vector2, Vector3}; use vector::{EuclideanVector, Vector2, Vector3};
/// A trait for a generic rotation. A rotation is a transformation that /// A trait for a generic rotation. A rotation is a transformation that
/// creates a circular motion, and preserves at least one point in the space. /// creates a circular motion, and preserves at least one point in the space.

View file

@ -62,7 +62,8 @@
//! and [cross products](http://en.wikipedia.org/wiki/Cross_product). //! and [cross products](http://en.wikipedia.org/wiki/Cross_product).
//! //!
//! ```rust //! ```rust
//! use cgmath::{Vector, Vector2, Vector3, Vector4, dot}; //! use cgmath::{Vector, EuclideanVector};
//! use cgmath::{Vector2, Vector3, Vector4};
//! //!
//! // All vectors implement the dot product as a method: //! // All vectors implement the dot product as a method:
//! let a: Vector2<f64> = Vector2::new(3.0, 6.0); //! let a: Vector2<f64> = Vector2::new(3.0, 6.0);
@ -70,7 +71,7 @@
//! assert_eq!(a.dot(b), 0.0); //! assert_eq!(a.dot(b), 0.0);
//! //!
//! // But there is also a top-level function: //! // But there is also a top-level function:
//! assert_eq!(a.dot(b), dot(a, b)); //! assert_eq!(a.dot(b), cgmath::dot(a, b));
//! //!
//! // Cross products are defined for 3-dimensional vectors: //! // Cross products are defined for 3-dimensional vectors:
//! let e: Vector3<f64> = Vector3::unit_x(); //! let e: Vector3<f64> = Vector3::unit_x();
@ -121,14 +122,8 @@ pub trait Vector: Copy + Clone where
/// The additive identity vector. Adding this vector with another has no effect. /// The additive identity vector. Adding this vector with another has no effect.
#[inline] #[inline]
fn zero() -> Self { Self::from_value(Self::Scalar::zero()) } fn zero() -> Self { Self::from_value(Self::Scalar::zero()) }
/// Vector dot product
fn dot(self, other: Self) -> Self::Scalar;
} }
/// Dot product of two vectors.
#[inline] pub fn dot<V: Vector>(a: V, b: V) -> V::Scalar { V::dot(a, b) }
/// A 2-dimensional vector. /// A 2-dimensional vector.
/// ///
/// This type is marked as `#[repr(C, packed)]`. /// This type is marked as `#[repr(C, packed)]`.
@ -207,9 +202,10 @@ macro_rules! impl_vector {
impl<S: BaseNum> Vector for $VectorN<S> { impl<S: BaseNum> Vector for $VectorN<S> {
type Scalar = S; type Scalar = S;
#[inline] fn from_value(scalar: S) -> $VectorN<S> { $VectorN { $($field: scalar),+ } } #[inline]
fn from_value(scalar: S) -> $VectorN<S> {
#[inline] fn dot(self, other: $VectorN<S>) -> S { $VectorN::mul_element_wise(self, other).sum() } $VectorN { $($field: scalar),+ }
}
} }
impl<S: Neg<Output = S>> Neg for $VectorN<S> { impl<S: Neg<Output = S>> Neg for $VectorN<S> {
@ -468,6 +464,9 @@ pub trait EuclideanVector: Vector + Sized where
<Self as Vector>::Scalar: BaseFloat, <Self as Vector>::Scalar: BaseFloat,
Self: ApproxEq<Epsilon = <Self as Vector>::Scalar>, Self: ApproxEq<Epsilon = <Self as Vector>::Scalar>,
{ {
/// Vector dot (or inner) product.
fn dot(self, other: Self) -> Self::Scalar;
/// Returns `true` if the vector is perpendicular (at right angles) to the /// Returns `true` if the vector is perpendicular (at right angles) to the
/// other vector. /// other vector.
fn is_perpendicular(self, other: Self) -> bool { fn is_perpendicular(self, other: Self) -> bool {
@ -519,7 +518,20 @@ pub trait EuclideanVector: Vector + Sized where
} }
} }
/// Dot product of two vectors.
#[inline]
pub fn dot<V: EuclideanVector>(a: V, b: V) -> V::Scalar where
V::Scalar: BaseFloat,
{
V::dot(a, b)
}
impl<S: BaseFloat> EuclideanVector for Vector2<S> { impl<S: BaseFloat> EuclideanVector for Vector2<S> {
#[inline]
fn dot(self, other: Vector2<S>) -> S {
Vector2::mul_element_wise(self, other).sum()
}
#[inline] #[inline]
fn angle(self, other: Vector2<S>) -> Rad<S> { fn angle(self, other: Vector2<S>) -> Rad<S> {
Rad::atan2(Self::perp_dot(self, other), Self::dot(self, other)) Rad::atan2(Self::perp_dot(self, other), Self::dot(self, other))
@ -527,6 +539,11 @@ impl<S: BaseFloat> EuclideanVector for Vector2<S> {
} }
impl<S: BaseFloat> EuclideanVector for Vector3<S> { impl<S: BaseFloat> EuclideanVector for Vector3<S> {
#[inline]
fn dot(self, other: Vector3<S>) -> S {
Vector3::mul_element_wise(self, other).sum()
}
#[inline] #[inline]
fn angle(self, other: Vector3<S>) -> Rad<S> { fn angle(self, other: Vector3<S>) -> Rad<S> {
Rad::atan2(self.cross(other).magnitude(), Self::dot(self, other)) Rad::atan2(self.cross(other).magnitude(), Self::dot(self, other))
@ -534,6 +551,11 @@ impl<S: BaseFloat> EuclideanVector for Vector3<S> {
} }
impl<S: BaseFloat> EuclideanVector for Vector4<S> { impl<S: BaseFloat> EuclideanVector for Vector4<S> {
#[inline]
fn dot(self, other: Vector4<S>) -> S {
Vector4::mul_element_wise(self, other).sum()
}
#[inline] #[inline]
fn angle(self, other: Vector4<S>) -> Rad<S> { fn angle(self, other: Vector4<S>) -> Rad<S> {
Rad::acos(Self::dot(self, other) / (self.magnitude() * other.magnitude())) Rad::acos(Self::dot(self, other) / (self.magnitude() * other.magnitude()))

View file

@ -122,9 +122,9 @@ fn test_rem() {
#[test] #[test]
fn test_dot() { fn test_dot() {
assert_eq!(Vector2::new(1isize, 2isize).dot(Vector2::new(3isize, 4isize)), 11isize); assert_eq!(Vector2::new(1.0, 2.0).dot(Vector2::new(3.0, 4.0)), 11.0);
assert_eq!(Vector3::new(1isize, 2isize, 3isize).dot(Vector3::new(4isize, 5isize, 6isize)), 32isize); assert_eq!(Vector3::new(1.0, 2.0, 3.0).dot(Vector3::new(4.0, 5.0, 6.0)), 32.0);
assert_eq!(Vector4::new(1isize, 2isize, 3isize, 4isize).dot(Vector4::new(5isize, 6isize, 7isize, 8isize)), 70isize); assert_eq!(Vector4::new(1.0, 2.0, 3.0, 4.0).dot(Vector4::new(5.0, 6.0, 7.0, 8.0)), 70.0);
} }
#[test] #[test]