Skip to content

Commit 3cd4fc4

Browse files
handling of sign nans
1 parent 802085d commit 3cd4fc4

File tree

2 files changed

+37
-5
lines changed

2 files changed

+37
-5
lines changed

Diff for: src/tools/miri/src/intrinsics/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,8 @@ fn fixed_powi_float_value<S: Semantics>(base: IeeeFloat<S>, exp: i32) -> Option<
632632
(Category::Zero, x) if x % 2 == 0 => Some(IeeeFloat::<S>::ZERO),
633633

634634
// x^0 = 1, if x is not a Signaling NaN
635+
// FIXME: The C ecosystem is inconsistent with handling sNaN's, some return 1 others propogate
636+
// the NaN. We should return either 1 or the NaN non-deterministically here.
635637
(_, 0) if !base.is_signaling() => Some(IeeeFloat::<S>::one()),
636638

637639
_ => None,

Diff for: src/tools/miri/tests/pass/float.rs

+35-5
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,31 @@ macro_rules! assert_approx_eq {
4444
};
4545
}
4646

47+
48+
/// From IEEE 754 a Signaling NaN for single precision has the following representation:
49+
/// ```
50+
/// s | 1111 1111 | 0x..x
51+
/// ````
52+
/// Were at least one `x` is a 1.
53+
///
54+
/// This sNaN has the following representation and is used for testing purposes.:
55+
/// ```
56+
/// 0 | 1111111 | 01..0
57+
/// ```
58+
const SINGLE_SNAN: f32 = f32::from_bits(0x7fa00000);
59+
60+
/// From IEEE 754 a Signaling NaN for double precision has the following representation:
61+
/// ```
62+
/// s | 1111 1111 111 | 0x..x
63+
/// ````
64+
/// Were at least one `x` is a 1.
65+
///
66+
/// This sNaN has the following representation and is used for testing purposes.:
67+
/// ```
68+
/// 0 | 1111 1111 111 | 01..0
69+
/// ```
70+
const DOUBLE_SNAN: f64 = f64::from_bits(0x7ff4000000000000);
71+
4772
fn main() {
4873
basic();
4974
casts();
@@ -1018,6 +1043,16 @@ pub fn libm() {
10181043
assert_eq!(1f32.powf(f32::NAN), 1f32);
10191044
assert_eq!(1f64.powf(f64::NAN), 1f64);
10201045

1046+
// For pown (powi in rust) the C standard says:
1047+
// x^0 = 1 for all x not a sNaN.
1048+
assert_ne!((SINGLE_SNAN).powi(0), 1.0);
1049+
assert_ne!((DOUBLE_SNAN).powi(0), 1.0);
1050+
assert_ne!((SINGLE_SNAN).powi(0), 1.0);
1051+
assert_ne!((DOUBLE_SNAN).powi(0), 1.0);
1052+
// f*::NAN is a quiet NAN and should return 1.
1053+
assert_eq!(f32::NAN.powi(0), 1f32);
1054+
assert_eq!(f64::NAN.powi(0), 1f64);
1055+
10211056
assert_eq!((-1f32).powf(f32::INFINITY), 1f32);
10221057
assert_eq!((-1f32).powf(f32::NEG_INFINITY), 1f32);
10231058
assert_eq!((-1f64).powf(f64::INFINITY), 1f64);
@@ -1039,11 +1074,6 @@ pub fn libm() {
10391074
assert_eq!(10.0f64.powi(0), 1.0f64);
10401075
assert_eq!(f32::INFINITY.powi(0), 1.0f32);
10411076
assert_eq!(f64::INFINITY.powi(0), 1.0f64);
1042-
// f*::NAN doesn't specify which what kind of bit pattern
1043-
// the NAN will have.
1044-
// We **assume** f*::NAN is not signaling.
1045-
assert_eq!(f32::NAN.powi(0), 1.0f32);
1046-
assert_eq!(f64::NAN.powi(0), 1.0f64);
10471077

10481078
assert_eq!((-0f32).powi(10), 0f32);
10491079
assert_eq!((-0f64).powi(100), 0f64);

0 commit comments

Comments
 (0)