Skip to content

Commit

Permalink
Fix floating point math (bevyengine#15239)
Browse files Browse the repository at this point in the history
# Objective

- Fixes bevyengine#15236

## Solution

- Use bevy_math::ops instead of std floating point operations.

## Testing

- Did you test these changes? If so, how?
Unit tests and `cargo run -p ci -- test`

- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
Execute `cargo run -p ci -- test` on Windows.

- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
Windows

## Migration Guide

- Not a breaking change
- Projects should use bevy math where applicable

---------

Co-authored-by: Alice Cecile <[email protected]>
Co-authored-by: IQuick 143 <[email protected]>
Co-authored-by: Joona Aalto <[email protected]>
  • Loading branch information
4 people authored Sep 16, 2024
1 parent 0dd00e9 commit 29508f0
Show file tree
Hide file tree
Showing 84 changed files with 331 additions and 266 deletions.
30 changes: 30 additions & 0 deletions clippy.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,33 @@ doc-valid-idents = [
"WebGPU",
"..",
]

disallowed-methods = [
{ path = "f32::powi", reason = "use bevy_math::ops::FloatPow::squared, bevy_math::ops::FloatPow::cubed, or bevy_math::ops::powf instead for libm determinism" },
{ path = "f32::log", reason = "use bevy_math::ops::ln, bevy_math::ops::log2, or bevy_math::ops::log10 instead for libm determinism" },
{ path = "f32::abs_sub", reason = "deprecated and deeply confusing method" },
{ path = "f32::powf", reason = "use bevy_math::ops::powf instead for libm determinism" },
{ path = "f32::exp", reason = "use bevy_math::ops::exp instead for libm determinism" },
{ path = "f32::exp2", reason = "use bevy_math::ops::exp2 instead for libm determinism" },
{ path = "f32::ln", reason = "use bevy_math::ops::ln instead for libm determinism" },
{ path = "f32::log2", reason = "use bevy_math::ops::log2 instead for libm determinism" },
{ path = "f32::log10", reason = "use bevy_math::ops::log10 instead for libm determinism" },
{ path = "f32::cbrt", reason = "use bevy_math::ops::cbrt instead for libm determinism" },
{ path = "f32::hypot", reason = "use bevy_math::ops::hypot instead for libm determinism" },
{ path = "f32::sin", reason = "use bevy_math::ops::sin instead for libm determinism" },
{ path = "f32::cos", reason = "use bevy_math::ops::cos instead for libm determinism" },
{ path = "f32::tan", reason = "use bevy_math::ops::tan instead for libm determinism" },
{ path = "f32::asin", reason = "use bevy_math::ops::asin instead for libm determinism" },
{ path = "f32::acos", reason = "use bevy_math::ops::acos instead for libm determinism" },
{ path = "f32::atan", reason = "use bevy_math::ops::atan instead for libm determinism" },
{ path = "f32::atan2", reason = "use bevy_math::ops::atan2 instead for libm determinism" },
{ path = "f32::sin_cos", reason = "use bevy_math::ops::sin_cos instead for libm determinism" },
{ path = "f32::exp_m1", reason = "use bevy_math::ops::exp_m1 instead for libm determinism" },
{ path = "f32::ln_1p", reason = "use bevy_math::ops::ln_1p instead for libm determinism" },
{ path = "f32::sinh", reason = "use bevy_math::ops::sinh instead for libm determinism" },
{ path = "f32::cosh", reason = "use bevy_math::ops::cosh instead for libm determinism" },
{ path = "f32::tanh", reason = "use bevy_math::ops::tanh instead for libm determinism" },
{ path = "f32::asinh", reason = "use bevy_math::ops::asinh instead for libm determinism" },
{ path = "f32::acosh", reason = "use bevy_math::ops::acosh instead for libm determinism" },
{ path = "f32::atanh", reason = "use bevy_math::ops::atanh instead for libm determinism" },
]
10 changes: 5 additions & 5 deletions crates/bevy_animation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use bevy_app::{App, Plugin, PostUpdate};
use bevy_asset::{Asset, AssetApp, Assets, Handle};
use bevy_core::Name;
use bevy_ecs::{entity::MapEntities, prelude::*, reflect::ReflectMapEntities};
use bevy_math::{FloatExt, Quat, Vec3};
use bevy_math::{FloatExt, FloatPow, Quat, Vec3};
use bevy_reflect::std_traits::ReflectDefault;
use bevy_reflect::Reflect;
use bevy_render::mesh::morph::MorphWeights;
Expand Down Expand Up @@ -1211,10 +1211,10 @@ fn cubic_spline_interpolation<T>(
where
T: Mul<f32, Output = T> + Add<Output = T>,
{
value_start * (2.0 * lerp.powi(3) - 3.0 * lerp.powi(2) + 1.0)
+ tangent_out_start * (step_duration) * (lerp.powi(3) - 2.0 * lerp.powi(2) + lerp)
+ value_end * (-2.0 * lerp.powi(3) + 3.0 * lerp.powi(2))
+ tangent_in_end * step_duration * (lerp.powi(3) - lerp.powi(2))
value_start * (2.0 * lerp.cubed() - 3.0 * lerp.squared() + 1.0)
+ tangent_out_start * (step_duration) * (lerp.cubed() - 2.0 * lerp.squared() + lerp)
+ value_end * (-2.0 * lerp.cubed() + 3.0 * lerp.squared())
+ tangent_in_end * step_duration * (lerp.cubed() - lerp.squared())
}

/// Adds animation support to an app
Expand Down
14 changes: 7 additions & 7 deletions crates/bevy_color/src/laba.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
impl_componentwise_vector_space, Alpha, ColorToComponents, Gray, Hsla, Hsva, Hwba, LinearRgba,
Luminance, Mix, Oklaba, Srgba, StandardColor, Xyza,
};
use bevy_math::{Vec3, Vec4};
use bevy_math::{ops, Vec3, Vec4};
#[cfg(feature = "bevy_reflect")]
use bevy_reflect::prelude::*;

Expand Down Expand Up @@ -225,7 +225,7 @@ impl From<Laba> for Xyza {
let fx = a / 500.0 + fy;
let fz = fy - b / 200.0;
let xr = {
let fx3 = fx.powf(3.0);
let fx3 = ops::powf(fx, 3.0);

if fx3 > Laba::CIE_EPSILON {
fx3
Expand All @@ -234,12 +234,12 @@ impl From<Laba> for Xyza {
}
};
let yr = if l > Laba::CIE_EPSILON * Laba::CIE_KAPPA {
((l + 16.0) / 116.0).powf(3.0)
ops::powf((l + 16.0) / 116.0, 3.0)
} else {
l / Laba::CIE_KAPPA
};
let zr = {
let fz3 = fz.powf(3.0);
let fz3 = ops::powf(fz, 3.0);

if fz3 > Laba::CIE_EPSILON {
fz3
Expand All @@ -262,17 +262,17 @@ impl From<Xyza> for Laba {
let yr = y / Xyza::D65_WHITE.y;
let zr = z / Xyza::D65_WHITE.z;
let fx = if xr > Laba::CIE_EPSILON {
xr.cbrt()
ops::cbrt(xr)
} else {
(Laba::CIE_KAPPA * xr + 16.0) / 116.0
};
let fy = if yr > Laba::CIE_EPSILON {
yr.cbrt()
ops::cbrt(yr)
} else {
(Laba::CIE_KAPPA * yr + 16.0) / 116.0
};
let fz = if yr > Laba::CIE_EPSILON {
zr.cbrt()
ops::cbrt(zr)
} else {
(Laba::CIE_KAPPA * zr + 16.0) / 116.0
};
Expand Down
11 changes: 6 additions & 5 deletions crates/bevy_color/src/lcha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
Alpha, ColorToComponents, Gray, Hue, Laba, LinearRgba, Luminance, Mix, Srgba, StandardColor,
Xyza,
};
use bevy_math::{Vec3, Vec4};
use bevy_math::{ops, Vec3, Vec4};
#[cfg(feature = "bevy_reflect")]
use bevy_reflect::prelude::*;

Expand Down Expand Up @@ -257,8 +257,9 @@ impl From<Lcha> for Laba {
) -> Self {
// Based on http://www.brucelindbloom.com/index.html?Eqn_LCH_to_Lab.html
let l = lightness;
let a = chroma * hue.to_radians().cos();
let b = chroma * hue.to_radians().sin();
let (sin, cos) = ops::sin_cos(hue.to_radians());
let a = chroma * cos;
let b = chroma * sin;

Laba::new(l, a, b, alpha)
}
Expand All @@ -274,9 +275,9 @@ impl From<Laba> for Lcha {
}: Laba,
) -> Self {
// Based on http://www.brucelindbloom.com/index.html?Eqn_Lab_to_LCH.html
let c = (a.powf(2.0) + b.powf(2.0)).sqrt();
let c = ops::hypot(a, b);
let h = {
let h = b.to_radians().atan2(a.to_radians()).to_degrees();
let h = ops::atan2(b.to_radians(), a.to_radians()).to_degrees();

if h < 0.0 {
h + 360.0
Expand Down
14 changes: 7 additions & 7 deletions crates/bevy_color/src/oklaba.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
color_difference::EuclideanDistance, impl_componentwise_vector_space, Alpha, ColorToComponents,
Gray, Hsla, Hsva, Hwba, Lcha, LinearRgba, Luminance, Mix, Srgba, StandardColor, Xyza,
};
use bevy_math::{Vec3, Vec4};
use bevy_math::{ops, FloatPow, Vec3, Vec4};
#[cfg(feature = "bevy_reflect")]
use bevy_reflect::prelude::*;

Expand Down Expand Up @@ -156,9 +156,9 @@ impl Luminance for Oklaba {
impl EuclideanDistance for Oklaba {
#[inline]
fn distance_squared(&self, other: &Self) -> f32 {
(self.lightness - other.lightness).powi(2)
+ (self.a - other.a).powi(2)
+ (self.b - other.b).powi(2)
(self.lightness - other.lightness).squared()
+ (self.a - other.a).squared()
+ (self.b - other.b).squared()
}
}

Expand Down Expand Up @@ -229,9 +229,9 @@ impl From<LinearRgba> for Oklaba {
let l = 0.4122214708 * red + 0.5363325363 * green + 0.0514459929 * blue;
let m = 0.2119034982 * red + 0.6806995451 * green + 0.1073969566 * blue;
let s = 0.0883024619 * red + 0.2817188376 * green + 0.6299787005 * blue;
let l_ = l.cbrt();
let m_ = m.cbrt();
let s_ = s.cbrt();
let l_ = ops::cbrt(l);
let m_ = ops::cbrt(m);
let s_ = ops::cbrt(s);
let l = 0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_;
let a = 1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_;
let b = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_;
Expand Down
17 changes: 9 additions & 8 deletions crates/bevy_color/src/oklcha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
color_difference::EuclideanDistance, Alpha, ColorToComponents, Gray, Hsla, Hsva, Hue, Hwba,
Laba, Lcha, LinearRgba, Luminance, Mix, Oklaba, Srgba, StandardColor, Xyza,
};
use bevy_math::{Vec3, Vec4};
use bevy_math::{ops, FloatPow, Vec3, Vec4};
#[cfg(feature = "bevy_reflect")]
use bevy_reflect::prelude::*;

Expand Down Expand Up @@ -191,9 +191,9 @@ impl Luminance for Oklcha {
impl EuclideanDistance for Oklcha {
#[inline]
fn distance_squared(&self, other: &Self) -> f32 {
(self.lightness - other.lightness).powi(2)
+ (self.chroma - other.chroma).powi(2)
+ (self.hue - other.hue).powi(2)
(self.lightness - other.lightness).squared()
+ (self.chroma - other.chroma).squared()
+ (self.hue - other.hue).squared()
}
}

Expand Down Expand Up @@ -260,8 +260,8 @@ impl From<Oklaba> for Oklcha {
alpha,
}: Oklaba,
) -> Self {
let chroma = a.hypot(b);
let hue = b.atan2(a).to_degrees();
let chroma = ops::hypot(a, b);
let hue = ops::atan2(b, a).to_degrees();

let hue = if hue < 0.0 { hue + 360.0 } else { hue };

Expand All @@ -279,8 +279,9 @@ impl From<Oklcha> for Oklaba {
}: Oklcha,
) -> Self {
let l = lightness;
let a = chroma * hue.to_radians().cos();
let b = chroma * hue.to_radians().sin();
let (sin, cos) = ops::sin_cos(hue.to_radians());
let a = chroma * cos;
let b = chroma * sin;

Oklaba::new(l, a, b, alpha)
}
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_color/src/srgba.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
impl_componentwise_vector_space, Alpha, ColorToComponents, ColorToPacked, Gray, LinearRgba,
Luminance, Mix, StandardColor, Xyza,
};
use bevy_math::{Vec3, Vec4};
use bevy_math::{ops, Vec3, Vec4};
#[cfg(feature = "bevy_reflect")]
use bevy_reflect::prelude::*;
use thiserror::Error;
Expand Down Expand Up @@ -215,7 +215,7 @@ impl Srgba {
if value <= 0.04045 {
value / 12.92 // linear falloff in dark values
} else {
((value + 0.055) / 1.055).powf(2.4) // gamma curve in other area
ops::powf((value + 0.055) / 1.055, 2.4) // gamma curve in other area
}
}

Expand All @@ -228,7 +228,7 @@ impl Srgba {
if value <= 0.0031308 {
value * 12.92 // linear falloff in dark values
} else {
(1.055 * value.powf(1.0 / 2.4)) - 0.055 // gamma curve in other area
(1.055 * ops::powf(value, 1.0 / 2.4)) - 0.055 // gamma curve in other area
}
}
}
Expand Down
10 changes: 6 additions & 4 deletions crates/bevy_core_pipeline/src/bloom/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::{
use bevy_app::{App, Plugin};
use bevy_asset::{load_internal_asset, Handle};
use bevy_ecs::{prelude::*, query::QueryItem};
use bevy_math::UVec2;
use bevy_math::{ops, UVec2};
use bevy_render::{
camera::ExtractedCamera,
diagnostic::RecordDiagnostics,
Expand Down Expand Up @@ -462,9 +462,11 @@ fn prepare_bloom_bind_groups(
/// This function can be visually previewed for all values of *mip* (normalized) with tweakable
/// [`Bloom`] parameters on [Desmos graphing calculator](https://www.desmos.com/calculator/ncc8xbhzzl).
fn compute_blend_factor(bloom: &Bloom, mip: f32, max_mip: f32) -> f32 {
let mut lf_boost = (1.0
- (1.0 - (mip / max_mip)).powf(1.0 / (1.0 - bloom.low_frequency_boost_curvature)))
* bloom.low_frequency_boost;
let mut lf_boost =
(1.0 - ops::powf(
1.0 - (mip / max_mip),
1.0 / (1.0 - bloom.low_frequency_boost_curvature),
)) * bloom.low_frequency_boost;
let high_pass_lq = 1.0
- (((mip / max_mip) - bloom.high_pass_frequency) / bloom.high_pass_frequency)
.clamp(0.0, 1.0);
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_core_pipeline/src/dof/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use bevy_ecs::{
system::{lifetimeless::Read, Commands, Query, Res, ResMut, Resource},
world::{FromWorld, World},
};
use bevy_math::ops;
use bevy_reflect::{prelude::ReflectDefault, Reflect};
use bevy_render::{
camera::{PhysicalCameraParameters, Projection},
Expand Down Expand Up @@ -848,7 +849,7 @@ fn extract_depth_of_field_settings(
///
/// See <https://photo.stackexchange.com/a/97218>.
pub fn calculate_focal_length(sensor_height: f32, fov: f32) -> f32 {
0.5 * sensor_height / f32::tan(0.5 * fov)
0.5 * sensor_height / ops::tan(0.5 * fov)
}

impl DepthOfFieldPipelines {
Expand Down
14 changes: 7 additions & 7 deletions crates/bevy_ecs/src/query/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {

let range = range.unwrap_or(0..table.entity_count());
accum =
// SAFETY:
// SAFETY:
// - The fetched table matches both D and F
// - caller ensures `range` is within `[0, table.entity_count)`
// - The if block ensures that the query iteration is dense
Expand Down Expand Up @@ -2083,15 +2083,15 @@ mod tests {
let mut query = world.query::<&Sparse>();
let mut iter = query.iter(&world);
println!(
"before_next_call: archetype_entities: {} table_entities: {} current_len: {} current_row: {}",
"before_next_call: archetype_entities: {} table_entities: {} current_len: {} current_row: {}",
iter.cursor.archetype_entities.len(),
iter.cursor.table_entities.len(),
iter.cursor.current_len,
iter.cursor.current_row
);
_ = iter.next();
println!(
"after_next_call: archetype_entities: {} table_entities: {} current_len: {} current_row: {}",
"after_next_call: archetype_entities: {} table_entities: {} current_len: {} current_row: {}",
iter.cursor.archetype_entities.len(),
iter.cursor.table_entities.len(),
iter.cursor.current_len,
Expand All @@ -2108,15 +2108,15 @@ mod tests {
let mut query = world.query::<(&A, &Sparse)>();
let mut iter = query.iter(&world);
println!(
"before_next_call: archetype_entities: {} table_entities: {} current_len: {} current_row: {}",
"before_next_call: archetype_entities: {} table_entities: {} current_len: {} current_row: {}",
iter.cursor.archetype_entities.len(),
iter.cursor.table_entities.len(),
iter.cursor.current_len,
iter.cursor.current_row
);
_ = iter.next();
println!(
"after_next_call: archetype_entities: {} table_entities: {} current_len: {} current_row: {}",
"after_next_call: archetype_entities: {} table_entities: {} current_len: {} current_row: {}",
iter.cursor.archetype_entities.len(),
iter.cursor.table_entities.len(),
iter.cursor.current_len,
Expand All @@ -2136,7 +2136,7 @@ mod tests {
let mut query = world.query::<(&A, &Sparse)>();
let mut iter = query.iter(&world);
println!(
"before_next_call: archetype_entities: {} table_entities: {} current_len: {} current_row: {}",
"before_next_call: archetype_entities: {} table_entities: {} current_len: {} current_row: {}",
iter.cursor.archetype_entities.len(),
iter.cursor.table_entities.len(),
iter.cursor.current_len,
Expand All @@ -2145,7 +2145,7 @@ mod tests {
assert!(iter.cursor.table_entities.len() | iter.cursor.archetype_entities.len() == 0);
_ = iter.next();
println!(
"after_next_call: archetype_entities: {} table_entities: {} current_len: {} current_row: {}",
"after_next_call: archetype_entities: {} table_entities: {} current_len: {} current_row: {}",
iter.cursor.archetype_entities.len(),
iter.cursor.table_entities.len(),
iter.cursor.current_len,
Expand Down
3 changes: 1 addition & 2 deletions crates/bevy_gizmos/src/arcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,7 @@ fn arc_2d_inner(arc_angle: f32, radius: f32, resolution: u32) -> impl Iterator<I
(0..=resolution)
.map(move |n| arc_angle * n as f32 / resolution as f32)
.map(|angle| angle + FRAC_PI_2)
.map(f32::sin_cos)
.map(|(sin, cos)| Vec2::new(cos, sin))
.map(Vec2::from_angle)
.map(move |vec2| vec2 * radius)
}

Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_gizmos/src/circles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use crate::prelude::{GizmoConfigGroup, Gizmos};
use bevy_color::Color;
use bevy_math::{Isometry2d, Isometry3d};
use bevy_math::{ops, Isometry2d, Isometry3d};
use bevy_math::{Quat, Vec2, Vec3};
use std::f32::consts::TAU;

Expand All @@ -14,7 +14,7 @@ pub(crate) const DEFAULT_CIRCLE_RESOLUTION: u32 = 32;
fn ellipse_inner(half_size: Vec2, resolution: u32) -> impl Iterator<Item = Vec2> {
(0..resolution + 1).map(move |i| {
let angle = i as f32 * TAU / resolution as f32;
let (x, y) = angle.sin_cos();
let (x, y) = ops::sin_cos(angle);
Vec2::new(x, y) * half_size
})
}
Expand Down
Loading

0 comments on commit 29508f0

Please sign in to comment.