Skip to content

Commit 5fa9df8

Browse files
committed
Auto merge of #152512 - okaneco:exact_integer, r=<try>
core: Implement feature `float_exact_integer_constants` try-job: dist-i586-gnu-i586-i686-musl
2 parents 1396514 + a2102f5 commit 5fa9df8

7 files changed

Lines changed: 331 additions & 1 deletion

File tree

compiler/rustc_codegen_cranelift/src/codegen_f16_f128.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ pub(crate) fn codegen_cast(
208208
let ret_ty = if to_ty.bits() < 32 { types::I32 } else { to_ty };
209209
let name = format!(
210210
"__fix{sign}tf{size}i",
211-
sign = if from_signed { "" } else { "un" },
211+
sign = if to_signed { "" } else { "uns" },
212212
size = match ret_ty {
213213
types::I32 => 's',
214214
types::I64 => 'd',

library/core/src/num/f128.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,68 @@ impl f128 {
275275
#[unstable(feature = "f128", issue = "116909")]
276276
pub const NEG_INFINITY: f128 = -1.0_f128 / 0.0_f128;
277277

278+
/// Maximum integer that can be represented exactly in an [`f128`] value,
279+
/// with no other integer converting to the same floating point value.
280+
///
281+
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
282+
/// there is a "one-to-one" mapping between [`i128`] and [`f128`] values.
283+
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f128`] and back to
284+
/// [`i128`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f128`] value
285+
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
286+
/// "one-to-one" mapping.
287+
///
288+
/// [`MAX_EXACT_INTEGER`]: f128::MAX_EXACT_INTEGER
289+
/// [`MIN_EXACT_INTEGER`]: f128::MIN_EXACT_INTEGER
290+
/// ```
291+
/// #![feature(f128)]
292+
/// #![feature(float_exact_integer_constants)]
293+
/// # #[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))] {
294+
/// # #[cfg(target_has_reliable_f128)] {
295+
/// let max_exact_int = f128::MAX_EXACT_INTEGER;
296+
/// assert_eq!(max_exact_int, max_exact_int as f128 as i128);
297+
/// assert_eq!(max_exact_int + 1, (max_exact_int + 1) as f128 as i128);
298+
/// assert_ne!(max_exact_int + 2, (max_exact_int + 2) as f128 as i128);
299+
///
300+
/// // Beyond `f128::MAX_EXACT_INTEGER`, multiple integers can map to one float value
301+
/// assert_eq!((max_exact_int + 1) as f128, (max_exact_int + 2) as f128);
302+
/// # }}
303+
/// ```
304+
// #[unstable(feature = "f128", issue = "116909")]
305+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
306+
pub const MAX_EXACT_INTEGER: i128 = (1 << Self::MANTISSA_DIGITS) - 1;
307+
308+
/// Minimum integer that can be represented exactly in an [`f128`] value,
309+
/// with no other integer converting to the same floating point value.
310+
///
311+
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
312+
/// there is a "one-to-one" mapping between [`i128`] and [`f128`] values.
313+
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f128`] and back to
314+
/// [`i128`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f128`] value
315+
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
316+
/// "one-to-one" mapping.
317+
///
318+
/// This constant is equivalent to `-MAX_EXACT_INTEGER`.
319+
///
320+
/// [`MAX_EXACT_INTEGER`]: f128::MAX_EXACT_INTEGER
321+
/// [`MIN_EXACT_INTEGER`]: f128::MIN_EXACT_INTEGER
322+
/// ```
323+
/// #![feature(f128)]
324+
/// #![feature(float_exact_integer_constants)]
325+
/// # #[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))] {
326+
/// # #[cfg(target_has_reliable_f128)] {
327+
/// let min_exact_int = f128::MIN_EXACT_INTEGER;
328+
/// assert_eq!(min_exact_int, min_exact_int as f128 as i128);
329+
/// assert_eq!(min_exact_int - 1, (min_exact_int - 1) as f128 as i128);
330+
/// assert_ne!(min_exact_int - 2, (min_exact_int - 2) as f128 as i128);
331+
///
332+
/// // Below `f128::MIN_EXACT_INTEGER`, multiple integers can map to one float value
333+
/// assert_eq!((min_exact_int - 1) as f128, (min_exact_int - 2) as f128);
334+
/// # }}
335+
/// ```
336+
// #[unstable(feature = "f128", issue = "116909")]
337+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
338+
pub const MIN_EXACT_INTEGER: i128 = -Self::MAX_EXACT_INTEGER;
339+
278340
/// Sign bit
279341
pub(crate) const SIGN_MASK: u128 = 0x8000_0000_0000_0000_0000_0000_0000_0000;
280342

library/core/src/num/f16.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,68 @@ impl f16 {
269269
#[unstable(feature = "f16", issue = "116909")]
270270
pub const NEG_INFINITY: f16 = -1.0_f16 / 0.0_f16;
271271

272+
/// Maximum integer that can be represented exactly in an [`f16`] value,
273+
/// with no other integer converting to the same floating point value.
274+
///
275+
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
276+
/// there is a "one-to-one" mapping between [`i16`] and [`f16`] values.
277+
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f16`] and back to
278+
/// [`i16`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f16`] value
279+
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
280+
/// "one-to-one" mapping.
281+
///
282+
/// [`MAX_EXACT_INTEGER`]: f16::MAX_EXACT_INTEGER
283+
/// [`MIN_EXACT_INTEGER`]: f16::MIN_EXACT_INTEGER
284+
/// ```
285+
/// #![feature(f16)]
286+
/// #![feature(float_exact_integer_constants)]
287+
/// # #[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))] {
288+
/// # #[cfg(target_has_reliable_f16)] {
289+
/// let max_exact_int = f16::MAX_EXACT_INTEGER;
290+
/// assert_eq!(max_exact_int, max_exact_int as f16 as i16);
291+
/// assert_eq!(max_exact_int + 1, (max_exact_int + 1) as f16 as i16);
292+
/// assert_ne!(max_exact_int + 2, (max_exact_int + 2) as f16 as i16);
293+
///
294+
/// // Beyond `f16::MAX_EXACT_INTEGER`, multiple integers can map to one float value
295+
/// assert_eq!((max_exact_int + 1) as f16, (max_exact_int + 2) as f16);
296+
/// # }}
297+
/// ```
298+
// #[unstable(feature = "f16", issue = "116909")]
299+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
300+
pub const MAX_EXACT_INTEGER: i16 = (1 << Self::MANTISSA_DIGITS) - 1;
301+
302+
/// Minimum integer that can be represented exactly in an [`f16`] value,
303+
/// with no other integer converting to the same floating point value.
304+
///
305+
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
306+
/// there is a "one-to-one" mapping between [`i16`] and [`f16`] values.
307+
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f16`] and back to
308+
/// [`i16`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f16`] value
309+
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
310+
/// "one-to-one" mapping.
311+
///
312+
/// This constant is equivalent to `-MAX_EXACT_INTEGER`.
313+
///
314+
/// [`MAX_EXACT_INTEGER`]: f16::MAX_EXACT_INTEGER
315+
/// [`MIN_EXACT_INTEGER`]: f16::MIN_EXACT_INTEGER
316+
/// ```
317+
/// #![feature(f16)]
318+
/// #![feature(float_exact_integer_constants)]
319+
/// # #[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))] {
320+
/// # #[cfg(target_has_reliable_f16)] {
321+
/// let min_exact_int = f16::MIN_EXACT_INTEGER;
322+
/// assert_eq!(min_exact_int, min_exact_int as f16 as i16);
323+
/// assert_eq!(min_exact_int - 1, (min_exact_int - 1) as f16 as i16);
324+
/// assert_ne!(min_exact_int - 2, (min_exact_int - 2) as f16 as i16);
325+
///
326+
/// // Below `f16::MIN_EXACT_INTEGER`, multiple integers can map to one float value
327+
/// assert_eq!((min_exact_int - 1) as f16, (min_exact_int - 2) as f16);
328+
/// # }}
329+
/// ```
330+
// #[unstable(feature = "f16", issue = "116909")]
331+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
332+
pub const MIN_EXACT_INTEGER: i16 = -Self::MAX_EXACT_INTEGER;
333+
272334
/// Sign bit
273335
pub(crate) const SIGN_MASK: u16 = 0x8000;
274336

library/core/src/num/f32.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,62 @@ impl f32 {
513513
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
514514
pub const NEG_INFINITY: f32 = -1.0_f32 / 0.0_f32;
515515

516+
/// Maximum integer that can be represented exactly in an [`f32`] value,
517+
/// with no other integer converting to the same floating point value.
518+
///
519+
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
520+
/// there is a "one-to-one" mapping between [`i32`] and [`f32`] values.
521+
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f32`] and back to
522+
/// [`i32`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f32`] value
523+
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
524+
/// "one-to-one" mapping.
525+
///
526+
/// [`MAX_EXACT_INTEGER`]: f32::MAX_EXACT_INTEGER
527+
/// [`MIN_EXACT_INTEGER`]: f32::MIN_EXACT_INTEGER
528+
/// ```
529+
/// #![feature(float_exact_integer_constants)]
530+
/// # #[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))] {
531+
/// let max_exact_int = f32::MAX_EXACT_INTEGER;
532+
/// assert_eq!(max_exact_int, max_exact_int as f32 as i32);
533+
/// assert_eq!(max_exact_int + 1, (max_exact_int + 1) as f32 as i32);
534+
/// assert_ne!(max_exact_int + 2, (max_exact_int + 2) as f32 as i32);
535+
///
536+
/// // Beyond `f32::MAX_EXACT_INTEGER`, multiple integers can map to one float value
537+
/// assert_eq!((max_exact_int + 1) as f32, (max_exact_int + 2) as f32);
538+
/// # }
539+
/// ```
540+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
541+
pub const MAX_EXACT_INTEGER: i32 = (1 << Self::MANTISSA_DIGITS) - 1;
542+
543+
/// Minimum integer that can be represented exactly in an [`f32`] value,
544+
/// with no other integer converting to the same floating point value.
545+
///
546+
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
547+
/// there is a "one-to-one" mapping between [`i32`] and [`f32`] values.
548+
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f32`] and back to
549+
/// [`i32`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f32`] value
550+
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
551+
/// "one-to-one" mapping.
552+
///
553+
/// This constant is equivalent to `-MAX_EXACT_INTEGER`.
554+
///
555+
/// [`MAX_EXACT_INTEGER`]: f32::MAX_EXACT_INTEGER
556+
/// [`MIN_EXACT_INTEGER`]: f32::MIN_EXACT_INTEGER
557+
/// ```
558+
/// #![feature(float_exact_integer_constants)]
559+
/// # #[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))] {
560+
/// let min_exact_int = f32::MIN_EXACT_INTEGER;
561+
/// assert_eq!(min_exact_int, min_exact_int as f32 as i32);
562+
/// assert_eq!(min_exact_int - 1, (min_exact_int - 1) as f32 as i32);
563+
/// assert_ne!(min_exact_int - 2, (min_exact_int - 2) as f32 as i32);
564+
///
565+
/// // Below `f32::MIN_EXACT_INTEGER`, multiple integers can map to one float value
566+
/// assert_eq!((min_exact_int - 1) as f32, (min_exact_int - 2) as f32);
567+
/// # }
568+
/// ```
569+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
570+
pub const MIN_EXACT_INTEGER: i32 = -Self::MAX_EXACT_INTEGER;
571+
516572
/// Sign bit
517573
pub(crate) const SIGN_MASK: u32 = 0x8000_0000;
518574

library/core/src/num/f64.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,62 @@ impl f64 {
512512
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
513513
pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64;
514514

515+
/// Maximum integer that can be represented exactly in an [`f64`] value,
516+
/// with no other integer converting to the same floating point value.
517+
///
518+
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
519+
/// there is a "one-to-one" mapping between [`i64`] and [`f64`] values.
520+
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f64`] and back to
521+
/// [`i64`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f64`] value
522+
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
523+
/// "one-to-one" mapping.
524+
///
525+
/// [`MAX_EXACT_INTEGER`]: f64::MAX_EXACT_INTEGER
526+
/// [`MIN_EXACT_INTEGER`]: f64::MIN_EXACT_INTEGER
527+
/// ```
528+
/// #![feature(float_exact_integer_constants)]
529+
/// # #[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))] {
530+
/// let max_exact_int = f64::MAX_EXACT_INTEGER;
531+
/// assert_eq!(max_exact_int, max_exact_int as f64 as i64);
532+
/// assert_eq!(max_exact_int + 1, (max_exact_int + 1) as f64 as i64);
533+
/// assert_ne!(max_exact_int + 2, (max_exact_int + 2) as f64 as i64);
534+
///
535+
/// // Beyond `f64::MAX_EXACT_INTEGER`, multiple integers can map to one float value
536+
/// assert_eq!((max_exact_int + 1) as f64, (max_exact_int + 2) as f64);
537+
/// # }
538+
/// ```
539+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
540+
pub const MAX_EXACT_INTEGER: i64 = (1 << Self::MANTISSA_DIGITS) - 1;
541+
542+
/// Minimum integer that can be represented exactly in an [`f64`] value,
543+
/// with no other integer converting to the same floating point value.
544+
///
545+
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
546+
/// there is a "one-to-one" mapping between [`i64`] and [`f64`] values.
547+
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f64`] and back to
548+
/// [`i64`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f64`] value
549+
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
550+
/// "one-to-one" mapping.
551+
///
552+
/// This constant is equivalent to `-MAX_EXACT_INTEGER`.
553+
///
554+
/// [`MAX_EXACT_INTEGER`]: f64::MAX_EXACT_INTEGER
555+
/// [`MIN_EXACT_INTEGER`]: f64::MIN_EXACT_INTEGER
556+
/// ```
557+
/// #![feature(float_exact_integer_constants)]
558+
/// # #[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))] {
559+
/// let min_exact_int = f64::MIN_EXACT_INTEGER;
560+
/// assert_eq!(min_exact_int, min_exact_int as f64 as i64);
561+
/// assert_eq!(min_exact_int - 1, (min_exact_int - 1) as f64 as i64);
562+
/// assert_ne!(min_exact_int - 2, (min_exact_int - 2) as f64 as i64);
563+
///
564+
/// // Below `f64::MIN_EXACT_INTEGER`, multiple integers can map to one float value
565+
/// assert_eq!((min_exact_int - 1) as f64, (min_exact_int - 2) as f64);
566+
/// # }
567+
/// ```
568+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
569+
pub const MIN_EXACT_INTEGER: i64 = -Self::MAX_EXACT_INTEGER;
570+
515571
/// Sign bit
516572
pub(crate) const SIGN_MASK: u64 = 0x8000_0000_0000_0000;
517573

0 commit comments

Comments
 (0)