vector_space/
inner.rs

1use crate::VectorSpace;
2use num_traits::{One, real::Real};
3
4/// This trait defines the scalar product and adds commom vector operations.
5pub trait InnerSpace: VectorSpace {
6    /// The scalar product.
7    fn scalar(&self, other: &Self) -> Self::Scalar;
8
9    /// The squared magnitude.
10    ///
11    /// This is more efficient than calculating the magnitude.
12    /// Useful if you need the squared magnitude anyway.
13    #[inline]
14    fn magnitude2(&self) -> Self::Scalar {
15        self.scalar(self)
16    }
17
18    /// The magnitude of a vector.
19    #[inline]
20    fn magnitude(&self) -> Self::Scalar {
21        self.magnitude2().sqrt()
22    }
23
24    /// The normalized vector.
25    #[inline]
26    fn normalize(self) -> Self {
27        let mag = self.magnitude();
28        self / mag
29    }
30
31    /// The angle between two vectors.
32    #[inline]
33    fn angle(&self, other: &Self) -> Self::Scalar {
34        (self.scalar(other) / (self.magnitude() * other.magnitude())).acos()
35    }
36
37    /// Sets the magnitude of a vector.
38    #[inline]
39    fn with_magnitude(self, magnitude: Self::Scalar) -> Self {
40        let mag = self.magnitude();
41        self * (magnitude / mag)
42    }
43
44    /// Sets the direction of a vector.
45    #[inline]
46    fn with_direction(self, dir: Self) -> Self {
47        dir * self.magnitude()
48    }
49
50    /// The value of the vector along the specified axis.
51    #[inline]
52    fn query_axis(&self, dir: Self) -> Self::Scalar {
53        self.scalar(&dir.normalize())
54    }
55
56    /// Projects a vector onto an already normalized direction vector.
57    #[inline]
58    fn normalized_project(self, dir: Self) -> Self {
59        let scalar = self.scalar(&dir);
60        dir * scalar
61    }
62
63    /// Projects a vector onto an arbitraty direction vector.
64    #[inline]
65    fn project(self, dir: Self) -> Self {
66        self.normalized_project(dir.normalize())
67    }
68
69    /// Rejects a vector from an already normalized direction vector.
70    #[inline]
71    fn normalized_reject(self, dir: Self) -> Self {
72        let scalar = self.scalar(&dir);
73        let proj = dir * scalar;
74        self - proj
75    }
76
77    /// Rejects a vector from an arbitraty direction vector.
78    #[inline]
79    fn reject(self, dir: Self) -> Self {
80        self.normalized_reject(dir.normalize())
81    }
82
83    /// Reflects a vector from an already normalized direction vector.
84    #[inline]
85    fn normalized_reflect(self, dir: Self) -> Self {
86        let scalar = self.scalar(&dir);
87        let proj = dir * scalar;
88        proj * (Self::Scalar::one() + Self::Scalar::one()) - self
89    }
90
91    /// Reflects a vector from an arbitraty direction vector.
92    #[inline]
93    fn reflect(self, dir: Self) -> Self {
94        self.normalized_reflect(dir.normalize())
95    }
96}
97
98impl InnerSpace for f32 {
99    fn scalar(&self, other: &Self) -> Self {
100        self * other
101    }
102}
103impl InnerSpace for f64 {
104    fn scalar(&self, other: &Self) -> Self {
105        self * other
106    }
107}