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:
MaxGraey
2020-08-31 19:02:20 +03:00
committed by Dan Gohman
parent a7f7c23bf9
commit a8f7041296

View File

@@ -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.
// Nearest is either ceil or floor depending on which is nearest or even.
// 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 {
// 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
} 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.
// Nearest is either ceil or floor depending on which is nearest or even.
// 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 {
// 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
} else {
d
}
(x.abs() + TOINT_64 - TOINT_64).copysign(x)
}
}