@@ -100,14 +100,39 @@ mod f_to_i {
100100 use super :: * ;
101101
102102 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) ;* ; ) => {
104104 $(
105105 // 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) ;
109134 if conv0 != conv1 {
110- panic!( "{}({}): std: {}, builtins: {}" , stringify!( $fn) , $x, conv0, conv1) ;
135+ panic!( "{}({:? }): std: {:? }, builtins: {:? }" , stringify!( $fn) , $x, conv0, conv1) ;
111136 }
112137 }
113138 ) *
0 commit comments