forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclassify-runtime-const.rs
130 lines (117 loc) · 4.73 KB
/
classify-runtime-const.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//@ run-pass
//@ revisions: opt noopt ctfe
//@[opt] compile-flags: -O
//@[noopt] compile-flags: -Zmir-opt-level=0
// ignore-tidy-linelength
// This tests the float classification functions, for regular runtime code and for const evaluation.
#![feature(f16_const)]
#![feature(f128_const)]
#![feature(const_float_classify)]
use std::num::FpCategory::*;
#[cfg(not(ctfe))]
use std::hint::black_box;
#[cfg(ctfe)]
#[allow(unused)]
const fn black_box<T>(x: T) -> T { x }
#[cfg(not(ctfe))]
macro_rules! assert_test {
($a:expr, NonDet) => {
{
// Compute `a`, but do not compare with anything as the result is non-deterministic.
let _val = $a;
}
};
($a:expr, $b:ident) => {
{
// Let-bind to avoid promotion.
// No black_box here! That can mask x87 failures.
let a = $a;
let b = $b;
assert_eq!(a, b, "{} produces wrong result", stringify!($a));
}
};
}
#[cfg(ctfe)]
macro_rules! assert_test {
($a:expr, NonDet) => {
{
// Compute `a`, but do not compare with anything as the result is non-deterministic.
const _: () = { let _val = $a; };
}
};
($a:expr, $b:ident) => {
{
const _: () = assert!(matches!($a, $b));
}
};
}
macro_rules! suite {
( $tyname:ident => $( $tt:tt )* ) => {
fn f32() {
#[allow(unused)]
type $tyname = f32;
suite_inner!(f32 => $($tt)*);
}
fn f64() {
#[allow(unused)]
type $tyname = f64;
suite_inner!(f64 => $($tt)*);
}
}
}
macro_rules! suite_inner {
(
$ty:ident => [$( $fn:ident ),*]:
$(@cfg: $attr:meta)?
$val:expr => [$($out:ident),*],
$( $tail:tt )*
) => {
$(#[cfg($attr)])?
{
// No black_box here! That can mask x87 failures.
$( assert_test!($ty::$fn($val), $out); )*
}
suite_inner!($ty => [$($fn),*]: $($tail)*)
};
( $ty:ident => [$( $fn:ident ),*]:) => {};
}
// The result of the `is_sign` methods are not checked for correctness, since we do not
// guarantee anything about the signedness of NaNs. See
// https://rust-lang.github.io/rfcs/3514-float-semantics.html.
suite! { T => // type alias for the type we are testing
[ classify, is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative]:
black_box(0.0) / black_box(0.0) =>
[ Nan, true, false, false, false, NonDet, NonDet],
black_box(0.0) / black_box(-0.0) =>
[ Nan, true, false, false, false, NonDet, NonDet],
black_box(0.0) * black_box(T::INFINITY) =>
[ Nan, true, false, false, false, NonDet, NonDet],
black_box(0.0) * black_box(T::NEG_INFINITY) =>
[ Nan, true, false, false, false, NonDet, NonDet],
1.0 => [ Normal, false, false, true, true, true, false],
-1.0 => [ Normal, false, false, true, true, false, true],
0.0 => [ Zero, false, false, true, false, true, false],
-0.0 => [ Zero, false, false, true, false, false, true],
1.0 / black_box(0.0) =>
[ Infinite, false, true, false, false, true, false],
-1.0 / black_box(0.0) =>
[ Infinite, false, true, false, false, false, true],
2.0 * black_box(T::MAX) =>
[ Infinite, false, true, false, false, true, false],
-2.0 * black_box(T::MAX) =>
[ Infinite, false, true, false, false, false, true],
1.0 / black_box(T::MAX) =>
[Subnormal, false, false, true, false, true, false],
-1.0 / black_box(T::MAX) =>
[Subnormal, false, false, true, false, false, true],
// This specific expression causes trouble on x87 due to
// <https://github.com/rust-lang/rust/issues/114479>.
@cfg: not(all(target_arch = "x86", not(target_feature = "sse2")))
{ let x = black_box(T::MAX); x * x } =>
[ Infinite, false, true, false, false, true, false],
}
fn main() {
f32();
f64();
// FIXME(f16_f128): also test f16 and f128
}