@@ -13,7 +13,7 @@ use rustc_span::{Symbol, sym};
13
13
use self :: atomic:: EvalContextExt as _;
14
14
use self :: helpers:: { ToHost , ToSoft , check_arg_count} ;
15
15
use self :: simd:: EvalContextExt as _;
16
- use crate :: math:: apply_random_float_error;
16
+ use crate :: math:: { apply_random_float_error, ulp_err_scale } ;
17
17
use crate :: * ;
18
18
19
19
impl < ' tcx > EvalContextExt < ' tcx > for crate :: MiriInterpCx < ' tcx > { }
@@ -248,9 +248,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
248
248
"log2f32" => host. log2 ( ) ,
249
249
_ => bug ! ( ) ,
250
250
} ;
251
- // Apply a relative error with a magnitude on the order of 2^-21 to simulate
252
- // non-deterministic behaviour of floats
253
- let res = apply_random_float_error ( this, res. to_soft ( ) , -21 ) ;
251
+ // Apply a relative error of 16ULP to simulate non-determinism
252
+ let res = apply_random_float_error (
253
+ this,
254
+ res. to_soft ( ) ,
255
+ ulp_err_scale :: < rustc_apfloat:: ieee:: Single > ( 4 )
256
+ ) ;
254
257
let res = this. adjust_nan ( res, & [ f] ) ;
255
258
this. write_scalar ( res, dest) ?;
256
259
}
@@ -278,9 +281,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
278
281
"log2f64" => host. log2 ( ) ,
279
282
_ => bug ! ( ) ,
280
283
} ;
281
- // Apply a relative error with a magnitude on the order of 2^-50 to simulate
282
- // non-deterministic behaviour of floats as per https://github.com/rust-lang/rust/pull/124609
283
- let res = apply_random_float_error ( this, res. to_soft ( ) , -50 ) ;
284
+ // Apply a relative error of 16ULP to simulate non-determinism
285
+ let res = apply_random_float_error (
286
+ this,
287
+ res. to_soft ( ) ,
288
+ ulp_err_scale :: < rustc_apfloat:: ieee:: Double > ( 4 ) ) ;
284
289
let res = this. adjust_nan ( res, & [ f] ) ;
285
290
this. write_scalar ( res, dest) ?;
286
291
}
@@ -395,23 +400,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
395
400
} ;
396
401
let res = this. binary_op ( op, & a, & b) ?;
397
402
// `binary_op` already called `generate_nan` if needed
398
- // Apply a relative error to simulate non-deterministic
399
- // behaviour of floats
403
+ // Apply a relative error of 16ULP to simulate non-determinism
400
404
fn apply_error_and_write < ' tcx , F : Float + Into < Scalar > > (
401
405
ecx : & mut MiriInterpCx < ' tcx > ,
402
- val : F ,
403
- dest : & MPlaceTy < ' tcx > ,
404
- err_scale : i32
406
+ res : F ,
407
+ dest : & MPlaceTy < ' tcx >
405
408
) -> InterpResult < ' tcx > {
406
- let res = apply_random_float_error ( ecx, val, err_scale) ;
409
+ let res = apply_random_float_error (
410
+ ecx,
411
+ res,
412
+ ulp_err_scale :: < F > ( 4 )
413
+ ) ;
407
414
ecx. write_scalar ( res, dest)
408
415
}
409
416
let scalar = res. to_scalar_int ( ) ?;
410
417
match res. layout . ty . kind ( ) {
411
- ty:: Float ( FloatTy :: F16 ) => apply_error_and_write ( this, scalar. to_f16 ( ) , dest, - 8 ) ,
412
- ty:: Float ( FloatTy :: F32 ) => apply_error_and_write ( this, scalar. to_f32 ( ) , dest, - 21 ) ,
413
- ty:: Float ( FloatTy :: F64 ) => apply_error_and_write ( this, scalar. to_f64 ( ) , dest, - 50 ) ,
414
- ty:: Float ( FloatTy :: F128 ) => apply_error_and_write ( this, scalar. to_f128 ( ) , dest, - 111 ) ,
418
+ ty:: Float ( FloatTy :: F16 ) => apply_error_and_write ( this, scalar. to_f16 ( ) , dest) ,
419
+ ty:: Float ( FloatTy :: F32 ) => apply_error_and_write ( this, scalar. to_f32 ( ) , dest) ,
420
+ ty:: Float ( FloatTy :: F64 ) => apply_error_and_write ( this, scalar. to_f64 ( ) , dest) ,
421
+ ty:: Float ( FloatTy :: F128 ) => apply_error_and_write ( this, scalar. to_f128 ( ) , dest) ,
415
422
_ => bug ! ( "`{intrinsic_name}` intrinsic called with non-float input type" )
416
423
} ?;
417
424
}
@@ -461,25 +468,27 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
461
468
if !float_finite ( & res) ? {
462
469
throw_ub_format ! ( "`{intrinsic_name}` intrinsic produced non-finite value as result" ) ;
463
470
}
464
- // Apply a relative error to simulate non-deterministic
465
- // behaviour of floats
471
+ // Apply a relative error of 16ULP to simulate non-determinism
466
472
fn apply_error_and_write < ' tcx , F : Float + Into < Scalar > > (
467
473
ecx : & mut MiriInterpCx < ' tcx > ,
468
- val : F ,
469
- dest : & MPlaceTy < ' tcx > ,
470
- err_scale : i32
474
+ res : F ,
475
+ dest : & MPlaceTy < ' tcx >
471
476
) -> InterpResult < ' tcx > {
472
- let res = apply_random_float_error ( ecx, val, err_scale) ;
477
+ let res = apply_random_float_error (
478
+ ecx,
479
+ res,
480
+ ulp_err_scale :: < F > ( 4 )
481
+ ) ;
473
482
ecx. write_scalar ( res, dest)
474
483
}
475
484
// This cannot be a NaN so we also don't have to apply any non-determinism.
476
485
// (Also, `binary_op` already called `generate_nan` if needed.)
477
486
let scalar = res. to_scalar_int ( ) ?;
478
487
match res. layout . ty . kind ( ) {
479
- ty:: Float ( FloatTy :: F16 ) => apply_error_and_write ( this, scalar. to_f16 ( ) , dest, - 8 ) ,
480
- ty:: Float ( FloatTy :: F32 ) => apply_error_and_write ( this, scalar. to_f32 ( ) , dest, - 21 ) ,
481
- ty:: Float ( FloatTy :: F64 ) => apply_error_and_write ( this, scalar. to_f64 ( ) , dest, - 50 ) ,
482
- ty:: Float ( FloatTy :: F128 ) => apply_error_and_write ( this, scalar. to_f128 ( ) , dest, - 111 ) ,
488
+ ty:: Float ( FloatTy :: F16 ) => apply_error_and_write ( this, scalar. to_f16 ( ) , dest) ,
489
+ ty:: Float ( FloatTy :: F32 ) => apply_error_and_write ( this, scalar. to_f32 ( ) , dest) ,
490
+ ty:: Float ( FloatTy :: F64 ) => apply_error_and_write ( this, scalar. to_f64 ( ) , dest) ,
491
+ ty:: Float ( FloatTy :: F128 ) => apply_error_and_write ( this, scalar. to_f128 ( ) , dest) ,
483
492
_ => bug ! ( "`{intrinsic_name}` intrinsic called with non-float input type" )
484
493
} ?;
485
494
}
0 commit comments