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