mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-26 13:01:27 +03:00
added float masks feature
This commit is contained in:
@@ -339,14 +339,78 @@ impl f128 {
|
||||
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
|
||||
pub const MIN_EXACT_INTEGER: i128 = -Self::MAX_EXACT_INTEGER;
|
||||
|
||||
/// Sign bit
|
||||
pub(crate) const SIGN_MASK: u128 = 0x8000_0000_0000_0000_0000_0000_0000_0000;
|
||||
/// The mask of the bit used to encode the sign of an [`f128`].
|
||||
///
|
||||
/// This bit is set when the sign is negative and unset when the sign is
|
||||
/// positive.
|
||||
/// If you only need to check whether a value is positive or negative,
|
||||
/// [`is_sign_positive`] or [`is_sign_negative`] can be used.
|
||||
///
|
||||
/// [`is_sign_positive`]: f128::is_sign_positive
|
||||
/// [`is_sign_negative`]: f128::is_sign_negative
|
||||
/// ```rust
|
||||
/// #![feature(float_masks)]
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
/// let sign_mask = f128::SIGN_MASK;
|
||||
/// let a = 1.6552f128;
|
||||
/// let a_bits = a.to_bits();
|
||||
///
|
||||
/// assert_eq!(a_bits & sign_mask, 0x0);
|
||||
/// assert_eq!(f128::from_bits(a_bits ^ sign_mask), -a);
|
||||
/// assert_eq!(sign_mask, (-0.0f128).to_bits());
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "float_masks", issue = "154064")]
|
||||
pub const SIGN_MASK: u128 = 0x8000_0000_0000_0000_0000_0000_0000_0000;
|
||||
|
||||
/// Exponent mask
|
||||
pub(crate) const EXP_MASK: u128 = 0x7fff_0000_0000_0000_0000_0000_0000_0000;
|
||||
/// The mask of the bits used to encode the exponent of an [`f128`].
|
||||
///
|
||||
/// Note that the exponent is stored as a biased value, with a bias of 16383 for `f128`.
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(float_masks)]
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
/// fn get_exp(a: f128) -> i128 {
|
||||
/// let bias = 16383;
|
||||
/// let biased = a.to_bits() & f128::EXPONENT_MASK;
|
||||
/// (biased >> (f128::MANTISSA_DIGITS - 1)).cast_signed() - bias
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(get_exp(0.5), -1);
|
||||
/// assert_eq!(get_exp(1.0), 0);
|
||||
/// assert_eq!(get_exp(2.0), 1);
|
||||
/// assert_eq!(get_exp(4.0), 2);
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "float_masks", issue = "154064")]
|
||||
pub const EXPONENT_MASK: u128 = 0x7fff_0000_0000_0000_0000_0000_0000_0000;
|
||||
|
||||
/// Mantissa mask
|
||||
pub(crate) const MAN_MASK: u128 = 0x0000_ffff_ffff_ffff_ffff_ffff_ffff_ffff;
|
||||
/// The mask of the bits used to encode the mantissa of an [`f128`].
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(float_masks)]
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
/// let mantissa_mask = f128::MANTISSA_MASK;
|
||||
///
|
||||
/// assert_eq!(0f128.to_bits() & mantissa_mask, 0x0);
|
||||
/// assert_eq!(1f128.to_bits() & mantissa_mask, 0x0);
|
||||
///
|
||||
/// // multiplying a finite value by a power of 2 doesn't change its mantissa
|
||||
/// // unless the result or initial value is not normal.
|
||||
/// let a = 1.6552f128;
|
||||
/// let b = 4.0 * a;
|
||||
/// assert_eq!(a.to_bits() & mantissa_mask, b.to_bits() & mantissa_mask);
|
||||
///
|
||||
/// // The maximum and minimum values have a saturated significand
|
||||
/// assert_eq!(f128::MAX.to_bits() & f128::MANTISSA_MASK, f128::MANTISSA_MASK);
|
||||
/// assert_eq!(f128::MIN.to_bits() & f128::MANTISSA_MASK, f128::MANTISSA_MASK);
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "float_masks", issue = "154064")]
|
||||
pub const MANTISSA_MASK: u128 = 0x0000_ffff_ffff_ffff_ffff_ffff_ffff_ffff;
|
||||
|
||||
/// Minimum representable positive value (min subnormal)
|
||||
const TINY_BITS: u128 = 0x1;
|
||||
@@ -510,9 +574,9 @@ pub const fn is_normal(self) -> bool {
|
||||
#[unstable(feature = "f128", issue = "116909")]
|
||||
pub const fn classify(self) -> FpCategory {
|
||||
let bits = self.to_bits();
|
||||
match (bits & Self::MAN_MASK, bits & Self::EXP_MASK) {
|
||||
(0, Self::EXP_MASK) => FpCategory::Infinite,
|
||||
(_, Self::EXP_MASK) => FpCategory::Nan,
|
||||
match (bits & Self::MANTISSA_MASK, bits & Self::EXPONENT_MASK) {
|
||||
(0, Self::EXPONENT_MASK) => FpCategory::Infinite,
|
||||
(_, Self::EXPONENT_MASK) => FpCategory::Nan,
|
||||
(0, 0) => FpCategory::Zero,
|
||||
(_, 0) => FpCategory::Subnormal,
|
||||
_ => FpCategory::Normal,
|
||||
|
||||
@@ -333,14 +333,80 @@ impl f16 {
|
||||
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
|
||||
pub const MIN_EXACT_INTEGER: i16 = -Self::MAX_EXACT_INTEGER;
|
||||
|
||||
/// Sign bit
|
||||
pub(crate) const SIGN_MASK: u16 = 0x8000;
|
||||
/// The mask of the bit used to encode the sign of an [`f16`].
|
||||
///
|
||||
/// This bit is set when the sign is negative and unset when the sign is
|
||||
/// positive.
|
||||
/// If you only need to check whether a value is positive or negative,
|
||||
/// [`is_sign_positive`] or [`is_sign_negative`] can be used.
|
||||
///
|
||||
/// [`is_sign_positive`]: f16::is_sign_positive
|
||||
/// [`is_sign_negative`]: f16::is_sign_negative
|
||||
/// ```rust
|
||||
/// #![feature(float_masks)]
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(target_has_reliable_f16)] {
|
||||
/// let sign_mask = f16::SIGN_MASK;
|
||||
/// let a = 1.6552f16;
|
||||
/// let a_bits = a.to_bits();
|
||||
///
|
||||
/// assert_eq!(a_bits & sign_mask, 0x0);
|
||||
/// assert_eq!(f16::from_bits(a_bits ^ sign_mask), -a);
|
||||
/// assert_eq!(sign_mask, (-0.0f16).to_bits());
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "float_masks", issue = "154064")]
|
||||
pub const SIGN_MASK: u16 = 0x8000;
|
||||
|
||||
/// Exponent mask
|
||||
pub(crate) const EXP_MASK: u16 = 0x7c00;
|
||||
/// The mask of the bits used to encode the exponent of an [`f16`].
|
||||
///
|
||||
/// Note that the exponent is stored as a biased value, with a bias of 15 for `f16`.
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(float_masks)]
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(target_has_reliable_f16)] {
|
||||
/// let exponent_mask = f16::EXPONENT_MASK;
|
||||
///
|
||||
/// fn get_exp(a: f16) -> i16 {
|
||||
/// let bias = 15;
|
||||
/// let biased = a.to_bits() & f16::EXPONENT_MASK;
|
||||
/// (biased >> (f16::MANTISSA_DIGITS - 1)).cast_signed() - bias
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(get_exp(0.5), -1);
|
||||
/// assert_eq!(get_exp(1.0), 0);
|
||||
/// assert_eq!(get_exp(2.0), 1);
|
||||
/// assert_eq!(get_exp(4.0), 2);
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "float_masks", issue = "154064")]
|
||||
pub const EXPONENT_MASK: u16 = 0x7c00;
|
||||
|
||||
/// Mantissa mask
|
||||
pub(crate) const MAN_MASK: u16 = 0x03ff;
|
||||
/// The mask of the bits used to encode the mantissa of an [`f16`].
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(float_masks)]
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(target_has_reliable_f16)] {
|
||||
/// let mantissa_mask = f16::MANTISSA_MASK;
|
||||
///
|
||||
/// assert_eq!(0f16.to_bits() & mantissa_mask, 0x0);
|
||||
/// assert_eq!(1f16.to_bits() & mantissa_mask, 0x0);
|
||||
///
|
||||
/// // multiplying a finite value by a power of 2 doesn't change its mantissa
|
||||
/// // unless the result or initial value is not normal.
|
||||
/// let a = 1.6552f16;
|
||||
/// let b = 4.0 * a;
|
||||
/// assert_eq!(a.to_bits() & mantissa_mask, b.to_bits() & mantissa_mask);
|
||||
///
|
||||
/// // The maximum and minimum values have a saturated significand
|
||||
/// assert_eq!(f16::MAX.to_bits() & f16::MANTISSA_MASK, f16::MANTISSA_MASK);
|
||||
/// assert_eq!(f16::MIN.to_bits() & f16::MANTISSA_MASK, f16::MANTISSA_MASK);
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "float_masks", issue = "154064")]
|
||||
pub const MANTISSA_MASK: u16 = 0x03ff;
|
||||
|
||||
/// Minimum representable positive value (min subnormal)
|
||||
const TINY_BITS: u16 = 0x1;
|
||||
@@ -502,9 +568,9 @@ pub const fn is_normal(self) -> bool {
|
||||
#[unstable(feature = "f16", issue = "116909")]
|
||||
pub const fn classify(self) -> FpCategory {
|
||||
let b = self.to_bits();
|
||||
match (b & Self::MAN_MASK, b & Self::EXP_MASK) {
|
||||
(0, Self::EXP_MASK) => FpCategory::Infinite,
|
||||
(_, Self::EXP_MASK) => FpCategory::Nan,
|
||||
match (b & Self::MANTISSA_MASK, b & Self::EXPONENT_MASK) {
|
||||
(0, Self::EXPONENT_MASK) => FpCategory::Infinite,
|
||||
(_, Self::EXPONENT_MASK) => FpCategory::Nan,
|
||||
(0, 0) => FpCategory::Zero,
|
||||
(_, 0) => FpCategory::Subnormal,
|
||||
_ => FpCategory::Normal,
|
||||
|
||||
@@ -572,14 +572,69 @@ impl f32 {
|
||||
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
|
||||
pub const MIN_EXACT_INTEGER: i32 = -Self::MAX_EXACT_INTEGER;
|
||||
|
||||
/// Sign bit
|
||||
pub(crate) const SIGN_MASK: u32 = 0x8000_0000;
|
||||
/// The mask of the bit used to encode the sign of an [`f32`].
|
||||
///
|
||||
/// This bit is set when the sign is negative and unset when the sign is
|
||||
/// positive.
|
||||
/// If you only need to check whether a value is positive or negative,
|
||||
/// [`is_sign_positive`] or [`is_sign_negative`] can be used.
|
||||
///
|
||||
/// [`is_sign_positive`]: f32::is_sign_positive
|
||||
/// [`is_sign_negative`]: f32::is_sign_negative
|
||||
/// ```rust
|
||||
/// #![feature(float_masks)]
|
||||
/// let sign_mask = f32::SIGN_MASK;
|
||||
/// let a = 1.6552f32;
|
||||
/// let a_bits = a.to_bits();
|
||||
///
|
||||
/// assert_eq!(a_bits & sign_mask, 0x0);
|
||||
/// assert_eq!(f32::from_bits(a_bits ^ sign_mask), -a);
|
||||
/// assert_eq!(sign_mask, (-0.0f32).to_bits());
|
||||
/// ```
|
||||
#[unstable(feature = "float_masks", issue = "154064")]
|
||||
pub const SIGN_MASK: u32 = 0x8000_0000;
|
||||
|
||||
/// Exponent mask
|
||||
pub(crate) const EXP_MASK: u32 = 0x7f80_0000;
|
||||
/// The mask of the bits used to encode the exponent of an [`f32`].
|
||||
///
|
||||
/// Note that the exponent is stored as a biased value, with a bias of 127 for `f32`.
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(float_masks)]
|
||||
/// fn get_exp(a: f32) -> i32 {
|
||||
/// let bias = 127;
|
||||
/// let biased = a.to_bits() & f32::EXPONENT_MASK;
|
||||
/// (biased >> (f32::MANTISSA_DIGITS - 1)).cast_signed() - bias
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(get_exp(0.5), -1);
|
||||
/// assert_eq!(get_exp(1.0), 0);
|
||||
/// assert_eq!(get_exp(2.0), 1);
|
||||
/// assert_eq!(get_exp(4.0), 2);
|
||||
/// ```
|
||||
#[unstable(feature = "float_masks", issue = "154064")]
|
||||
pub const EXPONENT_MASK: u32 = 0x7f80_0000;
|
||||
|
||||
/// Mantissa mask
|
||||
pub(crate) const MAN_MASK: u32 = 0x007f_ffff;
|
||||
/// The mask of the bits used to encode the mantissa of an [`f32`].
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(float_masks)]
|
||||
/// let mantissa_mask = f32::MANTISSA_MASK;
|
||||
///
|
||||
/// assert_eq!(0f32.to_bits() & mantissa_mask, 0x0);
|
||||
/// assert_eq!(1f32.to_bits() & mantissa_mask, 0x0);
|
||||
///
|
||||
/// // multiplying a finite value by a power of 2 doesn't change its mantissa
|
||||
/// // unless the result or initial value is not normal.
|
||||
/// let a = 1.6552f32;
|
||||
/// let b = 4.0 * a;
|
||||
/// assert_eq!(a.to_bits() & mantissa_mask, b.to_bits() & mantissa_mask);
|
||||
///
|
||||
/// // The maximum and minimum values have a saturated significand
|
||||
/// assert_eq!(f32::MAX.to_bits() & f32::MANTISSA_MASK, f32::MANTISSA_MASK);
|
||||
/// assert_eq!(f32::MIN.to_bits() & f32::MANTISSA_MASK, f32::MANTISSA_MASK);
|
||||
/// ```
|
||||
#[unstable(feature = "float_masks", issue = "154064")]
|
||||
pub const MANTISSA_MASK: u32 = 0x007f_ffff;
|
||||
|
||||
/// Minimum representable positive value (min subnormal)
|
||||
const TINY_BITS: u32 = 0x1;
|
||||
@@ -730,9 +785,9 @@ pub const fn classify(self) -> FpCategory {
|
||||
// of our tests is able to find any difference between the complicated and the naive
|
||||
// version, so now we are back to the naive version.
|
||||
let b = self.to_bits();
|
||||
match (b & Self::MAN_MASK, b & Self::EXP_MASK) {
|
||||
(0, Self::EXP_MASK) => FpCategory::Infinite,
|
||||
(_, Self::EXP_MASK) => FpCategory::Nan,
|
||||
match (b & Self::MANTISSA_MASK, b & Self::EXPONENT_MASK) {
|
||||
(0, Self::EXPONENT_MASK) => FpCategory::Infinite,
|
||||
(_, Self::EXPONENT_MASK) => FpCategory::Nan,
|
||||
(0, 0) => FpCategory::Zero,
|
||||
(_, 0) => FpCategory::Subnormal,
|
||||
_ => FpCategory::Normal,
|
||||
|
||||
@@ -571,14 +571,69 @@ impl f64 {
|
||||
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
|
||||
pub const MIN_EXACT_INTEGER: i64 = -Self::MAX_EXACT_INTEGER;
|
||||
|
||||
/// Sign bit
|
||||
pub(crate) const SIGN_MASK: u64 = 0x8000_0000_0000_0000;
|
||||
/// The mask of the bit used to encode the sign of an [`f64`].
|
||||
///
|
||||
/// This bit is set when the sign is negative and unset when the sign is
|
||||
/// positive.
|
||||
/// If you only need to check whether a value is positive or negative,
|
||||
/// [`is_sign_positive`] or [`is_sign_negative`] can be used.
|
||||
///
|
||||
/// [`is_sign_positive`]: f64::is_sign_positive
|
||||
/// [`is_sign_negative`]: f64::is_sign_negative
|
||||
/// ```rust
|
||||
/// #![feature(float_masks)]
|
||||
/// let sign_mask = f64::SIGN_MASK;
|
||||
/// let a = 1.6552f64;
|
||||
/// let a_bits = a.to_bits();
|
||||
///
|
||||
/// assert_eq!(a_bits & sign_mask, 0x0);
|
||||
/// assert_eq!(f64::from_bits(a_bits ^ sign_mask), -a);
|
||||
/// assert_eq!(sign_mask, (-0.0f64).to_bits());
|
||||
/// ```
|
||||
#[unstable(feature = "float_masks", issue = "154064")]
|
||||
pub const SIGN_MASK: u64 = 0x8000_0000_0000_0000;
|
||||
|
||||
/// Exponent mask
|
||||
pub(crate) const EXP_MASK: u64 = 0x7ff0_0000_0000_0000;
|
||||
/// The mask of the bits used to encode the exponent of an [`f64`].
|
||||
///
|
||||
/// Note that the exponent is stored as a biased value, with a bias of 1024 for `f64`.
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(float_masks)]
|
||||
/// fn get_exp(a: f64) -> i64 {
|
||||
/// let bias = 1023;
|
||||
/// let biased = a.to_bits() & f64::EXPONENT_MASK;
|
||||
/// (biased >> (f64::MANTISSA_DIGITS - 1)).cast_signed() - bias
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(get_exp(0.5), -1);
|
||||
/// assert_eq!(get_exp(1.0), 0);
|
||||
/// assert_eq!(get_exp(2.0), 1);
|
||||
/// assert_eq!(get_exp(4.0), 2);
|
||||
/// ```
|
||||
#[unstable(feature = "float_masks", issue = "154064")]
|
||||
pub const EXPONENT_MASK: u64 = 0x7ff0_0000_0000_0000;
|
||||
|
||||
/// Mantissa mask
|
||||
pub(crate) const MAN_MASK: u64 = 0x000f_ffff_ffff_ffff;
|
||||
/// The mask of the bits used to encode the mantissa of an [`f64`].
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(float_masks)]
|
||||
/// let mantissa_mask = f64::MANTISSA_MASK;
|
||||
///
|
||||
/// assert_eq!(0f64.to_bits() & mantissa_mask, 0x0);
|
||||
/// assert_eq!(1f64.to_bits() & mantissa_mask, 0x0);
|
||||
///
|
||||
/// // multiplying a finite value by a power of 2 doesn't change its mantissa
|
||||
/// // unless the result or initial value is not normal.
|
||||
/// let a = 1.6552f64;
|
||||
/// let b = 4.0 * a;
|
||||
/// assert_eq!(a.to_bits() & mantissa_mask, b.to_bits() & mantissa_mask);
|
||||
///
|
||||
/// // The maximum and minimum values have a saturated significand
|
||||
/// assert_eq!(f64::MAX.to_bits() & f64::MANTISSA_MASK, f64::MANTISSA_MASK);
|
||||
/// assert_eq!(f64::MIN.to_bits() & f64::MANTISSA_MASK, f64::MANTISSA_MASK);
|
||||
/// ```
|
||||
#[unstable(feature = "float_masks", issue = "154064")]
|
||||
pub const MANTISSA_MASK: u64 = 0x000f_ffff_ffff_ffff;
|
||||
|
||||
/// Minimum representable positive value (min subnormal)
|
||||
const TINY_BITS: u64 = 0x1;
|
||||
@@ -729,9 +784,9 @@ pub const fn classify(self) -> FpCategory {
|
||||
// of our tests is able to find any difference between the complicated and the naive
|
||||
// version, so now we are back to the naive version.
|
||||
let b = self.to_bits();
|
||||
match (b & Self::MAN_MASK, b & Self::EXP_MASK) {
|
||||
(0, Self::EXP_MASK) => FpCategory::Infinite,
|
||||
(_, Self::EXP_MASK) => FpCategory::Nan,
|
||||
match (b & Self::MANTISSA_MASK, b & Self::EXPONENT_MASK) {
|
||||
(0, Self::EXPONENT_MASK) => FpCategory::Infinite,
|
||||
(_, Self::EXPONENT_MASK) => FpCategory::Nan,
|
||||
(0, 0) => FpCategory::Zero,
|
||||
(_, 0) => FpCategory::Subnormal,
|
||||
_ => FpCategory::Normal,
|
||||
|
||||
@@ -204,8 +204,8 @@ impl Float for f16 {
|
||||
|
||||
const BITS: u32 = 16;
|
||||
const SIG_TOTAL_BITS: u32 = Self::MANTISSA_DIGITS;
|
||||
const EXP_MASK: Self::Int = Self::EXP_MASK;
|
||||
const SIG_MASK: Self::Int = Self::MAN_MASK;
|
||||
const EXP_MASK: Self::Int = Self::EXPONENT_MASK;
|
||||
const SIG_MASK: Self::Int = Self::MANTISSA_MASK;
|
||||
|
||||
const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -22;
|
||||
const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 5;
|
||||
@@ -238,8 +238,8 @@ impl Float for f32 {
|
||||
|
||||
const BITS: u32 = 32;
|
||||
const SIG_TOTAL_BITS: u32 = Self::MANTISSA_DIGITS;
|
||||
const EXP_MASK: Self::Int = Self::EXP_MASK;
|
||||
const SIG_MASK: Self::Int = Self::MAN_MASK;
|
||||
const EXP_MASK: Self::Int = Self::EXPONENT_MASK;
|
||||
const SIG_MASK: Self::Int = Self::MANTISSA_MASK;
|
||||
|
||||
const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -17;
|
||||
const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 10;
|
||||
@@ -271,8 +271,8 @@ impl Float for f64 {
|
||||
|
||||
const BITS: u32 = 64;
|
||||
const SIG_TOTAL_BITS: u32 = Self::MANTISSA_DIGITS;
|
||||
const EXP_MASK: Self::Int = Self::EXP_MASK;
|
||||
const SIG_MASK: Self::Int = Self::MAN_MASK;
|
||||
const EXP_MASK: Self::Int = Self::EXPONENT_MASK;
|
||||
const SIG_MASK: Self::Int = Self::MANTISSA_MASK;
|
||||
|
||||
const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -4;
|
||||
const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 23;
|
||||
|
||||
Reference in New Issue
Block a user