Skip to content

Commit 2988c0a

Browse files
committed
Reintroduce f32-based midpoint on some ARM targets
1 parent d251717 commit 2988c0a

File tree

1 file changed

+31
-1
lines changed

1 file changed

+31
-1
lines changed

library/core/src/num/f32.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,37 @@ impl f32 {
10161016
/// ```
10171017
#[unstable(feature = "num_midpoint", issue = "110840")]
10181018
pub fn midpoint(self, other: f32) -> f32 {
1019-
((f64::from(self) + f64::from(other)) / 2.0) as f32
1019+
cfg_if! {
1020+
if #[cfg(all(target_arch = "arm", target_pointer_width = "32",
1021+
not(target_feature = "vfp2")))] {
1022+
// some 32-bit ARM architectures don't have native double-precision floats
1023+
// so fall back to a similar algorithm as in f64, but using f32
1024+
// This should only differ in the NaNs specific NaNs reported.
1025+
1026+
const LO: f32 = f32::MIN_POSITIVE * 2.;
1027+
const HI: f32 = f32::MAX / 2.;
1028+
1029+
let (a, b) = (self, other);
1030+
let abs_a = a.abs_private();
1031+
let abs_b = b.abs_private();
1032+
1033+
if abs_a <= HI && abs_b <= HI {
1034+
// Overflow is impossible
1035+
(a + b) / 2.
1036+
} else if abs_a < LO {
1037+
// Not safe to halve a
1038+
a + (b / 2.)
1039+
} else if abs_b < LO {
1040+
// Not safe to halve b
1041+
(a / 2.) + b
1042+
} else {
1043+
// Not safe to halve a and b
1044+
(a / 2.) + (b / 2.)
1045+
}
1046+
} else {
1047+
((f64::from(self) + f64::from(other)) / 2.0) as f32
1048+
}
1049+
}
10201050
}
10211051

10221052
/// Rounds toward zero and converts to any primitive integer type,

0 commit comments

Comments
 (0)