@@ -370,59 +370,98 @@ 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)
403
421
}
404
422
}
405
423
406
424
#[ cfg( f128_enabled) ]
407
425
impl MaybeOverride < ( f128 , f128 ) > for SpecialCase {
408
426
fn check_float < F : Float > (
409
427
input : ( f128 , f128 ) ,
410
- _actual : F ,
428
+ actual : F ,
411
429
expected : F ,
412
430
_ulp : & mut u32 ,
413
431
ctx : & CheckCtx ,
414
432
) -> Option < TestResult > {
415
- maybe_skip_binop_nan ( input, expected, ctx)
433
+ binop_common ( input, actual , expected, ctx)
416
434
}
417
435
}
418
436
419
- /// Musl propagates NaNs if one is provided as the input, but we return the other input.
420
437
// F1 and F2 are always the same type, this is just to please generics
421
- fn maybe_skip_binop_nan < F1 : Float , F2 : Float > (
438
+ fn binop_common < F1 : Float , F2 : Float > (
422
439
input : ( F1 , F1 ) ,
440
+ actual : F2 ,
423
441
expected : F2 ,
424
442
ctx : & CheckCtx ,
425
443
) -> Option < TestResult > {
444
+ /* FIXME(#439): we do not compare signed zeros */
445
+
446
+ if ctx. base_name == BaseName :: Fmin
447
+ && input. 0 . biteq ( F1 :: NEG_ZERO )
448
+ && input. 1 . biteq ( F1 :: ZERO )
449
+ && expected. biteq ( F2 :: NEG_ZERO )
450
+ && actual. biteq ( F2 :: ZERO )
451
+ {
452
+ return XFAIL ;
453
+ }
454
+
455
+ if ctx. base_name == BaseName :: Fmax
456
+ && input. 0 . biteq ( F1 :: NEG_ZERO )
457
+ && input. 1 . biteq ( F1 :: ZERO )
458
+ && expected. biteq ( F2 :: ZERO )
459
+ && actual. biteq ( F2 :: NEG_ZERO )
460
+ {
461
+ return XFAIL ;
462
+ }
463
+
464
+ // Musl propagates NaNs if one is provided as the input, but we return the other input.
426
465
match ( & ctx. basis , ctx. base_name ) {
427
466
( Musl , BaseName :: Fmin | BaseName :: Fmax )
428
467
if ( input. 0 . is_nan ( ) || input. 1 . is_nan ( ) ) && expected. is_nan ( ) =>
@@ -502,7 +541,53 @@ fn bessel_prec_dropoff<F: Float>(
502
541
None
503
542
}
504
543
505
- impl MaybeOverride < ( f32 , f32 , f32 ) > for SpecialCase { }
506
- impl MaybeOverride < ( f64 , f64 , f64 ) > for SpecialCase { }
507
544
impl MaybeOverride < ( f32 , i32 ) > for SpecialCase { }
508
545
impl MaybeOverride < ( f64 , i32 ) > for SpecialCase { }
546
+
547
+ impl MaybeOverride < ( f32 , f32 , f32 ) > for SpecialCase {
548
+ fn check_float < F : Float > (
549
+ input : ( f32 , f32 , f32 ) ,
550
+ actual : F ,
551
+ expected : F ,
552
+ _ulp : & mut u32 ,
553
+ ctx : & CheckCtx ,
554
+ ) -> Option < TestResult > {
555
+ ternop_common ( input, actual, expected, ctx)
556
+ }
557
+ }
558
+ impl MaybeOverride < ( f64 , f64 , f64 ) > for SpecialCase {
559
+ fn check_float < F : Float > (
560
+ input : ( f64 , f64 , f64 ) ,
561
+ actual : F ,
562
+ expected : F ,
563
+ _ulp : & mut u32 ,
564
+ ctx : & CheckCtx ,
565
+ ) -> Option < TestResult > {
566
+ ternop_common ( input, actual, expected, ctx)
567
+ }
568
+ }
569
+
570
+ // F1 and F2 are always the same type, this is just to please generics
571
+ fn ternop_common < F1 : Float , F2 : Float > (
572
+ input : ( F1 , F1 , F1 ) ,
573
+ actual : F2 ,
574
+ expected : F2 ,
575
+ ctx : & CheckCtx ,
576
+ ) -> Option < TestResult > {
577
+ // FIXME(fma): 754-2020 says "When the exact result of (a × b) + c is non-zero yet the result
578
+ // of fusedMultiplyAdd is zero because of rounding, the zero result takes the sign of the
579
+ // exact result". Our implementation returns the wrong sign:
580
+ // fma(5e-324, -5e-324, 0.0) = 0.0 (should be -0.0)
581
+ if ctx. base_name == BaseName :: Fma
582
+ && ( input. 0 . is_sign_negative ( ) ^ input. 1 . is_sign_negative ( ) )
583
+ && input. 0 != F1 :: ZERO
584
+ && input. 1 != F1 :: ZERO
585
+ && input. 2 . biteq ( F1 :: ZERO )
586
+ && expected. biteq ( F2 :: NEG_ZERO )
587
+ && actual. biteq ( F2 :: ZERO )
588
+ {
589
+ return XFAIL ;
590
+ }
591
+
592
+ None
593
+ }
0 commit comments