@@ -506,6 +506,13 @@ fn random_nan<S: Semantics>(rng: &mut StdRng) -> IeeeFloat<S> {
506
506
/// - logf32, logf64, log2f32, log2f64, log10f32, log10f64
507
507
/// - powf32, powf64
508
508
///
509
+ /// # Return
510
+ ///
511
+ /// Returns `Some(output)` if the `intrinsic` results in a defined fixed `output` specified in the C standard
512
+ /// (specifically, C23 annex F.10) when given `args` as arguments. Outputs that are unaffected by a relative error
513
+ /// (such as INF and zero) are not handled here, they are assumed to be handled by the underlying
514
+ /// implementation. Returns `None` if no specific value is guaranteed.
515
+ ///
509
516
/// # Note
510
517
///
511
518
/// For `powf*` operations of the form:
@@ -520,12 +527,7 @@ fn random_nan<S: Semantics>(rng: &mut StdRng) -> IeeeFloat<S> {
520
527
/// This discrepancy exists because SNaN handling is not consistently defined across platforms,
521
528
/// and the C standard leaves behavior for SNaNs unspecified.
522
529
///
523
- /// # Return
524
- ///
525
- /// Returns `Some(output)` if the `intrinsic` results in a defined fixed `output` specified in the C standard
526
- /// (specifically, C23 annex F.10) when given `args` as arguments. Outputs that are unaffected by a relative error
527
- /// (such as INF and zero) are not handled here, they are assumed to be handled by the underlying
528
- /// implementation. Returns `None` if no specific value is guaranteed.
530
+ /// Miri chooses to adhere to both implementations and returns either one of them non-deterministically.
529
531
fn fixed_float_value < ' tcx , S : Semantics > (
530
532
ecx : & mut MiriInterpCx < ' tcx > ,
531
533
intrinsic_name : & str ,
@@ -539,12 +541,15 @@ fn fixed_float_value<'tcx, S: Semantics>(
539
541
// e^0 = 1
540
542
( "expf32" | "expf64" | "exp2f32" | "exp2f64" , [ input] ) if input. is_zero ( ) => one,
541
543
542
- // 1^y = 1 for any y, even a NaN
543
- ( "powf32" | "powf64" , [ base, _] ) if * base == one => one,
544
-
545
544
// (-1)^(±INF) = 1
546
545
( "powf32" | "powf64" , [ base, exp] ) if * base == -one && exp. is_infinite ( ) => one,
547
546
547
+ // 1^y = 1 for any y, even a NaN, *but* not a SNaN
548
+ ( "powf32" | "powf64" , [ base, exp] ) if * base == one => {
549
+ let rng = ecx. machine . rng . get_mut ( ) ;
550
+ // Handle both the musl and glibc cases non-deterministically.
551
+ if !exp. is_signaling ( ) || rng. random ( ) { one } else { random_nan ( rng) }
552
+ }
548
553
// x^(±0) = 1 for any x, even a NaN, *but* not a SNaN
549
554
( "powf32" | "powf64" , [ base, exp] ) if exp. is_zero ( ) => {
550
555
// Handle both the musl and glibc cases non-deterministically.
0 commit comments