
# Objective Closes #14474 Previously, the `libm` feature of bevy_math would just pass the same feature flag down to glam. However, bevy_math itself had many uses of floating-point arithmetic with unspecified precision. For example, `f32::sin_cos` and `f32::powi` have unspecified precision, which means that the exact details of their output are not guaranteed to be stable across different systems and/or versions of Rust. This means that users of bevy_math could observe slightly different behavior on different systems if these methods were used. The goal of this PR is to make it so that the `libm` feature flag actually guarantees some degree of determinacy within bevy_math itself by switching to the libm versions of these functions when the `libm` feature is enabled. ## Solution bevy_math now has an internal module `bevy_math::ops`, which re-exports either the standard versions of the operations or the libm versions depending on whether the `libm` feature is enabled. For example, `ops::sin` compiles to `f32::sin` without the `libm` feature and to `libm::sinf` with it. This approach has a small shortfall, which is that `f32::powi` (integer powers of floating point numbers) does not have an equivalent in `libm`. On the other hand, this method is only used for squaring and cubing numbers in bevy_math. Accordingly, this deficit is covered by the introduction of a trait `ops::FloatPow`: ```rust pub(crate) trait FloatPow { fn squared(self) -> Self; fn cubed(self) -> Self; } ``` Next, each current usage of the unspecified-precision methods has been replaced by its equivalent in `ops`, so that when `libm` is enabled, the libm version is used instead. The exception, of course, is that `.powi(2)`/`.powi(3)` have been replaced with `.squared()`/`.cubed()`. Finally, the usage of the plain `f32` methods with unspecified precision is now linted out of bevy_math (and hence disallowed in CI). For example, using `f32::sin` within bevy_math produces a warning that tells the user to use the `ops::sin` version instead. ## Testing Ran existing tests. It would be nice to check some benchmarks on NURBS things once #14677 merges. I'm happy to wait until then if the rest of this PR is fine. --- ## Discussion In the future, it might make sense to actually expose `bevy_math::ops` as public if any downstream Bevy crates want to provide similar determinacy guarantees. For now, it's all just `pub(crate)`. This PR also only covers `f32`. If we find ourselves using `f64` internally in parts of bevy_math for better robustness, we could extend the module and lints to cover the `f64` versions easily enough. I don't know how feasible it is, but it would also be nice if we could standardize the bevy_math tests with the `libm` feature in CI, since their success is currently platform-dependent (e.g. 8 of them fail on my machine when run locally). --------- Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
66 lines
1.8 KiB
Rust
66 lines
1.8 KiB
Rust
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
|
#![forbid(unsafe_code)]
|
|
#![doc(
|
|
html_logo_url = "https://bevyengine.org/assets/icon.png",
|
|
html_favicon_url = "https://bevyengine.org/assets/icon.png"
|
|
)]
|
|
|
|
//! Provides math types and functionality for the Bevy game engine.
|
|
//!
|
|
//! The commonly used types are vectors like [`Vec2`] and [`Vec3`],
|
|
//! matrices like [`Mat2`], [`Mat3`] and [`Mat4`] and orientation representations
|
|
//! like [`Quat`].
|
|
|
|
mod affine3;
|
|
mod aspect_ratio;
|
|
pub mod bounding;
|
|
pub mod common_traits;
|
|
mod compass;
|
|
pub mod cubic_splines;
|
|
pub mod curve;
|
|
mod direction;
|
|
mod float_ord;
|
|
mod isometry;
|
|
mod ops;
|
|
pub mod primitives;
|
|
mod ray;
|
|
mod rects;
|
|
mod rotation2d;
|
|
#[cfg(feature = "rand")]
|
|
pub mod sampling;
|
|
pub use compass::{CompassOctant, CompassQuadrant};
|
|
|
|
pub use affine3::*;
|
|
pub use aspect_ratio::AspectRatio;
|
|
pub use common_traits::*;
|
|
pub use direction::*;
|
|
pub use float_ord::*;
|
|
pub use isometry::{Isometry2d, Isometry3d};
|
|
pub use ray::{Ray2d, Ray3d};
|
|
pub use rects::*;
|
|
pub use rotation2d::Rot2;
|
|
#[cfg(feature = "rand")]
|
|
pub use sampling::{FromRng, ShapeSample};
|
|
|
|
/// The `bevy_math` prelude.
|
|
pub mod prelude {
|
|
#[doc(hidden)]
|
|
#[cfg(feature = "rand")]
|
|
pub use crate::sampling::{FromRng, ShapeSample};
|
|
#[doc(hidden)]
|
|
pub use crate::{
|
|
cubic_splines::{
|
|
CubicBSpline, CubicBezier, CubicCardinalSpline, CubicCurve, CubicGenerator,
|
|
CubicHermite, CubicNurbs, CubicNurbsError, CubicSegment, CyclicCubicGenerator,
|
|
RationalCurve, RationalGenerator, RationalSegment,
|
|
},
|
|
direction::{Dir2, Dir3, Dir3A},
|
|
primitives::*,
|
|
BVec2, BVec3, BVec4, EulerRot, FloatExt, IRect, IVec2, IVec3, IVec4, Mat2, Mat3, Mat4,
|
|
Quat, Ray2d, Ray3d, Rect, Rot2, StableInterpolate, URect, UVec2, UVec3, UVec4, Vec2,
|
|
Vec2Swizzles, Vec3, Vec3Swizzles, Vec4, Vec4Swizzles,
|
|
};
|
|
}
|
|
|
|
pub use glam::*;
|