Skip to content

Commit 5d22008

Browse files
committed
core: Implement feature float_exact_integer_constants
Implement accepted ACP for `MAX_EXACT_INTEGER` and `MIN_EXACT_INTEGER` on `f16`, `f32`, `f64`, and `f128` Add tests to `coretests/tests/floats/mod.rs`
1 parent 7057231 commit 5d22008

File tree

6 files changed

+318
-0
lines changed

6 files changed

+318
-0
lines changed

library/core/src/num/f128.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,66 @@ impl f128 {
272272
#[unstable(feature = "f128", issue = "116909")]
273273
pub const NEG_INFINITY: f128 = -1.0_f128 / 0.0_f128;
274274

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

library/core/src/num/f16.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,66 @@ impl f16 {
266266
#[unstable(feature = "f16", issue = "116909")]
267267
pub const NEG_INFINITY: f16 = -1.0_f16 / 0.0_f16;
268268

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

library/core/src/num/f32.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,58 @@ 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+
/// let max_exact_int = f32::MAX_EXACT_INTEGER;
531+
/// assert_eq!(max_exact_int, max_exact_int as f32 as i32);
532+
/// assert_eq!(max_exact_int + 1, (max_exact_int + 1) as f32 as i32);
533+
/// assert_ne!(max_exact_int + 2, (max_exact_int + 2) as f32 as i32);
534+
///
535+
/// // Beyond `f32::MAX_EXACT_INTEGER`, multiple integers can map to one float value
536+
/// assert_eq!((max_exact_int + 1) as f32, (max_exact_int + 2) as f32);
537+
/// ```
538+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
539+
pub const MAX_EXACT_INTEGER: i32 = (1 << Self::MANTISSA_DIGITS) - 1;
540+
541+
/// Minimum integer that can be represented exactly in an [`f32`] value,
542+
/// with no other integer converting to the same floating point value.
543+
///
544+
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
545+
/// there is a "one-to-one" mapping between [`i32`] and [`f32`] values.
546+
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f32`] and back to
547+
/// [`i32`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f32`] value
548+
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
549+
/// "one-to-one" mapping.
550+
///
551+
/// This constant is equivalent to `-MAX_EXACT_INTEGER`.
552+
///
553+
/// [`MAX_EXACT_INTEGER`]: f32::MAX_EXACT_INTEGER
554+
/// [`MIN_EXACT_INTEGER`]: f32::MIN_EXACT_INTEGER
555+
/// ```
556+
/// #![feature(float_exact_integer_constants)]
557+
/// let min_exact_int = f32::MIN_EXACT_INTEGER;
558+
/// assert_eq!(min_exact_int, min_exact_int as f32 as i32);
559+
/// assert_eq!(min_exact_int - 1, (min_exact_int - 1) as f32 as i32);
560+
/// assert_ne!(min_exact_int - 2, (min_exact_int - 2) as f32 as i32);
561+
///
562+
/// // Below `f32::MIN_EXACT_INTEGER`, multiple integers can map to one float value
563+
/// assert_eq!((min_exact_int - 1) as f32, (min_exact_int - 2) as f32);
564+
/// ```
565+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
566+
pub const MIN_EXACT_INTEGER: i32 = -Self::MAX_EXACT_INTEGER;
567+
516568
/// Sign bit
517569
pub(crate) const SIGN_MASK: u32 = 0x8000_0000;
518570

library/core/src/num/f64.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,58 @@ 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+
/// let max_exact_int = f64::MAX_EXACT_INTEGER;
530+
/// assert_eq!(max_exact_int, max_exact_int as f64 as i64);
531+
/// assert_eq!(max_exact_int + 1, (max_exact_int + 1) as f64 as i64);
532+
/// assert_ne!(max_exact_int + 2, (max_exact_int + 2) as f64 as i64);
533+
///
534+
/// // Beyond `f64::MAX_EXACT_INTEGER`, multiple integers can map to one float value
535+
/// assert_eq!((max_exact_int + 1) as f64, (max_exact_int + 2) as f64);
536+
/// ```
537+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
538+
pub const MAX_EXACT_INTEGER: i64 = (1 << Self::MANTISSA_DIGITS) - 1;
539+
540+
/// Minimum integer that can be represented exactly in an [`f64`] value,
541+
/// with no other integer converting to the same floating point value.
542+
///
543+
/// For an integer `x` which satisfies `MIN_EXACT_INTEGER <= x <= MAX_EXACT_INTEGER`,
544+
/// there is a "one-to-one" mapping between [`i64`] and [`f64`] values.
545+
/// `MAX_EXACT_INTEGER + 1` also converts losslessly to [`f64`] and back to
546+
/// [`i64`], but `MAX_EXACT_INTEGER + 2` converts to the same [`f64`] value
547+
/// (and back to `MAX_EXACT_INTEGER + 1` as an integer) so there is not a
548+
/// "one-to-one" mapping.
549+
///
550+
/// This constant is equivalent to `-MAX_EXACT_INTEGER`.
551+
///
552+
/// [`MAX_EXACT_INTEGER`]: f64::MAX_EXACT_INTEGER
553+
/// [`MIN_EXACT_INTEGER`]: f64::MIN_EXACT_INTEGER
554+
/// ```
555+
/// #![feature(float_exact_integer_constants)]
556+
/// let min_exact_int = f64::MIN_EXACT_INTEGER;
557+
/// assert_eq!(min_exact_int, min_exact_int as f64 as i64);
558+
/// assert_eq!(min_exact_int - 1, (min_exact_int - 1) as f64 as i64);
559+
/// assert_ne!(min_exact_int - 2, (min_exact_int - 2) as f64 as i64);
560+
///
561+
/// // Below `f64::MIN_EXACT_INTEGER`, multiple integers can map to one float value
562+
/// assert_eq!((min_exact_int - 1) as f64, (min_exact_int - 2) as f64);
563+
/// ```
564+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
565+
pub const MIN_EXACT_INTEGER: i64 = -Self::MAX_EXACT_INTEGER;
566+
515567
/// Sign bit
516568
pub(crate) const SIGN_MASK: u64 = 0x8000_0000_0000_0000;
517569

library/coretests/tests/floats/mod.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use std::ops::{Add, Div, Mul, Rem, Sub};
44
trait TestableFloat: Sized {
55
/// Unsigned int with the same size, for converting to/from bits.
66
type Int;
7+
/// Signed int with the same size.
8+
type SInt;
79
/// Set the default tolerance for float comparison based on the type.
810
const APPROX: Self;
911
/// Allow looser tolerance for f32 on miri
@@ -44,6 +46,7 @@ trait TestableFloat: Sized {
4446

4547
impl TestableFloat for f16 {
4648
type Int = u16;
49+
type SInt = i16;
4750
const APPROX: Self = 1e-3;
4851
const _180_TO_RADIANS_APPROX: Self = 1e-2;
4952
const PI_TO_DEGREES_APPROX: Self = 0.125;
@@ -71,6 +74,7 @@ impl TestableFloat for f16 {
7174

7275
impl TestableFloat for f32 {
7376
type Int = u32;
77+
type SInt = i32;
7478
const APPROX: Self = 1e-6;
7579
/// Miri adds some extra errors to float functions; make sure the tests still pass.
7680
/// These values are purely used as a canary to test against and are thus not a stable guarantee Rust provides.
@@ -100,6 +104,7 @@ impl TestableFloat for f32 {
100104

101105
impl TestableFloat for f64 {
102106
type Int = u64;
107+
type SInt = i64;
103108
const APPROX: Self = 1e-6;
104109
const ZERO: Self = 0.0;
105110
const ONE: Self = 1.0;
@@ -125,6 +130,7 @@ impl TestableFloat for f64 {
125130

126131
impl TestableFloat for f128 {
127132
type Int = u128;
133+
type SInt = i128;
128134
const APPROX: Self = 1e-9;
129135
const ZERO: Self = 0.0;
130136
const ONE: Self = 1.0;
@@ -1632,6 +1638,93 @@ float_test! {
16321638
}
16331639
}
16341640

1641+
// Test the `float_exact_integer_constants` feature
1642+
float_test! {
1643+
name: max_exact_integer_constant,
1644+
attrs: {
1645+
f16: #[cfg(any(miri, target_has_reliable_f16))],
1646+
f128: #[cfg(any(miri, target_has_reliable_f128))],
1647+
},
1648+
test<Float> {
1649+
// The maximum integer that converts to a unique floating point
1650+
// value.
1651+
const MAX_EXACT_INTEGER: <Float as TestableFloat>::SInt = Float::MAX_EXACT_INTEGER;
1652+
1653+
let max_minus_one = (MAX_EXACT_INTEGER - 1) as Float as <Float as TestableFloat>::SInt;
1654+
let max_plus_one = (MAX_EXACT_INTEGER + 1) as Float as <Float as TestableFloat>::SInt;
1655+
let max_plus_two = (MAX_EXACT_INTEGER + 2) as Float as <Float as TestableFloat>::SInt;
1656+
1657+
// This does an extra round trip back to float for the second operand in
1658+
// order to print the results if there is a mismatch
1659+
assert_biteq!((MAX_EXACT_INTEGER - 1) as Float, max_minus_one as Float);
1660+
assert_biteq!(MAX_EXACT_INTEGER as Float, MAX_EXACT_INTEGER as Float as <Float as TestableFloat>::SInt as Float);
1661+
assert_biteq!((MAX_EXACT_INTEGER + 1) as Float, max_plus_one as Float);
1662+
// The first non-unique conversion, where `max_plus_two` roundtrips to
1663+
// `max_plus_one`
1664+
assert_biteq!((MAX_EXACT_INTEGER + 1) as Float, (MAX_EXACT_INTEGER + 2) as Float);
1665+
assert_biteq!((MAX_EXACT_INTEGER + 2) as Float, max_plus_one as Float);
1666+
assert_biteq!((MAX_EXACT_INTEGER + 2) as Float, max_plus_two as Float);
1667+
1668+
// Lossless roundtrips, for integers
1669+
assert!(MAX_EXACT_INTEGER - 1 == max_minus_one);
1670+
assert!(MAX_EXACT_INTEGER == MAX_EXACT_INTEGER as Float as <Float as TestableFloat>::SInt);
1671+
assert!(MAX_EXACT_INTEGER + 1 == max_plus_one);
1672+
// The first non-unique conversion, where `max_plus_two` roundtrips to
1673+
// one less than the starting value
1674+
assert!(MAX_EXACT_INTEGER + 2 != max_plus_two);
1675+
1676+
// max-1 | max+0 | max+1 | max+2
1677+
// After roundtripping, +1 and +2 will equal each other
1678+
assert!(max_minus_one != MAX_EXACT_INTEGER);
1679+
assert!(MAX_EXACT_INTEGER != max_plus_one);
1680+
assert!(max_plus_one == max_plus_two);
1681+
}
1682+
}
1683+
1684+
float_test! {
1685+
name: min_exact_integer_constant,
1686+
attrs: {
1687+
f16: #[cfg(any(miri, target_has_reliable_f16))],
1688+
f128: #[cfg(any(miri, target_has_reliable_f128))],
1689+
},
1690+
test<Float> {
1691+
// The minimum integer that converts to a unique floating point
1692+
// value.
1693+
const MIN_EXACT_INTEGER: <Float as TestableFloat>::SInt = Float::MIN_EXACT_INTEGER;
1694+
1695+
// Same logic as the `max` test, but we work our way leftward
1696+
// across the number line from (min_exact + 1) to (min_exact - 2).
1697+
let min_plus_one = (MIN_EXACT_INTEGER + 1) as Float as <Float as TestableFloat>::SInt;
1698+
let min_minus_one = (MIN_EXACT_INTEGER - 1) as Float as <Float as TestableFloat>::SInt;
1699+
let min_minus_two = (MIN_EXACT_INTEGER - 2) as Float as <Float as TestableFloat>::SInt;
1700+
1701+
// This does an extra round trip back to float for the second operand in
1702+
// order to print the results if there is a mismatch
1703+
assert_biteq!((MIN_EXACT_INTEGER + 1) as Float, min_plus_one as Float);
1704+
assert_biteq!(MIN_EXACT_INTEGER as Float, MIN_EXACT_INTEGER as Float as <Float as TestableFloat>::SInt as Float);
1705+
assert_biteq!((MIN_EXACT_INTEGER - 1) as Float, min_minus_one as Float);
1706+
// The first non-unique conversion, which roundtrips to one
1707+
// greater than the starting value.
1708+
assert_biteq!((MIN_EXACT_INTEGER - 1) as Float, (MIN_EXACT_INTEGER - 2) as Float);
1709+
assert_biteq!((MIN_EXACT_INTEGER - 2) as Float, min_minus_one as Float);
1710+
assert_biteq!((MIN_EXACT_INTEGER - 2) as Float, min_minus_two as Float);
1711+
1712+
// Lossless roundtrips, for integers
1713+
assert!(MIN_EXACT_INTEGER + 1 == min_plus_one);
1714+
assert!(MIN_EXACT_INTEGER == MIN_EXACT_INTEGER as Float as <Float as TestableFloat>::SInt);
1715+
assert!(MIN_EXACT_INTEGER - 1 == min_minus_one);
1716+
// The first non-unique conversion, which roundtrips to one
1717+
// greater than the starting value.
1718+
assert!(MIN_EXACT_INTEGER - 2 != min_minus_two);
1719+
1720+
// min-2 | min-1 | min | min+1
1721+
// After roundtripping, -2 and -1 will equal each other.
1722+
assert!(min_plus_one != MIN_EXACT_INTEGER);
1723+
assert!(MIN_EXACT_INTEGER != min_minus_one);
1724+
assert!(min_minus_one == min_minus_two);
1725+
}
1726+
}
1727+
16351728
// FIXME(f128): Uncomment and adapt these tests once the From<{u64,i64}> impls are added.
16361729
// float_test! {
16371730
// name: from_u64_i64,

library/coretests/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#![feature(f16)]
5656
#![feature(f128)]
5757
#![feature(float_algebraic)]
58+
#![feature(float_exact_integer_constants)]
5859
#![feature(float_gamma)]
5960
#![feature(float_minimum_maximum)]
6061
#![feature(flt2dec)]

0 commit comments

Comments
 (0)