1
1
use float:: Float ;
2
2
use int:: { Int , CastInto } ;
3
3
4
- macro_rules! int_to_float {
5
- ( $i: expr, $ity: ty, $fty: ty) => ( {
6
- let i = $i;
7
- if i == 0 {
8
- return 0.0
9
- }
4
+ fn int_to_float < I : Int , F : Float > ( i : I ) -> F where
5
+ F :: Int : CastInto < u32 > ,
6
+ F :: Int : CastInto < I > ,
7
+ I :: UnsignedInt : CastInto < F :: Int > ,
8
+ u32 : CastInto < F :: Int > ,
9
+ {
10
+ if i == I :: ZERO {
11
+ return F :: ZERO ;
12
+ }
10
13
11
- let mant_dig = <$fty>:: SIGNIFICAND_BITS + 1 ;
12
- let exponent_bias = <$fty>:: EXPONENT_BIAS ;
14
+ let two = I :: UnsignedInt :: ONE + I :: UnsignedInt :: ONE ;
15
+ let four = two + two;
16
+ let mant_dig = F :: SIGNIFICAND_BITS + 1 ;
17
+ let exponent_bias = F :: EXPONENT_BIAS ;
13
18
14
- let n = <$ity> :: BITS ;
15
- let ( s, a) = i. extract_sign( ) ;
16
- let mut a = a;
19
+ let n = I :: BITS ;
20
+ let ( s, a) = i. extract_sign ( ) ;
21
+ let mut a = a;
17
22
18
- // number of significant digits
19
- let sd = n - a. leading_zeros( ) ;
23
+ // number of significant digits
24
+ let sd = n - a. leading_zeros ( ) ;
20
25
21
- // exponent
22
- let mut e = sd - 1 ;
26
+ // exponent
27
+ let mut e = sd - 1 ;
23
28
24
- if <$ity> :: BITS < mant_dig {
25
- return <$fty> :: from_parts( s,
26
- ( e + exponent_bias) as <$fty as Float > :: Int ,
27
- ( a as <$fty as Float > :: Int ) << ( mant_dig - e - 1 ) )
28
- }
29
+ if I :: BITS < mant_dig {
30
+ return F :: from_parts ( s,
31
+ ( e + exponent_bias) . cast ( ) ,
32
+ a . cast ( ) << ( mant_dig - e - 1 ) ) ;
33
+ }
29
34
30
- a = if sd > mant_dig {
31
- /* start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
32
- * finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR
33
- * 12345678901234567890123456
34
- * 1 = msb 1 bit
35
- * P = bit MANT_DIG-1 bits to the right of 1
36
- * Q = bit MANT_DIG bits to the right of 1
37
- * R = "or" of all bits to the right of Q
38
- */
39
- let mant_dig_plus_one = mant_dig + 1 ;
40
- let mant_dig_plus_two = mant_dig + 2 ;
41
- a = if sd == mant_dig_plus_one {
42
- a << 1
43
- } else if sd == mant_dig_plus_two {
44
- a
45
- } else {
46
- ( a >> ( sd - mant_dig_plus_two) ) as <$ity as Int >:: UnsignedInt |
47
- ( ( a & <$ity as Int >:: UnsignedInt :: max_value( ) ) . wrapping_shl( ( n + mant_dig_plus_two) - sd) != 0 ) as <$ity as Int >:: UnsignedInt
48
- } ;
49
-
50
- /* finish: */
51
- a |= ( ( a & 4 ) != 0 ) as <$ity as Int >:: UnsignedInt ; /* Or P into R */
52
- a += 1 ; /* round - this step may add a significant bit */
53
- a >>= 2 ; /* dump Q and R */
54
-
55
- /* a is now rounded to mant_dig or mant_dig+1 bits */
56
- if ( a & ( 1 << mant_dig) ) != 0 {
57
- a >>= 1 ; e += 1 ;
58
- }
35
+ a = if sd > mant_dig {
36
+ /* start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
37
+ * finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR
38
+ * 12345678901234567890123456
39
+ * 1 = msb 1 bit
40
+ * P = bit MANT_DIG-1 bits to the right of 1
41
+ * Q = bit MANT_DIG bits to the right of 1
42
+ * R = "or" of all bits to the right of Q
43
+ */
44
+ let mant_dig_plus_one = mant_dig + 1 ;
45
+ let mant_dig_plus_two = mant_dig + 2 ;
46
+ a = if sd == mant_dig_plus_one {
47
+ a << 1
48
+ } else if sd == mant_dig_plus_two {
59
49
a
60
- /* a is now rounded to mant_dig bits */
61
50
} else {
62
- a . wrapping_shl ( mant_dig - sd )
63
- /* a is now rounded to mant_dig bits */
51
+ ( a >> ( sd - mant_dig_plus_two ) ) |
52
+ Int :: from_bool ( ( a & I :: UnsignedInt :: max_value ( ) ) . wrapping_shl ( ( n + mant_dig_plus_two ) - sd ) != Int :: ZERO )
64
53
} ;
65
54
66
- <$fty>:: from_parts( s,
67
- ( e + exponent_bias) as <$fty as Float >:: Int ,
68
- a as <$fty as Float >:: Int )
69
- } )
55
+ /* finish: */
56
+ a |= Int :: from_bool ( ( a & four) != I :: UnsignedInt :: ZERO ) ; /* Or P into R */
57
+ a += Int :: ONE ; /* round - this step may add a significant bit */
58
+ a >>= 2 ; /* dump Q and R */
59
+
60
+ /* a is now rounded to mant_dig or mant_dig+1 bits */
61
+ if ( a & ( I :: UnsignedInt :: ONE << mant_dig) ) != Int :: ZERO {
62
+ a >>= 1 ; e += 1 ;
63
+ }
64
+ a
65
+ /* a is now rounded to mant_dig bits */
66
+ } else {
67
+ a. wrapping_shl ( mant_dig - sd)
68
+ /* a is now rounded to mant_dig bits */
69
+ } ;
70
+
71
+ F :: from_parts ( s,
72
+ ( e + exponent_bias) . cast ( ) ,
73
+ a. cast ( ) )
70
74
}
71
75
72
76
intrinsics ! {
73
77
#[ arm_aeabi_alias = __aeabi_i2f]
74
78
pub extern "C" fn __floatsisf( i: i32 ) -> f32 {
75
- int_to_float! ( i , i32 , f32 )
79
+ int_to_float( i )
76
80
}
77
81
78
82
#[ arm_aeabi_alias = __aeabi_i2d]
79
83
pub extern "C" fn __floatsidf( i: i32 ) -> f64 {
80
- int_to_float! ( i , i32 , f64 )
84
+ int_to_float( i )
81
85
}
82
86
83
87
#[ use_c_shim_if( all( target_arch = "x86" , not( target_env = "msvc" ) ) ) ]
@@ -88,46 +92,46 @@ intrinsics! {
88
92
if cfg!( target_arch = "x86_64" ) {
89
93
i as f64
90
94
} else {
91
- int_to_float! ( i , i64 , f64 )
95
+ int_to_float( i )
92
96
}
93
97
}
94
98
95
99
#[ unadjusted_on_win64]
96
100
pub extern "C" fn __floattisf( i: i128 ) -> f32 {
97
- int_to_float! ( i , i128 , f32 )
101
+ int_to_float( i )
98
102
}
99
103
100
104
#[ unadjusted_on_win64]
101
105
pub extern "C" fn __floattidf( i: i128 ) -> f64 {
102
- int_to_float! ( i , i128 , f64 )
106
+ int_to_float( i )
103
107
}
104
108
105
109
#[ arm_aeabi_alias = __aeabi_ui2f]
106
110
pub extern "C" fn __floatunsisf( i: u32 ) -> f32 {
107
- int_to_float! ( i , u32 , f32 )
111
+ int_to_float( i )
108
112
}
109
113
110
114
#[ arm_aeabi_alias = __aeabi_ui2d]
111
115
pub extern "C" fn __floatunsidf( i: u32 ) -> f64 {
112
- int_to_float! ( i , u32 , f64 )
116
+ int_to_float( i )
113
117
}
114
118
115
119
#[ use_c_shim_if( all( not( target_env = "msvc" ) ,
116
120
any( target_arch = "x86" ,
117
121
all( not( windows) , target_arch = "x86_64" ) ) ) ) ]
118
122
#[ arm_aeabi_alias = __aeabi_ul2d]
119
123
pub extern "C" fn __floatundidf( i: u64 ) -> f64 {
120
- int_to_float! ( i , u64 , f64 )
124
+ int_to_float( i )
121
125
}
122
126
123
127
#[ unadjusted_on_win64]
124
128
pub extern "C" fn __floatuntisf( i: u128 ) -> f32 {
125
- int_to_float! ( i , u128 , f32 )
129
+ int_to_float( i )
126
130
}
127
131
128
132
#[ unadjusted_on_win64]
129
133
pub extern "C" fn __floatuntidf( i: u128 ) -> f64 {
130
- int_to_float! ( i , u128 , f64 )
134
+ int_to_float( i )
131
135
}
132
136
}
133
137
0 commit comments