1
1
#![ feature( stmt_expr_attributes) ]
2
2
#![ feature( float_gamma) ]
3
3
#![ feature( core_intrinsics) ]
4
+ #![ feature( f128) ]
5
+ #![ feature( f16) ]
4
6
#![ allow( arithmetic_overflow) ]
5
7
6
8
use std:: fmt:: Debug ;
@@ -41,103 +43,23 @@ trait FloatToInt<Int>: Copy {
41
43
unsafe fn cast_unchecked ( self ) -> Int ;
42
44
}
43
45
44
- impl FloatToInt < i8 > for f32 {
45
- fn cast ( self ) -> i8 {
46
- self as _
47
- }
48
- unsafe fn cast_unchecked ( self ) -> i8 {
49
- self . to_int_unchecked ( )
50
- }
51
- }
52
- impl FloatToInt < i32 > for f32 {
53
- fn cast ( self ) -> i32 {
54
- self as _
55
- }
56
- unsafe fn cast_unchecked ( self ) -> i32 {
57
- self . to_int_unchecked ( )
58
- }
59
- }
60
- impl FloatToInt < u32 > for f32 {
61
- fn cast ( self ) -> u32 {
62
- self as _
63
- }
64
- unsafe fn cast_unchecked ( self ) -> u32 {
65
- self . to_int_unchecked ( )
66
- }
67
- }
68
- impl FloatToInt < i64 > for f32 {
69
- fn cast ( self ) -> i64 {
70
- self as _
71
- }
72
- unsafe fn cast_unchecked ( self ) -> i64 {
73
- self . to_int_unchecked ( )
74
- }
75
- }
76
- impl FloatToInt < u64 > for f32 {
77
- fn cast ( self ) -> u64 {
78
- self as _
79
- }
80
- unsafe fn cast_unchecked ( self ) -> u64 {
81
- self . to_int_unchecked ( )
82
- }
46
+ macro_rules! float_to_int {
47
+ ( $fty: ty => $( $ity: ty) ,+ $( , ) ?) => {
48
+ $(
49
+ impl FloatToInt <$ity> for $fty {
50
+ fn cast( self ) -> $ity {
51
+ self as _
52
+ }
53
+ unsafe fn cast_unchecked( self ) -> $ity {
54
+ self . to_int_unchecked( )
55
+ }
56
+ }
57
+ ) *
58
+ } ;
83
59
}
84
60
85
- impl FloatToInt < i8 > for f64 {
86
- fn cast ( self ) -> i8 {
87
- self as _
88
- }
89
- unsafe fn cast_unchecked ( self ) -> i8 {
90
- self . to_int_unchecked ( )
91
- }
92
- }
93
- impl FloatToInt < i32 > for f64 {
94
- fn cast ( self ) -> i32 {
95
- self as _
96
- }
97
- unsafe fn cast_unchecked ( self ) -> i32 {
98
- self . to_int_unchecked ( )
99
- }
100
- }
101
- impl FloatToInt < u32 > for f64 {
102
- fn cast ( self ) -> u32 {
103
- self as _
104
- }
105
- unsafe fn cast_unchecked ( self ) -> u32 {
106
- self . to_int_unchecked ( )
107
- }
108
- }
109
- impl FloatToInt < i64 > for f64 {
110
- fn cast ( self ) -> i64 {
111
- self as _
112
- }
113
- unsafe fn cast_unchecked ( self ) -> i64 {
114
- self . to_int_unchecked ( )
115
- }
116
- }
117
- impl FloatToInt < u64 > for f64 {
118
- fn cast ( self ) -> u64 {
119
- self as _
120
- }
121
- unsafe fn cast_unchecked ( self ) -> u64 {
122
- self . to_int_unchecked ( )
123
- }
124
- }
125
- impl FloatToInt < i128 > for f64 {
126
- fn cast ( self ) -> i128 {
127
- self as _
128
- }
129
- unsafe fn cast_unchecked ( self ) -> i128 {
130
- self . to_int_unchecked ( )
131
- }
132
- }
133
- impl FloatToInt < u128 > for f64 {
134
- fn cast ( self ) -> u128 {
135
- self as _
136
- }
137
- unsafe fn cast_unchecked ( self ) -> u128 {
138
- self . to_int_unchecked ( )
139
- }
140
- }
61
+ float_to_int ! ( f32 => i8 , u8 , i16 , u16 , i32 , u32 , i64 , u64 , i128 , u128 ) ;
62
+ float_to_int ! ( f64 => i8 , u8 , i16 , u16 , i32 , u32 , i64 , u64 , i128 , u128 ) ;
141
63
142
64
/// Test this cast both via `as` and via `approx_unchecked` (i.e., it must not saturate).
143
65
#[ track_caller]
@@ -153,18 +75,29 @@ where
153
75
154
76
fn basic ( ) {
155
77
// basic arithmetic
78
+ assert_eq ( 6.0_f16 * 6.0_f16 , 36.0_f16 ) ;
156
79
assert_eq ( 6.0_f32 * 6.0_f32 , 36.0_f32 ) ;
157
80
assert_eq ( 6.0_f64 * 6.0_f64 , 36.0_f64 ) ;
81
+ assert_eq ( 6.0_f128 * 6.0_f128 , 36.0_f128 ) ;
82
+ assert_eq ( -{ 5.0_f16 } , -5.0_f16 ) ;
158
83
assert_eq ( -{ 5.0_f32 } , -5.0_f32 ) ;
159
84
assert_eq ( -{ 5.0_f64 } , -5.0_f64 ) ;
85
+ assert_eq ( -{ 5.0_f128 } , -5.0_f128 ) ;
86
+
160
87
// infinities, NaN
88
+ // FIXME(f16_f128): add when constants and `is_infinite` are available
161
89
assert ! ( ( 5.0_f32 / 0.0 ) . is_infinite( ) ) ;
162
90
assert_ne ! ( { 5.0_f32 / 0.0 } , { -5.0_f32 / 0.0 } ) ;
163
91
assert ! ( ( 5.0_f64 / 0.0 ) . is_infinite( ) ) ;
164
92
assert_ne ! ( { 5.0_f64 / 0.0 } , { 5.0_f64 / -0.0 } ) ;
165
93
assert_ne ! ( f32 :: NAN , f32 :: NAN ) ;
166
94
assert_ne ! ( f64 :: NAN , f64 :: NAN ) ;
95
+
167
96
// negative zero
97
+ let posz = 0.0f16 ;
98
+ let negz = -0.0f16 ;
99
+ assert_eq ( posz, negz) ;
100
+ assert_ne ! ( posz. to_bits( ) , negz. to_bits( ) ) ;
168
101
let posz = 0.0f32 ;
169
102
let negz = -0.0f32 ;
170
103
assert_eq ( posz, negz) ;
@@ -173,15 +106,30 @@ fn basic() {
173
106
let negz = -0.0f64 ;
174
107
assert_eq ( posz, negz) ;
175
108
assert_ne ! ( posz. to_bits( ) , negz. to_bits( ) ) ;
109
+ let posz = 0.0f128 ;
110
+ let negz = -0.0f128 ;
111
+ assert_eq ( posz, negz) ;
112
+ assert_ne ! ( posz. to_bits( ) , negz. to_bits( ) ) ;
113
+
176
114
// byte-level transmute
177
- let x: u64 = unsafe { std:: mem:: transmute ( 42.0_f64 ) } ;
178
- let y: f64 = unsafe { std:: mem:: transmute ( x) } ;
179
- assert_eq ( y, 42.0_f64 ) ;
115
+ let x: u16 = unsafe { std:: mem:: transmute ( 42.0_f16 ) } ;
116
+ let y: f16 = unsafe { std:: mem:: transmute ( x) } ;
117
+ assert_eq ( y, 42.0_f16 ) ;
180
118
let x: u32 = unsafe { std:: mem:: transmute ( 42.0_f32 ) } ;
181
119
let y: f32 = unsafe { std:: mem:: transmute ( x) } ;
182
120
assert_eq ( y, 42.0_f32 ) ;
121
+ let x: u64 = unsafe { std:: mem:: transmute ( 42.0_f64 ) } ;
122
+ let y: f64 = unsafe { std:: mem:: transmute ( x) } ;
123
+ assert_eq ( y, 42.0_f64 ) ;
124
+ let x: u128 = unsafe { std:: mem:: transmute ( 42.0_f128 ) } ;
125
+ let y: f128 = unsafe { std:: mem:: transmute ( x) } ;
126
+ assert_eq ( y, 42.0_f128 ) ;
183
127
184
128
// `%` sign behavior, some of this used to be buggy
129
+ assert ! ( ( black_box( 1.0f16 ) % 1.0 ) . is_sign_positive( ) ) ;
130
+ assert ! ( ( black_box( 1.0f16 ) % -1.0 ) . is_sign_positive( ) ) ;
131
+ assert ! ( ( black_box( -1.0f16 ) % 1.0 ) . is_sign_negative( ) ) ;
132
+ assert ! ( ( black_box( -1.0f16 ) % -1.0 ) . is_sign_negative( ) ) ;
185
133
assert ! ( ( black_box( 1.0f32 ) % 1.0 ) . is_sign_positive( ) ) ;
186
134
assert ! ( ( black_box( 1.0f32 ) % -1.0 ) . is_sign_positive( ) ) ;
187
135
assert ! ( ( black_box( -1.0f32 ) % 1.0 ) . is_sign_negative( ) ) ;
@@ -190,7 +138,12 @@ fn basic() {
190
138
assert ! ( ( black_box( 1.0f64 ) % -1.0 ) . is_sign_positive( ) ) ;
191
139
assert ! ( ( black_box( -1.0f64 ) % 1.0 ) . is_sign_negative( ) ) ;
192
140
assert ! ( ( black_box( -1.0f64 ) % -1.0 ) . is_sign_negative( ) ) ;
141
+ assert ! ( ( black_box( 1.0f128 ) % 1.0 ) . is_sign_positive( ) ) ;
142
+ assert ! ( ( black_box( 1.0f128 ) % -1.0 ) . is_sign_positive( ) ) ;
143
+ assert ! ( ( black_box( -1.0f128 ) % 1.0 ) . is_sign_negative( ) ) ;
144
+ assert ! ( ( black_box( -1.0f128 ) % -1.0 ) . is_sign_negative( ) ) ;
193
145
146
+ // FIXME(f16_f128): add when `abs` is available
194
147
assert_eq ! ( ( -1.0f32 ) . abs( ) , 1.0f32 ) ;
195
148
assert_eq ! ( 34.2f64 . abs( ) , 34.2f64 ) ;
196
149
}
0 commit comments