11#![ feature( stmt_expr_attributes) ]
22#![ feature( float_gamma) ]
33#![ feature( core_intrinsics) ]
4+ #![ feature( f128) ]
5+ #![ feature( f16) ]
46#![ allow( arithmetic_overflow) ]
57
68use std:: fmt:: Debug ;
@@ -41,104 +43,43 @@ trait FloatToInt<Int>: Copy {
4143 unsafe fn cast_unchecked ( self ) -> Int ;
4244}
4345
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+ } ;
8359}
8460
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- }
61+ // FIXME(f16_f128): this is just used while we don't have `to_int_unchecked` on `f16` and `f128`.
62+ // Just use `float_to_int` once available.
63+ macro_rules! float_to_int_fallback {
64+ ( $fty: ty => $( $ity: ty) ,+ $( , ) ?) => {
65+ $(
66+ impl FloatToInt <$ity> for $fty {
67+ fn cast( self ) -> $ity {
68+ self as _
69+ }
70+ unsafe fn cast_unchecked( self ) -> $ity {
71+ self as _
72+ }
73+ }
74+ ) *
75+ } ;
14076}
14177
78+ float_to_int_fallback ! ( f16 => i8 , u8 , i16 , u16 , i32 , u32 , i64 , u64 , i128 , u128 ) ;
79+ float_to_int ! ( f32 => i8 , u8 , i16 , u16 , i32 , u32 , i64 , u64 , i128 , u128 ) ;
80+ float_to_int ! ( f64 => i8 , u8 , i16 , u16 , i32 , u32 , i64 , u64 , i128 , u128 ) ;
81+ float_to_int_fallback ! ( f128 => i8 , u8 , i16 , u16 , i32 , u32 , i64 , u64 , i128 , u128 ) ;
82+
14283/// Test this cast both via `as` and via `approx_unchecked` (i.e., it must not saturate).
14384#[ track_caller]
14485#[ inline( never) ]
@@ -153,18 +94,29 @@ where
15394
15495fn basic ( ) {
15596 // basic arithmetic
97+ assert_eq ( 6.0_f16 * 6.0_f16 , 36.0_f16 ) ;
15698 assert_eq ( 6.0_f32 * 6.0_f32 , 36.0_f32 ) ;
15799 assert_eq ( 6.0_f64 * 6.0_f64 , 36.0_f64 ) ;
100+ assert_eq ( 6.0_f128 * 6.0_f128 , 36.0_f128 ) ;
101+ assert_eq ( -{ 5.0_f16 } , -5.0_f16 ) ;
158102 assert_eq ( -{ 5.0_f32 } , -5.0_f32 ) ;
159103 assert_eq ( -{ 5.0_f64 } , -5.0_f64 ) ;
104+ assert_eq ( -{ 5.0_f128 } , -5.0_f128 ) ;
105+
160106 // infinities, NaN
107+ // FIXME(f16_f128): add when constants and `is_infinite` are available
161108 assert ! ( ( 5.0_f32 / 0.0 ) . is_infinite( ) ) ;
162109 assert_ne ! ( { 5.0_f32 / 0.0 } , { -5.0_f32 / 0.0 } ) ;
163110 assert ! ( ( 5.0_f64 / 0.0 ) . is_infinite( ) ) ;
164111 assert_ne ! ( { 5.0_f64 / 0.0 } , { 5.0_f64 / -0.0 } ) ;
165112 assert_ne ! ( f32 :: NAN , f32 :: NAN ) ;
166113 assert_ne ! ( f64 :: NAN , f64 :: NAN ) ;
114+
167115 // negative zero
116+ let posz = 0.0f16 ;
117+ let negz = -0.0f16 ;
118+ assert_eq ( posz, negz) ;
119+ assert_ne ! ( posz. to_bits( ) , negz. to_bits( ) ) ;
168120 let posz = 0.0f32 ;
169121 let negz = -0.0f32 ;
170122 assert_eq ( posz, negz) ;
@@ -173,15 +125,30 @@ fn basic() {
173125 let negz = -0.0f64 ;
174126 assert_eq ( posz, negz) ;
175127 assert_ne ! ( posz. to_bits( ) , negz. to_bits( ) ) ;
128+ let posz = 0.0f128 ;
129+ let negz = -0.0f128 ;
130+ assert_eq ( posz, negz) ;
131+ assert_ne ! ( posz. to_bits( ) , negz. to_bits( ) ) ;
132+
176133 // 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 ) ;
134+ let x: u16 = unsafe { std:: mem:: transmute ( 42.0_f16 ) } ;
135+ let y: f16 = unsafe { std:: mem:: transmute ( x) } ;
136+ assert_eq ( y, 42.0_f16 ) ;
180137 let x: u32 = unsafe { std:: mem:: transmute ( 42.0_f32 ) } ;
181138 let y: f32 = unsafe { std:: mem:: transmute ( x) } ;
182139 assert_eq ( y, 42.0_f32 ) ;
140+ let x: u64 = unsafe { std:: mem:: transmute ( 42.0_f64 ) } ;
141+ let y: f64 = unsafe { std:: mem:: transmute ( x) } ;
142+ assert_eq ( y, 42.0_f64 ) ;
143+ let x: u128 = unsafe { std:: mem:: transmute ( 42.0_f128 ) } ;
144+ let y: f128 = unsafe { std:: mem:: transmute ( x) } ;
145+ assert_eq ( y, 42.0_f128 ) ;
183146
184147 // `%` sign behavior, some of this used to be buggy
148+ assert ! ( ( black_box( 1.0f16 ) % 1.0 ) . is_sign_positive( ) ) ;
149+ assert ! ( ( black_box( 1.0f16 ) % -1.0 ) . is_sign_positive( ) ) ;
150+ assert ! ( ( black_box( -1.0f16 ) % 1.0 ) . is_sign_negative( ) ) ;
151+ assert ! ( ( black_box( -1.0f16 ) % -1.0 ) . is_sign_negative( ) ) ;
185152 assert ! ( ( black_box( 1.0f32 ) % 1.0 ) . is_sign_positive( ) ) ;
186153 assert ! ( ( black_box( 1.0f32 ) % -1.0 ) . is_sign_positive( ) ) ;
187154 assert ! ( ( black_box( -1.0f32 ) % 1.0 ) . is_sign_negative( ) ) ;
@@ -190,7 +157,12 @@ fn basic() {
190157 assert ! ( ( black_box( 1.0f64 ) % -1.0 ) . is_sign_positive( ) ) ;
191158 assert ! ( ( black_box( -1.0f64 ) % 1.0 ) . is_sign_negative( ) ) ;
192159 assert ! ( ( black_box( -1.0f64 ) % -1.0 ) . is_sign_negative( ) ) ;
160+ assert ! ( ( black_box( 1.0f128 ) % 1.0 ) . is_sign_positive( ) ) ;
161+ assert ! ( ( black_box( 1.0f128 ) % -1.0 ) . is_sign_positive( ) ) ;
162+ assert ! ( ( black_box( -1.0f128 ) % 1.0 ) . is_sign_negative( ) ) ;
163+ assert ! ( ( black_box( -1.0f128 ) % -1.0 ) . is_sign_negative( ) ) ;
193164
165+ // FIXME(f16_f128): add when `abs` is available
194166 assert_eq ! ( ( -1.0f32 ) . abs( ) , 1.0f32 ) ;
195167 assert_eq ! ( 34.2f64 . abs( ) , 34.2f64 ) ;
196168}
0 commit comments