1
1
use float:: Float ;
2
2
use int:: { Int , CastInto } ;
3
3
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
- }
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
+ }
13
10
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 ;
11
+ let mant_dig = <$fty>:: SIGNIFICAND_BITS + 1 ;
12
+ let exponent_bias = <$fty>:: EXPONENT_BIAS ;
18
13
19
- let n = I :: BITS ;
20
- let ( s, a) = i. extract_sign ( ) ;
21
- let mut a = a;
14
+ let n = <$ity> :: BITS ;
15
+ let ( s, a) = i. extract_sign( ) ;
16
+ let mut a = a;
22
17
23
- // number of significant digits
24
- let sd = n - a. leading_zeros ( ) ;
18
+ // number of significant digits
19
+ let sd = n - a. leading_zeros( ) ;
25
20
26
- // exponent
27
- let mut e = sd - 1 ;
21
+ // exponent
22
+ let mut e = sd - 1 ;
28
23
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
- }
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
+ }
34
29
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 {
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
+ }
49
59
a
60
+ /* a is now rounded to mant_dig bits */
50
61
} else {
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 )
62
+ a . wrapping_shl ( mant_dig - sd )
63
+ /* a is now rounded to mant_dig bits */
53
64
} ;
54
65
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 ( ) )
66
+ <$fty>:: from_parts( s,
67
+ ( e + exponent_bias) as <$fty as Float >:: Int ,
68
+ a as <$fty as Float >:: Int )
69
+ } )
74
70
}
75
71
76
72
intrinsics ! {
77
73
#[ arm_aeabi_alias = __aeabi_i2f]
78
74
pub extern "C" fn __floatsisf( i: i32 ) -> f32 {
79
- int_to_float( i )
75
+ int_to_float! ( i , i32 , f32 )
80
76
}
81
77
82
78
#[ arm_aeabi_alias = __aeabi_i2d]
83
79
pub extern "C" fn __floatsidf( i: i32 ) -> f64 {
84
- int_to_float( i )
80
+ int_to_float! ( i , i32 , f64 )
85
81
}
86
82
87
83
#[ use_c_shim_if( all( target_arch = "x86" , not( target_env = "msvc" ) ) ) ]
@@ -92,46 +88,46 @@ intrinsics! {
92
88
if cfg!( target_arch = "x86_64" ) {
93
89
i as f64
94
90
} else {
95
- int_to_float( i )
91
+ int_to_float! ( i , i64 , f64 )
96
92
}
97
93
}
98
94
99
95
#[ unadjusted_on_win64]
100
96
pub extern "C" fn __floattisf( i: i128 ) -> f32 {
101
- int_to_float( i )
97
+ int_to_float! ( i , i128 , f32 )
102
98
}
103
99
104
100
#[ unadjusted_on_win64]
105
101
pub extern "C" fn __floattidf( i: i128 ) -> f64 {
106
- int_to_float( i )
102
+ int_to_float! ( i , i128 , f64 )
107
103
}
108
104
109
105
#[ arm_aeabi_alias = __aeabi_ui2f]
110
106
pub extern "C" fn __floatunsisf( i: u32 ) -> f32 {
111
- int_to_float( i )
107
+ int_to_float! ( i , u32 , f32 )
112
108
}
113
109
114
110
#[ arm_aeabi_alias = __aeabi_ui2d]
115
111
pub extern "C" fn __floatunsidf( i: u32 ) -> f64 {
116
- int_to_float( i )
112
+ int_to_float! ( i , u32 , f64 )
117
113
}
118
114
119
115
#[ use_c_shim_if( all( not( target_env = "msvc" ) ,
120
116
any( target_arch = "x86" ,
121
117
all( not( windows) , target_arch = "x86_64" ) ) ) ) ]
122
118
#[ arm_aeabi_alias = __aeabi_ul2d]
123
119
pub extern "C" fn __floatundidf( i: u64 ) -> f64 {
124
- int_to_float( i )
120
+ int_to_float! ( i , u64 , f64 )
125
121
}
126
122
127
123
#[ unadjusted_on_win64]
128
124
pub extern "C" fn __floatuntisf( i: u128 ) -> f32 {
129
- int_to_float( i )
125
+ int_to_float! ( i , u128 , f32 )
130
126
}
131
127
132
128
#[ unadjusted_on_win64]
133
129
pub extern "C" fn __floatuntidf( i: u128 ) -> f64 {
134
- int_to_float( i )
130
+ int_to_float! ( i , u128 , f64 )
135
131
}
136
132
}
137
133
0 commit comments