Skip to content

Commit a514af5

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/num`
1 parent 7057231 commit a514af5

7 files changed

Lines changed: 164 additions & 0 deletions

File tree

library/core/src/num/f128.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,32 @@ 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+
/// Values contained inclusively within [`MIN_EXACT_INTEGER`] to
279+
/// [`MAX_EXACT_INTEGER`] can be losslessly converted between integer
280+
/// and floating point.
281+
///
282+
/// [`MAX_EXACT_INTEGER`]: f128::MAX_EXACT_INTEGER
283+
/// [`MIN_EXACT_INTEGER`]: f128::MIN_EXACT_INTEGER
284+
// #[unstable(feature = "f128", issue = "116909")]
285+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
286+
pub const MAX_EXACT_INTEGER: i128 = (1 << Self::MANTISSA_DIGITS) - 1;
287+
288+
/// Minimum integer that can be represented exactly in an [`f128`] value,
289+
/// with no other integer converting to the same floating point value.
290+
///
291+
/// Values contained inclusively within [`MIN_EXACT_INTEGER`] to
292+
/// [`MAX_EXACT_INTEGER`] can be losslessly converted between integer
293+
/// and floating point.
294+
///
295+
/// [`MAX_EXACT_INTEGER`]: f128::MAX_EXACT_INTEGER
296+
/// [`MIN_EXACT_INTEGER`]: f128::MIN_EXACT_INTEGER
297+
// #[unstable(feature = "f128", issue = "116909")]
298+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
299+
pub const MIN_EXACT_INTEGER: i128 = -Self::MAX_EXACT_INTEGER;
300+
275301
/// Sign bit
276302
pub(crate) const SIGN_MASK: u128 = 0x8000_0000_0000_0000_0000_0000_0000_0000;
277303

library/core/src/num/f16.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,32 @@ 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+
/// Values contained inclusively within [`MIN_EXACT_INTEGER`] to
273+
/// [`MAX_EXACT_INTEGER`] can be losslessly converted between integer
274+
/// and floating point.
275+
///
276+
/// [`MAX_EXACT_INTEGER`]: f16::MAX_EXACT_INTEGER
277+
/// [`MIN_EXACT_INTEGER`]: f16::MIN_EXACT_INTEGER
278+
// #[unstable(feature = "f16", issue = "116909")]
279+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
280+
pub const MAX_EXACT_INTEGER: i16 = (1 << Self::MANTISSA_DIGITS) - 1;
281+
282+
/// Minimum integer that can be represented exactly in an [`f16`] value,
283+
/// with no other integer converting to the same floating point value.
284+
///
285+
/// Values contained inclusively within [`MIN_EXACT_INTEGER`] to
286+
/// [`MAX_EXACT_INTEGER`] can be losslessly converted between integer
287+
/// and floating point.
288+
///
289+
/// [`MAX_EXACT_INTEGER`]: f16::MAX_EXACT_INTEGER
290+
/// [`MIN_EXACT_INTEGER`]: f16::MIN_EXACT_INTEGER
291+
// #[unstable(feature = "f16", issue = "116909")]
292+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
293+
pub const MIN_EXACT_INTEGER: i16 = -Self::MAX_EXACT_INTEGER;
294+
269295
/// Sign bit
270296
pub(crate) const SIGN_MASK: u16 = 0x8000;
271297

library/core/src/num/f32.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,30 @@ 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+
/// Values contained inclusively within [`MIN_EXACT_INTEGER`] to
520+
/// [`MAX_EXACT_INTEGER`] can be losslessly converted between integer
521+
/// and floating point.
522+
///
523+
/// [`MAX_EXACT_INTEGER`]: f32::MAX_EXACT_INTEGER
524+
/// [`MIN_EXACT_INTEGER`]: f32::MIN_EXACT_INTEGER
525+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
526+
pub const MAX_EXACT_INTEGER: i32 = (1 << Self::MANTISSA_DIGITS) - 1;
527+
528+
/// Minimum integer that can be represented exactly in an [`f32`] value,
529+
/// with no other integer converting to the same floating point value.
530+
///
531+
/// Values contained inclusively within [`MIN_EXACT_INTEGER`] to
532+
/// [`MAX_EXACT_INTEGER`] can be losslessly converted between integer
533+
/// and floating point.
534+
///
535+
/// [`MAX_EXACT_INTEGER`]: f32::MAX_EXACT_INTEGER
536+
/// [`MIN_EXACT_INTEGER`]: f32::MIN_EXACT_INTEGER
537+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
538+
pub const MIN_EXACT_INTEGER: i32 = -Self::MAX_EXACT_INTEGER;
539+
516540
/// Sign bit
517541
pub(crate) const SIGN_MASK: u32 = 0x8000_0000;
518542

library/core/src/num/f64.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,30 @@ 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+
/// Values contained inclusively within [`MIN_EXACT_INTEGER`] to
519+
/// [`MAX_EXACT_INTEGER`] can be losslessly converted between integer
520+
/// and floating point.
521+
///
522+
/// [`MAX_EXACT_INTEGER`]: f64::MAX_EXACT_INTEGER
523+
/// [`MIN_EXACT_INTEGER`]: f64::MIN_EXACT_INTEGER
524+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
525+
pub const MAX_EXACT_INTEGER: i64 = (1 << Self::MANTISSA_DIGITS) - 1;
526+
527+
/// Minimum integer that can be represented exactly in an [`f64`] value,
528+
/// with no other integer converting to the same floating point value.
529+
///
530+
/// Values contained inclusively within [`MIN_EXACT_INTEGER`] to
531+
/// [`MAX_EXACT_INTEGER`] can be losslessly converted between integer
532+
/// and floating point.
533+
///
534+
/// [`MAX_EXACT_INTEGER`]: f64::MAX_EXACT_INTEGER
535+
/// [`MIN_EXACT_INTEGER`]: f64::MIN_EXACT_INTEGER
536+
#[unstable(feature = "float_exact_integer_constants", issue = "152466")]
537+
pub const MIN_EXACT_INTEGER: i64 = -Self::MAX_EXACT_INTEGER;
538+
515539
/// Sign bit
516540
pub(crate) const SIGN_MASK: u64 = 0x8000_0000_0000_0000;
517541

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)]
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Test the `float_exact_integer_constants` feature
2+
macro_rules! test_float_exact_integer_constants {
3+
($fn_name:ident, $float:ty, $integer:ty) => {
4+
#[test]
5+
fn $fn_name() {
6+
{
7+
// The maximum integer that converts to a unique floating point
8+
// value.
9+
const MAX_EXACT_INTEGER: $integer = <$float>::MAX_EXACT_INTEGER;
10+
11+
let max_minus_one = (MAX_EXACT_INTEGER - 1) as $float as $integer;
12+
let max_plus_one = (MAX_EXACT_INTEGER + 1) as $float as $integer;
13+
let max_plus_two = (MAX_EXACT_INTEGER + 2) as $float as $integer;
14+
15+
// Lossless roundtrips.
16+
assert_eq!(MAX_EXACT_INTEGER - 1, max_minus_one);
17+
assert_eq!(MAX_EXACT_INTEGER, MAX_EXACT_INTEGER as $float as $integer);
18+
assert_eq!(MAX_EXACT_INTEGER + 1, max_plus_one);
19+
// The first non-unique conversion, which roundtrips to one less
20+
// than the starting value.
21+
assert_ne!(MAX_EXACT_INTEGER + 2, max_plus_two);
22+
23+
// max-1 | max+0 | max+1 | max+2
24+
// After roundtripping, +1 and +2 will equal each other.
25+
assert_ne!(max_minus_one, MAX_EXACT_INTEGER);
26+
assert_ne!(MAX_EXACT_INTEGER, max_plus_one);
27+
assert_eq!(max_plus_one, max_plus_two);
28+
}
29+
30+
{
31+
// The minimum integer that converts to a unique floating point
32+
// value.
33+
const MIN_EXACT_INTEGER: $integer = <$float>::MIN_EXACT_INTEGER;
34+
35+
// Same logic as the previous block, but we work our way leftward
36+
// across the number line from (min_exact + 1) to (min_exact - 2).
37+
let min_plus_one = (MIN_EXACT_INTEGER + 1) as $float as $integer;
38+
let min_minus_one = (MIN_EXACT_INTEGER - 1) as $float as $integer;
39+
let min_minus_two = (MIN_EXACT_INTEGER - 2) as $float as $integer;
40+
41+
// Lossless roundtrips.
42+
assert_eq!(MIN_EXACT_INTEGER + 1, min_plus_one);
43+
assert_eq!(MIN_EXACT_INTEGER, MIN_EXACT_INTEGER as $float as $integer);
44+
assert_eq!(MIN_EXACT_INTEGER - 1, min_minus_one);
45+
// The first non-unique conversion, which roundtrips to one
46+
// greater than the starting value.
47+
assert_ne!(MIN_EXACT_INTEGER - 2, min_minus_two);
48+
49+
// min-2 | min-1 | min | min+1
50+
// After roundtripping, -2 and -1 will equal each other.
51+
assert_ne!(min_plus_one, MIN_EXACT_INTEGER);
52+
assert_ne!(MIN_EXACT_INTEGER, min_minus_one);
53+
assert_eq!(min_minus_one, min_minus_two);
54+
}
55+
}
56+
};
57+
}
58+
59+
test_float_exact_integer_constants! { test_f16_min_max_exact_integer, f16, i16 }
60+
test_float_exact_integer_constants! { test_f32_min_max_exact_integer, f32, i32 }
61+
test_float_exact_integer_constants! { test_f64_min_max_exact_integer, f64, i64 }
62+
test_float_exact_integer_constants! { test_f128_min_max_exact_integer, f128, i128 }

library/coretests/tests/num/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ mod u8;
2424
mod bignum;
2525
mod const_from;
2626
mod dec2flt;
27+
mod float_exact_integer;
2728
mod float_iter_sum_identity;
2829
mod flt2dec;
2930
mod ieee754;

0 commit comments

Comments
 (0)