bevy/crates/bevy_math/clippy.toml

39 lines
3 KiB
TOML
Raw Normal View History

Make bevy_math's `libm` feature use `libm` for all `f32`methods with unspecified precision (#14693) # 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>
2024-08-12 16:13:36 +00:00
disallowed-methods = [
{ path = "f32::powi", reason = "use ops::FloatPow::squared, ops::FloatPow::cubed, or ops::powf instead for libm determinism" },
{ path = "f32::log", reason = "use ops::ln, ops::log2, or ops::log10 instead for libm determinism" },
{ path = "f32::abs_sub", reason = "deprecated and deeply confusing method" },
{ path = "f32::powf", reason = "use ops::powf instead for libm determinism" },
{ path = "f32::exp", reason = "use ops::exp instead for libm determinism" },
{ path = "f32::exp2", reason = "use ops::exp2 instead for libm determinism" },
{ path = "f32::ln", reason = "use ops::ln instead for libm determinism" },
{ path = "f32::log2", reason = "use ops::log2 instead for libm determinism" },
{ path = "f32::log10", reason = "use ops::log10 instead for libm determinism" },
{ path = "f32::cbrt", reason = "use ops::cbrt instead for libm determinism" },
{ path = "f32::hypot", reason = "use ops::hypot instead for libm determinism" },
{ path = "f32::sin", reason = "use ops::sin instead for libm determinism" },
{ path = "f32::cos", reason = "use ops::cos instead for libm determinism" },
{ path = "f32::tan", reason = "use ops::tan instead for libm determinism" },
{ path = "f32::asin", reason = "use ops::asin instead for libm determinism" },
{ path = "f32::acos", reason = "use ops::acos instead for libm determinism" },
{ path = "f32::atan", reason = "use ops::atan instead for libm determinism" },
{ path = "f32::atan2", reason = "use ops::atan2 instead for libm determinism" },
{ path = "f32::sin_cos", reason = "use ops::sin_cos instead for libm determinism" },
{ path = "f32::exp_m1", reason = "use ops::exp_m1 instead for libm determinism" },
{ path = "f32::ln_1p", reason = "use ops::ln_1p instead for libm determinism" },
{ path = "f32::sinh", reason = "use ops::sinh instead for libm determinism" },
{ path = "f32::cosh", reason = "use ops::cosh instead for libm determinism" },
{ path = "f32::tanh", reason = "use ops::tanh instead for libm determinism" },
{ path = "f32::asinh", reason = "use ops::asinh instead for libm determinism" },
{ path = "f32::acosh", reason = "use ops::acosh instead for libm determinism" },
{ path = "f32::atanh", reason = "use ops::atanh instead for libm determinism" },
Add `no_std` Support to `bevy_math` (#15810) # Objective - Contributes to #15460 ## Solution - Added two new features, `std` (default) and `alloc`, gating `std` and `alloc` behind them respectively. - Added missing `f32` functions to `std_ops` as required. These `f32` methods have been added to the `clippy.toml` deny list to aid in `no_std` development. ## Testing - CI - `cargo clippy -p bevy_math --no-default-features --features libm --target "x86_64-unknown-none"` - `cargo test -p bevy_math --no-default-features --features libm` - `cargo test -p bevy_math --no-default-features --features "libm, alloc"` - `cargo test -p bevy_math --no-default-features --features "libm, alloc, std"` - `cargo test -p bevy_math --no-default-features --features "std"` ## Notes The following items require the `alloc` feature to be enabled: - `CubicBSpline` - `CubicBezier` - `CubicCardinalSpline` - `CubicCurve` - `CubicGenerator` - `CubicHermite` - `CubicNurbs` - `CyclicCubicGenerator` - `RationalCurve` - `RationalGenerator` - `BoxedPolygon` - `BoxedPolyline2d` - `BoxedPolyline3d` - `SampleCurve` - `SampleAutoCurve` - `UnevenSampleCurve` - `UnevenSampleAutoCurve` - `EvenCore` - `UnevenCore` - `ChunkedUnevenCore` This requirement could be relaxed in certain cases, but I had erred on the side of gating rather than modifying. Since `no_std` is a new set of platforms we are adding support to, and the `alloc` feature is enabled by default, this is not a breaking change. --------- Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com> Co-authored-by: Matty <2975848+mweatherley@users.noreply.github.com> Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
2024-12-03 17:14:51 +00:00
# These methods have defined precision, but are only available from the standard library,
# not in core. Using these substitutes allows for no_std compatibility.
{ path = "f32::rem_euclid", reason = "use ops::rem_euclid instead for no_std compatibility" },
{ path = "f32::abs", reason = "use ops::abs instead for no_std compatibility" },
{ path = "f32::sqrt", reason = "use ops::sqrt instead for no_std compatibility" },
{ path = "f32::copysign", reason = "use ops::copysign instead for no_std compatibility" },
{ path = "f32::round", reason = "use ops::round instead for no_std compatibility" },
{ path = "f32::floor", reason = "use ops::floor instead for no_std compatibility" },
{ path = "f32::fract", reason = "use ops::fract instead for no_std compatibility" },
Make bevy_math's `libm` feature use `libm` for all `f32`methods with unspecified precision (#14693) # 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>
2024-08-12 16:13:36 +00:00
]