-
-
Notifications
You must be signed in to change notification settings - Fork 14.6k
Expand file tree
/
Copy pathclassify-runtime-const.rs
More file actions
135 lines (121 loc) · 4.8 KB
/
classify-runtime-const.rs
File metadata and controls
135 lines (121 loc) · 4.8 KB
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
131
132
133
134
135
//@ run-pass
//@ revisions: opt noopt ctfe
//@[opt] compile-flags: -O
//@[noopt] compile-flags: -Zmir-opt-level=0
// ignore-tidy-linelength
#![feature(f16)]
// This tests the float classification functions, for regular runtime code and for const evaluation.
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 f16() {
#[allow(unused)]
type $tyname = f16;
suite_inner!(f16 => $($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() {
f16();
f32();
f64();
// FIXME(f128): also test f128
}