Skip to content

Commit

Permalink
Implement approx traits for direction types (#11650)
Browse files Browse the repository at this point in the history
# 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`).
  • Loading branch information
Jondolf authored Feb 1, 2024
1 parent e618426 commit d30fdda
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 1 deletion.
3 changes: 2 additions & 1 deletion crates/bevy_math/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ 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"

[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
Expand Down
32 changes: 32 additions & 0 deletions crates/bevy_math/src/primitives/dim2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))]
Expand Down
32 changes: 32 additions & 0 deletions crates/bevy_math/src/primitives/dim3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))]
Expand Down

0 comments on commit d30fdda

Please sign in to comment.