From 8d0e3f4eae4e5b15a073470dff68aac874d7196d Mon Sep 17 00:00:00 2001 From: Nathan Stoddard Date: Tue, 2 Jun 2020 20:38:50 -0700 Subject: [PATCH] Remove Float bound from MetricSpace and InnerSpace; move Float bound to individual methods This makes it possible to call methods like `dot` on integers. --- src/structure.rs | 41 ++++++++++++++++++++--------------------- src/vector.rs | 16 +++++++++++----- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/structure.rs b/src/structure.rs index a563964..22cd2b0 100644 --- a/src/structure.rs +++ b/src/structure.rs @@ -195,7 +195,7 @@ where /// Examples are vectors, points, and quaternions. pub trait MetricSpace: Sized { /// The metric to be returned by the `distance` function. - type Metric: Float; + type Metric; /// Returns the squared distance. /// @@ -205,7 +205,7 @@ pub trait MetricSpace: Sized { fn distance2(self, other: Self) -> Self::Metric; /// The distance between two values. - fn distance(self, other: Self) -> Self::Metric { + fn distance(self, other: Self) -> Self::Metric where Self::Metric: Float { Float::sqrt(Self::distance2(self, other)) } } @@ -219,7 +219,6 @@ pub trait MetricSpace: Sized { /// Examples include vectors and quaternions. pub trait InnerSpace: VectorSpace where - Self::Scalar: Float, // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 Self: MetricSpace::Scalar> { @@ -242,29 +241,11 @@ where Self::dot(self, self) } - /// The distance from the tail to the tip of the vector. - #[inline] - fn magnitude(self) -> Self::Scalar { - Float::sqrt(self.magnitude2()) - } - /// Returns the angle between two vectors in radians. fn angle(self, other: Self) -> Rad where Self::Scalar: BaseFloat { Rad::acos(Self::dot(self, other) / (self.magnitude() * other.magnitude())) } - /// Returns a vector with the same direction, but with a magnitude of `1`. - #[inline] - fn normalize(self) -> Self { - self.normalize_to(Self::Scalar::one()) - } - - /// Returns a vector with the same direction and a given magnitude. - #[inline] - fn normalize_to(self, magnitude: Self::Scalar) -> Self { - self * (magnitude / self.magnitude()) - } - /// Returns the /// [vector projection](https://en.wikipedia.org/wiki/Vector_projection) /// of the current inner space projected onto the supplied argument. @@ -272,6 +253,24 @@ where fn project_on(self, other: Self) -> Self { other * (self.dot(other) / other.magnitude2()) } + + /// The distance from the tail to the tip of the vector. + #[inline] + fn magnitude(self) -> Self::Scalar where Self::Scalar: Float { + Float::sqrt(self.magnitude2()) + } + + /// Returns a vector with the same direction, but with a magnitude of `1`. + #[inline] + fn normalize(self) -> Self where Self::Scalar: Float { + self.normalize_to(Self::Scalar::one()) + } + + /// Returns a vector with the same direction and a given magnitude. + #[inline] + fn normalize_to(self, magnitude: Self::Scalar) -> Self where Self::Scalar: Float { + self * (magnitude / self.magnitude()) + } } /// Points in a [Euclidean space](https://en.wikipedia.org/wiki/Euclidean_space) diff --git a/src/vector.rs b/src/vector.rs index 40bf6c2..f22c59b 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -139,7 +139,7 @@ macro_rules! impl_vector { } } - impl MetricSpace for $VectorN { + impl MetricSpace for $VectorN { type Metric = S; #[inline] @@ -525,14 +525,14 @@ where V::dot(a, b) } -impl InnerSpace for Vector1 { +impl InnerSpace for Vector1 { #[inline] fn dot(self, other: Vector1) -> S { Vector1::mul_element_wise(self, other).sum() } } -impl InnerSpace for Vector2 { +impl InnerSpace for Vector2 { #[inline] fn dot(self, other: Vector2) -> S { Vector2::mul_element_wise(self, other).sum() @@ -544,7 +544,7 @@ impl InnerSpace for Vector2 { } } -impl InnerSpace for Vector3 { +impl InnerSpace for Vector3 { #[inline] fn dot(self, other: Vector3) -> S { Vector3::mul_element_wise(self, other).sum() @@ -556,7 +556,7 @@ impl InnerSpace for Vector3 { } } -impl InnerSpace for Vector4 { +impl InnerSpace for Vector4 { #[inline] fn dot(self, other: Vector4) -> S { Vector4::mul_element_wise(self, other).sum() @@ -966,5 +966,11 @@ mod tests { Vector4::new(-2, 1, 0, 1).zip(Vector4::new(-1, -1, -1, -1), |a, b| a < b) ); } + + #[test] + fn test_dot() { + assert_eq!(vec3(1.0, 2.0, 3.0).dot(vec3(4.0, 5.0, 6.0)), 32.0); + assert_eq!(vec3(1, 2, 3).dot(vec3(4, 5, 6)), 32); + } } }