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}