Skip to content

Commit 6fae65a

Browse files
authored
Add emath::fast_midpoint (#7435)
1 parent 3024c39 commit 6fae65a

File tree

5 files changed

+23
-6
lines changed

5 files changed

+23
-6
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ zero_sized_map_values = "warn"
300300
# doc_comment_double_space_linebreaks = "warn"
301301
# elidable_lifetime_names = "warn"
302302
# ignore_without_reason = "warn"
303-
# manual_midpoint = "warn"
303+
# manual_midpoint = "warn" # NOTE `midpoint` is often a lot slower for floats, so we have our own `emath::fast_midpoint` function.
304304
# non_std_lazy_statics = "warn"
305305
# precedence_bits = "warn"
306306
# return_and_then = "warn"

crates/emath/src/align.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ impl Align {
134134
if size == f32::INFINITY {
135135
Rangef::new(f32::NEG_INFINITY, f32::INFINITY)
136136
} else {
137-
let left = f32::midpoint(min, max) - size / 2.0;
137+
let left = crate::fast_midpoint(min, max) - size / 2.0;
138138
Rangef::new(left, left + size)
139139
}
140140
}

crates/emath/src/lib.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,21 @@ where
112112
(T::ONE - t) * *range.start() + t * *range.end()
113113
}
114114

115+
/// This is a faster version of [`f32::midpoint`] which doesn't handle overflow.
116+
///
117+
/// ```
118+
/// # use emath::fast_midpoint;
119+
/// assert_eq!(fast_midpoint(1.0, 5.0), 3.0);
120+
/// ```
121+
#[inline(always)]
122+
pub fn fast_midpoint<R>(a: R, b: R) -> R
123+
where
124+
R: Copy + Add<R, Output = R> + Div<R, Output = R> + One,
125+
{
126+
let two = R::ONE + R::ONE;
127+
(a + b) / two
128+
}
129+
115130
/// Where in the range is this value? Returns 0-1 if within the range.
116131
///
117132
/// Returns <0 if before and >1 if after.

crates/emath/src/rect.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::fmt;
22

3-
use crate::{Div, Mul, NumExt as _, Pos2, Rangef, Rot2, Vec2, lerp, pos2, vec2};
3+
use crate::{Div, Mul, NumExt as _, Pos2, Rangef, Rot2, Vec2, fast_midpoint, lerp, pos2, vec2};
44
use std::ops::{BitOr, BitOrAssign};
55

66
/// A rectangular region of space.
@@ -331,8 +331,8 @@ impl Rect {
331331
#[inline(always)]
332332
pub fn center(&self) -> Pos2 {
333333
Pos2 {
334-
x: f32::midpoint(self.min.x, self.max.x),
335-
y: f32::midpoint(self.min.y, self.max.y),
334+
x: fast_midpoint(self.min.x, self.max.x),
335+
y: fast_midpoint(self.min.y, self.max.y),
336336
}
337337
}
338338

crates/emath/src/smart_aim.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Find "simple" numbers is some range. Used by sliders.
22
3+
use crate::fast_midpoint;
4+
35
const NUM_DECIMALS: usize = 15;
46

57
/// 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 {
4345

4446
if min_exponent.floor() != max_exponent.floor() {
4547
// pick the geometric center of the two:
46-
let exponent = f64::midpoint(min_exponent, max_exponent);
48+
let exponent = fast_midpoint(min_exponent, max_exponent);
4749
return 10.0_f64.powi(exponent.round() as i32);
4850
}
4951

0 commit comments

Comments
 (0)