From ad47f0874a8161ad0b31d0e8c0d94f39766183d3 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Tue, 26 Feb 2019 16:47:33 +0100 Subject: [PATCH 1/2] Add float conversions to and from bytes Use the same API as for integers. Fixes #57492. --- src/libcore/num/f32.rs | 70 ++++++++++++++++++++++++++++++++++++++++++ src/libcore/num/f64.rs | 36 ++++++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 0bcd371b528e4..aa447aa893008 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -461,4 +461,74 @@ impl f32 { // It turns out the safety issues with sNaN were overblown! Hooray! unsafe { mem::transmute(v) } } + + /// Return the floating point value as a byte array in big-endian byte order. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(0.0f32.to_be_bytes(), [0b0000_0000, 0b0000_0000, 0b0000_0000, 0b0000_0000]); + /// assert_eq!(1.0f32.to_be_bytes(), [0b0111_1111, 0b1000_0000, 0b0000_0000, 0b0000_0000]); + /// ``` + #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[inline] + pub fn to_be_bytes(self) -> [u8; 4] { + self.to_bits().to_be_bytes() + } + + /// Return the floating point value as a byte array in little-endian byte order. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(0.0f32.to_le_bytes(), [0b0000_0000, 0b0000_0000, 0b0000_0000, 0b0000_0000]); + /// assert_eq!(1.0f32.to_le_bytes(), [0b0000_0000, 0b0000_0000, 0b1000_0000, 0b0111_1111]); + /// ``` + #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[inline] + pub fn to_le_bytes(self) -> [u8; 4] { + self.to_bits().to_le_bytes() + } + + /// Return the floating point value as a byte array in native byte order. + /// + /// + /// As the target platform's native endianness is used, portable code + /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead. + /// + /// # Examples + /// + /// ``` + /// assert_eq!( + /// u32::from_ne_bytes(0.0f32.to_ne_bytes()), + /// 0b0000_0000_0000_0000_0000_0000_0000_0000, + /// ); + /// assert_eq!( + /// u32::from_ne_bytes(1.0f32.to_ne_bytes()), + /// 0b0111_1111_1000_0000_0000_0000_0000_0000, + /// ); + /// ``` + #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[inline] + pub fn to_ne_bytes(self) -> [u8; 4] { + self.to_bits().to_ne_bytes() + } + + #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[inline] + pub fn from_be_bytes(bytes: [u8; 4]) -> Self { + Self::from_bits(u32::from_be_bytes(bytes)) + } + + #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[inline] + pub fn from_le_bytes(bytes: [u8; 4]) -> Self { + Self::from_bits(u32::from_le_bytes(bytes)) + } + + #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[inline] + pub fn from_ne_bytes(bytes: [u8; 4]) -> Self { + Self::from_bits(u32::from_ne_bytes(bytes)) + } } diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 4d4a2c9c5a97c..8c886db03ad60 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -474,4 +474,40 @@ impl f64 { // It turns out the safety issues with sNaN were overblown! Hooray! unsafe { mem::transmute(v) } } + + #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[inline] + pub fn to_be_bytes(self) -> [u8; 8] { + self.to_bits().to_be_bytes() + } + + #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[inline] + pub fn to_le_bytes(self) -> [u8; 8] { + self.to_bits().to_le_bytes() + } + + #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[inline] + pub fn to_ne_bytes(self) -> [u8; 8] { + self.to_bits().to_ne_bytes() + } + + #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[inline] + pub fn from_be_bytes(bytes: [u8; 8]) -> Self { + Self::from_bits(u64::from_be_bytes(bytes)) + } + + #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[inline] + pub fn from_le_bytes(bytes: [u8; 8]) -> Self { + Self::from_bits(u64::from_le_bytes(bytes)) + } + + #[unstable(feature = "float_to_from_bytes", issue = "60446")] + #[inline] + pub fn from_ne_bytes(bytes: [u8; 8]) -> Self { + Self::from_bits(u64::from_ne_bytes(bytes)) + } } From df53a3fd55a233cc04ce20d448f64ec70b937b06 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 4 Jul 2019 09:11:15 +0000 Subject: [PATCH 2/2] Add documentation to float conversion methods --- src/libcore/num/f32.rs | 79 ++++++++++++++++++++++++++++++--------- src/libcore/num/f64.rs | 85 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 144 insertions(+), 20 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index aa447aa893008..fc2c431ca0f9c 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -450,10 +450,8 @@ impl f32 { /// # Examples /// /// ``` - /// use std::f32; /// let v = f32::from_bits(0x41480000); - /// let difference = (v - 12.5).abs(); - /// assert!(difference <= 1e-5); + /// assert_eq!(v, 12.5); /// ``` #[stable(feature = "float_bits_conv", since = "1.20.0")] #[inline] @@ -462,13 +460,15 @@ impl f32 { unsafe { mem::transmute(v) } } - /// Return the floating point value as a byte array in big-endian byte order. + /// Return the memory representation of this floating point number as a byte array in + /// big-endian (network) byte order. /// /// # Examples /// /// ``` - /// assert_eq!(0.0f32.to_be_bytes(), [0b0000_0000, 0b0000_0000, 0b0000_0000, 0b0000_0000]); - /// assert_eq!(1.0f32.to_be_bytes(), [0b0111_1111, 0b1000_0000, 0b0000_0000, 0b0000_0000]); + /// #![feature(float_to_from_bytes)] + /// let bytes = 12.5f32.to_be_bytes(); + /// assert_eq!(bytes, [0x41, 0x48, 0x00, 0x00]); /// ``` #[unstable(feature = "float_to_from_bytes", issue = "60446")] #[inline] @@ -476,13 +476,15 @@ impl f32 { self.to_bits().to_be_bytes() } - /// Return the floating point value as a byte array in little-endian byte order. + /// Return the memory representation of this floating point number as a byte array in + /// little-endian byte order. /// /// # Examples /// /// ``` - /// assert_eq!(0.0f32.to_le_bytes(), [0b0000_0000, 0b0000_0000, 0b0000_0000, 0b0000_0000]); - /// assert_eq!(1.0f32.to_le_bytes(), [0b0000_0000, 0b0000_0000, 0b1000_0000, 0b0111_1111]); + /// #![feature(float_to_from_bytes)] + /// let bytes = 12.5f32.to_le_bytes(); + /// assert_eq!(bytes, [0x00, 0x00, 0x48, 0x41]); /// ``` #[unstable(feature = "float_to_from_bytes", issue = "60446")] #[inline] @@ -490,22 +492,27 @@ impl f32 { self.to_bits().to_le_bytes() } - /// Return the floating point value as a byte array in native byte order. - /// + /// Return the memory representation of this floating point number as a byte array in + /// native byte order. /// /// As the target platform's native endianness is used, portable code /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead. /// + /// [`to_be_bytes`]: #method.to_be_bytes + /// [`to_le_bytes`]: #method.to_le_bytes + /// /// # Examples /// /// ``` + /// #![feature(float_to_from_bytes)] + /// let bytes = 12.5f32.to_ne_bytes(); /// assert_eq!( - /// u32::from_ne_bytes(0.0f32.to_ne_bytes()), - /// 0b0000_0000_0000_0000_0000_0000_0000_0000, - /// ); - /// assert_eq!( - /// u32::from_ne_bytes(1.0f32.to_ne_bytes()), - /// 0b0111_1111_1000_0000_0000_0000_0000_0000, + /// bytes, + /// if cfg!(target_endian = "big") { + /// [0x41, 0x48, 0x00, 0x00] + /// } else { + /// [0x00, 0x00, 0x48, 0x41] + /// } /// ); /// ``` #[unstable(feature = "float_to_from_bytes", issue = "60446")] @@ -514,18 +521,56 @@ impl f32 { self.to_bits().to_ne_bytes() } + /// Create a floating point value from its representation as a byte array in big endian. + /// + /// # Examples + /// + /// ``` + /// #![feature(float_to_from_bytes)] + /// let value = f32::from_be_bytes([0x41, 0x48, 0x00, 0x00]); + /// assert_eq!(value, 12.5); + /// ``` #[unstable(feature = "float_to_from_bytes", issue = "60446")] #[inline] pub fn from_be_bytes(bytes: [u8; 4]) -> Self { Self::from_bits(u32::from_be_bytes(bytes)) } + /// Create a floating point value from its representation as a byte array in big endian. + /// + /// # Examples + /// + /// ``` + /// #![feature(float_to_from_bytes)] + /// let value = f32::from_le_bytes([0x00, 0x00, 0x48, 0x41]); + /// assert_eq!(value, 12.5); + /// ``` #[unstable(feature = "float_to_from_bytes", issue = "60446")] #[inline] pub fn from_le_bytes(bytes: [u8; 4]) -> Self { Self::from_bits(u32::from_le_bytes(bytes)) } + /// Create a floating point value from its representation as a byte array in big endian. + /// + /// As the target platform's native endianness is used, portable code + /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as + /// appropriate instead. + /// + /// [`from_be_bytes`]: #method.from_be_bytes + /// [`from_le_bytes`]: #method.from_le_bytes + /// + /// # Examples + /// + /// ``` + /// #![feature(float_to_from_bytes)] + /// let value = f32::from_ne_bytes(if cfg!(target_endian = "big") { + /// [0x41, 0x48, 0x00, 0x00] + /// } else { + /// [0x00, 0x00, 0x48, 0x41] + /// }); + /// assert_eq!(value, 12.5); + /// ``` #[unstable(feature = "float_to_from_bytes", issue = "60446")] #[inline] pub fn from_ne_bytes(bytes: [u8; 4]) -> Self { diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 8c886db03ad60..6bd0b6e5c7f77 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -463,10 +463,8 @@ impl f64 { /// # Examples /// /// ``` - /// use std::f64; /// let v = f64::from_bits(0x4029000000000000); - /// let difference = (v - 12.5).abs(); - /// assert!(difference <= 1e-5); + /// assert_eq!(v, 12.5); /// ``` #[stable(feature = "float_bits_conv", since = "1.20.0")] #[inline] @@ -475,36 +473,117 @@ impl f64 { unsafe { mem::transmute(v) } } + /// Return the memory representation of this floating point number as a byte array in + /// big-endian (network) byte order. + /// + /// # Examples + /// + /// ``` + /// #![feature(float_to_from_bytes)] + /// let bytes = 12.5f64.to_be_bytes(); + /// assert_eq!(bytes, [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + /// ``` #[unstable(feature = "float_to_from_bytes", issue = "60446")] #[inline] pub fn to_be_bytes(self) -> [u8; 8] { self.to_bits().to_be_bytes() } + /// Return the memory representation of this floating point number as a byte array in + /// little-endian byte order. + /// + /// # Examples + /// + /// ``` + /// #![feature(float_to_from_bytes)] + /// let bytes = 12.5f64.to_le_bytes(); + /// assert_eq!(bytes, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]); + /// ``` #[unstable(feature = "float_to_from_bytes", issue = "60446")] #[inline] pub fn to_le_bytes(self) -> [u8; 8] { self.to_bits().to_le_bytes() } + /// Return the memory representation of this floating point number as a byte array in + /// native byte order. + /// + /// As the target platform's native endianness is used, portable code + /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead. + /// + /// [`to_be_bytes`]: #method.to_be_bytes + /// [`to_le_bytes`]: #method.to_le_bytes + /// + /// # Examples + /// + /// ``` + /// #![feature(float_to_from_bytes)] + /// let bytes = 12.5f64.to_ne_bytes(); + /// assert_eq!( + /// bytes, + /// if cfg!(target_endian = "big") { + /// [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + /// } else { + /// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40] + /// } + /// ); + /// ``` #[unstable(feature = "float_to_from_bytes", issue = "60446")] #[inline] pub fn to_ne_bytes(self) -> [u8; 8] { self.to_bits().to_ne_bytes() } + /// Create a floating point value from its representation as a byte array in big endian. + /// + /// # Examples + /// + /// ``` + /// #![feature(float_to_from_bytes)] + /// let value = f64::from_be_bytes([0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + /// assert_eq!(value, 12.5); + /// ``` #[unstable(feature = "float_to_from_bytes", issue = "60446")] #[inline] pub fn from_be_bytes(bytes: [u8; 8]) -> Self { Self::from_bits(u64::from_be_bytes(bytes)) } + /// Create a floating point value from its representation as a byte array in big endian. + /// + /// # Examples + /// + /// ``` + /// #![feature(float_to_from_bytes)] + /// let value = f64::from_le_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]); + /// assert_eq!(value, 12.5); + /// ``` #[unstable(feature = "float_to_from_bytes", issue = "60446")] #[inline] pub fn from_le_bytes(bytes: [u8; 8]) -> Self { Self::from_bits(u64::from_le_bytes(bytes)) } + /// Create a floating point value from its representation as a byte array in big endian. + /// + /// As the target platform's native endianness is used, portable code + /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as + /// appropriate instead. + /// + /// [`from_be_bytes`]: #method.from_be_bytes + /// [`from_le_bytes`]: #method.from_le_bytes + /// + /// # Examples + /// + /// ``` + /// #![feature(float_to_from_bytes)] + /// let value = f64::from_ne_bytes(if cfg!(target_endian = "big") { + /// [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + /// } else { + /// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40] + /// }); + /// assert_eq!(value, 12.5); + /// ``` #[unstable(feature = "float_to_from_bytes", issue = "60446")] #[inline] pub fn from_ne_bytes(bytes: [u8; 8]) -> Self {