|
1 |
| -use float::Float; |
2 |
| -use int::Int; |
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 |
| - } |
10 |
| - |
11 |
| - let mant_dig = <$fty>::SIGNIFICAND_BITS + 1; |
12 |
| - let exponent_bias = <$fty>::EXPONENT_BIAS; |
13 |
| - |
14 |
| - let n = <$ity>::BITS; |
15 |
| - let (s, a) = i.extract_sign(); |
16 |
| - let mut a = a; |
17 |
| - |
18 |
| - // number of significant digits |
19 |
| - let sd = n - a.leading_zeros(); |
20 |
| - |
21 |
| - // exponent |
22 |
| - let mut e = sd - 1; |
23 |
| - |
24 |
| - if <$ity>::BITS < mant_dig { |
25 |
| - return <$fty>::from_parts( |
26 |
| - s, |
27 |
| - (e + exponent_bias) as <$fty as Float>::Int, |
28 |
| - (a as <$fty as Float>::Int) << (mant_dig - e - 1), |
29 |
| - ); |
30 |
| - } |
31 |
| - |
32 |
| - a = if sd > mant_dig { |
33 |
| - /* start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx |
34 |
| - * finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR |
35 |
| - * 12345678901234567890123456 |
36 |
| - * 1 = msb 1 bit |
37 |
| - * P = bit MANT_DIG-1 bits to the right of 1 |
38 |
| - * Q = bit MANT_DIG bits to the right of 1 |
39 |
| - * R = "or" of all bits to the right of Q |
40 |
| - */ |
41 |
| - let mant_dig_plus_one = mant_dig + 1; |
42 |
| - let mant_dig_plus_two = mant_dig + 2; |
43 |
| - a = if sd == mant_dig_plus_one { |
44 |
| - a << 1 |
45 |
| - } else if sd == mant_dig_plus_two { |
46 |
| - a |
47 |
| - } else { |
48 |
| - (a >> (sd - mant_dig_plus_two)) as <$ity as Int>::UnsignedInt |
49 |
| - | ((a & <$ity as Int>::UnsignedInt::max_value()) |
50 |
| - .wrapping_shl((n + mant_dig_plus_two) - sd) |
51 |
| - != 0) as <$ity as Int>::UnsignedInt |
52 |
| - }; |
53 |
| - |
54 |
| - /* finish: */ |
55 |
| - a |= ((a & 4) != 0) as <$ity as Int>::UnsignedInt; /* Or P into R */ |
56 |
| - a += 1; /* round - this step may add a significant bit */ |
57 |
| - a >>= 2; /* dump Q and R */ |
58 |
| - |
59 |
| - /* a is now rounded to mant_dig or mant_dig+1 bits */ |
60 |
| - if (a & (1 << mant_dig)) != 0 { |
61 |
| - a >>= 1; |
62 |
| - 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 |
| - <$fty>::from_parts( |
72 |
| - s, |
73 |
| - (e + exponent_bias) as <$fty as Float>::Int, |
74 |
| - a as <$fty as Float>::Int, |
75 |
| - ) |
76 |
| - }}; |
77 |
| -} |
78 |
| - |
79 | 1 | intrinsics! {
|
80 | 2 | #[arm_aeabi_alias = __aeabi_i2f]
|
81 | 3 | pub extern "C" fn __floatsisf(i: i32) -> f32 {
|
82 |
| - int_to_float!(i, i32, f32) |
| 4 | + floatconv::fast::i32_to_f32_round(i) |
83 | 5 | }
|
84 | 6 |
|
85 | 7 | #[arm_aeabi_alias = __aeabi_i2d]
|
86 | 8 | pub extern "C" fn __floatsidf(i: i32) -> f64 {
|
87 |
| - int_to_float!(i, i32, f64) |
| 9 | + floatconv::fast::i32_to_f64(i) |
88 | 10 | }
|
89 | 11 |
|
90 |
| - #[maybe_use_optimized_c_shim] |
91 | 12 | #[arm_aeabi_alias = __aeabi_l2f]
|
92 | 13 | pub extern "C" fn __floatdisf(i: i64) -> f32 {
|
93 |
| - // On x86_64 LLVM will use native instructions for this conversion, we |
94 |
| - // can just do it directly |
95 |
| - if cfg!(target_arch = "x86_64") { |
96 |
| - i as f32 |
97 |
| - } else { |
98 |
| - int_to_float!(i, i64, f32) |
99 |
| - } |
| 14 | + floatconv::fast::i64_to_f32_round(i) |
100 | 15 | }
|
101 | 16 |
|
102 |
| - #[maybe_use_optimized_c_shim] |
103 | 17 | #[arm_aeabi_alias = __aeabi_l2d]
|
104 | 18 | pub extern "C" fn __floatdidf(i: i64) -> f64 {
|
105 |
| - // On x86_64 LLVM will use native instructions for this conversion, we |
106 |
| - // can just do it directly |
107 |
| - if cfg!(target_arch = "x86_64") { |
108 |
| - i as f64 |
109 |
| - } else { |
110 |
| - int_to_float!(i, i64, f64) |
111 |
| - } |
| 19 | + floatconv::fast::i64_to_f64_round(i) |
112 | 20 | }
|
113 | 21 |
|
114 | 22 | #[unadjusted_on_win64]
|
115 | 23 | pub extern "C" fn __floattisf(i: i128) -> f32 {
|
116 |
| - int_to_float!(i, i128, f32) |
| 24 | + floatconv::fast::i128_to_f32_round(i) |
117 | 25 | }
|
118 | 26 |
|
119 | 27 | #[unadjusted_on_win64]
|
120 | 28 | pub extern "C" fn __floattidf(i: i128) -> f64 {
|
121 |
| - int_to_float!(i, i128, f64) |
| 29 | + floatconv::fast::i128_to_f64_round(i) |
122 | 30 | }
|
123 | 31 |
|
124 | 32 | #[arm_aeabi_alias = __aeabi_ui2f]
|
125 | 33 | pub extern "C" fn __floatunsisf(i: u32) -> f32 {
|
126 |
| - int_to_float!(i, u32, f32) |
| 34 | + floatconv::fast::u32_to_f32_round(i) |
127 | 35 | }
|
128 | 36 |
|
129 | 37 | #[arm_aeabi_alias = __aeabi_ui2d]
|
130 | 38 | pub extern "C" fn __floatunsidf(i: u32) -> f64 {
|
131 |
| - int_to_float!(i, u32, f64) |
| 39 | + floatconv::fast::u32_to_f64(i) |
132 | 40 | }
|
133 | 41 |
|
134 |
| - #[maybe_use_optimized_c_shim] |
135 | 42 | #[arm_aeabi_alias = __aeabi_ul2f]
|
136 | 43 | pub extern "C" fn __floatundisf(i: u64) -> f32 {
|
137 |
| - int_to_float!(i, u64, f32) |
| 44 | + floatconv::fast::u64_to_f32_round(i) |
138 | 45 | }
|
139 | 46 |
|
140 |
| - #[maybe_use_optimized_c_shim] |
141 | 47 | #[arm_aeabi_alias = __aeabi_ul2d]
|
142 | 48 | pub extern "C" fn __floatundidf(i: u64) -> f64 {
|
143 |
| - int_to_float!(i, u64, f64) |
| 49 | + floatconv::fast::u64_to_f64_round(i) |
144 | 50 | }
|
145 | 51 |
|
146 | 52 | #[unadjusted_on_win64]
|
147 | 53 | pub extern "C" fn __floatuntisf(i: u128) -> f32 {
|
148 |
| - int_to_float!(i, u128, f32) |
| 54 | + floatconv::fast::u128_to_f32_round(i) |
149 | 55 | }
|
150 | 56 |
|
151 | 57 | #[unadjusted_on_win64]
|
152 | 58 | pub extern "C" fn __floatuntidf(i: u128) -> f64 {
|
153 |
| - int_to_float!(i, u128, f64) |
| 59 | + floatconv::fast::u128_to_f64_round(i) |
154 | 60 | }
|
155 |
| -} |
156 |
| - |
157 |
| -#[derive(PartialEq)] |
158 |
| -enum Sign { |
159 |
| - Positive, |
160 |
| - Negative, |
161 |
| -} |
162 |
| - |
163 |
| -macro_rules! float_to_int { |
164 |
| - ($f:expr, $fty:ty, $ity:ty) => {{ |
165 |
| - let f = $f; |
166 |
| - let fixint_min = <$ity>::min_value(); |
167 |
| - let fixint_max = <$ity>::max_value(); |
168 |
| - let fixint_bits = <$ity>::BITS as usize; |
169 |
| - let fixint_unsigned = fixint_min == 0; |
170 |
| - |
171 |
| - let sign_bit = <$fty>::SIGN_MASK; |
172 |
| - let significand_bits = <$fty>::SIGNIFICAND_BITS as usize; |
173 |
| - let exponent_bias = <$fty>::EXPONENT_BIAS as usize; |
174 |
| - //let exponent_max = <$fty>::exponent_max() as usize; |
175 |
| - |
176 |
| - // Break a into sign, exponent, significand |
177 |
| - let a_rep = <$fty>::repr(f); |
178 |
| - let a_abs = a_rep & !sign_bit; |
179 | 61 |
|
180 |
| - // this is used to work around -1 not being available for unsigned |
181 |
| - let sign = if (a_rep & sign_bit) == 0 { |
182 |
| - Sign::Positive |
183 |
| - } else { |
184 |
| - Sign::Negative |
185 |
| - }; |
186 |
| - let mut exponent = (a_abs >> significand_bits) as usize; |
187 |
| - let significand = (a_abs & <$fty>::SIGNIFICAND_MASK) | <$fty>::IMPLICIT_BIT; |
188 |
| - |
189 |
| - // if < 1 or unsigned & negative |
190 |
| - if exponent < exponent_bias || fixint_unsigned && sign == Sign::Negative { |
191 |
| - return 0; |
192 |
| - } |
193 |
| - exponent -= exponent_bias; |
194 |
| - |
195 |
| - // If the value is infinity, saturate. |
196 |
| - // If the value is too large for the integer type, 0. |
197 |
| - if exponent |
198 |
| - >= (if fixint_unsigned { |
199 |
| - fixint_bits |
200 |
| - } else { |
201 |
| - fixint_bits - 1 |
202 |
| - }) |
203 |
| - { |
204 |
| - return if sign == Sign::Positive { |
205 |
| - fixint_max |
206 |
| - } else { |
207 |
| - fixint_min |
208 |
| - }; |
209 |
| - } |
210 |
| - // If 0 <= exponent < significand_bits, right shift to get the result. |
211 |
| - // Otherwise, shift left. |
212 |
| - // (sign - 1) will never overflow as negative signs are already returned as 0 for unsigned |
213 |
| - let r = if exponent < significand_bits { |
214 |
| - (significand >> (significand_bits - exponent)) as $ity |
215 |
| - } else { |
216 |
| - (significand as $ity) << (exponent - significand_bits) |
217 |
| - }; |
218 |
| - |
219 |
| - if sign == Sign::Negative { |
220 |
| - (!r).wrapping_add(1) |
221 |
| - } else { |
222 |
| - r |
223 |
| - } |
224 |
| - }}; |
225 |
| -} |
226 |
| - |
227 |
| -intrinsics! { |
228 | 62 | #[arm_aeabi_alias = __aeabi_f2iz]
|
229 | 63 | pub extern "C" fn __fixsfsi(f: f32) -> i32 {
|
230 |
| - float_to_int!(f, f32, i32) |
| 64 | + floatconv::fast::f32_to_i32(f) |
231 | 65 | }
|
232 | 66 |
|
233 | 67 | #[arm_aeabi_alias = __aeabi_f2lz]
|
234 | 68 | pub extern "C" fn __fixsfdi(f: f32) -> i64 {
|
235 |
| - float_to_int!(f, f32, i64) |
| 69 | + floatconv::fast::f32_to_i64(f) |
236 | 70 | }
|
237 | 71 |
|
238 | 72 | #[unadjusted_on_win64]
|
239 | 73 | pub extern "C" fn __fixsfti(f: f32) -> i128 {
|
240 |
| - float_to_int!(f, f32, i128) |
| 74 | + floatconv::fast::f32_to_i128(f) |
241 | 75 | }
|
242 | 76 |
|
243 | 77 | #[arm_aeabi_alias = __aeabi_d2iz]
|
244 | 78 | pub extern "C" fn __fixdfsi(f: f64) -> i32 {
|
245 |
| - float_to_int!(f, f64, i32) |
| 79 | + floatconv::fast::f64_to_i32(f) |
246 | 80 | }
|
247 | 81 |
|
248 | 82 | #[arm_aeabi_alias = __aeabi_d2lz]
|
249 | 83 | pub extern "C" fn __fixdfdi(f: f64) -> i64 {
|
250 |
| - float_to_int!(f, f64, i64) |
| 84 | + floatconv::fast::f64_to_i64(f) |
251 | 85 | }
|
252 | 86 |
|
253 | 87 | #[unadjusted_on_win64]
|
254 | 88 | pub extern "C" fn __fixdfti(f: f64) -> i128 {
|
255 |
| - float_to_int!(f, f64, i128) |
| 89 | + floatconv::fast::f64_to_i128(f) |
256 | 90 | }
|
257 | 91 |
|
258 | 92 | #[arm_aeabi_alias = __aeabi_f2uiz]
|
259 | 93 | pub extern "C" fn __fixunssfsi(f: f32) -> u32 {
|
260 |
| - float_to_int!(f, f32, u32) |
| 94 | + floatconv::fast::f32_to_u32(f) |
261 | 95 | }
|
262 | 96 |
|
263 | 97 | #[arm_aeabi_alias = __aeabi_f2ulz]
|
264 | 98 | pub extern "C" fn __fixunssfdi(f: f32) -> u64 {
|
265 |
| - float_to_int!(f, f32, u64) |
| 99 | + floatconv::fast::f32_to_u64(f) |
266 | 100 | }
|
267 | 101 |
|
268 | 102 | #[unadjusted_on_win64]
|
269 | 103 | pub extern "C" fn __fixunssfti(f: f32) -> u128 {
|
270 |
| - float_to_int!(f, f32, u128) |
| 104 | + floatconv::fast::f32_to_u128(f) |
271 | 105 | }
|
272 | 106 |
|
273 | 107 | #[arm_aeabi_alias = __aeabi_d2uiz]
|
274 | 108 | pub extern "C" fn __fixunsdfsi(f: f64) -> u32 {
|
275 |
| - float_to_int!(f, f64, u32) |
| 109 | + floatconv::fast::f64_to_u32(f) |
276 | 110 | }
|
277 | 111 |
|
278 | 112 | #[arm_aeabi_alias = __aeabi_d2ulz]
|
279 | 113 | pub extern "C" fn __fixunsdfdi(f: f64) -> u64 {
|
280 |
| - float_to_int!(f, f64, u64) |
| 114 | + floatconv::fast::f64_to_u64(f) |
281 | 115 | }
|
282 | 116 |
|
283 | 117 | #[unadjusted_on_win64]
|
284 | 118 | pub extern "C" fn __fixunsdfti(f: f64) -> u128 {
|
285 |
| - float_to_int!(f, f64, u128) |
| 119 | + floatconv::fast::f64_to_u128(f) |
286 | 120 | }
|
287 | 121 | }
|
0 commit comments