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
This commit is contained in:
@@ -67,6 +67,9 @@ use wasmtime_environ::wasm::{
|
|||||||
TableIndex,
|
TableIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const TOINT_32: f32 = 1.0 / f32::EPSILON;
|
||||||
|
const TOINT_64: f64 = 1.0 / f64::EPSILON;
|
||||||
|
|
||||||
/// Implementation of f32.ceil
|
/// Implementation of f32.ceil
|
||||||
pub extern "C" fn wasmtime_f32_ceil(x: f32) -> f32 {
|
pub extern "C" fn wasmtime_f32_ceil(x: f32) -> f32 {
|
||||||
x.ceil()
|
x.ceil()
|
||||||
@@ -86,25 +89,14 @@ pub extern "C" fn wasmtime_f32_trunc(x: f32) -> f32 {
|
|||||||
#[allow(clippy::float_arithmetic, clippy::float_cmp)]
|
#[allow(clippy::float_arithmetic, clippy::float_cmp)]
|
||||||
pub extern "C" fn wasmtime_f32_nearest(x: f32) -> f32 {
|
pub extern "C" fn wasmtime_f32_nearest(x: f32) -> f32 {
|
||||||
// Rust doesn't have a nearest function, so do it manually.
|
// Rust doesn't have a nearest function, so do it manually.
|
||||||
if x == 0.0 {
|
// Nearest is either ceil or floor depending on which is nearest or even.
|
||||||
// Preserve the sign of zero.
|
// 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
|
x
|
||||||
} else {
|
} else {
|
||||||
// Nearest is either ceil or floor depending on which is nearest or even.
|
(x.abs() + TOINT_32 - TOINT_32).copysign(x)
|
||||||
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
|
|
||||||
} else {
|
|
||||||
d
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,25 +154,14 @@ pub extern "C" fn wasmtime_f64_trunc(x: f64) -> f64 {
|
|||||||
#[allow(clippy::float_arithmetic, clippy::float_cmp)]
|
#[allow(clippy::float_arithmetic, clippy::float_cmp)]
|
||||||
pub extern "C" fn wasmtime_f64_nearest(x: f64) -> f64 {
|
pub extern "C" fn wasmtime_f64_nearest(x: f64) -> f64 {
|
||||||
// Rust doesn't have a nearest function, so do it manually.
|
// Rust doesn't have a nearest function, so do it manually.
|
||||||
if x == 0.0 {
|
// Nearest is either ceil or floor depending on which is nearest or even.
|
||||||
// Preserve the sign of zero.
|
// 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
|
x
|
||||||
} else {
|
} else {
|
||||||
// Nearest is either ceil or floor depending on which is nearest or even.
|
(x.abs() + TOINT_64 - TOINT_64).copysign(x)
|
||||||
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
|
|
||||||
} else {
|
|
||||||
d
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user