about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBen Kimock <kimockb@gmail.com>2023-03-10 22:28:31 -0500
committerBen Kimock <kimockb@gmail.com>2023-03-11 14:43:41 -0500
commit0ea51e101e7c6bf56b83572e2d818a6da3c907e7 (patch)
treed0135fd35529d6baab3d8035fc1e2b535d30d291
parent0f1f7b0840885fac83ff3f36053cb04833c1af5a (diff)
downloadrust-0ea51e101e7c6bf56b83572e2d818a6da3c907e7.tar.gz
rust-0ea51e101e7c6bf56b83572e2d818a6da3c907e7.zip
Implement intrinsics for round_ties_even
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/src/shims/intrinsics/mod.rs4
-rw-r--r--src/tools/miri/tests/pass/float.rs30
3 files changed, 35 insertions, 0 deletions
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index f64f216520f..5412507ecfa 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -9,6 +9,7 @@
 #![feature(nonzero_ops)]
 #![feature(local_key_cell_methods)]
 #![feature(is_terminal)]
+#![feature(round_ties_even)]
 // Configure clippy and other lints
 #![allow(
     clippy::collapsible_else_if,
diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs
index d21a1560699..9ecbb18ef5a 100644
--- a/src/tools/miri/src/shims/intrinsics/mod.rs
+++ b/src/tools/miri/src/shims/intrinsics/mod.rs
@@ -157,6 +157,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             | "ceilf32"
             | "truncf32"
             | "roundf32"
+            | "rintf32"
             => {
                 let [f] = check_arg_count(args)?;
                 // FIXME: Using host floats.
@@ -174,6 +175,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     "ceilf32" => f.ceil(),
                     "truncf32" => f.trunc(),
                     "roundf32" => f.round(),
+                    "rintf32" => f.round_ties_even(),
                     _ => bug!(),
                 };
                 this.write_scalar(Scalar::from_u32(f.to_bits()), dest)?;
@@ -192,6 +194,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             | "ceilf64"
             | "truncf64"
             | "roundf64"
+            | "rintf64"
             => {
                 let [f] = check_arg_count(args)?;
                 // FIXME: Using host floats.
@@ -209,6 +212,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     "ceilf64" => f.ceil(),
                     "truncf64" => f.trunc(),
                     "roundf64" => f.round(),
+                    "rintf64" => f.round_ties_even(),
                     _ => bug!(),
                 };
                 this.write_scalar(Scalar::from_u64(f.to_bits()), dest)?;
diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs
index ce62fb0de04..fee5ca44ffb 100644
--- a/src/tools/miri/tests/pass/float.rs
+++ b/src/tools/miri/tests/pass/float.rs
@@ -1,4 +1,5 @@
 #![feature(stmt_expr_attributes)]
+#![feature(round_ties_even)]
 #![allow(arithmetic_overflow)]
 use std::fmt::Debug;
 use std::hint::black_box;
@@ -9,6 +10,7 @@ fn main() {
     more_casts();
     ops();
     nan_casts();
+    rounding();
 }
 
 // Helper function to avoid promotion so that this tests "run-time" casts, not CTFE.
@@ -553,3 +555,31 @@ fn nan_casts() {
     assert!(nan1_32.is_nan());
     assert!(nan2_32.is_nan());
 }
+
+fn rounding() {
+    // Test cases taken from the library's tests for this feature
+    // f32
+    assert_eq(2.5f32.round_ties_even(), 2.0f32);
+    assert_eq(1.0f32.round_ties_even(), 1.0f32);
+    assert_eq(1.3f32.round_ties_even(), 1.0f32);
+    assert_eq(1.5f32.round_ties_even(), 2.0f32);
+    assert_eq(1.7f32.round_ties_even(), 2.0f32);
+    assert_eq(0.0f32.round_ties_even(), 0.0f32);
+    assert_eq((-0.0f32).round_ties_even(), -0.0f32);
+    assert_eq((-1.0f32).round_ties_even(), -1.0f32);
+    assert_eq((-1.3f32).round_ties_even(), -1.0f32);
+    assert_eq((-1.5f32).round_ties_even(), -2.0f32);
+    assert_eq((-1.7f32).round_ties_even(), -2.0f32);
+    // f64
+    assert_eq(2.5f64.round_ties_even(), 2.0f64);
+    assert_eq(1.0f64.round_ties_even(), 1.0f64);
+    assert_eq(1.3f64.round_ties_even(), 1.0f64);
+    assert_eq(1.5f64.round_ties_even(), 2.0f64);
+    assert_eq(1.7f64.round_ties_even(), 2.0f64);
+    assert_eq(0.0f64.round_ties_even(), 0.0f64);
+    assert_eq((-0.0f64).round_ties_even(), -0.0f64);
+    assert_eq((-1.0f64).round_ties_even(), -1.0f64);
+    assert_eq((-1.3f64).round_ties_even(), -1.0f64);
+    assert_eq((-1.5f64).round_ties_even(), -2.0f64);
+    assert_eq((-1.7f64).round_ties_even(), -2.0f64);
+}