1
1
use float:: Float ;
2
- use int:: { Int , CastInto } ;
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
- }
2
+ use int:: Int ;
13
3
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 ;
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
+ }
18
10
19
- let n = I :: BITS ;
20
- let ( s, a) = i. extract_sign ( ) ;
21
- let mut a = a;
11
+ let mant_dig = <$fty>:: SIGNIFICAND_BITS + 1 ;
12
+ let exponent_bias = <$fty>:: EXPONENT_BIAS ;
22
13
23
- // number of significant digits
24
- let sd = n - a. leading_zeros ( ) ;
14
+ let n = <$ity>:: BITS ;
15
+ let ( s, a) = i. extract_sign( ) ;
16
+ let mut a = a;
25
17
26
- // exponent
27
- let mut e = sd - 1 ;
18
+ // number of significant digits
19
+ let sd = n - a . leading_zeros ( ) ;
28
20
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
- }
21
+ // exponent
22
+ let mut e = sd - 1 ;
23
+
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
@@ -141,116 +137,115 @@ enum Sign {
141
137
Negative
142
138
}
143
139
144
- fn float_to_int < F : Float , I : Int > ( f : F ) -> I where
145
- F :: Int : CastInto < u32 > ,
146
- F :: Int : CastInto < I > ,
147
- {
148
- let f = f;
149
- let fixint_min = I :: min_value ( ) ;
150
- let fixint_max = I :: max_value ( ) ;
151
- let fixint_bits = I :: BITS ;
152
- let fixint_unsigned = fixint_min == I :: ZERO ;
153
-
154
- let sign_bit = F :: SIGN_MASK ;
155
- let significand_bits = F :: SIGNIFICAND_BITS ;
156
- let exponent_bias = F :: EXPONENT_BIAS ;
157
- //let exponent_max = F::exponent_max() as usize;
158
-
159
- // Break a into sign, exponent, significand
160
- let a_rep = F :: repr ( f) ;
161
- let a_abs = a_rep & !sign_bit;
162
-
163
- // this is used to work around -1 not being available for unsigned
164
- let sign = if ( a_rep & sign_bit) == F :: Int :: ZERO { Sign :: Positive } else { Sign :: Negative } ;
165
- let mut exponent: u32 = ( a_abs >> significand_bits) . cast ( ) ;
166
- let significand = ( a_abs & F :: SIGNIFICAND_MASK ) | F :: IMPLICIT_BIT ;
167
-
168
- // if < 1 or unsigned & negative
169
- if exponent < exponent_bias ||
170
- fixint_unsigned && sign == Sign :: Negative {
171
- return I :: ZERO ;
172
- }
173
- exponent -= exponent_bias;
140
+ macro_rules! float_to_int {
141
+ ( $f: expr, $fty: ty, $ity: ty) => ( {
142
+ let f = $f;
143
+ let fixint_min = <$ity>:: min_value( ) ;
144
+ let fixint_max = <$ity>:: max_value( ) ;
145
+ let fixint_bits = <$ity>:: BITS as usize ;
146
+ let fixint_unsigned = fixint_min == 0 ;
147
+
148
+ let sign_bit = <$fty>:: SIGN_MASK ;
149
+ let significand_bits = <$fty>:: SIGNIFICAND_BITS as usize ;
150
+ let exponent_bias = <$fty>:: EXPONENT_BIAS as usize ;
151
+ //let exponent_max = <$fty>::exponent_max() as usize;
152
+
153
+ // Break a into sign, exponent, significand
154
+ let a_rep = <$fty>:: repr( f) ;
155
+ let a_abs = a_rep & !sign_bit;
156
+
157
+ // this is used to work around -1 not being available for unsigned
158
+ let sign = if ( a_rep & sign_bit) == 0 { Sign :: Positive } else { Sign :: Negative } ;
159
+ let mut exponent = ( a_abs >> significand_bits) as usize ;
160
+ let significand = ( a_abs & <$fty>:: SIGNIFICAND_MASK ) | <$fty>:: IMPLICIT_BIT ;
161
+
162
+ // if < 1 or unsigned & negative
163
+ if exponent < exponent_bias ||
164
+ fixint_unsigned && sign == Sign :: Negative {
165
+ return 0
166
+ }
167
+ exponent -= exponent_bias;
174
168
175
- // If the value is infinity, saturate.
176
- // If the value is too large for the integer type, 0.
177
- if exponent >= ( if fixint_unsigned { fixint_bits} else { fixint_bits -1 } ) {
178
- return if sign == Sign :: Positive { fixint_max} else { fixint_min}
179
- }
180
- // If 0 <= exponent < significand_bits, right shift to get the result.
181
- // Otherwise, shift left.
182
- // (sign - 1) will never overflow as negative signs are already returned as 0 for unsigned
183
- let r: I = if exponent < significand_bits {
184
- ( significand >> ( significand_bits - exponent) ) . cast ( )
185
- } else {
186
- ( significand << ( exponent - significand_bits) ) . cast ( )
187
- } ;
188
-
189
- if sign == Sign :: Negative {
190
- ( !r) . wrapping_add ( I :: ONE )
191
- } else {
192
- r
193
- }
169
+ // If the value is infinity, saturate.
170
+ // If the value is too large for the integer type, 0.
171
+ if exponent >= ( if fixint_unsigned { fixint_bits} else { fixint_bits -1 } ) {
172
+ return if sign == Sign :: Positive { fixint_max} else { fixint_min}
173
+ }
174
+ // If 0 <= exponent < significand_bits, right shift to get the result.
175
+ // Otherwise, shift left.
176
+ // (sign - 1) will never overflow as negative signs are already returned as 0 for unsigned
177
+ let r = if exponent < significand_bits {
178
+ ( significand >> ( significand_bits - exponent) ) as $ity
179
+ } else {
180
+ ( significand as $ity) << ( exponent - significand_bits)
181
+ } ;
182
+
183
+ if sign == Sign :: Negative {
184
+ ( !r) . wrapping_add( 1 )
185
+ } else {
186
+ r
187
+ }
188
+ } )
194
189
}
195
190
196
191
intrinsics ! {
197
192
#[ arm_aeabi_alias = __aeabi_f2iz]
198
193
pub extern "C" fn __fixsfsi( f: f32 ) -> i32 {
199
- float_to_int( f )
194
+ float_to_int! ( f , f32 , i32 )
200
195
}
201
196
202
197
#[ arm_aeabi_alias = __aeabi_f2lz]
203
198
pub extern "C" fn __fixsfdi( f: f32 ) -> i64 {
204
- float_to_int( f )
199
+ float_to_int! ( f , f32 , i64 )
205
200
}
206
201
207
202
#[ unadjusted_on_win64]
208
203
pub extern "C" fn __fixsfti( f: f32 ) -> i128 {
209
- float_to_int( f )
204
+ float_to_int! ( f , f32 , i128 )
210
205
}
211
206
212
207
#[ arm_aeabi_alias = __aeabi_d2iz]
213
208
pub extern "C" fn __fixdfsi( f: f64 ) -> i32 {
214
- float_to_int( f )
209
+ float_to_int! ( f , f64 , i32 )
215
210
}
216
211
217
212
#[ arm_aeabi_alias = __aeabi_d2lz]
218
213
pub extern "C" fn __fixdfdi( f: f64 ) -> i64 {
219
- float_to_int( f )
214
+ float_to_int! ( f , f64 , i64 )
220
215
}
221
216
222
217
#[ unadjusted_on_win64]
223
218
pub extern "C" fn __fixdfti( f: f64 ) -> i128 {
224
- float_to_int( f )
219
+ float_to_int! ( f , f64 , i128 )
225
220
}
226
221
227
222
#[ arm_aeabi_alias = __aeabi_f2uiz]
228
223
pub extern "C" fn __fixunssfsi( f: f32 ) -> u32 {
229
- float_to_int( f )
224
+ float_to_int! ( f , f32 , u32 )
230
225
}
231
226
232
227
#[ arm_aeabi_alias = __aeabi_f2ulz]
233
228
pub extern "C" fn __fixunssfdi( f: f32 ) -> u64 {
234
- float_to_int( f )
229
+ float_to_int! ( f , f32 , u64 )
235
230
}
236
231
237
232
#[ unadjusted_on_win64]
238
233
pub extern "C" fn __fixunssfti( f: f32 ) -> u128 {
239
- float_to_int( f )
234
+ float_to_int! ( f , f32 , u128 )
240
235
}
241
236
242
237
#[ arm_aeabi_alias = __aeabi_d2uiz]
243
238
pub extern "C" fn __fixunsdfsi( f: f64 ) -> u32 {
244
- float_to_int( f )
239
+ float_to_int! ( f , f64 , u32 )
245
240
}
246
241
247
242
#[ arm_aeabi_alias = __aeabi_d2ulz]
248
243
pub extern "C" fn __fixunsdfdi( f: f64 ) -> u64 {
249
- float_to_int( f )
244
+ float_to_int! ( f , f64 , u64 )
250
245
}
251
246
252
247
#[ unadjusted_on_win64]
253
248
pub extern "C" fn __fixunsdfti( f: f64 ) -> u128 {
254
- float_to_int( f )
249
+ float_to_int! ( f , f64 , u128 )
255
250
}
256
251
}
0 commit comments