88#![ allow( internal_features) ]
99#![ allow( unnecessary_transmutes) ]
1010
11+ #[ path = "../utils/mod.rs" ]
12+ mod utils;
1113use std:: any:: type_name;
1214use std:: cmp:: min;
1315use std:: fmt:: { Debug , Display , LowerHex } ;
1416use std:: hint:: black_box;
1517use std:: { f32, f64} ;
1618
19+ use utils:: check_nondet;
20+
1721/// Compare the two floats, allowing for $ulp many ULPs of error.
1822///
1923/// ULP means "Units in the Last Place" or "Units of Least Precision".
@@ -1429,29 +1433,14 @@ fn test_fmuladd() {
14291433
14301434/// `min` and `max` on equal arguments are non-deterministic.
14311435fn test_min_max_nondet ( ) {
1432- /// Ensure that if we call the closure often enough, we see both `true` and `false.`
1433- #[ track_caller]
1434- fn ensure_both ( f : impl Fn ( ) -> bool ) {
1435- let rounds = 32 ;
1436- let first = f ( ) ;
1437- for _ in 1 ..rounds {
1438- if f ( ) != first {
1439- // We saw two different values!
1440- return ;
1441- }
1442- }
1443- // We saw the same thing N times.
1444- panic ! ( "expected non-determinism, got {rounds} times the same result: {first:?}" ) ;
1445- }
1446-
1447- ensure_both ( || f16:: min ( 0.0 , -0.0 ) . is_sign_positive ( ) ) ;
1448- ensure_both ( || f16:: max ( 0.0 , -0.0 ) . is_sign_positive ( ) ) ;
1449- ensure_both ( || f32:: min ( 0.0 , -0.0 ) . is_sign_positive ( ) ) ;
1450- ensure_both ( || f32:: max ( 0.0 , -0.0 ) . is_sign_positive ( ) ) ;
1451- ensure_both ( || f64:: min ( 0.0 , -0.0 ) . is_sign_positive ( ) ) ;
1452- ensure_both ( || f64:: max ( 0.0 , -0.0 ) . is_sign_positive ( ) ) ;
1453- ensure_both ( || f128:: min ( 0.0 , -0.0 ) . is_sign_positive ( ) ) ;
1454- ensure_both ( || f128:: max ( 0.0 , -0.0 ) . is_sign_positive ( ) ) ;
1436+ check_nondet ( || f16:: min ( 0.0 , -0.0 ) . is_sign_positive ( ) ) ;
1437+ check_nondet ( || f16:: max ( 0.0 , -0.0 ) . is_sign_positive ( ) ) ;
1438+ check_nondet ( || f32:: min ( 0.0 , -0.0 ) . is_sign_positive ( ) ) ;
1439+ check_nondet ( || f32:: max ( 0.0 , -0.0 ) . is_sign_positive ( ) ) ;
1440+ check_nondet ( || f64:: min ( 0.0 , -0.0 ) . is_sign_positive ( ) ) ;
1441+ check_nondet ( || f64:: max ( 0.0 , -0.0 ) . is_sign_positive ( ) ) ;
1442+ check_nondet ( || f128:: min ( 0.0 , -0.0 ) . is_sign_positive ( ) ) ;
1443+ check_nondet ( || f128:: max ( 0.0 , -0.0 ) . is_sign_positive ( ) ) ;
14551444}
14561445
14571446fn test_non_determinism ( ) {
@@ -1461,35 +1450,20 @@ fn test_non_determinism() {
14611450 } ;
14621451 use std:: { f32, f64} ;
14631452
1464- /// Ensure that the operation is non-deterministic
1465- #[ track_caller]
1466- fn ensure_nondet < T : PartialEq + std:: fmt:: Debug > ( f : impl Fn ( ) -> T ) {
1467- let rounds = 16 ;
1468- let first = f ( ) ;
1469- for _ in 1 ..rounds {
1470- if f ( ) != first {
1471- // We saw two different values!
1472- return ;
1473- }
1474- }
1475- // We saw the same thing N times.
1476- panic ! ( "expected non-determinism, got {rounds} times the same result: {first:?}" ) ;
1477- }
1478-
14791453 macro_rules! test_operations_f {
14801454 ( $a: expr, $b: expr) => {
1481- ensure_nondet ( || fadd_algebraic( $a, $b) ) ;
1482- ensure_nondet ( || fsub_algebraic( $a, $b) ) ;
1483- ensure_nondet ( || fmul_algebraic( $a, $b) ) ;
1484- ensure_nondet ( || fdiv_algebraic( $a, $b) ) ;
1485- ensure_nondet ( || frem_algebraic( $a, $b) ) ;
1455+ check_nondet ( || fadd_algebraic( $a, $b) ) ;
1456+ check_nondet ( || fsub_algebraic( $a, $b) ) ;
1457+ check_nondet ( || fmul_algebraic( $a, $b) ) ;
1458+ check_nondet ( || fdiv_algebraic( $a, $b) ) ;
1459+ check_nondet ( || frem_algebraic( $a, $b) ) ;
14861460
14871461 unsafe {
1488- ensure_nondet ( || fadd_fast( $a, $b) ) ;
1489- ensure_nondet ( || fsub_fast( $a, $b) ) ;
1490- ensure_nondet ( || fmul_fast( $a, $b) ) ;
1491- ensure_nondet ( || fdiv_fast( $a, $b) ) ;
1492- ensure_nondet ( || frem_fast( $a, $b) ) ;
1462+ check_nondet ( || fadd_fast( $a, $b) ) ;
1463+ check_nondet ( || fsub_fast( $a, $b) ) ;
1464+ check_nondet ( || fmul_fast( $a, $b) ) ;
1465+ check_nondet ( || fdiv_fast( $a, $b) ) ;
1466+ check_nondet ( || frem_fast( $a, $b) ) ;
14931467 }
14941468 } ;
14951469 }
@@ -1499,70 +1473,70 @@ fn test_non_determinism() {
14991473 }
15001474 pub fn test_operations_f32 ( a : f32 , b : f32 ) {
15011475 test_operations_f ! ( a, b) ;
1502- ensure_nondet ( || a. powf ( b) ) ;
1503- ensure_nondet ( || a. powi ( 2 ) ) ;
1504- ensure_nondet ( || a. log ( b) ) ;
1505- ensure_nondet ( || a. exp ( ) ) ;
1506- ensure_nondet ( || 10f32 . exp2 ( ) ) ;
1507- ensure_nondet ( || f32:: consts:: E . ln ( ) ) ;
1508- ensure_nondet ( || 10f32 . log10 ( ) ) ;
1509- ensure_nondet ( || 8f32 . log2 ( ) ) ;
1510- ensure_nondet ( || 1f32 . ln_1p ( ) ) ;
1511- ensure_nondet ( || 27.0f32 . cbrt ( ) ) ;
1512- ensure_nondet ( || 3.0f32 . hypot ( 4.0f32 ) ) ;
1513- ensure_nondet ( || 1f32 . sin ( ) ) ;
1514- ensure_nondet ( || 1f32 . cos ( ) ) ;
1476+ check_nondet ( || a. powf ( b) ) ;
1477+ check_nondet ( || a. powi ( 2 ) ) ;
1478+ check_nondet ( || a. log ( b) ) ;
1479+ check_nondet ( || a. exp ( ) ) ;
1480+ check_nondet ( || 10f32 . exp2 ( ) ) ;
1481+ check_nondet ( || f32:: consts:: E . ln ( ) ) ;
1482+ check_nondet ( || 10f32 . log10 ( ) ) ;
1483+ check_nondet ( || 8f32 . log2 ( ) ) ;
1484+ check_nondet ( || 1f32 . ln_1p ( ) ) ;
1485+ check_nondet ( || 27.0f32 . cbrt ( ) ) ;
1486+ check_nondet ( || 3.0f32 . hypot ( 4.0f32 ) ) ;
1487+ check_nondet ( || 1f32 . sin ( ) ) ;
1488+ check_nondet ( || 1f32 . cos ( ) ) ;
15151489 // On i686-pc-windows-msvc , these functions are implemented by calling the `f64` version,
15161490 // which means the little rounding errors Miri introduces are discarded by the cast down to
15171491 // `f32`. Just skip the test for them.
15181492 if !cfg ! ( all( target_os = "windows" , target_env = "msvc" , target_arch = "x86" ) ) {
1519- ensure_nondet ( || 1.0f32 . tan ( ) ) ;
1520- ensure_nondet ( || 1.0f32 . asin ( ) ) ;
1521- ensure_nondet ( || 5.0f32 . acos ( ) ) ;
1522- ensure_nondet ( || 1.0f32 . atan ( ) ) ;
1523- ensure_nondet ( || 1.0f32 . atan2 ( 2.0f32 ) ) ;
1524- ensure_nondet ( || 1.0f32 . sinh ( ) ) ;
1525- ensure_nondet ( || 1.0f32 . cosh ( ) ) ;
1526- ensure_nondet ( || 1.0f32 . tanh ( ) ) ;
1493+ check_nondet ( || 1.0f32 . tan ( ) ) ;
1494+ check_nondet ( || 1.0f32 . asin ( ) ) ;
1495+ check_nondet ( || 5.0f32 . acos ( ) ) ;
1496+ check_nondet ( || 1.0f32 . atan ( ) ) ;
1497+ check_nondet ( || 1.0f32 . atan2 ( 2.0f32 ) ) ;
1498+ check_nondet ( || 1.0f32 . sinh ( ) ) ;
1499+ check_nondet ( || 1.0f32 . cosh ( ) ) ;
1500+ check_nondet ( || 1.0f32 . tanh ( ) ) ;
15271501 }
1528- ensure_nondet ( || 1.0f32 . asinh ( ) ) ;
1529- ensure_nondet ( || 2.0f32 . acosh ( ) ) ;
1530- ensure_nondet ( || 0.5f32 . atanh ( ) ) ;
1531- ensure_nondet ( || 5.0f32 . gamma ( ) ) ;
1532- ensure_nondet ( || 5.0f32 . ln_gamma ( ) ) ;
1533- ensure_nondet ( || 5.0f32 . erf ( ) ) ;
1534- ensure_nondet ( || 5.0f32 . erfc ( ) ) ;
1502+ check_nondet ( || 1.0f32 . asinh ( ) ) ;
1503+ check_nondet ( || 2.0f32 . acosh ( ) ) ;
1504+ check_nondet ( || 0.5f32 . atanh ( ) ) ;
1505+ check_nondet ( || 5.0f32 . gamma ( ) ) ;
1506+ check_nondet ( || 5.0f32 . ln_gamma ( ) ) ;
1507+ check_nondet ( || 5.0f32 . erf ( ) ) ;
1508+ check_nondet ( || 5.0f32 . erfc ( ) ) ;
15351509 }
15361510 pub fn test_operations_f64 ( a : f64 , b : f64 ) {
15371511 test_operations_f ! ( a, b) ;
1538- ensure_nondet ( || a. powf ( b) ) ;
1539- ensure_nondet ( || a. powi ( 2 ) ) ;
1540- ensure_nondet ( || a. log ( b) ) ;
1541- ensure_nondet ( || a. exp ( ) ) ;
1542- ensure_nondet ( || 50f64 . exp2 ( ) ) ;
1543- ensure_nondet ( || 3f64 . ln ( ) ) ;
1544- ensure_nondet ( || f64:: consts:: E . log10 ( ) ) ;
1545- ensure_nondet ( || f64:: consts:: E . log2 ( ) ) ;
1546- ensure_nondet ( || 1f64 . ln_1p ( ) ) ;
1547- ensure_nondet ( || 27.0f64 . cbrt ( ) ) ;
1548- ensure_nondet ( || 3.0f64 . hypot ( 4.0f64 ) ) ;
1549- ensure_nondet ( || 1f64 . sin ( ) ) ;
1550- ensure_nondet ( || 1f64 . cos ( ) ) ;
1551- ensure_nondet ( || 1.0f64 . tan ( ) ) ;
1552- ensure_nondet ( || 1.0f64 . asin ( ) ) ;
1553- ensure_nondet ( || 5.0f64 . acos ( ) ) ;
1554- ensure_nondet ( || 1.0f64 . atan ( ) ) ;
1555- ensure_nondet ( || 1.0f64 . atan2 ( 2.0f64 ) ) ;
1556- ensure_nondet ( || 1.0f64 . sinh ( ) ) ;
1557- ensure_nondet ( || 1.0f64 . cosh ( ) ) ;
1558- ensure_nondet ( || 1.0f64 . tanh ( ) ) ;
1559- ensure_nondet ( || 1.0f64 . asinh ( ) ) ;
1560- ensure_nondet ( || 3.0f64 . acosh ( ) ) ;
1561- ensure_nondet ( || 0.5f64 . atanh ( ) ) ;
1562- ensure_nondet ( || 5.0f64 . gamma ( ) ) ;
1563- ensure_nondet ( || 5.0f64 . ln_gamma ( ) ) ;
1564- ensure_nondet ( || 5.0f64 . erf ( ) ) ;
1565- ensure_nondet ( || 5.0f64 . erfc ( ) ) ;
1512+ check_nondet ( || a. powf ( b) ) ;
1513+ check_nondet ( || a. powi ( 2 ) ) ;
1514+ check_nondet ( || a. log ( b) ) ;
1515+ check_nondet ( || a. exp ( ) ) ;
1516+ check_nondet ( || 50f64 . exp2 ( ) ) ;
1517+ check_nondet ( || 3f64 . ln ( ) ) ;
1518+ check_nondet ( || f64:: consts:: E . log10 ( ) ) ;
1519+ check_nondet ( || f64:: consts:: E . log2 ( ) ) ;
1520+ check_nondet ( || 1f64 . ln_1p ( ) ) ;
1521+ check_nondet ( || 27.0f64 . cbrt ( ) ) ;
1522+ check_nondet ( || 3.0f64 . hypot ( 4.0f64 ) ) ;
1523+ check_nondet ( || 1f64 . sin ( ) ) ;
1524+ check_nondet ( || 1f64 . cos ( ) ) ;
1525+ check_nondet ( || 1.0f64 . tan ( ) ) ;
1526+ check_nondet ( || 1.0f64 . asin ( ) ) ;
1527+ check_nondet ( || 5.0f64 . acos ( ) ) ;
1528+ check_nondet ( || 1.0f64 . atan ( ) ) ;
1529+ check_nondet ( || 1.0f64 . atan2 ( 2.0f64 ) ) ;
1530+ check_nondet ( || 1.0f64 . sinh ( ) ) ;
1531+ check_nondet ( || 1.0f64 . cosh ( ) ) ;
1532+ check_nondet ( || 1.0f64 . tanh ( ) ) ;
1533+ check_nondet ( || 1.0f64 . asinh ( ) ) ;
1534+ check_nondet ( || 3.0f64 . acosh ( ) ) ;
1535+ check_nondet ( || 0.5f64 . atanh ( ) ) ;
1536+ check_nondet ( || 5.0f64 . gamma ( ) ) ;
1537+ check_nondet ( || 5.0f64 . ln_gamma ( ) ) ;
1538+ check_nondet ( || 5.0f64 . erf ( ) ) ;
1539+ check_nondet ( || 5.0f64 . erfc ( ) ) ;
15661540 }
15671541 pub fn test_operations_f128 ( a : f128 , b : f128 ) {
15681542 test_operations_f ! ( a, b) ;
@@ -1574,15 +1548,15 @@ fn test_non_determinism() {
15741548 test_operations_f128 ( 25. , 18. ) ;
15751549
15761550 // SNaN^0 = (1 | NaN)
1577- ensure_nondet ( || f32:: powf ( SNAN_F32 , 0.0 ) . is_nan ( ) ) ;
1578- ensure_nondet ( || f64:: powf ( SNAN_F64 , 0.0 ) . is_nan ( ) ) ;
1551+ check_nondet ( || f32:: powf ( SNAN_F32 , 0.0 ) . is_nan ( ) ) ;
1552+ check_nondet ( || f64:: powf ( SNAN_F64 , 0.0 ) . is_nan ( ) ) ;
15791553
15801554 // 1^SNaN = (1 | NaN)
1581- ensure_nondet ( || f32:: powf ( 1.0 , SNAN_F32 ) . is_nan ( ) ) ;
1582- ensure_nondet ( || f64:: powf ( 1.0 , SNAN_F64 ) . is_nan ( ) ) ;
1555+ check_nondet ( || f32:: powf ( 1.0 , SNAN_F32 ) . is_nan ( ) ) ;
1556+ check_nondet ( || f64:: powf ( 1.0 , SNAN_F64 ) . is_nan ( ) ) ;
15831557
15841558 // same as powf (keep it consistent):
15851559 // x^SNaN = (1 | NaN)
1586- ensure_nondet ( || f32:: powi ( SNAN_F32 , 0 ) . is_nan ( ) ) ;
1587- ensure_nondet ( || f64:: powi ( SNAN_F64 , 0 ) . is_nan ( ) ) ;
1560+ check_nondet ( || f32:: powi ( SNAN_F32 , 0 ) . is_nan ( ) ) ;
1561+ check_nondet ( || f64:: powi ( SNAN_F64 , 0 ) . is_nan ( ) ) ;
15881562}
0 commit comments