Skip to content

Commit 6718b82

Browse files
authored
various minor tweaks
1 parent f49980c commit 6718b82

File tree

2 files changed

+12
-9
lines changed

2 files changed

+12
-9
lines changed

src/tools/miri/src/intrinsics/mod.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use self::atomic::EvalContextExt as _;
1717
use self::helpers::{ToHost, ToSoft, check_intrinsic_arg_count};
1818
use self::simd::EvalContextExt as _;
1919
use crate::math::{IeeeExt, apply_random_float_error_ulp};
20-
use crate::operator::EvalContextExt as _;
2120
use crate::*;
2221

2322
impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
@@ -535,18 +534,20 @@ fn fixed_float_value<S: Semantics>(
535534
// (-1)^(±INF) = 1
536535
("powf32" | "powf64", [base, exp]) if *base == -one && exp.is_infinite() => one,
537536

538-
// 1^y = 1 for any y, even a NaN, *but* not a SNaN
537+
// 1^y = 1 for any y, even a NaN
539538
("powf32" | "powf64", [base, exp]) if *base == one => {
540539
let rng = ecx.machine.rng.get_mut();
541-
let return_nan = ecx.machine.float_nondet && rng.random() && exp.is_signaling();
540+
// SNaN exponents get special treatment: they might return 1, or a NaN.
541+
let return_nan = exp.is_signaling() && ecx.machine.float_nondet && rng.random();
542542
// Handle both the musl and glibc cases non-deterministically.
543543
if return_nan { ecx.generate_nan(args) } else { one }
544544
}
545545

546-
// x^(±0) = 1 for any x, even a NaN, *but* not a SNaN
546+
// x^(±0) = 1 for any x, even a NaN
547547
("powf32" | "powf64", [base, exp]) if exp.is_zero() => {
548548
let rng = ecx.machine.rng.get_mut();
549-
let return_nan = ecx.machine.float_nondet && rng.random() && base.is_signaling();
549+
// SNaN bases get special treatment: they might return 1, or a NaN.
550+
let return_nan = base.is_signaling() && ecx.machine.float_nondet && rng.random();
550551
// Handle both the musl and glibc cases non-deterministically.
551552
if return_nan { ecx.generate_nan(args) } else { one }
552553
}
@@ -559,7 +560,9 @@ fn fixed_float_value<S: Semantics>(
559560

560561
/// Returns `Some(output)` if `powi` (called `pown` in C) results in a fixed value specified in the C standard
561562
/// (specifically, C23 annex F.10.4.6) when doing `base^exp`. Otherwise, returns `None`.
562-
// TODO: I'm not sure what I should document here about pown(1, SNaN) since musl and glibc do the same and the C standard is explicit here.
563+
/// For SNaN treatment, we are consistent with `powf`above.
564+
/// (We wouldn't have two, unlike powf all implementations seem to agree for powi,
565+
/// but for now we are maximally conservative.)
563566
fn fixed_powi_float_value<S: Semantics>(
564567
ecx: &mut MiriInterpCx<'_>,
565568
base: IeeeFloat<S>,

src/tools/miri/tests/pass/float.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,16 +1491,16 @@ fn test_non_determinism() {
14911491
test_operations_f128(25., 18.);
14921492

14931493

1494-
// x^(SNaN) = (1 | NaN)
1494+
// SNaN^0 = (1 | NaN)
14951495
ensure_nondet(|| f32::powf(SNAN_F32, 0.0));
14961496
ensure_nondet(|| f64::powf(SNAN_F64, 0.0));
14971497

1498-
// 1^(SNaN) = (1 | NaN)
1498+
// 1^SNaN = (1 | NaN)
14991499
ensure_nondet(|| f32::powf(1.0, SNAN_F32));
15001500
ensure_nondet(|| f64::powf(1.0, SNAN_F64));
15011501

15021502
// same as powf (keep it consistent):
1503-
// x^(SNaN) = (1 | NaN)
1503+
// x^SNaN = (1 | NaN)
15041504
ensure_nondet(|| f32::powi(SNAN_F32, 0));
15051505
ensure_nondet(|| f64::powi(SNAN_F64, 0));
15061506
}

0 commit comments

Comments
 (0)