about summary refs log tree commit diff
path: root/src/tools/miri/tests/pass/float_nan.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/miri/tests/pass/float_nan.rs')
-rw-r--r--src/tools/miri/tests/pass/float_nan.rs325
1 files changed, 147 insertions, 178 deletions
diff --git a/src/tools/miri/tests/pass/float_nan.rs b/src/tools/miri/tests/pass/float_nan.rs
index 3ffdb6868ac..90281630740 100644
--- a/src/tools/miri/tests/pass/float_nan.rs
+++ b/src/tools/miri/tests/pass/float_nan.rs
@@ -1,7 +1,8 @@
+// This test's runtime explodes if the GC interval is set to 1 (which we do in CI), so we
+// override it internally back to the default frequency.
+//@compile-flags: -Zmiri-provenance-gc=10000
 #![feature(float_gamma, portable_simd, core_intrinsics)]
-use std::collections::HashSet;
 use std::fmt;
-use std::hash::Hash;
 use std::hint::black_box;
 
 fn ldexp(a: f64, b: i32) -> f64 {
@@ -25,15 +26,26 @@ enum NaNKind {
 }
 use NaNKind::*;
 
+/// Check that the function produces the intended set of outcomes.
 #[track_caller]
-fn check_all_outcomes<T: Eq + Hash + fmt::Display>(expected: HashSet<T>, generate: impl Fn() -> T) {
+fn check_all_outcomes<T: Eq + std::hash::Hash + fmt::Display>(
+    expected: impl IntoIterator<Item = T>,
+    generate: impl Fn() -> T,
+) {
+    use std::collections::HashSet;
+
+    let expected: HashSet<T> = HashSet::from_iter(expected);
     let mut seen = HashSet::new();
-    // Let's give it sixteen times as many tries as we are expecting values.
-    let tries = expected.len() * 16;
-    for _ in 0..tries {
+    // Let's give it N times as many tries as we are expecting values.
+    let tries = expected.len() * 12;
+    for i in 0..tries {
         let val = generate();
         assert!(expected.contains(&val), "got an unexpected value: {val}");
         seen.insert(val);
+        if i > tries / 2 && expected.len() == seen.len() {
+            // We saw everything and we did quite a few tries, let's avoid wasting time.
+            return;
+        }
     }
     // Let's see if we saw them all.
     for val in expected {
@@ -193,51 +205,50 @@ impl F64 {
 
 fn test_f32() {
     // Freshly generated NaNs can have either sign.
-    check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(0.0 / black_box(0.0)),
-    );
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(0.0 / black_box(0.0))
+    });
     // When there are NaN inputs, their payload can be propagated, with any sign.
     let all1_payload = u32_ones(22);
     let all1 = F32::nan(Pos, Quiet, all1_payload).as_f32();
     check_all_outcomes(
-        HashSet::from_iter([
+        [
             F32::nan(Pos, Quiet, 0),
             F32::nan(Neg, Quiet, 0),
             F32::nan(Pos, Quiet, all1_payload),
             F32::nan(Neg, Quiet, all1_payload),
-        ]),
+        ],
         || F32::from(0.0 + all1),
     );
     // When there are two NaN inputs, the output can be either one, or the preferred NaN.
     let just1 = F32::nan(Neg, Quiet, 1).as_f32();
     check_all_outcomes(
-        HashSet::from_iter([
+        [
             F32::nan(Pos, Quiet, 0),
             F32::nan(Neg, Quiet, 0),
             F32::nan(Pos, Quiet, 1),
             F32::nan(Neg, Quiet, 1),
             F32::nan(Pos, Quiet, all1_payload),
             F32::nan(Neg, Quiet, all1_payload),
-        ]),
+        ],
         || F32::from(just1 - all1),
     );
     // When there are *signaling* NaN inputs, they might be quieted or not.
     let all1_snan = F32::nan(Pos, Signaling, all1_payload).as_f32();
     check_all_outcomes(
-        HashSet::from_iter([
+        [
             F32::nan(Pos, Quiet, 0),
             F32::nan(Neg, Quiet, 0),
             F32::nan(Pos, Quiet, all1_payload),
             F32::nan(Neg, Quiet, all1_payload),
             F32::nan(Pos, Signaling, all1_payload),
             F32::nan(Neg, Signaling, all1_payload),
-        ]),
+        ],
         || F32::from(0.0 * all1_snan),
     );
     // Mix signaling and non-signaling NaN.
     check_all_outcomes(
-        HashSet::from_iter([
+        [
             F32::nan(Pos, Quiet, 0),
             F32::nan(Neg, Quiet, 0),
             F32::nan(Pos, Quiet, 1),
@@ -246,35 +257,26 @@ fn test_f32() {
             F32::nan(Neg, Quiet, all1_payload),
             F32::nan(Pos, Signaling, all1_payload),
             F32::nan(Neg, Signaling, all1_payload),
-        ]),
+        ],
         || F32::from(just1 % all1_snan),
     );
 
     // Unary `-` must preserve payloads exactly.
-    check_all_outcomes(HashSet::from_iter([F32::nan(Neg, Quiet, all1_payload)]), || {
-        F32::from(-all1)
-    });
-    check_all_outcomes(HashSet::from_iter([F32::nan(Neg, Signaling, all1_payload)]), || {
-        F32::from(-all1_snan)
-    });
+    check_all_outcomes([F32::nan(Neg, Quiet, all1_payload)], || F32::from(-all1));
+    check_all_outcomes([F32::nan(Neg, Signaling, all1_payload)], || F32::from(-all1_snan));
 
     // Intrinsics
     let nan = F32::nan(Neg, Quiet, 0).as_f32();
     let snan = F32::nan(Neg, Signaling, 1).as_f32();
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(f32::min(nan, nan))
+    });
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(nan.floor())
+    });
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || F32::from(nan.sin()));
     check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(f32::min(nan, nan)),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(nan.floor()),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(nan.sin()),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([
+        [
             F32::nan(Pos, Quiet, 0),
             F32::nan(Neg, Quiet, 0),
             F32::nan(Pos, Quiet, 1),
@@ -285,37 +287,32 @@ fn test_f32() {
             F32::nan(Neg, Quiet, all1_payload),
             F32::nan(Pos, Signaling, all1_payload),
             F32::nan(Neg, Signaling, all1_payload),
-        ]),
+        ],
         || F32::from(just1.mul_add(F32::nan(Neg, Quiet, 2).as_f32(), all1_snan)),
     );
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(nan.powf(nan))
+    });
     check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(nan.powf(nan)),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([1.0f32.into()]),
+        [1.0f32.into()],
         || F32::from(1.0f32.powf(nan)), // special `pow` rule
     );
-    check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(nan.powi(1)),
-    );
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(nan.powi(1))
+    });
 
     // libm functions
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(nan.sinh())
+    });
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(nan.atan2(nan))
+    });
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(nan.ln_gamma().0)
+    });
     check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(nan.sinh()),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(nan.atan2(nan)),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(nan.ln_gamma().0),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([
+        [
             F32::from(1.0),
             F32::nan(Pos, Quiet, 0),
             F32::nan(Neg, Quiet, 0),
@@ -323,58 +320,57 @@ fn test_f32() {
             F32::nan(Neg, Quiet, 1),
             F32::nan(Pos, Signaling, 1),
             F32::nan(Neg, Signaling, 1),
-        ]),
+        ],
         || F32::from(snan.powf(0.0)),
     );
 }
 
 fn test_f64() {
     // Freshly generated NaNs can have either sign.
-    check_all_outcomes(
-        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
-        || F64::from(0.0 / black_box(0.0)),
-    );
+    check_all_outcomes([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)], || {
+        F64::from(0.0 / black_box(0.0))
+    });
     // When there are NaN inputs, their payload can be propagated, with any sign.
     let all1_payload = u64_ones(51);
     let all1 = F64::nan(Pos, Quiet, all1_payload).as_f64();
     check_all_outcomes(
-        HashSet::from_iter([
+        [
             F64::nan(Pos, Quiet, 0),
             F64::nan(Neg, Quiet, 0),
             F64::nan(Pos, Quiet, all1_payload),
             F64::nan(Neg, Quiet, all1_payload),
-        ]),
+        ],
         || F64::from(0.0 + all1),
     );
     // When there are two NaN inputs, the output can be either one, or the preferred NaN.
     let just1 = F64::nan(Neg, Quiet, 1).as_f64();
     check_all_outcomes(
-        HashSet::from_iter([
+        [
             F64::nan(Pos, Quiet, 0),
             F64::nan(Neg, Quiet, 0),
             F64::nan(Pos, Quiet, 1),
             F64::nan(Neg, Quiet, 1),
             F64::nan(Pos, Quiet, all1_payload),
             F64::nan(Neg, Quiet, all1_payload),
-        ]),
+        ],
         || F64::from(just1 - all1),
     );
     // When there are *signaling* NaN inputs, they might be quieted or not.
     let all1_snan = F64::nan(Pos, Signaling, all1_payload).as_f64();
     check_all_outcomes(
-        HashSet::from_iter([
+        [
             F64::nan(Pos, Quiet, 0),
             F64::nan(Neg, Quiet, 0),
             F64::nan(Pos, Quiet, all1_payload),
             F64::nan(Neg, Quiet, all1_payload),
             F64::nan(Pos, Signaling, all1_payload),
             F64::nan(Neg, Signaling, all1_payload),
-        ]),
+        ],
         || F64::from(0.0 * all1_snan),
     );
     // Mix signaling and non-signaling NaN.
     check_all_outcomes(
-        HashSet::from_iter([
+        [
             F64::nan(Pos, Quiet, 0),
             F64::nan(Neg, Quiet, 0),
             F64::nan(Pos, Quiet, 1),
@@ -383,27 +379,22 @@ fn test_f64() {
             F64::nan(Neg, Quiet, all1_payload),
             F64::nan(Pos, Signaling, all1_payload),
             F64::nan(Neg, Signaling, all1_payload),
-        ]),
+        ],
         || F64::from(just1 % all1_snan),
     );
 
     // Intrinsics
     let nan = F64::nan(Neg, Quiet, 0).as_f64();
     let snan = F64::nan(Neg, Signaling, 1).as_f64();
+    check_all_outcomes([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)], || {
+        F64::from(f64::min(nan, nan))
+    });
+    check_all_outcomes([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)], || {
+        F64::from(nan.floor())
+    });
+    check_all_outcomes([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)], || F64::from(nan.sin()));
     check_all_outcomes(
-        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
-        || F64::from(f64::min(nan, nan)),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
-        || F64::from(nan.floor()),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
-        || F64::from(nan.sin()),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([
+        [
             F64::nan(Pos, Quiet, 0),
             F64::nan(Neg, Quiet, 0),
             F64::nan(Pos, Quiet, 1),
@@ -414,41 +405,35 @@ fn test_f64() {
             F64::nan(Neg, Quiet, all1_payload),
             F64::nan(Pos, Signaling, all1_payload),
             F64::nan(Neg, Signaling, all1_payload),
-        ]),
+        ],
         || F64::from(just1.mul_add(F64::nan(Neg, Quiet, 2).as_f64(), all1_snan)),
     );
+    check_all_outcomes([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)], || {
+        F64::from(nan.powf(nan))
+    });
     check_all_outcomes(
-        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
-        || F64::from(nan.powf(nan)),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([1.0f64.into()]),
+        [1.0f64.into()],
         || F64::from(1.0f64.powf(nan)), // special `pow` rule
     );
-    check_all_outcomes(
-        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
-        || F64::from(nan.powi(1)),
-    );
+    check_all_outcomes([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)], || {
+        F64::from(nan.powi(1))
+    });
 
     // libm functions
+    check_all_outcomes([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)], || {
+        F64::from(nan.sinh())
+    });
+    check_all_outcomes([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)], || {
+        F64::from(nan.atan2(nan))
+    });
+    check_all_outcomes([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)], || {
+        F64::from(ldexp(nan, 1))
+    });
+    check_all_outcomes([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)], || {
+        F64::from(nan.ln_gamma().0)
+    });
     check_all_outcomes(
-        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
-        || F64::from(nan.sinh()),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
-        || F64::from(nan.atan2(nan)),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
-        || F64::from(ldexp(nan, 1)),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
-        || F64::from(nan.ln_gamma().0),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([
+        [
             F64::from(1.0),
             F64::nan(Pos, Quiet, 0),
             F64::nan(Neg, Quiet, 0),
@@ -456,7 +441,7 @@ fn test_f64() {
             F64::nan(Neg, Quiet, 1),
             F64::nan(Pos, Signaling, 1),
             F64::nan(Neg, Signaling, 1),
-        ]),
+        ],
         || F64::from(snan.powf(0.0)),
     );
 }
@@ -467,82 +452,79 @@ fn test_casts() {
     let left1_payload_64 = (all1_payload_32 as u64) << (51 - 22);
 
     // 64-to-32
-    check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(F64::nan(Pos, Quiet, 0).as_f64() as f32),
-    );
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(F64::nan(Pos, Quiet, 0).as_f64() as f32)
+    });
     // The preferred payload is always a possibility.
     check_all_outcomes(
-        HashSet::from_iter([
+        [
             F32::nan(Pos, Quiet, 0),
             F32::nan(Neg, Quiet, 0),
             F32::nan(Pos, Quiet, all1_payload_32),
             F32::nan(Neg, Quiet, all1_payload_32),
-        ]),
+        ],
         || F32::from(F64::nan(Pos, Quiet, all1_payload_64).as_f64() as f32),
     );
     // If the input is signaling, then the output *may* also be signaling.
     check_all_outcomes(
-        HashSet::from_iter([
+        [
             F32::nan(Pos, Quiet, 0),
             F32::nan(Neg, Quiet, 0),
             F32::nan(Pos, Quiet, all1_payload_32),
             F32::nan(Neg, Quiet, all1_payload_32),
             F32::nan(Pos, Signaling, all1_payload_32),
             F32::nan(Neg, Signaling, all1_payload_32),
-        ]),
+        ],
         || F32::from(F64::nan(Pos, Signaling, all1_payload_64).as_f64() as f32),
     );
     // Check that the low bits are gone (not the high bits).
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(F64::nan(Pos, Quiet, 1).as_f64() as f32)
+    });
     check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(F64::nan(Pos, Quiet, 1).as_f64() as f32),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([
+        [
             F32::nan(Pos, Quiet, 0),
             F32::nan(Neg, Quiet, 0),
             F32::nan(Pos, Quiet, 1),
             F32::nan(Neg, Quiet, 1),
-        ]),
+        ],
         || F32::from(F64::nan(Pos, Quiet, 1 << (51 - 22)).as_f64() as f32),
     );
     check_all_outcomes(
-        HashSet::from_iter([
+        [
             F32::nan(Pos, Quiet, 0),
             F32::nan(Neg, Quiet, 0),
             // The `1` payload becomes `0`, and the `0` payload cannot be signaling,
             // so these are the only options.
-        ]),
+        ],
         || F32::from(F64::nan(Pos, Signaling, 1).as_f64() as f32),
     );
 
     // 32-to-64
-    check_all_outcomes(
-        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
-        || F64::from(F32::nan(Pos, Quiet, 0).as_f32() as f64),
-    );
+    check_all_outcomes([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)], || {
+        F64::from(F32::nan(Pos, Quiet, 0).as_f32() as f64)
+    });
     // The preferred payload is always a possibility.
     // Also checks that 0s are added on the right.
     check_all_outcomes(
-        HashSet::from_iter([
+        [
             F64::nan(Pos, Quiet, 0),
             F64::nan(Neg, Quiet, 0),
             F64::nan(Pos, Quiet, left1_payload_64),
             F64::nan(Neg, Quiet, left1_payload_64),
-        ]),
+        ],
         || F64::from(F32::nan(Pos, Quiet, all1_payload_32).as_f32() as f64),
     );
     // If the input is signaling, then the output *may* also be signaling.
     check_all_outcomes(
-        HashSet::from_iter([
+        [
             F64::nan(Pos, Quiet, 0),
             F64::nan(Neg, Quiet, 0),
             F64::nan(Pos, Quiet, left1_payload_64),
             F64::nan(Neg, Quiet, left1_payload_64),
             F64::nan(Pos, Signaling, left1_payload_64),
             F64::nan(Neg, Signaling, left1_payload_64),
-        ]),
+        ],
         || F64::from(F32::nan(Pos, Signaling, all1_payload_32).as_f32() as f64),
     );
 }
@@ -552,48 +534,35 @@ fn test_simd() {
     use std::simd::*;
 
     let nan = F32::nan(Neg, Quiet, 0).as_f32();
-    check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(unsafe { simd_div(f32x4::splat(0.0), f32x4::splat(0.0)) }[0]),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(unsafe { simd_fmin(f32x4::splat(nan), f32x4::splat(nan)) }[0]),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(unsafe { simd_fmax(f32x4::splat(nan), f32x4::splat(nan)) }[0]),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || {
-            F32::from(
-                unsafe { simd_fma(f32x4::splat(nan), f32x4::splat(nan), f32x4::splat(nan)) }[0],
-            )
-        },
-    );
-    check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(unsafe { simd_reduce_add_ordered::<_, f32>(f32x4::splat(nan), nan) }),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(unsafe { simd_reduce_max::<_, f32>(f32x4::splat(nan)) }),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(unsafe { simd_fsqrt(f32x4::splat(nan)) }[0]),
-    );
-    check_all_outcomes(
-        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
-        || F32::from(unsafe { simd_ceil(f32x4::splat(nan)) }[0]),
-    );
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(unsafe { simd_div(f32x4::splat(0.0), f32x4::splat(0.0)) }[0])
+    });
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(unsafe { simd_fmin(f32x4::splat(nan), f32x4::splat(nan)) }[0])
+    });
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(unsafe { simd_fmax(f32x4::splat(nan), f32x4::splat(nan)) }[0])
+    });
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(unsafe { simd_fma(f32x4::splat(nan), f32x4::splat(nan), f32x4::splat(nan)) }[0])
+    });
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(unsafe { simd_reduce_add_ordered::<_, f32>(f32x4::splat(nan), nan) })
+    });
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(unsafe { simd_reduce_max::<_, f32>(f32x4::splat(nan)) })
+    });
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(unsafe { simd_fsqrt(f32x4::splat(nan)) }[0])
+    });
+    check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || {
+        F32::from(unsafe { simd_ceil(f32x4::splat(nan)) }[0])
+    });
 
     // Casts
-    check_all_outcomes(
-        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
-        || F64::from(unsafe { simd_cast::<f32x4, f64x4>(f32x4::splat(nan)) }[0]),
-    );
+    check_all_outcomes([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)], || {
+        F64::from(unsafe { simd_cast::<f32x4, f64x4>(f32x4::splat(nan)) }[0])
+    });
 }
 
 fn main() {