Skip to content

Commit 3daa951

Browse files
RalfJungworkingjubilee
authored andcommitted
enable and extend float-classify test
1 parent c40ee79 commit 3daa951

File tree

3 files changed

+128
-126
lines changed

3 files changed

+128
-126
lines changed
+40-34
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,46 @@
11
//@ compile-flags: -Zmir-opt-level=0 -Znext-solver
2-
//@ known-bug: #110395
3-
// FIXME(effects) run-pass
2+
//@ run-pass
3+
// ignore-tidy-linelength
44

5+
// This tests the float classification functions, for regular runtime code and for const evaluation.
6+
7+
#![feature(f16_const)]
8+
#![feature(f128_const)]
59
#![feature(const_float_classify)]
6-
#![feature(const_trait_impl, effects)]
7-
#![allow(incomplete_features)]
810

9-
// Don't promote
10-
const fn nop<T>(x: T) -> T { x }
11+
use std::hint::black_box;
12+
use std::num::FpCategory::*;
1113

12-
impl const PartialEq<NonDet> for bool {
13-
fn eq(&self, _: &NonDet) -> bool {
14-
true
15-
}
16-
}
17-
18-
macro_rules! const_assert {
19-
($a:expr, $b:expr) => {
14+
macro_rules! both_assert {
15+
($a:expr, NonDet) => {
2016
{
21-
const _: () = assert!($a == $b);
22-
assert!(nop($a) == nop($b));
17+
// Compute `a`, but do not compare with anything as the result is non-deterministic.
18+
const _: () = { let _val = $a; };
19+
// `black_box` prevents promotion, and MIR opts are disabled above, so this is truly
20+
// going through LLVM.
21+
let _val = black_box($a);
22+
}
23+
};
24+
($a:expr, $b:ident) => {
25+
{
26+
const _: () = assert!(matches!($a, $b));
27+
assert!(black_box($a) == black_box($b));
2328
}
2429
};
2530
}
2631

2732
macro_rules! suite {
28-
( $( $tt:tt )* ) => {
33+
( $tyname:ident: $( $tt:tt )* ) => {
2934
fn f32() {
35+
type $tyname = f32;
3036
suite_inner!(f32 $($tt)*);
3137
}
3238

3339
fn f64() {
40+
type $tyname = f64;
3441
suite_inner!(f64 $($tt)*);
3542
}
3643
}
37-
3844
}
3945

4046
macro_rules! suite_inner {
@@ -44,33 +50,33 @@ macro_rules! suite_inner {
4450

4551
$( $tail:tt )*
4652
) => {
47-
$( const_assert!($ty::$fn($val), $out); )*
53+
$( both_assert!($ty::$fn($val), $out); )*
4854
suite_inner!($ty [$($fn),*] $($tail)*)
4955
};
5056

5157
( $ty:ident [$( $fn:ident ),*]) => {};
5258
}
5359

54-
#[derive(Debug)]
55-
struct NonDet;
56-
57-
// The result of the `is_sign` methods are not checked for correctness, since LLVM does not
60+
// The result of the `is_sign` methods are not checked for correctness, since we do not
5861
// guarantee anything about the signedness of NaNs. See
59-
// https://github.com/rust-lang/rust/issues/55131.
62+
// https://rust-lang.github.io/rfcs/3514-float-semantics.html.
6063

61-
suite! {
62-
[is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative]
63-
-0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
64-
0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
65-
1.0 => [ false, false, true, true, true, false]
66-
-1.0 => [ false, false, true, true, false, true]
67-
0.0 => [ false, false, true, false, true, false]
68-
-0.0 => [ false, false, true, false, false, true]
69-
1.0 / 0.0 => [ false, true, false, false, true, false]
70-
-1.0 / 0.0 => [ false, true, false, false, false, true]
64+
suite! { T: // type alias for the type we are testing
65+
[ classify, is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative]
66+
-0.0 / 0.0 => [ Nan, true, false, false, false, NonDet, NonDet]
67+
0.0 / 0.0 => [ Nan, true, false, false, false, NonDet, NonDet]
68+
1.0 => [ Normal, false, false, true, true, true, false]
69+
-1.0 => [ Normal, false, false, true, true, false, true]
70+
0.0 => [ Zero, false, false, true, false, true, false]
71+
-0.0 => [ Zero, false, false, true, false, false, true]
72+
1.0 / 0.0 => [ Infinite, false, true, false, false, true, false]
73+
-1.0 / 0.0 => [ Infinite, false, true, false, false, false, true]
74+
1.0 / T::MAX => [Subnormal, false, false, true, false, true, false]
75+
-1.0 / T::MAX => [Subnormal, false, false, true, false, false, true]
7176
}
7277

7378
fn main() {
7479
f32();
7580
f64();
81+
// FIXME(f16_f128): also test f16 and f128
7682
}

tests/ui/float/classify-runtime-const.stderr

-11
This file was deleted.
+88-81
Original file line numberDiff line numberDiff line change
@@ -1,161 +1,168 @@
11
//@ compile-flags: -Zmir-opt-level=0
22
//@ run-pass
33

4+
// This tests the float classification functions, for regular runtime code and for const evaluation.
5+
46
#![feature(const_float_classify)]
5-
#![feature(f16, f16_const)]
6-
#![feature(f128, f128_const)]
7+
#![feature(f16)]
8+
#![feature(f128)]
9+
#![feature(f16_const)]
10+
#![feature(f128_const)]
711
#![allow(unused_macro_rules)]
8-
// Don't promote
9-
const fn nop<T>(x: T) -> T { x }
1012

11-
macro_rules! const_assert {
13+
use std::hint::black_box;
14+
15+
macro_rules! both_assert {
1216
($a:expr) => {
1317
{
1418
const _: () = assert!($a);
15-
assert!(nop($a));
19+
// `black_box` prevents promotion, and MIR opts are disabled above, so this is truly
20+
// going through LLVM.
21+
assert!(black_box($a));
1622
}
1723
};
1824
($a:expr, $b:expr) => {
1925
{
2026
const _: () = assert!($a == $b);
21-
assert_eq!(nop($a), nop($b));
27+
assert_eq!(black_box($a), black_box($b));
2228
}
2329
};
2430
}
2531

2632
fn has_broken_floats() -> bool {
2733
// i586 targets are broken due to <https://github.com/rust-lang/rust/issues/114479>.
28-
std::env::var("TARGET").is_ok_and(|v| v.contains("i586"))
34+
cfg!(all(target_arch = "x86", not(target_feature = "sse2")))
2935
}
3036

3137
#[cfg(target_arch = "x86_64")]
3238
fn f16(){
33-
const_assert!((1f16).to_bits(), 0x3c00);
34-
const_assert!(u16::from_be_bytes(1f16.to_be_bytes()), 0x3c00);
35-
const_assert!((12.5f16).to_bits(), 0x4a40);
36-
const_assert!(u16::from_le_bytes(12.5f16.to_le_bytes()), 0x4a40);
37-
const_assert!((1337f16).to_bits(), 0x6539);
38-
const_assert!(u16::from_ne_bytes(1337f16.to_ne_bytes()), 0x6539);
39-
const_assert!((-14.25f16).to_bits(), 0xcb20);
40-
const_assert!(f16::from_bits(0x3c00), 1.0);
41-
const_assert!(f16::from_be_bytes(0x3c00u16.to_be_bytes()), 1.0);
42-
const_assert!(f16::from_bits(0x4a40), 12.5);
43-
const_assert!(f16::from_le_bytes(0x4a40u16.to_le_bytes()), 12.5);
44-
const_assert!(f16::from_bits(0x5be0), 252.0);
45-
const_assert!(f16::from_ne_bytes(0x5be0u16.to_ne_bytes()), 252.0);
46-
const_assert!(f16::from_bits(0xcb20), -14.25);
39+
both_assert!((1f16).to_bits(), 0x3c00);
40+
both_assert!(u16::from_be_bytes(1f16.to_be_bytes()), 0x3c00);
41+
both_assert!((12.5f16).to_bits(), 0x4a40);
42+
both_assert!(u16::from_le_bytes(12.5f16.to_le_bytes()), 0x4a40);
43+
both_assert!((1337f16).to_bits(), 0x6539);
44+
both_assert!(u16::from_ne_bytes(1337f16.to_ne_bytes()), 0x6539);
45+
both_assert!((-14.25f16).to_bits(), 0xcb20);
46+
both_assert!(f16::from_bits(0x3c00), 1.0);
47+
both_assert!(f16::from_be_bytes(0x3c00u16.to_be_bytes()), 1.0);
48+
both_assert!(f16::from_bits(0x4a40), 12.5);
49+
both_assert!(f16::from_le_bytes(0x4a40u16.to_le_bytes()), 12.5);
50+
both_assert!(f16::from_bits(0x5be0), 252.0);
51+
both_assert!(f16::from_ne_bytes(0x5be0u16.to_ne_bytes()), 252.0);
52+
both_assert!(f16::from_bits(0xcb20), -14.25);
4753

4854
// Check that NaNs roundtrip their bits regardless of signalingness
4955
// 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
5056
// NOTE: These names assume `f{BITS}::NAN` is a quiet NAN and IEEE754-2008's NaN rules apply!
5157
const QUIET_NAN: u16 = f16::NAN.to_bits() ^ 0x0155;
5258
const SIGNALING_NAN: u16 = f16::NAN.to_bits() ^ 0x02AA;
5359

54-
const_assert!(f16::from_bits(QUIET_NAN).is_nan());
55-
const_assert!(f16::from_bits(SIGNALING_NAN).is_nan());
56-
const_assert!(f16::from_bits(QUIET_NAN).to_bits(), QUIET_NAN);
60+
both_assert!(f16::from_bits(QUIET_NAN).is_nan());
61+
both_assert!(f16::from_bits(SIGNALING_NAN).is_nan());
62+
both_assert!(f16::from_bits(QUIET_NAN).to_bits(), QUIET_NAN);
5763
if !has_broken_floats() {
58-
const_assert!(f16::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN);
64+
both_assert!(f16::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN);
5965
}
6066
}
6167

6268
fn f32() {
63-
const_assert!((1f32).to_bits(), 0x3f800000);
64-
const_assert!(u32::from_be_bytes(1f32.to_be_bytes()), 0x3f800000);
65-
const_assert!((12.5f32).to_bits(), 0x41480000);
66-
const_assert!(u32::from_le_bytes(12.5f32.to_le_bytes()), 0x41480000);
67-
const_assert!((1337f32).to_bits(), 0x44a72000);
68-
const_assert!(u32::from_ne_bytes(1337f32.to_ne_bytes()), 0x44a72000);
69-
const_assert!((-14.25f32).to_bits(), 0xc1640000);
70-
const_assert!(f32::from_bits(0x3f800000), 1.0);
71-
const_assert!(f32::from_be_bytes(0x3f800000u32.to_be_bytes()), 1.0);
72-
const_assert!(f32::from_bits(0x41480000), 12.5);
73-
const_assert!(f32::from_le_bytes(0x41480000u32.to_le_bytes()), 12.5);
74-
const_assert!(f32::from_bits(0x44a72000), 1337.0);
75-
const_assert!(f32::from_ne_bytes(0x44a72000u32.to_ne_bytes()), 1337.0);
76-
const_assert!(f32::from_bits(0xc1640000), -14.25);
69+
both_assert!((1f32).to_bits(), 0x3f800000);
70+
both_assert!(u32::from_be_bytes(1f32.to_be_bytes()), 0x3f800000);
71+
both_assert!((12.5f32).to_bits(), 0x41480000);
72+
both_assert!(u32::from_le_bytes(12.5f32.to_le_bytes()), 0x41480000);
73+
both_assert!((1337f32).to_bits(), 0x44a72000);
74+
both_assert!(u32::from_ne_bytes(1337f32.to_ne_bytes()), 0x44a72000);
75+
both_assert!((-14.25f32).to_bits(), 0xc1640000);
76+
both_assert!(f32::from_bits(0x3f800000), 1.0);
77+
both_assert!(f32::from_be_bytes(0x3f800000u32.to_be_bytes()), 1.0);
78+
both_assert!(f32::from_bits(0x41480000), 12.5);
79+
both_assert!(f32::from_le_bytes(0x41480000u32.to_le_bytes()), 12.5);
80+
both_assert!(f32::from_bits(0x44a72000), 1337.0);
81+
both_assert!(f32::from_ne_bytes(0x44a72000u32.to_ne_bytes()), 1337.0);
82+
both_assert!(f32::from_bits(0xc1640000), -14.25);
7783

7884
// Check that NaNs roundtrip their bits regardless of signalingness
7985
// 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
8086
// NOTE: These names assume `f{BITS}::NAN` is a quiet NAN and IEEE754-2008's NaN rules apply!
8187
const QUIET_NAN: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA;
8288
const SIGNALING_NAN: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
8389

84-
const_assert!(f32::from_bits(QUIET_NAN).is_nan());
85-
const_assert!(f32::from_bits(SIGNALING_NAN).is_nan());
86-
const_assert!(f32::from_bits(QUIET_NAN).to_bits(), QUIET_NAN);
90+
both_assert!(f32::from_bits(QUIET_NAN).is_nan());
91+
both_assert!(f32::from_bits(SIGNALING_NAN).is_nan());
92+
both_assert!(f32::from_bits(QUIET_NAN).to_bits(), QUIET_NAN);
8793
if !has_broken_floats() {
88-
const_assert!(f32::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN);
94+
both_assert!(f32::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN);
8995
}
9096
}
9197

9298
fn f64() {
93-
const_assert!((1f64).to_bits(), 0x3ff0000000000000);
94-
const_assert!(u64::from_be_bytes(1f64.to_be_bytes()), 0x3ff0000000000000);
95-
const_assert!((12.5f64).to_bits(), 0x4029000000000000);
96-
const_assert!(u64::from_le_bytes(12.5f64.to_le_bytes()), 0x4029000000000000);
97-
const_assert!((1337f64).to_bits(), 0x4094e40000000000);
98-
const_assert!(u64::from_ne_bytes(1337f64.to_ne_bytes()), 0x4094e40000000000);
99-
const_assert!((-14.25f64).to_bits(), 0xc02c800000000000);
100-
const_assert!(f64::from_bits(0x3ff0000000000000), 1.0);
101-
const_assert!(f64::from_be_bytes(0x3ff0000000000000u64.to_be_bytes()), 1.0);
102-
const_assert!(f64::from_bits(0x4029000000000000), 12.5);
103-
const_assert!(f64::from_le_bytes(0x4029000000000000u64.to_le_bytes()), 12.5);
104-
const_assert!(f64::from_bits(0x4094e40000000000), 1337.0);
105-
const_assert!(f64::from_ne_bytes(0x4094e40000000000u64.to_ne_bytes()), 1337.0);
106-
const_assert!(f64::from_bits(0xc02c800000000000), -14.25);
99+
both_assert!((1f64).to_bits(), 0x3ff0000000000000);
100+
both_assert!(u64::from_be_bytes(1f64.to_be_bytes()), 0x3ff0000000000000);
101+
both_assert!((12.5f64).to_bits(), 0x4029000000000000);
102+
both_assert!(u64::from_le_bytes(12.5f64.to_le_bytes()), 0x4029000000000000);
103+
both_assert!((1337f64).to_bits(), 0x4094e40000000000);
104+
both_assert!(u64::from_ne_bytes(1337f64.to_ne_bytes()), 0x4094e40000000000);
105+
both_assert!((-14.25f64).to_bits(), 0xc02c800000000000);
106+
both_assert!(f64::from_bits(0x3ff0000000000000), 1.0);
107+
both_assert!(f64::from_be_bytes(0x3ff0000000000000u64.to_be_bytes()), 1.0);
108+
both_assert!(f64::from_bits(0x4029000000000000), 12.5);
109+
both_assert!(f64::from_le_bytes(0x4029000000000000u64.to_le_bytes()), 12.5);
110+
both_assert!(f64::from_bits(0x4094e40000000000), 1337.0);
111+
both_assert!(f64::from_ne_bytes(0x4094e40000000000u64.to_ne_bytes()), 1337.0);
112+
both_assert!(f64::from_bits(0xc02c800000000000), -14.25);
107113

108114
// Check that NaNs roundtrip their bits regardless of signalingness
109115
// 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
110116
// NOTE: These names assume `f{BITS}::NAN` is a quiet NAN and IEEE754-2008's NaN rules apply!
111117
const QUIET_NAN: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
112118
const SIGNALING_NAN: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
113119

114-
const_assert!(f64::from_bits(QUIET_NAN).is_nan());
115-
const_assert!(f64::from_bits(SIGNALING_NAN).is_nan());
116-
const_assert!(f64::from_bits(QUIET_NAN).to_bits(), QUIET_NAN);
120+
both_assert!(f64::from_bits(QUIET_NAN).is_nan());
121+
both_assert!(f64::from_bits(SIGNALING_NAN).is_nan());
122+
both_assert!(f64::from_bits(QUIET_NAN).to_bits(), QUIET_NAN);
117123
if !has_broken_floats() {
118-
const_assert!(f64::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN);
124+
both_assert!(f64::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN);
119125
}
120126
}
121127

122128
#[cfg(target_arch = "x86_64")]
123129
fn f128() {
124-
const_assert!((1f128).to_bits(), 0x3fff0000000000000000000000000000);
125-
const_assert!(u128::from_be_bytes(1f128.to_be_bytes()), 0x3fff0000000000000000000000000000);
126-
const_assert!((12.5f128).to_bits(), 0x40029000000000000000000000000000);
127-
const_assert!(u128::from_le_bytes(12.5f128.to_le_bytes()), 0x40029000000000000000000000000000);
128-
const_assert!((1337f128).to_bits(), 0x40094e40000000000000000000000000);
129-
const_assert!(u128::from_ne_bytes(1337f128.to_ne_bytes()), 0x40094e40000000000000000000000000);
130-
const_assert!((-14.25f128).to_bits(), 0xc002c800000000000000000000000000);
131-
const_assert!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0);
132-
const_assert!(f128::from_be_bytes(0x3fff0000000000000000000000000000u128.to_be_bytes()), 1.0);
133-
const_assert!(f128::from_bits(0x40029000000000000000000000000000), 12.5);
134-
const_assert!(f128::from_le_bytes(0x40029000000000000000000000000000u128.to_le_bytes()), 12.5);
135-
const_assert!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0);
130+
both_assert!((1f128).to_bits(), 0x3fff0000000000000000000000000000);
131+
both_assert!(u128::from_be_bytes(1f128.to_be_bytes()), 0x3fff0000000000000000000000000000);
132+
both_assert!((12.5f128).to_bits(), 0x40029000000000000000000000000000);
133+
both_assert!(u128::from_le_bytes(12.5f128.to_le_bytes()), 0x40029000000000000000000000000000);
134+
both_assert!((1337f128).to_bits(), 0x40094e40000000000000000000000000);
135+
both_assert!(u128::from_ne_bytes(1337f128.to_ne_bytes()), 0x40094e40000000000000000000000000);
136+
both_assert!((-14.25f128).to_bits(), 0xc002c800000000000000000000000000);
137+
both_assert!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0);
138+
both_assert!(f128::from_be_bytes(0x3fff0000000000000000000000000000u128.to_be_bytes()), 1.0);
139+
both_assert!(f128::from_bits(0x40029000000000000000000000000000), 12.5);
140+
both_assert!(f128::from_le_bytes(0x40029000000000000000000000000000u128.to_le_bytes()), 12.5);
141+
both_assert!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0);
136142
assert_eq!(f128::from_ne_bytes(0x40094e40000000000000000000000000u128.to_ne_bytes()), 1337.0);
137-
const_assert!(f128::from_bits(0xc002c800000000000000000000000000), -14.25);
143+
both_assert!(f128::from_bits(0xc002c800000000000000000000000000), -14.25);
138144

139145
// Check that NaNs roundtrip their bits regardless of signalingness
140146
// 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
141147
// NOTE: These names assume `f{BITS}::NAN` is a quiet NAN and IEEE754-2008's NaN rules apply!
142148
const QUIET_NAN: u128 = f128::NAN.to_bits() | 0x0000_AAAA_AAAA_AAAA_AAAA_AAAA_AAAA_AAAA;
143149
const SIGNALING_NAN: u128 = f128::NAN.to_bits() ^ 0x0000_5555_5555_5555_5555_5555_5555_5555;
144150

145-
const_assert!(f128::from_bits(QUIET_NAN).is_nan());
146-
const_assert!(f128::from_bits(SIGNALING_NAN).is_nan());
147-
const_assert!(f128::from_bits(QUIET_NAN).to_bits(), QUIET_NAN);
151+
both_assert!(f128::from_bits(QUIET_NAN).is_nan());
152+
both_assert!(f128::from_bits(SIGNALING_NAN).is_nan());
153+
both_assert!(f128::from_bits(QUIET_NAN).to_bits(), QUIET_NAN);
148154
if !has_broken_floats() {
149-
const_assert!(f128::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN);
155+
both_assert!(f128::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN);
150156
}
151157
}
152158

153159
fn main() {
160+
f32();
161+
f64();
162+
154163
#[cfg(target_arch = "x86_64")]
155164
{
156165
f16();
157166
f128();
158167
}
159-
f32();
160-
f64();
161168
}

0 commit comments

Comments
 (0)