about summary refs log tree commit diff
path: root/tests/ui/float/classify-runtime-const.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/float/classify-runtime-const.rs')
-rw-r--r--tests/ui/float/classify-runtime-const.rs130
1 files changed, 130 insertions, 0 deletions
diff --git a/tests/ui/float/classify-runtime-const.rs b/tests/ui/float/classify-runtime-const.rs
new file mode 100644
index 00000000000..b19e67d5284
--- /dev/null
+++ b/tests/ui/float/classify-runtime-const.rs
@@ -0,0 +1,130 @@
+//@ run-pass
+//@ revisions: opt noopt ctfe
+//@[opt] compile-flags: -O
+//@[noopt] compile-flags: -Zmir-opt-level=0
+// ignore-tidy-linelength
+
+// This tests the float classification functions, for regular runtime code and for const evaluation.
+
+#![feature(f16_const)]
+#![feature(f128_const)]
+#![feature(const_float_classify)]
+
+use std::num::FpCategory::*;
+
+#[cfg(not(ctfe))]
+use std::hint::black_box;
+#[cfg(ctfe)]
+#[allow(unused)]
+const fn black_box<T>(x: T) -> T { x }
+
+#[cfg(not(ctfe))]
+macro_rules! assert_test {
+    ($a:expr, NonDet) => {
+        {
+            // Compute `a`, but do not compare with anything as the result is non-deterministic.
+            let _val = $a;
+        }
+    };
+    ($a:expr, $b:ident) => {
+        {
+            // Let-bind to avoid promotion.
+            // No black_box here! That can mask x87 failures.
+            let a = $a;
+            let b = $b;
+            assert_eq!(a, b, "{} produces wrong result", stringify!($a));
+        }
+    };
+}
+#[cfg(ctfe)]
+macro_rules! assert_test {
+    ($a:expr, NonDet) => {
+        {
+            // Compute `a`, but do not compare with anything as the result is non-deterministic.
+            const _: () = { let _val = $a; };
+        }
+    };
+    ($a:expr, $b:ident) => {
+        {
+            const _: () = assert!(matches!($a, $b));
+        }
+    };
+}
+
+macro_rules! suite {
+    ( $tyname:ident => $( $tt:tt )* ) => {
+        fn f32() {
+            #[allow(unused)]
+            type $tyname = f32;
+            suite_inner!(f32 => $($tt)*);
+        }
+
+        fn f64() {
+            #[allow(unused)]
+            type $tyname = f64;
+            suite_inner!(f64 => $($tt)*);
+        }
+    }
+}
+
+macro_rules! suite_inner {
+    (
+        $ty:ident => [$( $fn:ident ),*]:
+        $(@cfg: $attr:meta)?
+        $val:expr => [$($out:ident),*],
+
+        $( $tail:tt )*
+    ) => {
+        $(#[cfg($attr)])?
+        {
+            // No black_box here! That can mask x87 failures.
+            $( assert_test!($ty::$fn($val), $out); )*
+        }
+        suite_inner!($ty => [$($fn),*]: $($tail)*)
+    };
+
+    ( $ty:ident => [$( $fn:ident ),*]:) => {};
+}
+
+// The result of the `is_sign` methods are not checked for correctness, since we do not
+// guarantee anything about the signedness of NaNs. See
+// https://rust-lang.github.io/rfcs/3514-float-semantics.html.
+
+suite! { T => // type alias for the type we are testing
+                    [ classify, is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative]:
+    black_box(0.0) / black_box(0.0) =>
+                    [      Nan,   true,       false,     false,     false,           NonDet,           NonDet],
+    black_box(0.0) / black_box(-0.0) =>
+                    [      Nan,   true,       false,     false,     false,           NonDet,           NonDet],
+    black_box(0.0) * black_box(T::INFINITY) =>
+                    [      Nan,   true,       false,     false,     false,           NonDet,           NonDet],
+    black_box(0.0) * black_box(T::NEG_INFINITY) =>
+                    [      Nan,   true,       false,     false,     false,           NonDet,           NonDet],
+             1.0 => [   Normal,  false,       false,      true,      true,             true,            false],
+            -1.0 => [   Normal,  false,       false,      true,      true,            false,             true],
+             0.0 => [     Zero,  false,       false,      true,     false,             true,            false],
+            -0.0 => [     Zero,  false,       false,      true,     false,            false,             true],
+    1.0 / black_box(0.0) =>
+                    [ Infinite,  false,        true,     false,     false,             true,            false],
+    -1.0 / black_box(0.0) =>
+                    [ Infinite,  false,        true,     false,     false,            false,             true],
+    2.0 * black_box(T::MAX) =>
+                    [ Infinite,  false,        true,     false,     false,             true,            false],
+    -2.0 * black_box(T::MAX) =>
+                    [ Infinite,  false,        true,     false,     false,            false,             true],
+    1.0 / black_box(T::MAX) =>
+                    [Subnormal,  false,       false,      true,     false,             true,            false],
+   -1.0 / black_box(T::MAX) =>
+                    [Subnormal,  false,       false,      true,     false,            false,             true],
+    // This specific expression causes trouble on x87 due to
+    // <https://github.com/rust-lang/rust/issues/114479>.
+    @cfg: not(all(target_arch = "x86", not(target_feature = "sse2")))
+    { let x = black_box(T::MAX); x * x } =>
+                    [ Infinite,  false,        true,     false,     false,             true,            false],
+}
+
+fn main() {
+    f32();
+    f64();
+    // FIXME(f16_f128): also test f16 and f128
+}