//! This module contains abstract mathematical traits shared by types used in `bevy_math`.12use crate::{ops, DVec2, DVec3, DVec4, Dir2, Dir3, Dir3A, Quat, Rot2, Vec2, Vec3, Vec3A, Vec4};3use core::{4fmt::Debug,5ops::{Add, Div, Mul, Neg, Sub},6};7use variadics_please::all_tuples_enumerated;89/// A type that supports the mathematical operations of a real vector space, irrespective of dimension.10/// In particular, this means that the implementing type supports:11/// - Scalar multiplication and division on the right by elements of `Self::Scalar`12/// - Negation13/// - Addition and subtraction14/// - Zero15///16/// Within the limitations of floating point arithmetic, all the following are required to hold:17/// - (Associativity of addition) For all `u, v, w: Self`, `(u + v) + w == u + (v + w)`.18/// - (Commutativity of addition) For all `u, v: Self`, `u + v == v + u`.19/// - (Additive identity) For all `v: Self`, `v + Self::ZERO == v`.20/// - (Additive inverse) For all `v: Self`, `v - v == v + (-v) == Self::ZERO`.21/// - (Compatibility of multiplication) For all `a, b: Self::Scalar`, `v: Self`, `v * (a * b) == (v * a) * b`.22/// - (Multiplicative identity) For all `v: Self`, `v * 1.0 == v`.23/// - (Distributivity for vector addition) For all `a: Self::Scalar`, `u, v: Self`, `(u + v) * a == u * a + v * a`.24/// - (Distributivity for scalar addition) For all `a, b: Self::Scalar`, `v: Self`, `v * (a + b) == v * a + v * b`.25///26/// Note that, because implementing types use floating point arithmetic, they are not required to actually27/// implement `PartialEq` or `Eq`.28pub trait VectorSpace:29Mul<Self::Scalar, Output = Self>30+ Div<Self::Scalar, Output = Self>31+ Add<Self, Output = Self>32+ Sub<Self, Output = Self>33+ Neg<Output = Self>34+ Default35+ Debug36+ Clone37+ Copy38{39/// The scalar type of this vector space.40type Scalar: ScalarField;4142/// The zero vector, which is the identity of addition for the vector space type.43const ZERO: Self;4445/// Perform vector space linear interpolation between this element and another, based46/// on the parameter `t`. When `t` is `0`, `self` is recovered. When `t` is `1`, `rhs`47/// is recovered.48///49/// Note that the value of `t` is not clamped by this function, so extrapolating outside50/// of the interval `[0,1]` is allowed.51#[inline]52fn lerp(self, rhs: Self, t: Self::Scalar) -> Self {53self * (Self::Scalar::ONE - t) + rhs * t54}55}5657impl VectorSpace for Vec4 {58type Scalar = f32;59const ZERO: Self = Vec4::ZERO;60}6162impl VectorSpace for Vec3 {63type Scalar = f32;64const ZERO: Self = Vec3::ZERO;65}6667impl VectorSpace for Vec3A {68type Scalar = f32;69const ZERO: Self = Vec3A::ZERO;70}7172impl VectorSpace for Vec2 {73type Scalar = f32;74const ZERO: Self = Vec2::ZERO;75}7677impl VectorSpace for DVec4 {78type Scalar = f64;79const ZERO: Self = DVec4::ZERO;80}8182impl VectorSpace for DVec3 {83type Scalar = f64;84const ZERO: Self = DVec3::ZERO;85}8687impl VectorSpace for DVec2 {88type Scalar = f64;89const ZERO: Self = DVec2::ZERO;90}9192// Every scalar field is a 1-dimensional vector space over itself.93impl<T: ScalarField> VectorSpace for T {94type Scalar = Self;95const ZERO: Self = Self::ZERO;96}9798/// A type that supports the operations of a scalar field. An implementation should support:99/// - Addition and subtraction100/// - Multiplication and division101/// - Negation102/// - Zero (additive identity)103/// - One (multiplicative identity)104///105/// Within the limitations of floating point arithmetic, all the following are required to hold:106/// - (Associativity of addition) For all `u, v, w: Self`, `(u + v) + w == u + (v + w)`.107/// - (Commutativity of addition) For all `u, v: Self`, `u + v == v + u`.108/// - (Additive identity) For all `v: Self`, `v + Self::ZERO == v`.109/// - (Additive inverse) For all `v: Self`, `v - v == v + (-v) == Self::ZERO`.110/// - (Associativity of multiplication) For all `u, v, w: Self`, `(u * v) * w == u * (v * w)`.111/// - (Commutativity of multiplication) For all `u, v: Self`, `u * v == v * u`.112/// - (Multiplicative identity) For all `v: Self`, `v * Self::ONE == v`.113/// - (Multiplicative inverse) For all `v: Self`, `v / v == v * v.inverse() == Self::ONE`.114/// - (Distributivity over addition) For all `a, b: Self`, `u, v: Self`, `(u + v) * a == u * a + v * a`.115pub trait ScalarField:116Mul<Self, Output = Self>117+ Div<Self, Output = Self>118+ Add<Self, Output = Self>119+ Sub<Self, Output = Self>120+ Neg<Output = Self>121+ Default122+ Debug123+ Clone124+ Copy125{126/// The additive identity.127const ZERO: Self;128/// The multiplicative identity.129const ONE: Self;130131/// The multiplicative inverse of this element. This is equivalent to `1.0 / self`.132fn recip(self) -> Self {133Self::ONE / self134}135}136137impl ScalarField for f32 {138const ZERO: Self = 0.0;139const ONE: Self = 1.0;140}141142impl ScalarField for f64 {143const ZERO: Self = 0.0;144const ONE: Self = 1.0;145}146147/// A type consisting of formal sums of elements from `V` and `W`. That is,148/// each value `Sum(v, w)` is thought of as `v + w`, with no available149/// simplification. In particular, if `V` and `W` are [vector spaces], then150/// `Sum<V, W>` is a vector space whose dimension is the sum of those of `V`151/// and `W`, and the field accessors `.0` and `.1` are vector space projections.152///153/// [vector spaces]: VectorSpace154#[derive(Debug, Clone, Copy)]155#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]156#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]157pub struct Sum<V, W>(pub V, pub W);158159impl<F: ScalarField, V, W> Mul<F> for Sum<V, W>160where161V: VectorSpace<Scalar = F>,162W: VectorSpace<Scalar = F>,163{164type Output = Self;165fn mul(self, rhs: F) -> Self::Output {166Sum(self.0 * rhs, self.1 * rhs)167}168}169170impl<F: ScalarField, V, W> Div<F> for Sum<V, W>171where172V: VectorSpace<Scalar = F>,173W: VectorSpace<Scalar = F>,174{175type Output = Self;176fn div(self, rhs: F) -> Self::Output {177Sum(self.0 / rhs, self.1 / rhs)178}179}180181impl<V, W> Add<Self> for Sum<V, W>182where183V: VectorSpace,184W: VectorSpace,185{186type Output = Self;187fn add(self, other: Self) -> Self::Output {188Sum(self.0 + other.0, self.1 + other.1)189}190}191192impl<V, W> Sub<Self> for Sum<V, W>193where194V: VectorSpace,195W: VectorSpace,196{197type Output = Self;198fn sub(self, other: Self) -> Self::Output {199Sum(self.0 - other.0, self.1 - other.1)200}201}202203impl<V, W> Neg for Sum<V, W>204where205V: VectorSpace,206W: VectorSpace,207{208type Output = Self;209fn neg(self) -> Self::Output {210Sum(-self.0, -self.1)211}212}213214impl<V, W> Default for Sum<V, W>215where216V: VectorSpace,217W: VectorSpace,218{219fn default() -> Self {220Sum(V::default(), W::default())221}222}223224impl<F: ScalarField, V, W> VectorSpace for Sum<V, W>225where226V: VectorSpace<Scalar = F>,227W: VectorSpace<Scalar = F>,228{229type Scalar = F;230const ZERO: Self = Sum(V::ZERO, W::ZERO);231}232233/// A type that supports the operations of a normed vector space; i.e. a norm operation in addition234/// to those of [`VectorSpace`]. Specifically, the implementor must guarantee that the following235/// relationships hold, within the limitations of floating point arithmetic:236/// - (Nonnegativity) For all `v: Self`, `v.norm() >= 0.0`.237/// - (Positive definiteness) For all `v: Self`, `v.norm() == 0.0` implies `v == Self::ZERO`.238/// - (Absolute homogeneity) For all `c: Self::Scalar`, `v: Self`, `(v * c).norm() == v.norm() * c.abs()`.239/// - (Triangle inequality) For all `v, w: Self`, `(v + w).norm() <= v.norm() + w.norm()`.240///241/// Note that, because implementing types use floating point arithmetic, they are not required to actually242/// implement `PartialEq` or `Eq`.243pub trait NormedVectorSpace: VectorSpace {244/// The size of this element. The return value should always be nonnegative.245fn norm(self) -> Self::Scalar;246247/// The squared norm of this element. Computing this is often faster than computing248/// [`NormedVectorSpace::norm`].249#[inline]250fn norm_squared(self) -> Self::Scalar {251self.norm() * self.norm()252}253254/// The distance between this element and another, as determined by the norm.255#[inline]256fn distance(self, rhs: Self) -> Self::Scalar {257(rhs - self).norm()258}259260/// The squared distance between this element and another, as determined by the norm. Note that261/// this is often faster to compute in practice than [`NormedVectorSpace::distance`].262#[inline]263fn distance_squared(self, rhs: Self) -> Self::Scalar {264(rhs - self).norm_squared()265}266}267268impl NormedVectorSpace for Vec4 {269#[inline]270fn norm(self) -> f32 {271self.length()272}273274#[inline]275fn norm_squared(self) -> f32 {276self.length_squared()277}278}279280impl NormedVectorSpace for Vec3 {281#[inline]282fn norm(self) -> f32 {283self.length()284}285286#[inline]287fn norm_squared(self) -> f32 {288self.length_squared()289}290}291292impl NormedVectorSpace for Vec3A {293#[inline]294fn norm(self) -> f32 {295self.length()296}297298#[inline]299fn norm_squared(self) -> f32 {300self.length_squared()301}302}303304impl NormedVectorSpace for Vec2 {305#[inline]306fn norm(self) -> f32 {307self.length()308}309310#[inline]311fn norm_squared(self) -> f32 {312self.length_squared()313}314}315316impl NormedVectorSpace for f32 {317#[inline]318fn norm(self) -> f32 {319ops::abs(self)320}321}322323impl NormedVectorSpace for DVec4 {324#[inline]325fn norm(self) -> f64 {326self.length()327}328329#[inline]330fn norm_squared(self) -> f64 {331self.length_squared()332}333}334335impl NormedVectorSpace for DVec3 {336#[inline]337fn norm(self) -> f64 {338self.length()339}340341#[inline]342fn norm_squared(self) -> f64 {343self.length_squared()344}345}346347impl NormedVectorSpace for DVec2 {348#[inline]349fn norm(self) -> f64 {350self.length()351}352353#[inline]354fn norm_squared(self) -> f64 {355self.length_squared()356}357}358359impl NormedVectorSpace for f64 {360#[inline]361#[cfg(feature = "std")]362fn norm(self) -> f64 {363f64::abs(self)364}365366#[inline]367#[cfg(all(any(feature = "libm", feature = "nostd-libm"), not(feature = "std")))]368fn norm(self) -> f64 {369libm::fabs(self)370}371}372373/// A type with a natural interpolation that provides strong subdivision guarantees.374///375/// Although the only required method is `interpolate_stable`, many things are expected of it:376///377/// 1. The notion of interpolation should follow naturally from the semantics of the type, so378/// that inferring the interpolation mode from the type alone is sensible.379///380/// 2. The interpolation recovers something equivalent to the starting value at `t = 0.0`381/// and likewise with the ending value at `t = 1.0`. They do not have to be data-identical, but382/// they should be semantically identical. For example, [`Quat::slerp`] doesn't always yield its383/// second rotation input exactly at `t = 1.0`, but it always returns an equivalent rotation.384///385/// 3. Importantly, the interpolation must be *subdivision-stable*: for any interpolation curve386/// between two (unnamed) values and any parameter-value pairs `(t0, p)` and `(t1, q)`, the387/// interpolation curve between `p` and `q` must be the *linear* reparameterization of the original388/// interpolation curve restricted to the interval `[t0, t1]`.389///390/// The last of these conditions is very strong and indicates something like constant speed. It391/// is called "subdivision stability" because it guarantees that breaking up the interpolation392/// into segments and joining them back together has no effect.393///394/// Here is a diagram depicting it:395/// ```text396/// top curve = u.interpolate_stable(v, t)397///398/// t0 => p t1 => q399/// |-------------|---------|-------------|400/// 0 => u / \ 1 => v401/// / \402/// / \403/// / linear \404/// / reparameterization \405/// / t = t0 * (1 - s) + t1 * s \406/// / \407/// |-------------------------------------|408/// 0 => p 1 => q409///410/// bottom curve = p.interpolate_stable(q, s)411/// ```412///413/// Note that some common forms of interpolation do not satisfy this criterion. For example,414/// [`Quat::lerp`] and [`Rot2::nlerp`] are not subdivision-stable.415///416/// Furthermore, this is not to be used as a general trait for abstract interpolation.417/// Consumers rely on the strong guarantees in order for behavior based on this trait to be418/// well-behaved.419///420/// [`Quat::slerp`]: crate::Quat::slerp421/// [`Quat::lerp`]: crate::Quat::lerp422/// [`Rot2::nlerp`]: crate::Rot2::nlerp423pub trait StableInterpolate: Clone {424/// Interpolate between this value and the `other` given value using the parameter `t`. At425/// `t = 0.0`, a value equivalent to `self` is recovered, while `t = 1.0` recovers a value426/// equivalent to `other`, with intermediate values interpolating between the two.427/// See the [trait-level documentation] for details.428///429/// [trait-level documentation]: StableInterpolate430fn interpolate_stable(&self, other: &Self, t: f32) -> Self;431432/// A version of [`interpolate_stable`] that assigns the result to `self` for convenience.433///434/// [`interpolate_stable`]: StableInterpolate::interpolate_stable435fn interpolate_stable_assign(&mut self, other: &Self, t: f32) {436*self = self.interpolate_stable(other, t);437}438439/// Smoothly nudge this value towards the `target` at a given decay rate. The `decay_rate`440/// parameter controls how fast the distance between `self` and `target` decays relative to441/// the units of `delta`; the intended usage is for `decay_rate` to generally remain fixed,442/// while `delta` is something like `delta_time` from an updating system. This produces a443/// smooth following of the target that is independent of framerate.444///445/// More specifically, when this is called repeatedly, the result is that the distance between446/// `self` and a fixed `target` attenuates exponentially, with the rate of this exponential447/// decay given by `decay_rate`.448///449/// For example, at `decay_rate = 0.0`, this has no effect.450/// At `decay_rate = f32::INFINITY`, `self` immediately snaps to `target`.451/// In general, higher rates mean that `self` moves more quickly towards `target`.452///453/// # Example454/// ```455/// # use bevy_math::{Vec3, StableInterpolate};456/// # let delta_time: f32 = 1.0 / 60.0;457/// let mut object_position: Vec3 = Vec3::ZERO;458/// let target_position: Vec3 = Vec3::new(2.0, 3.0, 5.0);459/// // Decay rate of ln(10) => after 1 second, remaining distance is 1/10th460/// let decay_rate = f32::ln(10.0);461/// // Calling this repeatedly will move `object_position` towards `target_position`:462/// object_position.smooth_nudge(&target_position, decay_rate, delta_time);463/// ```464fn smooth_nudge(&mut self, target: &Self, decay_rate: f32, delta: f32) {465self.interpolate_stable_assign(target, 1.0 - ops::exp(-decay_rate * delta));466}467}468469// Conservatively, we presently only apply this for normed vector spaces, where the notion470// of being constant-speed is literally true. The technical axioms are satisfied for any471// VectorSpace type, but the "natural from the semantics" part is less clear in general.472impl<V> StableInterpolate for V473where474V: NormedVectorSpace<Scalar = f32>,475{476#[inline]477fn interpolate_stable(&self, other: &Self, t: f32) -> Self {478self.lerp(*other, t)479}480}481482impl StableInterpolate for Rot2 {483#[inline]484fn interpolate_stable(&self, other: &Self, t: f32) -> Self {485self.slerp(*other, t)486}487}488489impl StableInterpolate for Quat {490#[inline]491fn interpolate_stable(&self, other: &Self, t: f32) -> Self {492self.slerp(*other, t)493}494}495496impl StableInterpolate for Dir2 {497#[inline]498fn interpolate_stable(&self, other: &Self, t: f32) -> Self {499self.slerp(*other, t)500}501}502503impl StableInterpolate for Dir3 {504#[inline]505fn interpolate_stable(&self, other: &Self, t: f32) -> Self {506self.slerp(*other, t)507}508}509510impl StableInterpolate for Dir3A {511#[inline]512fn interpolate_stable(&self, other: &Self, t: f32) -> Self {513self.slerp(*other, t)514}515}516517macro_rules! impl_stable_interpolate_tuple {518($(#[$meta:meta])* $(($n:tt, $T:ident)),*) => {519$(#[$meta])*520impl<$($T: StableInterpolate),*> StableInterpolate for ($($T,)*) {521fn interpolate_stable(&self, other: &Self, t: f32) -> Self {522(523$(524<$T as StableInterpolate>::interpolate_stable(&self.$n, &other.$n, t),525)*526)527}528}529};530}531532all_tuples_enumerated!(533#[doc(fake_variadic)]534impl_stable_interpolate_tuple,5351,53611,537T538);539540/// A type that has tangents.541pub trait HasTangent {542/// The tangent type.543type Tangent: VectorSpace;544}545546/// A value with its derivative.547#[derive(Debug, Clone, Copy)]548#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]549#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]550pub struct WithDerivative<T>551where552T: HasTangent,553{554/// The underlying value.555pub value: T,556557/// The derivative at `value`.558pub derivative: T::Tangent,559}560561/// A value together with its first and second derivatives.562#[derive(Debug, Clone, Copy)]563#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]564#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]565pub struct WithTwoDerivatives<T>566where567T: HasTangent,568{569/// The underlying value.570pub value: T,571572/// The derivative at `value`.573pub derivative: T::Tangent,574575/// The second derivative at `value`.576pub second_derivative: <T::Tangent as HasTangent>::Tangent,577}578579impl<V: VectorSpace> HasTangent for V {580type Tangent = V;581}582583impl<F, U, V, M, N> HasTangent for (M, N)584where585F: ScalarField,586U: VectorSpace<Scalar = F>,587V: VectorSpace<Scalar = F>,588M: HasTangent<Tangent = U>,589N: HasTangent<Tangent = V>,590{591type Tangent = Sum<M::Tangent, N::Tangent>;592}593594595