Add `emath::fast_midpoint` (#7435)

This commit is contained in:
Emil Ernerfeldt 2025-08-08 12:04:51 +02:00 committed by GitHub
parent 3024c39eaf
commit 6fae65a3fa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 23 additions and 6 deletions

View File

@ -300,7 +300,7 @@ zero_sized_map_values = "warn"
# doc_comment_double_space_linebreaks = "warn" # doc_comment_double_space_linebreaks = "warn"
# elidable_lifetime_names = "warn" # elidable_lifetime_names = "warn"
# ignore_without_reason = "warn" # ignore_without_reason = "warn"
# manual_midpoint = "warn" # manual_midpoint = "warn" # NOTE `midpoint` is often a lot slower for floats, so we have our own `emath::fast_midpoint` function.
# non_std_lazy_statics = "warn" # non_std_lazy_statics = "warn"
# precedence_bits = "warn" # precedence_bits = "warn"
# return_and_then = "warn" # return_and_then = "warn"

View File

@ -134,7 +134,7 @@ impl Align {
if size == f32::INFINITY { if size == f32::INFINITY {
Rangef::new(f32::NEG_INFINITY, f32::INFINITY) Rangef::new(f32::NEG_INFINITY, f32::INFINITY)
} else { } else {
let left = f32::midpoint(min, max) - size / 2.0; let left = crate::fast_midpoint(min, max) - size / 2.0;
Rangef::new(left, left + size) Rangef::new(left, left + size)
} }
} }

View File

@ -112,6 +112,21 @@ where
(T::ONE - t) * *range.start() + t * *range.end() (T::ONE - t) * *range.start() + t * *range.end()
} }
/// This is a faster version of [`f32::midpoint`] which doesn't handle overflow.
///
/// ```
/// # use emath::fast_midpoint;
/// assert_eq!(fast_midpoint(1.0, 5.0), 3.0);
/// ```
#[inline(always)]
pub fn fast_midpoint<R>(a: R, b: R) -> R
where
R: Copy + Add<R, Output = R> + Div<R, Output = R> + One,
{
let two = R::ONE + R::ONE;
(a + b) / two
}
/// Where in the range is this value? Returns 0-1 if within the range. /// Where in the range is this value? Returns 0-1 if within the range.
/// ///
/// Returns <0 if before and >1 if after. /// Returns <0 if before and >1 if after.

View File

@ -1,6 +1,6 @@
use std::fmt; use std::fmt;
use crate::{Div, Mul, NumExt as _, Pos2, Rangef, Rot2, Vec2, lerp, pos2, vec2}; use crate::{Div, Mul, NumExt as _, Pos2, Rangef, Rot2, Vec2, fast_midpoint, lerp, pos2, vec2};
use std::ops::{BitOr, BitOrAssign}; use std::ops::{BitOr, BitOrAssign};
/// A rectangular region of space. /// A rectangular region of space.
@ -331,8 +331,8 @@ impl Rect {
#[inline(always)] #[inline(always)]
pub fn center(&self) -> Pos2 { pub fn center(&self) -> Pos2 {
Pos2 { Pos2 {
x: f32::midpoint(self.min.x, self.max.x), x: fast_midpoint(self.min.x, self.max.x),
y: f32::midpoint(self.min.y, self.max.y), y: fast_midpoint(self.min.y, self.max.y),
} }
} }

View File

@ -1,5 +1,7 @@
//! Find "simple" numbers is some range. Used by sliders. //! Find "simple" numbers is some range. Used by sliders.
use crate::fast_midpoint;
const NUM_DECIMALS: usize = 15; const NUM_DECIMALS: usize = 15;
/// Find the "simplest" number in a closed range [min, max], i.e. the one with the fewest decimal digits. /// Find the "simplest" number in a closed range [min, max], i.e. the one with the fewest decimal digits.
@ -43,7 +45,7 @@ pub fn best_in_range_f64(min: f64, max: f64) -> f64 {
if min_exponent.floor() != max_exponent.floor() { if min_exponent.floor() != max_exponent.floor() {
// pick the geometric center of the two: // pick the geometric center of the two:
let exponent = f64::midpoint(min_exponent, max_exponent); let exponent = fast_midpoint(min_exponent, max_exponent);
return 10.0_f64.powi(exponent.round() as i32); return 10.0_f64.powi(exponent.round() as i32);
} }