bevy_math/common_traits.rs
1use glam::{Vec2, Vec3, Vec3A, Vec4};
2use std::fmt::Debug;
3use std::ops::{Add, Div, Mul, Neg, Sub};
4
5/// A type that supports the mathematical operations of a real vector space, irrespective of dimension.
6/// In particular, this means that the implementing type supports:
7/// - Scalar multiplication and division on the right by elements of `f32`
8/// - Negation
9/// - Addition and subtraction
10/// - Zero
11///
12/// Within the limitations of floating point arithmetic, all the following are required to hold:
13/// - (Associativity of addition) For all `u, v, w: Self`, `(u + v) + w == u + (v + w)`.
14/// - (Commutativity of addition) For all `u, v: Self`, `u + v == v + u`.
15/// - (Additive identity) For all `v: Self`, `v + Self::ZERO == v`.
16/// - (Additive inverse) For all `v: Self`, `v - v == v + (-v) == Self::ZERO`.
17/// - (Compatibility of multiplication) For all `a, b: f32`, `v: Self`, `v * (a * b) == (v * a) * b`.
18/// - (Multiplicative identity) For all `v: Self`, `v * 1.0 == v`.
19/// - (Distributivity for vector addition) For all `a: f32`, `u, v: Self`, `(u + v) * a == u * a + v * a`.
20/// - (Distributivity for scalar addition) For all `a, b: f32`, `v: Self`, `v * (a + b) == v * a + v * b`.
21///
22/// Note that, because implementing types use floating point arithmetic, they are not required to actually
23/// implement `PartialEq` or `Eq`.
24pub trait VectorSpace:
25 Mul<f32, Output = Self>
26 + Div<f32, Output = Self>
27 + Add<Self, Output = Self>
28 + Sub<Self, Output = Self>
29 + Neg
30 + Default
31 + Debug
32 + Clone
33 + Copy
34{
35 /// The zero vector, which is the identity of addition for the vector space type.
36 const ZERO: Self;
37
38 /// Perform vector space linear interpolation between this element and another, based
39 /// on the parameter `t`. When `t` is `0`, `self` is recovered. When `t` is `1`, `rhs`
40 /// is recovered.
41 ///
42 /// Note that the value of `t` is not clamped by this function, so interpolating outside
43 /// of the interval `[0,1]` is allowed.
44 #[inline]
45 fn lerp(&self, rhs: Self, t: f32) -> Self {
46 *self * (1. - t) + rhs * t
47 }
48}
49
50impl VectorSpace for Vec4 {
51 const ZERO: Self = Vec4::ZERO;
52}
53
54impl VectorSpace for Vec3 {
55 const ZERO: Self = Vec3::ZERO;
56}
57
58impl VectorSpace for Vec3A {
59 const ZERO: Self = Vec3A::ZERO;
60}
61
62impl VectorSpace for Vec2 {
63 const ZERO: Self = Vec2::ZERO;
64}
65
66impl VectorSpace for f32 {
67 const ZERO: Self = 0.0;
68}
69
70/// A type that supports the operations of a normed vector space; i.e. a norm operation in addition
71/// to those of [`VectorSpace`]. Specifically, the implementor must guarantee that the following
72/// relationships hold, within the limitations of floating point arithmetic:
73/// - (Nonnegativity) For all `v: Self`, `v.norm() >= 0.0`.
74/// - (Positive definiteness) For all `v: Self`, `v.norm() == 0.0` implies `v == Self::ZERO`.
75/// - (Absolute homogeneity) For all `c: f32`, `v: Self`, `(v * c).norm() == v.norm() * c.abs()`.
76/// - (Triangle inequality) For all `v, w: Self`, `(v + w).norm() <= v.norm() + w.norm()`.
77///
78/// Note that, because implementing types use floating point arithmetic, they are not required to actually
79/// implement `PartialEq` or `Eq`.
80pub trait NormedVectorSpace: VectorSpace {
81 /// The size of this element. The return value should always be nonnegative.
82 fn norm(self) -> f32;
83
84 /// The squared norm of this element. Computing this is often faster than computing
85 /// [`NormedVectorSpace::norm`].
86 #[inline]
87 fn norm_squared(self) -> f32 {
88 self.norm() * self.norm()
89 }
90
91 /// The distance between this element and another, as determined by the norm.
92 #[inline]
93 fn distance(self, rhs: Self) -> f32 {
94 (rhs - self).norm()
95 }
96
97 /// The squared distance between this element and another, as determined by the norm. Note that
98 /// this is often faster to compute in practice than [`NormedVectorSpace::distance`].
99 #[inline]
100 fn distance_squared(self, rhs: Self) -> f32 {
101 (rhs - self).norm_squared()
102 }
103}
104
105impl NormedVectorSpace for Vec4 {
106 #[inline]
107 fn norm(self) -> f32 {
108 self.length()
109 }
110
111 #[inline]
112 fn norm_squared(self) -> f32 {
113 self.length_squared()
114 }
115}
116
117impl NormedVectorSpace for Vec3 {
118 #[inline]
119 fn norm(self) -> f32 {
120 self.length()
121 }
122
123 #[inline]
124 fn norm_squared(self) -> f32 {
125 self.length_squared()
126 }
127}
128
129impl NormedVectorSpace for Vec3A {
130 #[inline]
131 fn norm(self) -> f32 {
132 self.length()
133 }
134
135 #[inline]
136 fn norm_squared(self) -> f32 {
137 self.length_squared()
138 }
139}
140
141impl NormedVectorSpace for Vec2 {
142 #[inline]
143 fn norm(self) -> f32 {
144 self.length()
145 }
146
147 #[inline]
148 fn norm_squared(self) -> f32 {
149 self.length_squared()
150 }
151}
152
153impl NormedVectorSpace for f32 {
154 #[inline]
155 fn norm(self) -> f32 {
156 self.abs()
157 }
158
159 #[inline]
160 fn norm_squared(self) -> f32 {
161 self * self
162 }
163}