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