Add functions to safely transmute float to int
This commit is contained in:
parent
5516bcc458
commit
32a43da68a
@ -1226,6 +1226,45 @@ impl f32 {
|
||||
pub fn atanh(self) -> f32 {
|
||||
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
|
||||
}
|
||||
|
||||
/// Raw transmutation to `u32`.
|
||||
///
|
||||
/// Converts the `f32` into its raw memory representation,
|
||||
/// similar to the `transmute` function.
|
||||
///
|
||||
/// Note that this function is distinct from casting.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(float_bits_conv)]
|
||||
/// assert!((1f32).to_bits() != 1f32 as u32); // to_bits() is not casting!
|
||||
/// assert_eq!((12.5f32).to_bits(), 0x41480000);
|
||||
///
|
||||
/// ```
|
||||
#[unstable(feature = "float_bits_conv", reason = "recently added", issue = "0")]
|
||||
#[inline]
|
||||
pub fn to_bits(self) -> u32 {
|
||||
unsafe { ::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Raw transmutation from `u32`.
|
||||
///
|
||||
/// Converts the given `u32` containing the float's raw memory
|
||||
/// representation into the `f32` type, similar to the
|
||||
/// `transmute` function.
|
||||
///
|
||||
/// Note that this function is distinct from casting.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(float_bits_conv)]
|
||||
/// use std::f32;
|
||||
/// let difference = (f32::from_bits(0x41480000) - 12.5).abs();
|
||||
/// assert!(difference <= 1e-5);
|
||||
/// ```
|
||||
#[unstable(feature = "float_bits_conv", reason = "recently added", issue = "0")]
|
||||
#[inline]
|
||||
pub fn from_bits(v: u32) -> Self {
|
||||
unsafe { ::mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -1870,4 +1909,16 @@ mod tests {
|
||||
assert_approx_eq!(ln_2, 2f32.ln());
|
||||
assert_approx_eq!(ln_10, 10f32.ln());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_float_bits_conv() {
|
||||
assert_eq!((1f32).to_bits(), 0x3f800000);
|
||||
assert_eq!((12.5f32).to_bits(), 0x41480000);
|
||||
assert_eq!((1337f32).to_bits(), 0x44a72000);
|
||||
assert_eq!((-14.25f32).to_bits(), 0xc1640000);
|
||||
assert_approx_eq!(f32::from_bits(0x3f800000), 1.0);
|
||||
assert_approx_eq!(f32::from_bits(0x41480000), 12.5);
|
||||
assert_approx_eq!(f32::from_bits(0x44a72000), 1337.0);
|
||||
assert_approx_eq!(f32::from_bits(0xc1640000), -14.25);
|
||||
}
|
||||
}
|
||||
|
@ -1118,6 +1118,45 @@ impl f64 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Raw transmutation to `u64`.
|
||||
///
|
||||
/// Converts the `f64` into its raw memory representation,
|
||||
/// similar to the `transmute` function.
|
||||
///
|
||||
/// Note that this function is distinct from casting.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(float_bits_conv)]
|
||||
/// assert!((1f64).to_bits() != 1f64 as u64); // to_bits() is not casting!
|
||||
/// assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
|
||||
///
|
||||
/// ```
|
||||
#[unstable(feature = "float_bits_conv", reason = "recently added", issue = "0")]
|
||||
#[inline]
|
||||
pub fn to_bits(self) -> u64 {
|
||||
unsafe { ::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Raw transmutation from `u64`.
|
||||
///
|
||||
/// Converts the given `u64` containing the float's raw memory
|
||||
/// representation into the `f64` type, similar to the
|
||||
/// `transmute` function.
|
||||
///
|
||||
/// Note that this function is distinct from casting.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(float_bits_conv)]
|
||||
/// use std::f64;
|
||||
/// let difference = (f64::from_bits(0x4029000000000000) - 12.5).abs();
|
||||
/// assert!(difference <= 1e-5);
|
||||
/// ```
|
||||
#[unstable(feature = "float_bits_conv", reason = "recently added", issue = "0")]
|
||||
#[inline]
|
||||
pub fn from_bits(v: u64) -> Self {
|
||||
unsafe { ::mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -1755,4 +1794,16 @@ mod tests {
|
||||
assert_approx_eq!(ln_2, 2f64.ln());
|
||||
assert_approx_eq!(ln_10, 10f64.ln());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_float_bits_conv() {
|
||||
assert_eq!((1f64).to_bits(), 0x3ff0000000000000);
|
||||
assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
|
||||
assert_eq!((1337f64).to_bits(), 0x4094e40000000000);
|
||||
assert_eq!((-14.25f64).to_bits(), 0xc02c800000000000);
|
||||
assert_approx_eq!(f64::from_bits(0x3ff0000000000000), 1.0);
|
||||
assert_approx_eq!(f64::from_bits(0x4029000000000000), 12.5);
|
||||
assert_approx_eq!(f64::from_bits(0x4094e40000000000), 1337.0);
|
||||
assert_approx_eq!(f64::from_bits(0xc02c800000000000), -14.25);
|
||||
}
|
||||
}
|
||||
|
@ -321,6 +321,7 @@
|
||||
#![feature(zero_one)]
|
||||
#![cfg_attr(test, feature(update_panic_count))]
|
||||
#![cfg_attr(stage0, feature(pub_restricted))]
|
||||
#![cfg_attr(test, feature(float_bits_conv))]
|
||||
|
||||
// Explicitly import the prelude. The compiler uses this same unstable attribute
|
||||
// to import the prelude implicitly when building crates that depend on std.
|
||||
|
Loading…
x
Reference in New Issue
Block a user