libm-test: Fix unintentional skips in binop_common
`binop_common` emits a `SKIP` that is intended to apply only to `copysign`, but is instead applying to all binary operators. Correct the general case but leave the currently-failing `maximum_num` tests as a FIXME, to be resolved separately in [1]. Also simplify skip logic and NaN checking, and add a few more `copysign` checks. [1]: https://github.com/rust-lang/compiler-builtins/pull/939
This commit is contained in:
parent
ba7cdb6814
commit
5778643174
4 changed files with 34 additions and 12 deletions
|
|
@ -51,6 +51,7 @@ where
|
|||
|
||||
// Check some special values that aren't included in the above ranges
|
||||
values.push(Op::FTy::NAN);
|
||||
values.push(Op::FTy::NEG_NAN);
|
||||
values.extend(Op::FTy::consts().iter());
|
||||
|
||||
// Check around the maximum subnormal value
|
||||
|
|
|
|||
|
|
@ -444,13 +444,18 @@ fn binop_common<F1: Float, F2: Float>(
|
|||
expected: F2,
|
||||
ctx: &CheckCtx,
|
||||
) -> CheckAction {
|
||||
// MPFR only has one NaN bitpattern; allow the default `.is_nan()` checks to validate. Skip if
|
||||
// the first input (magnitude source) is NaN and the output is also a NaN, or if the second
|
||||
// input (sign source) is NaN.
|
||||
if ctx.basis == CheckBasis::Mpfr
|
||||
// MPFR only has one NaN bitpattern; skip tests in cases where the first argument would take
|
||||
// the sign of a NaN second argument. The default NaN checks cover other cases.
|
||||
if ctx.base_name == BaseName::Copysign && ctx.basis == CheckBasis::Mpfr && input.1.is_nan() {
|
||||
return SKIP;
|
||||
}
|
||||
|
||||
// FIXME(#939): this should not be skipped, there is a bug in our implementationi.
|
||||
if ctx.base_name == BaseName::FmaximumNum
|
||||
&& ctx.basis == CheckBasis::Mpfr
|
||||
&& ((input.0.is_nan() && actual.is_nan() && expected.is_nan()) || input.1.is_nan())
|
||||
{
|
||||
return SKIP;
|
||||
return XFAIL_NOCHECK;
|
||||
}
|
||||
|
||||
/* FIXME(#439): our fmin and fmax do not compare signed zeros */
|
||||
|
|
|
|||
|
|
@ -312,12 +312,9 @@ where
|
|||
let mut inner = || -> TestResult {
|
||||
let mut allowed_ulp = ctx.ulp;
|
||||
|
||||
// Forbid overrides if the items came from an explicit list, as long as we are checking
|
||||
// against either MPFR or the result itself.
|
||||
let require_biteq = ctx.gen_kind == GeneratorKind::List && ctx.basis != CheckBasis::Musl;
|
||||
|
||||
match SpecialCase::check_float(input, actual, expected, ctx) {
|
||||
_ if require_biteq => (),
|
||||
// Forbid overrides if the items came from an explicit list
|
||||
_ if ctx.gen_kind == GeneratorKind::List => (),
|
||||
CheckAction::AssertSuccess => (),
|
||||
CheckAction::AssertFailure(msg) => assert_failure_msg = Some(msg),
|
||||
CheckAction::Custom(res) => return res,
|
||||
|
|
@ -327,9 +324,20 @@ where
|
|||
|
||||
// Check when both are NaNs
|
||||
if actual.is_nan() && expected.is_nan() {
|
||||
if require_biteq && ctx.basis == CheckBasis::None {
|
||||
// Don't assert NaN bitwise equality if:
|
||||
//
|
||||
// * Testing against MPFR (there is a single NaN representation)
|
||||
// * Testing against Musl except for explicit tests (Musl does some NaN quieting)
|
||||
//
|
||||
// In these cases, just the check that actual and expected are both NaNs is
|
||||
// sufficient.
|
||||
let skip_nan_biteq = ctx.basis == CheckBasis::Mpfr
|
||||
|| (ctx.basis == CheckBasis::Musl && ctx.gen_kind != GeneratorKind::List);
|
||||
|
||||
if !skip_nan_biteq {
|
||||
ensure!(actual.biteq(expected), "mismatched NaN bitpatterns");
|
||||
}
|
||||
|
||||
// By default, NaNs have nothing special to check.
|
||||
return Ok(());
|
||||
} else if actual.is_nan() || expected.is_nan() {
|
||||
|
|
|
|||
|
|
@ -59,9 +59,17 @@ mod tests {
|
|||
|
||||
// Not required but we expect it
|
||||
assert_biteq!(f(F::NAN, F::NAN), F::NAN);
|
||||
assert_biteq!(f(F::NEG_NAN, F::NAN), F::NAN);
|
||||
assert_biteq!(f(F::NAN, F::ONE), F::NAN);
|
||||
assert_biteq!(f(F::NAN, F::NEG_ONE), F::NEG_NAN);
|
||||
assert_biteq!(f(F::NAN, F::NEG_NAN), F::NEG_NAN);
|
||||
assert_biteq!(f(F::NEG_NAN, F::NAN), F::NAN);
|
||||
assert_biteq!(f(F::NEG_NAN, F::ONE), F::NAN);
|
||||
assert_biteq!(f(F::NEG_NAN, F::NEG_ONE), F::NEG_NAN);
|
||||
assert_biteq!(f(F::NEG_NAN, F::NEG_NAN), F::NEG_NAN);
|
||||
assert_biteq!(f(F::ONE, F::NAN), F::ONE);
|
||||
assert_biteq!(f(F::ONE, F::NEG_NAN), F::NEG_ONE);
|
||||
assert_biteq!(f(F::NEG_ONE, F::NAN), F::ONE);
|
||||
assert_biteq!(f(F::NEG_ONE, F::NEG_NAN), F::NEG_ONE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue