Implement approx traits for direction types (#11650)

# Objective

`approx` has traits like
[`AbsDiffEq`](https://docs.rs/approx/latest/approx/trait.AbsDiffEq.html),
[`RelativeEq`](https://docs.rs/approx/latest/approx/trait.RelativeEq.html),
and [`UlpsEq`](https://docs.rs/approx/latest/approx/trait.UlpsEq.html).
Glam implements them for its math types when the `approx` feature is
enabled. Bevy's `Direction2d` and `Direction3d` should implement these
too.

## Solution

Implement the traits. See [how Glam implements them for its own math
types](https://github.com/bitshifter/glam-rs/blob/main/src/features/impl_approx.rs).
For the epsilon values, I use the same as `Vec2`/`Vec3` (just
`f32::EPSILON`).
This commit is contained in:
Joona Aalto 2024-02-01 21:22:28 +02:00 committed by GitHub
parent e618426faa
commit d30fdda2c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 66 additions and 1 deletions

View file

@ -11,6 +11,7 @@ keywords = ["bevy"]
[dependencies]
glam = { version = "0.25", features = ["bytemuck"] }
serde = { version = "1", features = ["derive"], optional = true }
approx = { version = "0.5", optional = true }
[dev-dependencies]
approx = "0.5"
@ -18,7 +19,7 @@ approx = "0.5"
[features]
serialize = ["dep:serde", "glam/serde"]
# Enable approx for glam types to approximate floating point equality comparisons and assertions
approx = ["glam/approx"]
approx = ["dep:approx", "glam/approx"]
# Enable interoperation of glam types with mint-compatible libraries
mint = ["glam/mint"]
# Enable libm mathematical functions for glam types to ensure consistent outputs

View file

@ -81,6 +81,38 @@ impl std::ops::Neg for Direction2d {
}
}
#[cfg(feature = "approx")]
impl approx::AbsDiffEq for Direction2d {
type Epsilon = f32;
fn default_epsilon() -> f32 {
f32::EPSILON
}
fn abs_diff_eq(&self, other: &Self, epsilon: f32) -> bool {
self.as_ref().abs_diff_eq(other.as_ref(), epsilon)
}
}
#[cfg(feature = "approx")]
impl approx::RelativeEq for Direction2d {
fn default_max_relative() -> f32 {
f32::EPSILON
}
fn relative_eq(&self, other: &Self, epsilon: f32, max_relative: f32) -> bool {
self.as_ref()
.relative_eq(other.as_ref(), epsilon, max_relative)
}
}
#[cfg(feature = "approx")]
impl approx::UlpsEq for Direction2d {
fn default_max_ulps() -> u32 {
4
}
fn ulps_eq(&self, other: &Self, epsilon: f32, max_ulps: u32) -> bool {
self.as_ref().ulps_eq(other.as_ref(), epsilon, max_ulps)
}
}
/// A circle primitive
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]

View file

@ -85,6 +85,38 @@ impl std::ops::Neg for Direction3d {
}
}
#[cfg(feature = "approx")]
impl approx::AbsDiffEq for Direction3d {
type Epsilon = f32;
fn default_epsilon() -> f32 {
f32::EPSILON
}
fn abs_diff_eq(&self, other: &Self, epsilon: f32) -> bool {
self.as_ref().abs_diff_eq(other.as_ref(), epsilon)
}
}
#[cfg(feature = "approx")]
impl approx::RelativeEq for Direction3d {
fn default_max_relative() -> f32 {
f32::EPSILON
}
fn relative_eq(&self, other: &Self, epsilon: f32, max_relative: f32) -> bool {
self.as_ref()
.relative_eq(other.as_ref(), epsilon, max_relative)
}
}
#[cfg(feature = "approx")]
impl approx::UlpsEq for Direction3d {
fn default_max_ulps() -> u32 {
4
}
fn ulps_eq(&self, other: &Self, epsilon: f32, max_ulps: u32) -> bool {
self.as_ref().ulps_eq(other.as_ref(), epsilon, max_ulps)
}
}
/// A sphere primitive
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]