@@ -100,14 +100,39 @@ mod f_to_i {
100
100
use super :: * ;
101
101
102
102
macro_rules! f_to_i {
103
- ( $x: ident, $( $f : ty, $fn: ident) ;* ; ) => {
103
+ ( $x: ident, $f_ty : ty , $apfloat_ty : ident , $sys_available : meta , $ ( $i_ty : ty, $fn: ident) ;* ; ) => {
104
104
$(
105
105
// it is undefined behavior in the first place to do conversions with NaNs
106
- if !$x. is_nan( ) {
107
- let conv0 = $x as $f;
108
- let conv1: $f = $fn( $x) ;
106
+ if !apfloat_fallback!(
107
+ $f_ty, $apfloat_ty, $sys_available, |x: FloatTy | x. is_nan( ) => no_convert, $x
108
+ ) {
109
+ let conv0 = apfloat_fallback!(
110
+ $f_ty, $apfloat_ty, $sys_available,
111
+ // Use an `as` cast when the builtin is available on the system.
112
+ |x| x as $i_ty;
113
+ // When the builtin is not available, we need to use a different conversion
114
+ // method (since apfloat doesn't support `as` casting).
115
+ |x: $f_ty| {
116
+ use compiler_builtins:: int:: MinInt ;
117
+
118
+ let apf = FloatTy :: from_bits( x. to_bits( ) . into( ) ) ;
119
+ let bits: usize = <$i_ty>:: BITS . try_into( ) . unwrap( ) ;
120
+
121
+ let err_fn = || panic!(
122
+ "Unable to convert value {x:?} to type {}:" , stringify!( $i_ty)
123
+ ) ;
124
+
125
+ if <$i_ty>:: SIGNED {
126
+ <$i_ty>:: try_from( apf. to_i128( bits) . value) . ok( ) . unwrap_or_else( err_fn)
127
+ } else {
128
+ <$i_ty>:: try_from( apf. to_u128( bits) . value) . ok( ) . unwrap_or_else( err_fn)
129
+ }
130
+ } ,
131
+ $x
132
+ ) ;
133
+ let conv1: $i_ty = $fn( $x) ;
109
134
if conv0 != conv1 {
110
- panic!( "{}({}): std: {}, builtins: {}" , stringify!( $fn) , $x, conv0, conv1) ;
135
+ panic!( "{}({:? }): std: {:? }, builtins: {:? }" , stringify!( $fn) , $x, conv0, conv1) ;
111
136
}
112
137
}
113
138
) *
0 commit comments