cranelift: Use round_ties_even for nearest in interpreter (#4413)
As @MaxGraey pointed out (thanks!) in #4397, `round` has different behavior from `nearest`. And it looks like the native rust implementation is still pending stabilization. Right now we duplicate the wasmtime implementation, merged in #2171. However, we definitely should switch to the rust native version when it is available.
This commit is contained in:
@@ -816,9 +816,20 @@ impl Ieee32 {
|
||||
Self::with_float(self.as_f32().trunc())
|
||||
}
|
||||
|
||||
/// Returns the nearest integer to `self`. Round half-way cases away from `0.0`.
|
||||
pub fn nearest(self) -> Self {
|
||||
Self::with_float(self.as_f32().round())
|
||||
/// Returns the nearest integer to `self`. Rounds half-way cases to the number
|
||||
/// with an even least significant digit.
|
||||
pub fn round_ties_even(self) -> Self {
|
||||
// TODO: Replace with the native implementation once
|
||||
// https://github.com/rust-lang/rust/issues/96710 is stabilized
|
||||
let toint_32: f32 = 1.0 / f32::EPSILON;
|
||||
|
||||
let f = self.as_f32();
|
||||
let e = self.0 >> 23 & 0xff;
|
||||
if e >= 0x7f_u32 + 23 {
|
||||
self
|
||||
} else {
|
||||
Self::with_float((f.abs() + toint_32 - toint_32).copysign(f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -965,9 +976,20 @@ impl Ieee64 {
|
||||
Self::with_float(self.as_f64().trunc())
|
||||
}
|
||||
|
||||
/// Returns the nearest integer to `self`. Round half-way cases away from `0.0`.
|
||||
pub fn nearest(self) -> Self {
|
||||
Self::with_float(self.as_f64().round())
|
||||
/// Returns the nearest integer to `self`. Rounds half-way cases to the number
|
||||
/// with an even least significant digit.
|
||||
pub fn round_ties_even(self) -> Self {
|
||||
// TODO: Replace with the native implementation once
|
||||
// https://github.com/rust-lang/rust/issues/96710 is stabilized
|
||||
let toint_64: f64 = 1.0 / f64::EPSILON;
|
||||
|
||||
let f = self.as_f64();
|
||||
let e = self.0 >> 52 & 0x7ff_u64;
|
||||
if e >= 0x3ff_u64 + 52 {
|
||||
self
|
||||
} else {
|
||||
Self::with_float((f.abs() + toint_64 - toint_64).copysign(f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,13 @@ block0(v0: f32):
|
||||
; run: %ceil_f32(0x1.5) == 0x1.0p1
|
||||
; run: %ceil_f32(0x2.9) == 0x1.8p1
|
||||
; run: %ceil_f32(0x1.1p10) == 0x1.1p10
|
||||
; run: %ceil_f32(0x1.400000p1) == 0x1.8p1
|
||||
; run: %ceil_f32(0x1.4cccccp0) == 0x1.0p1
|
||||
; run: %ceil_f32(0x1.800000p0) == 0x1.0p1
|
||||
; run: %ceil_f32(0x1.b33334p0) == 0x1.0p1
|
||||
; run: %ceil_f32(0x1.99999ap-2) == 0x1.0
|
||||
; run: %ceil_f32(0x1.333334p-1) == 0x1.0
|
||||
; run: %ceil_f32(0x1.666666p1) == 0x1.8p1
|
||||
|
||||
; Negatives
|
||||
; run: %ceil_f32(-0x0.5) == -0x0.0
|
||||
@@ -21,6 +28,13 @@ block0(v0: f32):
|
||||
; run: %ceil_f32(-0x1.5) == -0x1.0
|
||||
; run: %ceil_f32(-0x2.9) == -0x1.0p1
|
||||
; run: %ceil_f32(-0x1.1p10) == -0x1.1p10
|
||||
; run: %ceil_f32(-0x1.333334p-1) == -0x0.0
|
||||
; run: %ceil_f32(-0x1.99999ap-2) == -0x0.0
|
||||
; run: %ceil_f32(-0x1.4cccccp0) == -0x1.0
|
||||
; run: %ceil_f32(-0x1.800000p0) == -0x1.0
|
||||
; run: %ceil_f32(-0x1.b33334p0) == -0x1.0
|
||||
; run: %ceil_f32(-0x1.400000p1) == -0x1.0p1
|
||||
; run: %ceil_f32(-0x1.666666p1) == -0x1.0p1
|
||||
|
||||
; Specials
|
||||
; run: %ceil_f32(0x0.0) == 0x0.0
|
||||
@@ -71,6 +85,13 @@ block0(v0: f64):
|
||||
; run: %ceil_f64(0x1.5) == 0x1.0p1
|
||||
; run: %ceil_f64(0x2.9) == 0x1.8p1
|
||||
; run: %ceil_f64(0x1.1p10) == 0x1.1p10
|
||||
; run: %ceil_f64(0x1.4000000000000p1) == 0x1.8p1
|
||||
; run: %ceil_f64(0x1.4cccccccccccdp0) == 0x1.0p1
|
||||
; run: %ceil_f64(0x1.8000000000000p0) == 0x1.0p1
|
||||
; run: %ceil_f64(0x1.b333333333333p0) == 0x1.0p1
|
||||
; run: %ceil_f64(0x1.999999999999ap-2) == 0x1.0
|
||||
; run: %ceil_f64(0x1.3333333333333p-1) == 0x1.0
|
||||
; run: %ceil_f64(0x1.6666666666666p1) == 0x1.8p1
|
||||
|
||||
; Negatives
|
||||
; run: %ceil_f64(-0x0.5) == -0x0.0
|
||||
@@ -78,6 +99,13 @@ block0(v0: f64):
|
||||
; run: %ceil_f64(-0x1.5) == -0x1.0
|
||||
; run: %ceil_f64(-0x2.9) == -0x1.0p1
|
||||
; run: %ceil_f64(-0x1.1p10) == -0x1.1p10
|
||||
; run: %ceil_f64(-0x1.3333333333333p-1) == -0x0.0
|
||||
; run: %ceil_f64(-0x1.999999999999ap-2) == -0x0.0
|
||||
; run: %ceil_f64(-0x1.4cccccccccccdp0) == -0x1.0
|
||||
; run: %ceil_f64(-0x1.8000000000000p0) == -0x1.0
|
||||
; run: %ceil_f64(-0x1.b333333333333p0) == -0x1.0
|
||||
; run: %ceil_f64(-0x1.4000000000000p1) == -0x1.0p1
|
||||
; run: %ceil_f64(-0x1.6666666666666p1) == -0x1.0p1
|
||||
|
||||
; Specials
|
||||
; run: %ceil_f64(0x0.0) == 0x0.0
|
||||
|
||||
@@ -14,6 +14,13 @@ block0(v0: f32):
|
||||
; run: %floor_f32(0x1.5) == 0x1.0
|
||||
; run: %floor_f32(0x2.9) == 0x1.0p1
|
||||
; run: %floor_f32(0x1.1p10) == 0x1.1p10
|
||||
; run: %floor_f32(0x1.400000p1) == 0x1.0p1
|
||||
; run: %floor_f32(0x1.4cccccp0) == 0x1.0
|
||||
; run: %floor_f32(0x1.800000p0) == 0x1.0
|
||||
; run: %floor_f32(0x1.b33334p0) == 0x1.0
|
||||
; run: %floor_f32(0x1.99999ap-2) == 0x0.0
|
||||
; run: %floor_f32(0x1.333334p-1) == 0x0.0
|
||||
; run: %floor_f32(0x1.666666p1) == 0x1.0p1
|
||||
|
||||
; Negatives
|
||||
; run: %floor_f32(-0x0.5) == -0x1.0
|
||||
@@ -21,6 +28,13 @@ block0(v0: f32):
|
||||
; run: %floor_f32(-0x1.5) == -0x1.0p1
|
||||
; run: %floor_f32(-0x2.9) == -0x1.8p1
|
||||
; run: %floor_f32(-0x1.1p10) == -0x1.1p10
|
||||
; run: %floor_f32(-0x1.333334p-1) == -0x1.0
|
||||
; run: %floor_f32(-0x1.99999ap-2) == -0x1.0
|
||||
; run: %floor_f32(-0x1.4cccccp0) == -0x1.0p1
|
||||
; run: %floor_f32(-0x1.800000p0) == -0x1.0p1
|
||||
; run: %floor_f32(-0x1.b33334p0) == -0x1.0p1
|
||||
; run: %floor_f32(-0x1.400000p1) == -0x1.8p1
|
||||
; run: %floor_f32(-0x1.666666p1) == -0x1.8p1
|
||||
|
||||
; Specials
|
||||
; run: %floor_f32(0x0.0) == 0x0.0
|
||||
@@ -71,6 +85,13 @@ block0(v0: f64):
|
||||
; run: %floor_f64(0x1.5) == 0x1.0
|
||||
; run: %floor_f64(0x2.9) == 0x1.0p1
|
||||
; run: %floor_f64(0x1.1p10) == 0x1.1p10
|
||||
; run: %floor_f64(0x1.4000000000000p1) == 0x1.0p1
|
||||
; run: %floor_f64(0x1.4cccccccccccdp0) == 0x1.0
|
||||
; run: %floor_f64(0x1.8000000000000p0) == 0x1.0
|
||||
; run: %floor_f64(0x1.b333333333333p0) == 0x1.0
|
||||
; run: %floor_f64(0x1.999999999999ap-2) == 0x0.0
|
||||
; run: %floor_f64(0x1.3333333333333p-1) == 0x0.0
|
||||
; run: %floor_f64(0x1.6666666666666p1) == 0x1.0p1
|
||||
|
||||
; Negatives
|
||||
; run: %floor_f64(-0x0.5) == -0x1.0
|
||||
@@ -78,6 +99,13 @@ block0(v0: f64):
|
||||
; run: %floor_f64(-0x1.5) == -0x1.0p1
|
||||
; run: %floor_f64(-0x2.9) == -0x1.8p1
|
||||
; run: %floor_f64(-0x1.1p10) == -0x1.1p10
|
||||
; run: %floor_f64(-0x1.3333333333333p-1) == -0x1.0
|
||||
; run: %floor_f64(-0x1.999999999999ap-2) == -0x1.0
|
||||
; run: %floor_f64(-0x1.4cccccccccccdp0) == -0x1.0p1
|
||||
; run: %floor_f64(-0x1.8000000000000p0) == -0x1.0p1
|
||||
; run: %floor_f64(-0x1.b333333333333p0) == -0x1.0p1
|
||||
; run: %floor_f64(-0x1.4000000000000p1) == -0x1.8p1
|
||||
; run: %floor_f64(-0x1.6666666666666p1) == -0x1.8p1
|
||||
|
||||
; Specials
|
||||
; run: %floor_f64(0x0.0) == 0x0.0
|
||||
|
||||
@@ -14,6 +14,13 @@ block0(v0: f32):
|
||||
; run: %nearest_f32(0x1.5) == 0x1.0
|
||||
; run: %nearest_f32(0x2.9) == 0x1.8p1
|
||||
; run: %nearest_f32(0x1.1p10) == 0x1.1p10
|
||||
; run: %nearest_f32(0x1.400000p1) == 0x1.0p1
|
||||
; run: %nearest_f32(0x1.4cccccp0) == 0x1.0
|
||||
; run: %nearest_f32(0x1.800000p0) == 0x1.0p1
|
||||
; run: %nearest_f32(0x1.b33334p0) == 0x1.0p1
|
||||
; run: %nearest_f32(0x1.99999ap-2) == 0x0.0
|
||||
; run: %nearest_f32(0x1.333334p-1) == 0x1.0
|
||||
; run: %nearest_f32(0x1.666666p1) == 0x1.8p1
|
||||
|
||||
; Negatives
|
||||
; run: %nearest_f32(-0x0.5) == -0x0.0
|
||||
@@ -21,6 +28,13 @@ block0(v0: f32):
|
||||
; run: %nearest_f32(-0x1.5) == -0x1.0
|
||||
; run: %nearest_f32(-0x2.9) == -0x1.8p1
|
||||
; run: %nearest_f32(-0x1.1p10) == -0x1.1p10
|
||||
; run: %nearest_f32(-0x1.333334p-1) == -0x1.0
|
||||
; run: %nearest_f32(-0x1.99999ap-2) == -0x0.0
|
||||
; run: %nearest_f32(-0x1.4cccccp0) == -0x1.0
|
||||
; run: %nearest_f32(-0x1.800000p0) == -0x1.0p1
|
||||
; run: %nearest_f32(-0x1.b33334p0) == -0x1.0p1
|
||||
; run: %nearest_f32(-0x1.400000p1) == -0x1.0p1
|
||||
; run: %nearest_f32(-0x1.666666p1) == -0x1.8p1
|
||||
|
||||
; Specials
|
||||
; run: %nearest_f32(0x0.0) == 0x0.0
|
||||
@@ -71,6 +85,13 @@ block0(v0: f64):
|
||||
; run: %nearest_f64(0x1.5) == 0x1.0
|
||||
; run: %nearest_f64(0x2.9) == 0x1.8p1
|
||||
; run: %nearest_f64(0x1.1p10) == 0x1.1p10
|
||||
; run: %nearest_f64(0x1.4000000000000p1) == 0x1.0p1
|
||||
; run: %nearest_f64(0x1.4cccccccccccdp0) == 0x1.0
|
||||
; run: %nearest_f64(0x1.8000000000000p0) == 0x1.0p1
|
||||
; run: %nearest_f64(0x1.b333333333333p0) == 0x1.0p1
|
||||
; run: %nearest_f64(0x1.999999999999ap-2) == 0x0.0
|
||||
; run: %nearest_f64(0x1.3333333333333p-1) == 0x1.0
|
||||
; run: %nearest_f64(0x1.6666666666666p1) == 0x1.8p1
|
||||
|
||||
; Negatives
|
||||
; run: %nearest_f64(-0x0.5) == -0x0.0
|
||||
@@ -78,6 +99,13 @@ block0(v0: f64):
|
||||
; run: %nearest_f64(-0x1.5) == -0x1.0
|
||||
; run: %nearest_f64(-0x2.9) == -0x1.8p1
|
||||
; run: %nearest_f64(-0x1.1p10) == -0x1.1p10
|
||||
; run: %nearest_f64(-0x1.3333333333333p-1) == -0x1.0
|
||||
; run: %nearest_f64(-0x1.999999999999ap-2) == -0x0.0
|
||||
; run: %nearest_f64(-0x1.4cccccccccccdp0) == -0x1.0
|
||||
; run: %nearest_f64(-0x1.8000000000000p0) == -0x1.0p1
|
||||
; run: %nearest_f64(-0x1.b333333333333p0) == -0x1.0p1
|
||||
; run: %nearest_f64(-0x1.4000000000000p1) == -0x1.0p1
|
||||
; run: %nearest_f64(-0x1.6666666666666p1) == -0x1.8p1
|
||||
|
||||
; Specials
|
||||
; run: %nearest_f64(0x0.0) == 0x0.0
|
||||
|
||||
@@ -14,6 +14,13 @@ block0(v0: f32):
|
||||
; run: %trunc_f32(0x1.5) == 0x1.0
|
||||
; run: %trunc_f32(0x2.9) == 0x1.0p1
|
||||
; run: %trunc_f32(0x1.1p10) == 0x1.1p10
|
||||
; run: %trunc_f32(0x1.400000p1) == 0x1.0p1
|
||||
; run: %trunc_f32(0x1.4cccccp0) == 0x1.0
|
||||
; run: %trunc_f32(0x1.800000p0) == 0x1.0
|
||||
; run: %trunc_f32(0x1.b33334p0) == 0x1.0
|
||||
; run: %trunc_f32(0x1.99999ap-2) == 0x0.0
|
||||
; run: %trunc_f32(0x1.333334p-1) == 0x0.0
|
||||
; run: %trunc_f32(0x1.666666p1) == 0x1.0p1
|
||||
|
||||
; Negatives
|
||||
; run: %trunc_f32(-0x0.5) == -0x0.0
|
||||
@@ -21,6 +28,13 @@ block0(v0: f32):
|
||||
; run: %trunc_f32(-0x1.5) == -0x1.0
|
||||
; run: %trunc_f32(-0x2.9) == -0x1.0p1
|
||||
; run: %trunc_f32(-0x1.1p10) == -0x1.1p10
|
||||
; run: %trunc_f32(-0x1.333334p-1) == -0x0.0
|
||||
; run: %trunc_f32(-0x1.99999ap-2) == -0x0.0
|
||||
; run: %trunc_f32(-0x1.4cccccp0) == -0x1.0
|
||||
; run: %trunc_f32(-0x1.800000p0) == -0x1.0
|
||||
; run: %trunc_f32(-0x1.b33334p0) == -0x1.0
|
||||
; run: %trunc_f32(-0x1.400000p1) == -0x1.0p1
|
||||
; run: %trunc_f32(-0x1.666666p1) == -0x1.0p1
|
||||
|
||||
; Specials
|
||||
; run: %trunc_f32(0x0.0) == 0x0.0
|
||||
@@ -71,6 +85,13 @@ block0(v0: f64):
|
||||
; run: %trunc_f64(0x1.5) == 0x1.0
|
||||
; run: %trunc_f64(0x2.9) == 0x1.0p1
|
||||
; run: %trunc_f64(0x1.1p10) == 0x1.1p10
|
||||
; run: %trunc_f64(0x1.4000000000000p1) == 0x1.0p1
|
||||
; run: %trunc_f64(0x1.4cccccccccccdp0) == 0x1.0
|
||||
; run: %trunc_f64(0x1.8000000000000p0) == 0x1.0
|
||||
; run: %trunc_f64(0x1.b333333333333p0) == 0x1.0
|
||||
; run: %trunc_f64(0x1.999999999999ap-2) == 0x0.0
|
||||
; run: %trunc_f64(0x1.3333333333333p-1) == 0x0.0
|
||||
; run: %trunc_f64(0x1.6666666666666p1) == 0x1.0p1
|
||||
|
||||
; Negatives
|
||||
; run: %trunc_f64(-0x0.5) == -0x0.0
|
||||
@@ -78,6 +99,13 @@ block0(v0: f64):
|
||||
; run: %trunc_f64(-0x1.5) == -0x1.0
|
||||
; run: %trunc_f64(-0x2.9) == -0x1.0p1
|
||||
; run: %trunc_f64(-0x1.1p10) == -0x1.1p10
|
||||
; run: %trunc_f64(-0x1.3333333333333p-1) == -0x0.0
|
||||
; run: %trunc_f64(-0x1.999999999999ap-2) == -0x0.0
|
||||
; run: %trunc_f64(-0x1.4cccccccccccdp0) == -0x1.0
|
||||
; run: %trunc_f64(-0x1.8000000000000p0) == -0x1.0
|
||||
; run: %trunc_f64(-0x1.b333333333333p0) == -0x1.0
|
||||
; run: %trunc_f64(-0x1.4000000000000p1) == -0x1.0p1
|
||||
; run: %trunc_f64(-0x1.6666666666666p1) == -0x1.0p1
|
||||
|
||||
; Specials
|
||||
; run: %trunc_f64(0x0.0) == 0x0.0
|
||||
|
||||
@@ -534,7 +534,7 @@ impl Value for DataValue {
|
||||
}
|
||||
|
||||
fn nearest(self) -> ValueResult<Self> {
|
||||
unary_match!(nearest(&self); [F32, F64])
|
||||
unary_match!(round_ties_even(&self); [F32, F64])
|
||||
}
|
||||
|
||||
fn add_sat(self, other: Self) -> ValueResult<Self> {
|
||||
|
||||
Reference in New Issue
Block a user