also use nicer check_all_outcomes in float_nan
This commit is contained in:
parent
21e3111ef9
commit
655b847434
1 changed files with 142 additions and 177 deletions
|
|
@ -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,11 +26,18 @@ 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;
|
||||
// Let's give it N times as many tries as we are expecting values.
|
||||
let tries = expected.len() * 12;
|
||||
for _ in 0..tries {
|
||||
let val = generate();
|
||||
assert!(expected.contains(&val), "got an unexpected value: {val}");
|
||||
|
|
@ -193,51 +201,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 +253,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 +283,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 +316,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 +375,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 +401,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 +437,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 +448,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 +530,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() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue