Skip to content

Commit a5d0592

Browse files
committed
Auto merge of rust-lang#138062 - LorrensP-2158466:miri-enable-float-nondet, r=<try>
Enable Non-determinism of float operations in Miri and change std tests Links to [rust-lang#4208](rust-lang/miri#4208) and [rust-lang#3555](rust-lang/miri#3555) in Miri. Non-determinism of floating point operations was disabled in rust-lang#137594 because it breaks the tests and doc-tests in core/coretests and std. This PR: - enables the float non-determinism but with a lower relative error of 4ULP instead of 16ULP - changes tests that made incorrect assumptions about the operations not to make that assumption anymore (from `assert_eq!` to `assert_approx_eq!`. - changes the `assert_approx_eq!` macro to allow up to 1e-4 to make the tests pass TODO: - I didn't touch the doc tests because I do not know nearly enough to come near them :) - probably change the `assert_approx_eq` to use the same technique as Miri (i.e., using ULP instead of EPSILON) try-job: x86_64-gnu-aux
2 parents 8fb32ab + 6245a59 commit a5d0592

File tree

8 files changed

+349
-103
lines changed

8 files changed

+349
-103
lines changed

library/coretests/tests/num/dec2flt/float.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use core::num::dec2flt::float::RawFloat;
44
fn test_f32_integer_decode() {
55
assert_eq!(3.14159265359f32.integer_decode(), (13176795, -22, 1));
66
assert_eq!((-8573.5918555f32).integer_decode(), (8779358, -10, -1));
7-
assert_eq!(2f32.powf(100.0).integer_decode(), (8388608, 77, 1));
7+
// Set 2^100 directly instead of using powf, because it doesn't guarentee precision
8+
assert_eq!(1.2676506e30_f32.integer_decode(), (8388608, 77, 1));
89
assert_eq!(0f32.integer_decode(), (0, -150, 1));
910
assert_eq!((-0f32).integer_decode(), (0, -150, -1));
1011
assert_eq!(f32::INFINITY.integer_decode(), (8388608, 105, 1));
@@ -20,7 +21,8 @@ fn test_f32_integer_decode() {
2021
fn test_f64_integer_decode() {
2122
assert_eq!(3.14159265359f64.integer_decode(), (7074237752028906, -51, 1));
2223
assert_eq!((-8573.5918555f64).integer_decode(), (4713381968463931, -39, -1));
23-
assert_eq!(2f64.powf(100.0).integer_decode(), (4503599627370496, 48, 1));
24+
// Set 2^100 directly instead of using powf, because it doesn't guarentee precision
25+
assert_eq!(1.2676506002282294e30_f64.integer_decode(), (4503599627370496, 48, 1));
2426
assert_eq!(0f64.integer_decode(), (0, -1075, 1));
2527
assert_eq!((-0f64).integer_decode(), (0, -1075, -1));
2628
assert_eq!(f64::INFINITY.integer_decode(), (4503599627370496, 972, 1));

library/std/src/f32.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ impl f32 {
303303
/// ```
304304
/// let x = 2.0_f32;
305305
/// let abs_difference = (x.powi(2) - (x * x)).abs();
306-
/// assert!(abs_difference <= f32::EPSILON);
306+
/// assert!(abs_difference <= 8.0 * f32::EPSILON);
307307
///
308308
/// assert_eq!(f32::powi(f32::NAN, 0), 1.0);
309309
/// ```
@@ -327,7 +327,7 @@ impl f32 {
327327
/// ```
328328
/// let x = 2.0_f32;
329329
/// let abs_difference = (x.powf(2.0) - (x * x)).abs();
330-
/// assert!(abs_difference <= f32::EPSILON);
330+
/// assert!(abs_difference <= 8.0 * f32::EPSILON);
331331
///
332332
/// assert_eq!(f32::powf(1.0, f32::NAN), 1.0);
333333
/// assert_eq!(f32::powf(f32::NAN, 0.0), 1.0);
@@ -387,7 +387,7 @@ impl f32 {
387387
/// // ln(e) - 1 == 0
388388
/// let abs_difference = (e.ln() - 1.0).abs();
389389
///
390-
/// assert!(abs_difference <= f32::EPSILON);
390+
/// assert!(abs_difference <= 4.0 * f32::EPSILON);
391391
/// ```
392392
#[rustc_allow_incoherent_impl]
393393
#[must_use = "method returns a new number and does not mutate the original value"]
@@ -412,7 +412,7 @@ impl f32 {
412412
/// // 2^2 - 4 == 0
413413
/// let abs_difference = (f.exp2() - 4.0).abs();
414414
///
415-
/// assert!(abs_difference <= f32::EPSILON);
415+
/// assert!(abs_difference <= 8.0 * f32::EPSILON);
416416
/// ```
417417
#[rustc_allow_incoherent_impl]
418418
#[must_use = "method returns a new number and does not mutate the original value"]
@@ -441,7 +441,7 @@ impl f32 {
441441
/// // ln(e) - 1 == 0
442442
/// let abs_difference = (e.ln() - 1.0).abs();
443443
///
444-
/// assert!(abs_difference <= f32::EPSILON);
444+
/// assert!(abs_difference <= 4.0 * f32::EPSILON);
445445
/// ```
446446
///
447447
/// Non-positive values:
@@ -478,7 +478,7 @@ impl f32 {
478478
/// // log5(5) - 1 == 0
479479
/// let abs_difference = (five.log(5.0) - 1.0).abs();
480480
///
481-
/// assert!(abs_difference <= f32::EPSILON);
481+
/// assert!(abs_difference <= 4.0 * f32::EPSILON);
482482
/// ```
483483
///
484484
/// Non-positive values:
@@ -511,7 +511,7 @@ impl f32 {
511511
/// // log2(2) - 1 == 0
512512
/// let abs_difference = (two.log2() - 1.0).abs();
513513
///
514-
/// assert!(abs_difference <= f32::EPSILON);
514+
/// assert!(abs_difference <= 4.0 * f32::EPSILON);
515515
/// ```
516516
///
517517
/// Non-positive values:
@@ -544,7 +544,7 @@ impl f32 {
544544
/// // log10(10) - 1 == 0
545545
/// let abs_difference = (ten.log10() - 1.0).abs();
546546
///
547-
/// assert!(abs_difference <= f32::EPSILON);
547+
/// assert!(abs_difference <= 4.0 * f32::EPSILON);
548548
/// ```
549549
///
550550
/// Non-positive values:
@@ -650,7 +650,7 @@ impl f32 {
650650
/// // sqrt(x^2 + y^2)
651651
/// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs();
652652
///
653-
/// assert!(abs_difference <= f32::EPSILON);
653+
/// assert!(abs_difference <= 4.0 * f32::EPSILON);
654654
/// ```
655655
#[rustc_allow_incoherent_impl]
656656
#[must_use = "method returns a new number and does not mutate the original value"]
@@ -674,7 +674,7 @@ impl f32 {
674674
///
675675
/// let abs_difference = (x.sin() - 1.0).abs();
676676
///
677-
/// assert!(abs_difference <= f32::EPSILON);
677+
/// assert!(abs_difference <= 4.0 * f32::EPSILON);
678678
/// ```
679679
#[rustc_allow_incoherent_impl]
680680
#[must_use = "method returns a new number and does not mutate the original value"]
@@ -698,7 +698,7 @@ impl f32 {
698698
///
699699
/// let abs_difference = (x.cos() - 1.0).abs();
700700
///
701-
/// assert!(abs_difference <= f32::EPSILON);
701+
/// assert!(abs_difference <= 4.0 * f32::EPSILON);
702702
/// ```
703703
#[rustc_allow_incoherent_impl]
704704
#[must_use = "method returns a new number and does not mutate the original value"]
@@ -782,7 +782,7 @@ impl f32 {
782782
/// // acos(cos(pi/4))
783783
/// let abs_difference = (f.cos().acos() - std::f32::consts::FRAC_PI_4).abs();
784784
///
785-
/// assert!(abs_difference <= f32::EPSILON);
785+
/// assert!(abs_difference <= 4.0 * f32::EPSILON);
786786
/// ```
787787
#[doc(alias = "arccos")]
788788
#[rustc_allow_incoherent_impl]
@@ -882,8 +882,8 @@ impl f32 {
882882
/// let abs_difference_0 = (f.0 - x.sin()).abs();
883883
/// let abs_difference_1 = (f.1 - x.cos()).abs();
884884
///
885-
/// assert!(abs_difference_0 <= f32::EPSILON);
886-
/// assert!(abs_difference_1 <= f32::EPSILON);
885+
/// assert!(abs_difference_0 <= 4.0 * f32::EPSILON);
886+
/// assert!(abs_difference_1 <= 4.0 * f32::EPSILON);
887887
/// ```
888888
#[doc(alias = "sincos")]
889889
#[rustc_allow_incoherent_impl]
@@ -1065,7 +1065,7 @@ impl f32 {
10651065
///
10661066
/// let abs_difference = (f - x).abs();
10671067
///
1068-
/// assert!(abs_difference <= f32::EPSILON);
1068+
/// assert!(abs_difference <= 4.0 * f32::EPSILON);
10691069
/// ```
10701070
#[doc(alias = "arcsinh")]
10711071
#[rustc_allow_incoherent_impl]
@@ -1093,7 +1093,7 @@ impl f32 {
10931093
///
10941094
/// let abs_difference = (f - x).abs();
10951095
///
1096-
/// assert!(abs_difference <= f32::EPSILON);
1096+
/// assert!(abs_difference <= 4.0 * f32::EPSILON);
10971097
/// ```
10981098
#[doc(alias = "arccosh")]
10991099
#[rustc_allow_incoherent_impl]

library/std/src/f64.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ impl f64 {
303303
/// ```
304304
/// let x = 2.0_f64;
305305
/// let abs_difference = (x.powi(2) - (x * x)).abs();
306-
/// assert!(abs_difference <= f64::EPSILON);
306+
/// assert!(abs_difference <= 8.0 * f64::EPSILON);
307307
///
308308
/// assert_eq!(f64::powi(f64::NAN, 0), 1.0);
309309
/// ```
@@ -327,7 +327,7 @@ impl f64 {
327327
/// ```
328328
/// let x = 2.0_f64;
329329
/// let abs_difference = (x.powf(2.0) - (x * x)).abs();
330-
/// assert!(abs_difference <= f64::EPSILON);
330+
/// assert!(abs_difference <= 8.0 * f64::EPSILON);
331331
///
332332
/// assert_eq!(f64::powf(1.0, f64::NAN), 1.0);
333333
/// assert_eq!(f64::powf(f64::NAN, 0.0), 1.0);

library/std/tests/floats/f32.rs

+49-12
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ const NAN_MASK1: u32 = 0x002a_aaaa;
2222
/// Second pattern over the mantissa
2323
const NAN_MASK2: u32 = 0x0055_5555;
2424

25+
/// Miri adds some extra errors to float functions; make sure the tests still pass.
26+
/// These values are purely used as a canary to test against and are thus not a stable guarantee Rust provides.
27+
/// They serve as a way to get an idea of the real precision of floating point operations on different platforms.
28+
const APPROX_DETLA: f32 = if cfg!(miri) { 1e-4 } else { 1e-6 };
29+
2530
#[allow(unused_macros)]
2631
macro_rules! assert_f32_biteq {
2732
($left : expr, $right : expr) => {
@@ -442,8 +447,12 @@ fn test_powi() {
442447
let nan: f32 = f32::NAN;
443448
let inf: f32 = f32::INFINITY;
444449
let neg_inf: f32 = f32::NEG_INFINITY;
445-
assert_eq!(1.0f32.powi(1), 1.0);
446-
assert_approx_eq!((-3.1f32).powi(2), 9.61);
450+
assert_approx_eq!(1.0f32.powi(1), 1.0);
451+
assert_approx_eq!(
452+
(-3.1f32).powi(2),
453+
9.61,
454+
APPROX_DETLA /* Miri float-non-det: Make tests pass for now */
455+
);
447456
assert_approx_eq!(5.9f32.powi(-2), 0.028727);
448457
assert_eq!(8.3f32.powi(0), 1.0);
449458
assert!(nan.powi(2).is_nan());
@@ -457,9 +466,17 @@ fn test_powf() {
457466
let inf: f32 = f32::INFINITY;
458467
let neg_inf: f32 = f32::NEG_INFINITY;
459468
assert_eq!(1.0f32.powf(1.0), 1.0);
460-
assert_approx_eq!(3.4f32.powf(4.5), 246.408218);
469+
assert_approx_eq!(
470+
3.4f32.powf(4.5),
471+
246.408218,
472+
APPROX_DETLA /* Miri float-non-det: Make tests pass for now */
473+
);
461474
assert_approx_eq!(2.7f32.powf(-3.2), 0.041652);
462-
assert_approx_eq!((-3.1f32).powf(2.0), 9.61);
475+
assert_approx_eq!(
476+
(-3.1f32).powf(2.0),
477+
9.61,
478+
APPROX_DETLA /* Miri float-non-det: Make tests pass for now */
479+
);
463480
assert_approx_eq!(5.9f32.powf(-2.0), 0.028727);
464481
assert_eq!(8.3f32.powf(0.0), 1.0);
465482
assert!(nan.powf(2.0).is_nan());
@@ -482,7 +499,11 @@ fn test_sqrt_domain() {
482499
fn test_exp() {
483500
assert_eq!(1.0, 0.0f32.exp());
484501
assert_approx_eq!(2.718282, 1.0f32.exp());
485-
assert_approx_eq!(148.413162, 5.0f32.exp());
502+
assert_approx_eq!(
503+
148.413162,
504+
5.0f32.exp(),
505+
APPROX_DETLA /* Miri float-non-det: Make tests pass for now */
506+
);
486507

487508
let inf: f32 = f32::INFINITY;
488509
let neg_inf: f32 = f32::NEG_INFINITY;
@@ -494,7 +515,11 @@ fn test_exp() {
494515

495516
#[test]
496517
fn test_exp2() {
497-
assert_eq!(32.0, 5.0f32.exp2());
518+
assert_approx_eq!(
519+
32.0,
520+
5.0f32.exp2(),
521+
APPROX_DETLA /* Miri float-non-det: Make tests pass for now */
522+
);
498523
assert_eq!(1.0, 0.0f32.exp2());
499524

500525
let inf: f32 = f32::INFINITY;
@@ -517,17 +542,21 @@ fn test_ln() {
517542
assert!((-2.3f32).ln().is_nan());
518543
assert_eq!((-0.0f32).ln(), neg_inf);
519544
assert_eq!(0.0f32.ln(), neg_inf);
520-
assert_approx_eq!(4.0f32.ln(), 1.386294);
545+
assert_approx_eq!(
546+
4.0f32.ln(),
547+
1.386294,
548+
APPROX_DETLA /* Miri float-non-det: Make tests pass for now */
549+
);
521550
}
522551

523552
#[test]
524553
fn test_log() {
525554
let nan: f32 = f32::NAN;
526555
let inf: f32 = f32::INFINITY;
527556
let neg_inf: f32 = f32::NEG_INFINITY;
528-
assert_eq!(10.0f32.log(10.0), 1.0);
557+
assert_approx_eq!(10.0f32.log(10.0), 1.0);
529558
assert_approx_eq!(2.3f32.log(3.5), 0.664858);
530-
assert_eq!(1.0f32.exp().log(1.0f32.exp()), 1.0);
559+
assert_approx_eq!(1.0f32.exp().log(1.0f32.exp()), 1.0);
531560
assert!(1.0f32.log(1.0).is_nan());
532561
assert!(1.0f32.log(-13.9).is_nan());
533562
assert!(nan.log(2.3).is_nan());
@@ -559,7 +588,7 @@ fn test_log10() {
559588
let nan: f32 = f32::NAN;
560589
let inf: f32 = f32::INFINITY;
561590
let neg_inf: f32 = f32::NEG_INFINITY;
562-
assert_eq!(10.0f32.log10(), 1.0);
591+
assert_approx_eq!(10.0f32.log10(), 1.0);
563592
assert_approx_eq!(2.3f32.log10(), 0.361728);
564593
assert_approx_eq!(1.0f32.exp().log10(), 0.434294);
565594
assert_eq!(1.0f32.log10(), 0.0);
@@ -639,7 +668,11 @@ fn test_acosh() {
639668
assert_approx_eq!(3.0f32.acosh(), 1.76274717403908605046521864995958461f32);
640669

641670
// test for low accuracy from issue 104548
642-
assert_approx_eq!(60.0f32, 60.0f32.cosh().acosh());
671+
assert_approx_eq!(
672+
60.0f32,
673+
60.0f32.cosh().acosh(),
674+
APPROX_DETLA /* Miri float-non-det: Make tests pass for now */
675+
);
643676
}
644677

645678
#[test]
@@ -718,7 +751,11 @@ fn test_real_consts() {
718751
let ln_10: f32 = consts::LN_10;
719752

720753
assert_approx_eq!(frac_pi_2, pi / 2f32);
721-
assert_approx_eq!(frac_pi_3, pi / 3f32);
754+
assert_approx_eq!(
755+
frac_pi_3,
756+
pi / 3f32,
757+
APPROX_DETLA /* Miri float-non-det: Make tests pass for now */
758+
);
722759
assert_approx_eq!(frac_pi_4, pi / 4f32);
723760
assert_approx_eq!(frac_pi_6, pi / 6f32);
724761
assert_approx_eq!(frac_pi_8, pi / 8f32);

library/std/tests/floats/f64.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ fn test_powi() {
427427
let nan: f64 = f64::NAN;
428428
let inf: f64 = f64::INFINITY;
429429
let neg_inf: f64 = f64::NEG_INFINITY;
430-
assert_eq!(1.0f64.powi(1), 1.0);
430+
assert_approx_eq!(1.0f64.powi(1), 1.0);
431431
assert_approx_eq!((-3.1f64).powi(2), 9.61);
432432
assert_approx_eq!(5.9f64.powi(-2), 0.028727);
433433
assert_eq!(8.3f64.powi(0), 1.0);
@@ -479,7 +479,7 @@ fn test_exp() {
479479

480480
#[test]
481481
fn test_exp2() {
482-
assert_eq!(32.0, 5.0f64.exp2());
482+
assert_approx_eq!(32.0, 5.0f64.exp2());
483483
assert_eq!(1.0, 0.0f64.exp2());
484484

485485
let inf: f64 = f64::INFINITY;
@@ -510,9 +510,9 @@ fn test_log() {
510510
let nan: f64 = f64::NAN;
511511
let inf: f64 = f64::INFINITY;
512512
let neg_inf: f64 = f64::NEG_INFINITY;
513-
assert_eq!(10.0f64.log(10.0), 1.0);
513+
assert_approx_eq!(10.0f64.log(10.0), 1.0);
514514
assert_approx_eq!(2.3f64.log(3.5), 0.664858);
515-
assert_eq!(1.0f64.exp().log(1.0f64.exp()), 1.0);
515+
assert_approx_eq!(1.0f64.exp().log(1.0f64.exp()), 1.0);
516516
assert!(1.0f64.log(1.0).is_nan());
517517
assert!(1.0f64.log(-13.9).is_nan());
518518
assert!(nan.log(2.3).is_nan());
@@ -544,7 +544,7 @@ fn test_log10() {
544544
let nan: f64 = f64::NAN;
545545
let inf: f64 = f64::INFINITY;
546546
let neg_inf: f64 = f64::NEG_INFINITY;
547-
assert_eq!(10.0f64.log10(), 1.0);
547+
assert_approx_eq!(10.0f64.log10(), 1.0);
548548
assert_approx_eq!(2.3f64.log10(), 0.361728);
549549
assert_approx_eq!(1.0f64.exp().log10(), 0.434294);
550550
assert_eq!(1.0f64.log10(), 0.0);

0 commit comments

Comments
 (0)