diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 53bd2d3dc08..92eb4a80fca 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -708,6 +708,23 @@ impl Float for f32 { fn next_after(&self, other: f32) -> f32 { next_after(*self, other) } + + /// Returns the mantissa, exponent and sign as integers. + fn integer_decode(&self) -> (u64, i16, i8) { + let bits: u32 = unsafe { + ::cast::transmute(*self) + }; + let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 }; + let mut exponent: i16 = ((bits >> 23) & 0xff) as i16; + let mantissa = if exponent == 0 { + (bits & 0x7fffff) << 1 + } else { + (bits & 0x7fffff) | 0x800000 + }; + // Exponent bias + mantissa shift + exponent -= 127 + 23; + (mantissa as u64, exponent, sign) + } } // @@ -1273,4 +1290,16 @@ mod tests { assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf) assert!(match nan.frexp() { (x, _) => x.is_nan() }) } + + #[test] + fn test_integer_decode() { + assert_eq!(3.14159265359f32.integer_decode(), (13176795u64, -22i16, 1i8)); + assert_eq!((-8573.5918555f32).integer_decode(), (8779358u64, -10i16, -1i8)); + assert_eq!(2f32.pow(&100.0).integer_decode(), (8388608u64, 77i16, 1i8)); + assert_eq!(0f32.integer_decode(), (0u64, -150i16, 1i8)); + assert_eq!((-0f32).integer_decode(), (0u64, -150i16, -1i8)); + assert_eq!(INFINITY.integer_decode(), (8388608u64, 105i16, 1i8)); + assert_eq!(NEG_INFINITY.integer_decode(), (8388608u64, 105i16, -1i8)); + assert_eq!(NAN.integer_decode(), (12582912u64, 105i16, 1i8)); + } } diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 49b20b2c4f4..2dfb23283df 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -756,6 +756,23 @@ impl Float for f64 { fn next_after(&self, other: f64) -> f64 { next_after(*self, other) } + + /// Returns the mantissa, exponent and sign as integers. + fn integer_decode(&self) -> (u64, i16, i8) { + let bits: u64 = unsafe { + ::cast::transmute(*self) + }; + let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 }; + let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16; + let mantissa = if exponent == 0 { + (bits & 0xfffffffffffff) << 1 + } else { + (bits & 0xfffffffffffff) | 0x10000000000000 + }; + // Exponent bias + mantissa shift + exponent -= 1023 + 52; + (mantissa, exponent, sign) + } } // @@ -1323,4 +1340,16 @@ mod tests { assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf) assert!(match nan.frexp() { (x, _) => x.is_nan() }) } + + #[test] + fn test_integer_decode() { + assert_eq!(3.14159265359f64.integer_decode(), (7074237752028906u64, -51i16, 1i8)); + assert_eq!((-8573.5918555f64).integer_decode(), (4713381968463931u64, -39i16, -1i8)); + assert_eq!(2f64.pow(&100.0).integer_decode(), (4503599627370496u64, 48i16, 1i8)); + assert_eq!(0f64.integer_decode(), (0u64, -1075i16, 1i8)); + assert_eq!((-0f64).integer_decode(), (0u64, -1075i16, -1i8)); + assert_eq!(INFINITY.integer_decode(), (4503599627370496u64, 972i16, 1i8)); + assert_eq!(NEG_INFINITY.integer_decode(), (4503599627370496, 972, -1)); + assert_eq!(NAN.integer_decode(), (6755399441055744u64, 972i16, 1i8)); + } } diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index 456011d5172..79efe5934d5 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -532,6 +532,8 @@ pub trait Float: Real fn ln_1p(&self) -> Self; fn mul_add(&self, a: Self, b: Self) -> Self; fn next_after(&self, other: Self) -> Self; + + fn integer_decode(&self) -> (u64, i16, i8); } /// Returns the exponential of the number, minus `1`, `exp(n) - 1`, in a way