@@ -370,59 +370,116 @@ fn maybe_check_nan_bits<F: Float>(actual: F, expected: F, ctx: &CheckCtx) -> Opt
370
370
impl MaybeOverride < ( f16 , f16 ) > for SpecialCase {
371
371
fn check_float < F : Float > (
372
372
input : ( f16 , f16 ) ,
373
- _actual : F ,
373
+ actual : F ,
374
374
expected : F ,
375
375
_ulp : & mut u32 ,
376
376
ctx : & CheckCtx ,
377
377
) -> Option < TestResult > {
378
- maybe_skip_binop_nan ( input, expected, ctx)
378
+ binop_common ( input, actual , expected, ctx)
379
379
}
380
380
}
381
381
382
382
impl MaybeOverride < ( f32 , f32 ) > for SpecialCase {
383
383
fn check_float < F : Float > (
384
384
input : ( f32 , f32 ) ,
385
- _actual : F ,
385
+ actual : F ,
386
386
expected : F ,
387
387
_ulp : & mut u32 ,
388
388
ctx : & CheckCtx ,
389
389
) -> Option < TestResult > {
390
- maybe_skip_binop_nan ( input, expected, ctx)
390
+ if ctx. base_name == BaseName :: Fmin
391
+ && input. 0 . biteq ( f32:: NEG_ZERO )
392
+ && input. 1 . biteq ( f32:: ZERO )
393
+ && expected. biteq ( F :: NEG_ZERO )
394
+ && actual. biteq ( F :: ZERO )
395
+ {
396
+ return XFAIL ;
397
+ }
398
+
399
+ binop_common ( input, actual, expected, ctx)
391
400
}
392
401
}
393
402
394
403
impl MaybeOverride < ( f64 , f64 ) > for SpecialCase {
395
404
fn check_float < F : Float > (
396
405
input : ( f64 , f64 ) ,
397
- _actual : F ,
406
+ actual : F ,
398
407
expected : F ,
399
408
_ulp : & mut u32 ,
400
409
ctx : & CheckCtx ,
401
410
) -> Option < TestResult > {
402
- maybe_skip_binop_nan ( input, expected, ctx)
411
+ if ctx. base_name == BaseName :: Fmin
412
+ && input. 0 . biteq ( f64:: NEG_ZERO )
413
+ && input. 1 . biteq ( f64:: ZERO )
414
+ && expected. biteq ( F :: ZERO )
415
+ && actual. biteq ( F :: NEG_ZERO )
416
+ {
417
+ return XFAIL ;
418
+ }
419
+
420
+ binop_common ( input, actual, expected, ctx)
421
+ }
422
+
423
+ fn check_int < I : Int > (
424
+ _input : ( f64 , f64 ) ,
425
+ actual : I ,
426
+ expected : I ,
427
+ ctx : & CheckCtx ,
428
+ ) -> Option < TestResult > {
429
+ // FIXME: Our MPFR implementation disagrees with musl and may need to be updated.
430
+ if ctx. basis == CheckBasis :: Mpfr
431
+ && ctx. base_name == BaseName :: Remquo
432
+ && expected == I :: MIN
433
+ && actual == I :: ZERO
434
+ {
435
+ return XFAIL ;
436
+ }
437
+
438
+ None
403
439
}
404
440
}
405
441
406
442
#[ cfg( f128_enabled) ]
407
443
impl MaybeOverride < ( f128 , f128 ) > for SpecialCase {
408
444
fn check_float < F : Float > (
409
445
input : ( f128 , f128 ) ,
410
- _actual : F ,
446
+ actual : F ,
411
447
expected : F ,
412
448
_ulp : & mut u32 ,
413
449
ctx : & CheckCtx ,
414
450
) -> Option < TestResult > {
415
- maybe_skip_binop_nan ( input, expected, ctx)
451
+ binop_common ( input, actual , expected, ctx)
416
452
}
417
453
}
418
454
419
- /// Musl propagates NaNs if one is provided as the input, but we return the other input.
420
455
// F1 and F2 are always the same type, this is just to please generics
421
- fn maybe_skip_binop_nan < F1 : Float , F2 : Float > (
456
+ fn binop_common < F1 : Float , F2 : Float > (
422
457
input : ( F1 , F1 ) ,
458
+ actual : F2 ,
423
459
expected : F2 ,
424
460
ctx : & CheckCtx ,
425
461
) -> Option < TestResult > {
462
+ /* FIXME(#439): we do not compare signed zeros */
463
+
464
+ if ctx. base_name == BaseName :: Fmin
465
+ && input. 0 . biteq ( F1 :: NEG_ZERO )
466
+ && input. 1 . biteq ( F1 :: ZERO )
467
+ && expected. biteq ( F2 :: NEG_ZERO )
468
+ && actual. biteq ( F2 :: ZERO )
469
+ {
470
+ return XFAIL ;
471
+ }
472
+
473
+ if ctx. base_name == BaseName :: Fmax
474
+ && input. 0 . biteq ( F1 :: NEG_ZERO )
475
+ && input. 1 . biteq ( F1 :: ZERO )
476
+ && expected. biteq ( F2 :: ZERO )
477
+ && actual. biteq ( F2 :: NEG_ZERO )
478
+ {
479
+ return XFAIL ;
480
+ }
481
+
482
+ // Musl propagates NaNs if one is provided as the input, but we return the other input.
426
483
match ( & ctx. basis , ctx. base_name ) {
427
484
( Musl , BaseName :: Fmin | BaseName :: Fmax )
428
485
if ( input. 0 . is_nan ( ) || input. 1 . is_nan ( ) ) && expected. is_nan ( ) =>
@@ -502,7 +559,53 @@ fn bessel_prec_dropoff<F: Float>(
502
559
None
503
560
}
504
561
505
- impl MaybeOverride < ( f32 , f32 , f32 ) > for SpecialCase { }
506
- impl MaybeOverride < ( f64 , f64 , f64 ) > for SpecialCase { }
507
562
impl MaybeOverride < ( f32 , i32 ) > for SpecialCase { }
508
563
impl MaybeOverride < ( f64 , i32 ) > for SpecialCase { }
564
+
565
+ impl MaybeOverride < ( f32 , f32 , f32 ) > for SpecialCase {
566
+ fn check_float < F : Float > (
567
+ input : ( f32 , f32 , f32 ) ,
568
+ actual : F ,
569
+ expected : F ,
570
+ _ulp : & mut u32 ,
571
+ ctx : & CheckCtx ,
572
+ ) -> Option < TestResult > {
573
+ ternop_common ( input, actual, expected, ctx)
574
+ }
575
+ }
576
+ impl MaybeOverride < ( f64 , f64 , f64 ) > for SpecialCase {
577
+ fn check_float < F : Float > (
578
+ input : ( f64 , f64 , f64 ) ,
579
+ actual : F ,
580
+ expected : F ,
581
+ _ulp : & mut u32 ,
582
+ ctx : & CheckCtx ,
583
+ ) -> Option < TestResult > {
584
+ ternop_common ( input, actual, expected, ctx)
585
+ }
586
+ }
587
+
588
+ // F1 and F2 are always the same type, this is just to please generics
589
+ fn ternop_common < F1 : Float , F2 : Float > (
590
+ input : ( F1 , F1 , F1 ) ,
591
+ actual : F2 ,
592
+ expected : F2 ,
593
+ ctx : & CheckCtx ,
594
+ ) -> Option < TestResult > {
595
+ // FIXME(fma): 754-2020 says "When the exact result of (a × b) + c is non-zero yet the result
596
+ // of fusedMultiplyAdd is zero because of rounding, the zero result takes the sign of the
597
+ // exact result". Our implementation returns the wrong sign:
598
+ // fma(5e-324, -5e-324, 0.0) = 0.0 (should be -0.0)
599
+ if ctx. base_name == BaseName :: Fma
600
+ && ( input. 0 . is_sign_negative ( ) ^ input. 1 . is_sign_negative ( ) )
601
+ && input. 0 != F1 :: ZERO
602
+ && input. 1 != F1 :: ZERO
603
+ && input. 2 . biteq ( F1 :: ZERO )
604
+ && expected. biteq ( F2 :: NEG_ZERO )
605
+ && actual. biteq ( F2 :: ZERO )
606
+ {
607
+ return XFAIL ;
608
+ }
609
+
610
+ None
611
+ }
0 commit comments