new implementations for nearest lib calls
use approach with copysign for handling negative zero
format
refactor for better branch prediction
move copysign back to internal branch
format
fix
use abs instead branches
better comments
switch arms for better branch prediction
@@ -67,6 +67,9 @@ use wasmtime_environ::wasm::{
TableIndex,
};
+const TOINT_32: f32 = 1.0 / f32::EPSILON;
+const TOINT_64: f64 = 1.0 / f64::EPSILON;
+
/// Implementation of f32.ceil
pub extern "C" fn wasmtime_f32_ceil(x: f32) -> f32 {
x.ceil()
@@ -86,25 +89,14 @@ pub extern "C" fn wasmtime_f32_trunc(x: f32) -> f32 {
#[allow(clippy::float_arithmetic, clippy::float_cmp)]
pub extern "C" fn wasmtime_f32_nearest(x: f32) -> f32 {
// Rust doesn't have a nearest function, so do it manually.
- if x == 0.0 {
- // Preserve the sign of zero.
- x
- } else {
// Nearest is either ceil or floor depending on which is nearest or even.
- let u = x.ceil();
- let d = x.floor();
- let um = (x - u).abs();
- let dm = (x - d).abs();
- if um < dm
- || (um == dm && {
- let h = u / 2.;
- h.floor() == h
- })
- {
- u
+ // This approach exploited round half to even default mode.
+ let i = x.to_bits();
+ let e = i >> 23 & 0xff;
+ if e >= 0x7f_u32 + 23 {
+ x
} else {
- d
- }
+ (x.abs() + TOINT_32 - TOINT_32).copysign(x)
}
}
@@ -162,25 +154,14 @@ pub extern "C" fn wasmtime_f64_trunc(x: f64) -> f64 {
#[allow(clippy::float_arithmetic, clippy::float_cmp)]
pub extern "C" fn wasmtime_f64_nearest(x: f64) -> f64 {
// Rust doesn't have a nearest function, so do it manually.
- if x == 0.0 {
- // Preserve the sign of zero.
- x
- } else {
// Nearest is either ceil or floor depending on which is nearest or even.
- let u = x.ceil();
- let d = x.floor();
- let um = (x - u).abs();
- let dm = (x - d).abs();
- if um < dm
- || (um == dm && {
- let h = u / 2.;
- h.floor() == h
- })
- {
- u
+ // This approach exploited round half to even default mode.
+ let i = x.to_bits();
+ let e = i >> 52 & 0x7ff;
+ if e >= 0x3ff_u64 + 52 {
+ x
} else {
- d
- }
+ (x.abs() + TOINT_64 - TOINT_64).copysign(x)
}
}
