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"
# elidable_lifetime_names = "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"
# precedence_bits = "warn"
# return_and_then = "warn"

View File

@ -134,7 +134,7 @@ impl Align {
if size == f32::INFINITY {
Rangef::new(f32::NEG_INFINITY, f32::INFINITY)
} 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)
}
}

View File

@ -112,6 +112,21 @@ where
(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.
///
/// Returns <0 if before and >1 if after.

View File

@ -1,6 +1,6 @@
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};
/// A rectangular region of space.
@ -331,8 +331,8 @@ impl Rect {
#[inline(always)]
pub fn center(&self) -> Pos2 {
Pos2 {
x: f32::midpoint(self.min.x, self.max.x),
y: f32::midpoint(self.min.y, self.max.y),
x: fast_midpoint(self.min.x, self.max.x),
y: fast_midpoint(self.min.y, self.max.y),
}
}

View File

@ -1,5 +1,7 @@
//! Find "simple" numbers is some range. Used by sliders.
use crate::fast_midpoint;
const NUM_DECIMALS: usize = 15;
/// 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() {
// 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);
}