Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 73 additions & 9 deletions library/core/src/num/f128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -510,9 +574,9 @@ impl f128 {
#[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,
Expand Down
84 changes: 75 additions & 9 deletions library/core/src/num/f16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Comment thread
Apersoma marked this conversation as resolved.
/// # #[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);
/// # }
/// ```
Comment thread
Apersoma marked this conversation as resolved.
#[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;
Expand Down Expand Up @@ -502,9 +568,9 @@ impl f16 {
#[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,
Expand Down
73 changes: 64 additions & 9 deletions library/core/src/num/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -730,9 +785,9 @@ impl f32 {
// 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,
Expand Down
73 changes: 64 additions & 9 deletions library/core/src/num/f64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -729,9 +784,9 @@ impl f64 {
// 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,
Expand Down
Loading
Loading