Skip to content
Open
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
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/codegen_f16_f128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ pub(crate) fn codegen_cast(
let ret_ty = if to_ty.bits() < 32 { types::I32 } else { to_ty };
let name = format!(
"__fix{sign}tf{size}i",
sign = if from_signed { "" } else { "un" },
sign = if to_signed { "" } else { "uns" },
size = match ret_ty {
types::I32 => 's',
types::I64 => 'd',
Expand Down
62 changes: 62 additions & 0 deletions library/core/src/num/f128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,68 @@ impl f128 {
#[unstable(feature = "f128", issue = "116909")]
pub const NEG_INFINITY: f128 = -1.0_f128 / 0.0_f128;

/// Maximum integer that can be represented exactly in an [`f128`] value,
/// with no other integer converting to the same floating point value.
///
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
/// there is a "one-to-one" mapping between [`i128`] and [`f128`] values.
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f128`] and back to
/// [`i128`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f128`] value
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
/// "one-to-one" mapping.
///
/// [`MAX_EXACT_INTEGER`]: f128::MAX_EXACT_INTEGER
/// [`MIN_EXACT_INTEGER`]: f128::MIN_EXACT_INTEGER
/// ```
/// #![feature(f128)]
/// #![feature(float_exact_integer_constants)]
/// # #[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))] {
/// # #[cfg(target_has_reliable_f128)] {
/// let max_exact_int = f128::MAX_EXACT_INTEGER;
/// assert_eq!(max_exact_int, max_exact_int as f128 as i128);
/// assert_eq!(max_exact_int + 1, (max_exact_int + 1) as f128 as i128);
/// assert_ne!(max_exact_int + 2, (max_exact_int + 2) as f128 as i128);
///
/// // Beyond `f128::MAX_EXACT_INTEGER`, multiple integers can map to one float value
/// assert_eq!((max_exact_int + 1) as f128, (max_exact_int + 2) as f128);
/// # }}
/// ```
// #[unstable(feature = "f128", issue = "116909")]
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
pub const MAX_EXACT_INTEGER: i128 = (1 << Self::MANTISSA_DIGITS) - 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add examples to both constants? It would be good to demo the MAX_EXACT_INTEGER, MAX_EXACT_INTEGER + 1, MAX_EXACT_INTEGER + 2 property.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was uncertain about adding examples because every other float const seems to lack examples, but they'd come in handy here.

Added examples.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think examples are particularly important here because I would have expected this to be the value without the - 1, so the more opportunities to emphasize its definition the better.

(Things like f32::INFINITY don't have that issue.)


/// Minimum integer that can be represented exactly in an [`f128`] value,
/// with no other integer converting to the same floating point value.
///
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
/// there is a "one-to-one" mapping between [`i128`] and [`f128`] values.
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f128`] and back to
/// [`i128`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f128`] value
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
/// "one-to-one" mapping.
///
/// This constant is equivalent to `-MAX_EXACT_INTEGER`.
///
/// [`MAX_EXACT_INTEGER`]: f128::MAX_EXACT_INTEGER
/// [`MIN_EXACT_INTEGER`]: f128::MIN_EXACT_INTEGER
/// ```
/// #![feature(f128)]
/// #![feature(float_exact_integer_constants)]
/// # #[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))] {
/// # #[cfg(target_has_reliable_f128)] {
/// let min_exact_int = f128::MIN_EXACT_INTEGER;
/// assert_eq!(min_exact_int, min_exact_int as f128 as i128);
/// assert_eq!(min_exact_int - 1, (min_exact_int - 1) as f128 as i128);
/// assert_ne!(min_exact_int - 2, (min_exact_int - 2) as f128 as i128);
///
/// // Below `f128::MIN_EXACT_INTEGER`, multiple integers can map to one float value
/// assert_eq!((min_exact_int - 1) as f128, (min_exact_int - 2) as f128);
/// # }}
/// ```
// #[unstable(feature = "f128", issue = "116909")]
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
pub const MIN_EXACT_INTEGER: i128 = -Self::MAX_EXACT_INTEGER;
Comment on lines 308 to 338
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's worth mentioning that this is just -MAX_EXACT_INTEGER

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.


/// Sign bit
pub(crate) const SIGN_MASK: u128 = 0x8000_0000_0000_0000_0000_0000_0000_0000;

Expand Down
62 changes: 62 additions & 0 deletions library/core/src/num/f16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,68 @@ impl f16 {
#[unstable(feature = "f16", issue = "116909")]
pub const NEG_INFINITY: f16 = -1.0_f16 / 0.0_f16;

/// Maximum integer that can be represented exactly in an [`f16`] value,
/// with no other integer converting to the same floating point value.
///
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
/// there is a "one-to-one" mapping between [`i16`] and [`f16`] values.
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f16`] and back to
/// [`i16`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f16`] value
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
/// "one-to-one" mapping.
///
/// [`MAX_EXACT_INTEGER`]: f16::MAX_EXACT_INTEGER
/// [`MIN_EXACT_INTEGER`]: f16::MIN_EXACT_INTEGER
/// ```
/// #![feature(f16)]
/// #![feature(float_exact_integer_constants)]
/// # #[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))] {
/// # #[cfg(target_has_reliable_f16)] {
/// let max_exact_int = f16::MAX_EXACT_INTEGER;
/// assert_eq!(max_exact_int, max_exact_int as f16 as i16);
/// assert_eq!(max_exact_int + 1, (max_exact_int + 1) as f16 as i16);
/// assert_ne!(max_exact_int + 2, (max_exact_int + 2) as f16 as i16);
///
/// // Beyond `f16::MAX_EXACT_INTEGER`, multiple integers can map to one float value
/// assert_eq!((max_exact_int + 1) as f16, (max_exact_int + 2) as f16);
/// # }}
/// ```
// #[unstable(feature = "f16", issue = "116909")]
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
pub const MAX_EXACT_INTEGER: i16 = (1 << Self::MANTISSA_DIGITS) - 1;

/// Minimum integer that can be represented exactly in an [`f16`] value,
/// with no other integer converting to the same floating point value.
///
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
/// there is a "one-to-one" mapping between [`i16`] and [`f16`] values.
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f16`] and back to
/// [`i16`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f16`] value
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
/// "one-to-one" mapping.
///
/// This constant is equivalent to `-MAX_EXACT_INTEGER`.
///
/// [`MAX_EXACT_INTEGER`]: f16::MAX_EXACT_INTEGER
/// [`MIN_EXACT_INTEGER`]: f16::MIN_EXACT_INTEGER
/// ```
/// #![feature(f16)]
/// #![feature(float_exact_integer_constants)]
/// # #[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))] {
/// # #[cfg(target_has_reliable_f16)] {
/// let min_exact_int = f16::MIN_EXACT_INTEGER;
/// assert_eq!(min_exact_int, min_exact_int as f16 as i16);
/// assert_eq!(min_exact_int - 1, (min_exact_int - 1) as f16 as i16);
/// assert_ne!(min_exact_int - 2, (min_exact_int - 2) as f16 as i16);
///
/// // Below `f16::MIN_EXACT_INTEGER`, multiple integers can map to one float value
/// assert_eq!((min_exact_int - 1) as f16, (min_exact_int - 2) as f16);
/// # }}
/// ```
// #[unstable(feature = "f16", issue = "116909")]
#[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;

Expand Down
56 changes: 56 additions & 0 deletions library/core/src/num/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,62 @@ impl f32 {
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const NEG_INFINITY: f32 = -1.0_f32 / 0.0_f32;

/// Maximum integer that can be represented exactly in an [`f32`] value,
/// with no other integer converting to the same floating point value.
///
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
/// there is a "one-to-one" mapping between [`i32`] and [`f32`] values.
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f32`] and back to
/// [`i32`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f32`] value
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
/// "one-to-one" mapping.
///
/// [`MAX_EXACT_INTEGER`]: f32::MAX_EXACT_INTEGER
/// [`MIN_EXACT_INTEGER`]: f32::MIN_EXACT_INTEGER
/// ```
/// #![feature(float_exact_integer_constants)]
/// # #[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))] {
/// let max_exact_int = f32::MAX_EXACT_INTEGER;
/// assert_eq!(max_exact_int, max_exact_int as f32 as i32);
/// assert_eq!(max_exact_int + 1, (max_exact_int + 1) as f32 as i32);
/// assert_ne!(max_exact_int + 2, (max_exact_int + 2) as f32 as i32);
///
/// // Beyond `f32::MAX_EXACT_INTEGER`, multiple integers can map to one float value
/// assert_eq!((max_exact_int + 1) as f32, (max_exact_int + 2) as f32);
/// # }
/// ```
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
pub const MAX_EXACT_INTEGER: i32 = (1 << Self::MANTISSA_DIGITS) - 1;

/// Minimum integer that can be represented exactly in an [`f32`] value,
/// with no other integer converting to the same floating point value.
///
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
/// there is a "one-to-one" mapping between [`i32`] and [`f32`] values.
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f32`] and back to
/// [`i32`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f32`] value
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
/// "one-to-one" mapping.
///
/// This constant is equivalent to `-MAX_EXACT_INTEGER`.
///
/// [`MAX_EXACT_INTEGER`]: f32::MAX_EXACT_INTEGER
/// [`MIN_EXACT_INTEGER`]: f32::MIN_EXACT_INTEGER
/// ```
/// #![feature(float_exact_integer_constants)]
/// # #[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))] {
/// let min_exact_int = f32::MIN_EXACT_INTEGER;
/// assert_eq!(min_exact_int, min_exact_int as f32 as i32);
/// assert_eq!(min_exact_int - 1, (min_exact_int - 1) as f32 as i32);
/// assert_ne!(min_exact_int - 2, (min_exact_int - 2) as f32 as i32);
///
/// // Below `f32::MIN_EXACT_INTEGER`, multiple integers can map to one float value
/// assert_eq!((min_exact_int - 1) as f32, (min_exact_int - 2) as 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;

Expand Down
56 changes: 56 additions & 0 deletions library/core/src/num/f64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,62 @@ impl f64 {
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64;

/// Maximum integer that can be represented exactly in an [`f64`] value,
/// with no other integer converting to the same floating point value.
///
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
/// there is a "one-to-one" mapping between [`i64`] and [`f64`] values.
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f64`] and back to
/// [`i64`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f64`] value
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
/// "one-to-one" mapping.
///
/// [`MAX_EXACT_INTEGER`]: f64::MAX_EXACT_INTEGER
/// [`MIN_EXACT_INTEGER`]: f64::MIN_EXACT_INTEGER
/// ```
/// #![feature(float_exact_integer_constants)]
/// # #[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))] {
/// let max_exact_int = f64::MAX_EXACT_INTEGER;
/// assert_eq!(max_exact_int, max_exact_int as f64 as i64);
/// assert_eq!(max_exact_int + 1, (max_exact_int + 1) as f64 as i64);
/// assert_ne!(max_exact_int + 2, (max_exact_int + 2) as f64 as i64);
///
/// // Beyond `f64::MAX_EXACT_INTEGER`, multiple integers can map to one float value
/// assert_eq!((max_exact_int + 1) as f64, (max_exact_int + 2) as f64);
/// # }
/// ```
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
pub const MAX_EXACT_INTEGER: i64 = (1 << Self::MANTISSA_DIGITS) - 1;

/// Minimum integer that can be represented exactly in an [`f64`] value,
/// with no other integer converting to the same floating point value.
///
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
/// there is a "one-to-one" mapping between [`i64`] and [`f64`] values.
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f64`] and back to
/// [`i64`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f64`] value
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
/// "one-to-one" mapping.
///
/// This constant is equivalent to `-MAX_EXACT_INTEGER`.
///
/// [`MAX_EXACT_INTEGER`]: f64::MAX_EXACT_INTEGER
/// [`MIN_EXACT_INTEGER`]: f64::MIN_EXACT_INTEGER
/// ```
/// #![feature(float_exact_integer_constants)]
/// # #[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))] {
/// let min_exact_int = f64::MIN_EXACT_INTEGER;
/// assert_eq!(min_exact_int, min_exact_int as f64 as i64);
/// assert_eq!(min_exact_int - 1, (min_exact_int - 1) as f64 as i64);
/// assert_ne!(min_exact_int - 2, (min_exact_int - 2) as f64 as i64);
///
/// // Below `f64::MIN_EXACT_INTEGER`, multiple integers can map to one float value
/// assert_eq!((min_exact_int - 1) as f64, (min_exact_int - 2) as 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;

Expand Down
Loading
Loading