1use crate::VectorSpace;
2use num_traits::{One, real::Real};
3
4pub trait InnerSpace: VectorSpace {
6 fn scalar(&self, other: &Self) -> Self::Scalar;
8
9 #[inline]
14 fn magnitude2(&self) -> Self::Scalar {
15 self.scalar(self)
16 }
17
18 #[inline]
20 fn magnitude(&self) -> Self::Scalar {
21 self.magnitude2().sqrt()
22 }
23
24 #[inline]
26 fn normalize(self) -> Self {
27 let mag = self.magnitude();
28 self / mag
29 }
30
31 #[inline]
33 fn angle(&self, other: &Self) -> Self::Scalar {
34 (self.scalar(other) / (self.magnitude() * other.magnitude())).acos()
35 }
36
37 #[inline]
39 fn with_magnitude(self, magnitude: Self::Scalar) -> Self {
40 let mag = self.magnitude();
41 self * (magnitude / mag)
42 }
43
44 #[inline]
46 fn with_direction(self, dir: Self) -> Self {
47 dir * self.magnitude()
48 }
49
50 #[inline]
52 fn query_axis(&self, dir: Self) -> Self::Scalar {
53 self.scalar(&dir.normalize())
54 }
55
56 #[inline]
58 fn normalized_project(self, dir: Self) -> Self {
59 let scalar = self.scalar(&dir);
60 dir * scalar
61 }
62
63 #[inline]
65 fn project(self, dir: Self) -> Self {
66 self.normalized_project(dir.normalize())
67 }
68
69 #[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 #[inline]
79 fn reject(self, dir: Self) -> Self {
80 self.normalized_reject(dir.normalize())
81 }
82
83 #[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 #[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}