]>
Commit | Line | Data |
---|---|---|
923072b8 FG |
1 | /// Conversions from integers to floats. |
2 | /// | |
3 | /// These are hand-optimized bit twiddling code, | |
4 | /// which unfortunately isn't the easiest kind of code to read. | |
5 | /// | |
6 | /// The algorithm is explained here: https://blog.m-ou.se/floats/ | |
7 | mod int_to_float { | |
8 | pub fn u32_to_f32_bits(i: u32) -> u32 { | |
9 | if i == 0 { | |
10 | return 0; | |
17df50a5 | 11 | } |
923072b8 FG |
12 | let n = i.leading_zeros(); |
13 | let a = (i << n) >> 8; // Significant bits, with bit 24 still in tact. | |
14 | let b = (i << n) << 24; // Insignificant bits, only relevant for rounding. | |
15 | let m = a + ((b - (b >> 31 & !a)) >> 31); // Add one when we need to round up. Break ties to even. | |
2b03887a | 16 | let e = 157 - n; // Exponent plus 127, minus one. |
923072b8 | 17 | (e << 23) + m // + not |, so the mantissa can overflow into the exponent. |
041b39d2 XL |
18 | } |
19 | ||
923072b8 FG |
20 | pub fn u32_to_f64_bits(i: u32) -> u64 { |
21 | if i == 0 { | |
22 | return 0; | |
23 | } | |
24 | let n = i.leading_zeros(); | |
25 | let m = (i as u64) << (21 + n); // Significant bits, with bit 53 still in tact. | |
26 | let e = 1053 - n as u64; // Exponent plus 1023, minus one. | |
27 | (e << 52) + m // Bit 53 of m will overflow into e. | |
041b39d2 XL |
28 | } |
29 | ||
923072b8 FG |
30 | pub fn u64_to_f32_bits(i: u64) -> u32 { |
31 | let n = i.leading_zeros(); | |
32 | let y = i.wrapping_shl(n); | |
33 | let a = (y >> 40) as u32; // Significant bits, with bit 24 still in tact. | |
34 | let b = (y >> 8 | y & 0xFFFF) as u32; // Insignificant bits, only relevant for rounding. | |
35 | let m = a + ((b - (b >> 31 & !a)) >> 31); // Add one when we need to round up. Break ties to even. | |
36 | let e = if i == 0 { 0 } else { 189 - n }; // Exponent plus 127, minus one, except for zero. | |
37 | (e << 23) + m // + not |, so the mantissa can overflow into the exponent. | |
94b46f34 XL |
38 | } |
39 | ||
923072b8 FG |
40 | pub fn u64_to_f64_bits(i: u64) -> u64 { |
41 | if i == 0 { | |
42 | return 0; | |
041b39d2 | 43 | } |
923072b8 | 44 | let n = i.leading_zeros(); |
2b03887a FG |
45 | let a = (i << n) >> 11; // Significant bits, with bit 53 still in tact. |
46 | let b = (i << n) << 53; // Insignificant bits, only relevant for rounding. | |
923072b8 FG |
47 | let m = a + ((b - (b >> 63 & !a)) >> 63); // Add one when we need to round up. Break ties to even. |
48 | let e = 1085 - n as u64; // Exponent plus 1023, minus one. | |
49 | (e << 52) + m // + not |, so the mantissa can overflow into the exponent. | |
50 | } | |
51 | ||
52 | pub fn u128_to_f32_bits(i: u128) -> u32 { | |
53 | let n = i.leading_zeros(); | |
54 | let y = i.wrapping_shl(n); | |
55 | let a = (y >> 104) as u32; // Significant bits, with bit 24 still in tact. | |
56 | let b = (y >> 72) as u32 | ((y << 32) >> 32 != 0) as u32; // Insignificant bits, only relevant for rounding. | |
57 | let m = a + ((b - (b >> 31 & !a)) >> 31); // Add one when we need to round up. Break ties to even. | |
58 | let e = if i == 0 { 0 } else { 253 - n }; // Exponent plus 127, minus one, except for zero. | |
59 | (e << 23) + m // + not |, so the mantissa can overflow into the exponent. | |
60 | } | |
61 | ||
62 | pub fn u128_to_f64_bits(i: u128) -> u64 { | |
63 | let n = i.leading_zeros(); | |
64 | let y = i.wrapping_shl(n); | |
65 | let a = (y >> 75) as u64; // Significant bits, with bit 53 still in tact. | |
66 | let b = (y >> 11 | y & 0xFFFF_FFFF) as u64; // Insignificant bits, only relevant for rounding. | |
67 | let m = a + ((b - (b >> 63 & !a)) >> 63); // Add one when we need to round up. Break ties to even. | |
68 | let e = if i == 0 { 0 } else { 1149 - n as u64 }; // Exponent plus 1023, minus one, except for zero. | |
69 | (e << 52) + m // + not |, so the mantissa can overflow into the exponent. | |
041b39d2 | 70 | } |
923072b8 | 71 | } |
041b39d2 | 72 | |
923072b8 FG |
73 | // Conversions from unsigned integers to floats. |
74 | intrinsics! { | |
041b39d2 XL |
75 | #[arm_aeabi_alias = __aeabi_ui2f] |
76 | pub extern "C" fn __floatunsisf(i: u32) -> f32 { | |
923072b8 | 77 | f32::from_bits(int_to_float::u32_to_f32_bits(i)) |
041b39d2 XL |
78 | } |
79 | ||
80 | #[arm_aeabi_alias = __aeabi_ui2d] | |
81 | pub extern "C" fn __floatunsidf(i: u32) -> f64 { | |
923072b8 | 82 | f64::from_bits(int_to_float::u32_to_f64_bits(i)) |
041b39d2 XL |
83 | } |
84 | ||
94b46f34 XL |
85 | #[arm_aeabi_alias = __aeabi_ul2f] |
86 | pub extern "C" fn __floatundisf(i: u64) -> f32 { | |
923072b8 | 87 | f32::from_bits(int_to_float::u64_to_f32_bits(i)) |
94b46f34 XL |
88 | } |
89 | ||
041b39d2 XL |
90 | #[arm_aeabi_alias = __aeabi_ul2d] |
91 | pub extern "C" fn __floatundidf(i: u64) -> f64 { | |
923072b8 | 92 | f64::from_bits(int_to_float::u64_to_f64_bits(i)) |
041b39d2 | 93 | } |
041b39d2 | 94 | |
f2b60f7d | 95 | #[cfg_attr(any(not(target_feature = "llvm14-builtins-abi"), target_os = "uefi"), unadjusted_on_win64)] |
923072b8 FG |
96 | pub extern "C" fn __floatuntisf(i: u128) -> f32 { |
97 | f32::from_bits(int_to_float::u128_to_f32_bits(i)) | |
17df50a5 | 98 | } |
17df50a5 | 99 | |
f2b60f7d | 100 | #[cfg_attr(any(not(target_feature = "llvm14-builtins-abi"), target_os = "uefi"), unadjusted_on_win64)] |
923072b8 FG |
101 | pub extern "C" fn __floatuntidf(i: u128) -> f64 { |
102 | f64::from_bits(int_to_float::u128_to_f64_bits(i)) | |
17df50a5 | 103 | } |
041b39d2 XL |
104 | } |
105 | ||
923072b8 | 106 | // Conversions from signed integers to floats. |
041b39d2 | 107 | intrinsics! { |
923072b8 FG |
108 | #[arm_aeabi_alias = __aeabi_i2f] |
109 | pub extern "C" fn __floatsisf(i: i32) -> f32 { | |
110 | let sign_bit = ((i >> 31) as u32) << 31; | |
111 | f32::from_bits(int_to_float::u32_to_f32_bits(i.unsigned_abs()) | sign_bit) | |
041b39d2 XL |
112 | } |
113 | ||
923072b8 FG |
114 | #[arm_aeabi_alias = __aeabi_i2d] |
115 | pub extern "C" fn __floatsidf(i: i32) -> f64 { | |
116 | let sign_bit = ((i >> 31) as u64) << 63; | |
117 | f64::from_bits(int_to_float::u32_to_f64_bits(i.unsigned_abs()) | sign_bit) | |
041b39d2 XL |
118 | } |
119 | ||
923072b8 FG |
120 | #[arm_aeabi_alias = __aeabi_l2f] |
121 | pub extern "C" fn __floatdisf(i: i64) -> f32 { | |
122 | let sign_bit = ((i >> 63) as u32) << 31; | |
123 | f32::from_bits(int_to_float::u64_to_f32_bits(i.unsigned_abs()) | sign_bit) | |
041b39d2 XL |
124 | } |
125 | ||
923072b8 FG |
126 | #[arm_aeabi_alias = __aeabi_l2d] |
127 | pub extern "C" fn __floatdidf(i: i64) -> f64 { | |
128 | let sign_bit = ((i >> 63) as u64) << 63; | |
129 | f64::from_bits(int_to_float::u64_to_f64_bits(i.unsigned_abs()) | sign_bit) | |
041b39d2 | 130 | } |
5099ac24 | 131 | |
f2b60f7d | 132 | #[cfg_attr(any(not(target_feature = "llvm14-builtins-abi"), target_os = "uefi"), unadjusted_on_win64)] |
5099ac24 | 133 | pub extern "C" fn __floattisf(i: i128) -> f32 { |
923072b8 FG |
134 | let sign_bit = ((i >> 127) as u32) << 31; |
135 | f32::from_bits(int_to_float::u128_to_f32_bits(i.unsigned_abs()) | sign_bit) | |
5099ac24 FG |
136 | } |
137 | ||
f2b60f7d | 138 | #[cfg_attr(any(not(target_feature = "llvm14-builtins-abi"), target_os = "uefi"), unadjusted_on_win64)] |
5099ac24 | 139 | pub extern "C" fn __floattidf(i: i128) -> f64 { |
923072b8 FG |
140 | let sign_bit = ((i >> 127) as u64) << 63; |
141 | f64::from_bits(int_to_float::u128_to_f64_bits(i.unsigned_abs()) | sign_bit) | |
5099ac24 | 142 | } |
923072b8 | 143 | } |
5099ac24 | 144 | |
923072b8 FG |
145 | // Conversions from floats to unsigned integers. |
146 | intrinsics! { | |
147 | #[arm_aeabi_alias = __aeabi_f2uiz] | |
148 | pub extern "C" fn __fixunssfsi(f: f32) -> u32 { | |
149 | let fbits = f.to_bits(); | |
150 | if fbits < 127 << 23 { // >= 0, < 1 | |
151 | 0 | |
152 | } else if fbits < 159 << 23 { // >= 1, < max | |
153 | let m = 1 << 31 | fbits << 8; // Mantissa and the implicit 1-bit. | |
154 | let s = 158 - (fbits >> 23); // Shift based on the exponent and bias. | |
155 | m >> s | |
156 | } else if fbits <= 255 << 23 { // >= max (incl. inf) | |
157 | u32::MAX | |
158 | } else { // Negative or NaN | |
159 | 0 | |
160 | } | |
5099ac24 FG |
161 | } |
162 | ||
923072b8 FG |
163 | #[arm_aeabi_alias = __aeabi_f2ulz] |
164 | pub extern "C" fn __fixunssfdi(f: f32) -> u64 { | |
165 | let fbits = f.to_bits(); | |
166 | if fbits < 127 << 23 { // >= 0, < 1 | |
167 | 0 | |
168 | } else if fbits < 191 << 23 { // >= 1, < max | |
169 | let m = 1 << 63 | (fbits as u64) << 40; // Mantissa and the implicit 1-bit. | |
170 | let s = 190 - (fbits >> 23); // Shift based on the exponent and bias. | |
171 | m >> s | |
172 | } else if fbits <= 255 << 23 { // >= max (incl. inf) | |
173 | u64::MAX | |
174 | } else { // Negative or NaN | |
175 | 0 | |
176 | } | |
5099ac24 FG |
177 | } |
178 | ||
923072b8 FG |
179 | #[cfg_attr(target_feature = "llvm14-builtins-abi", win64_128bit_abi_hack)] |
180 | #[cfg_attr(not(target_feature = "llvm14-builtins-abi"), unadjusted_on_win64)] | |
181 | pub extern "C" fn __fixunssfti(f: f32) -> u128 { | |
182 | let fbits = f.to_bits(); | |
183 | if fbits < 127 << 23 { // >= 0, < 1 | |
184 | 0 | |
185 | } else if fbits < 255 << 23 { // >= 1, < inf | |
186 | let m = 1 << 127 | (fbits as u128) << 104; // Mantissa and the implicit 1-bit. | |
187 | let s = 254 - (fbits >> 23); // Shift based on the exponent and bias. | |
188 | m >> s | |
189 | } else if fbits == 255 << 23 { // == inf | |
190 | u128::MAX | |
191 | } else { // Negative or NaN | |
192 | 0 | |
193 | } | |
5099ac24 FG |
194 | } |
195 | ||
923072b8 FG |
196 | #[arm_aeabi_alias = __aeabi_d2uiz] |
197 | pub extern "C" fn __fixunsdfsi(f: f64) -> u32 { | |
198 | let fbits = f.to_bits(); | |
199 | if fbits < 1023 << 52 { // >= 0, < 1 | |
200 | 0 | |
201 | } else if fbits < 1055 << 52 { // >= 1, < max | |
202 | let m = 1 << 31 | (fbits >> 21) as u32; // Mantissa and the implicit 1-bit. | |
203 | let s = 1054 - (fbits >> 52); // Shift based on the exponent and bias. | |
204 | m >> s | |
205 | } else if fbits <= 2047 << 52 { // >= max (incl. inf) | |
206 | u32::MAX | |
207 | } else { // Negative or NaN | |
208 | 0 | |
209 | } | |
5099ac24 FG |
210 | } |
211 | ||
923072b8 FG |
212 | #[arm_aeabi_alias = __aeabi_d2ulz] |
213 | pub extern "C" fn __fixunsdfdi(f: f64) -> u64 { | |
214 | let fbits = f.to_bits(); | |
215 | if fbits < 1023 << 52 { // >= 0, < 1 | |
216 | 0 | |
217 | } else if fbits < 1087 << 52 { // >= 1, < max | |
218 | let m = 1 << 63 | fbits << 11; // Mantissa and the implicit 1-bit. | |
219 | let s = 1086 - (fbits >> 52); // Shift based on the exponent and bias. | |
220 | m >> s | |
221 | } else if fbits <= 2047 << 52 { // >= max (incl. inf) | |
222 | u64::MAX | |
223 | } else { // Negative or NaN | |
224 | 0 | |
225 | } | |
5099ac24 FG |
226 | } |
227 | ||
923072b8 FG |
228 | #[cfg_attr(target_feature = "llvm14-builtins-abi", win64_128bit_abi_hack)] |
229 | #[cfg_attr(not(target_feature = "llvm14-builtins-abi"), unadjusted_on_win64)] | |
5099ac24 | 230 | pub extern "C" fn __fixunsdfti(f: f64) -> u128 { |
923072b8 FG |
231 | let fbits = f.to_bits(); |
232 | if fbits < 1023 << 52 { // >= 0, < 1 | |
233 | 0 | |
234 | } else if fbits < 1151 << 52 { // >= 1, < max | |
235 | let m = 1 << 127 | (fbits as u128) << 75; // Mantissa and the implicit 1-bit. | |
236 | let s = 1150 - (fbits >> 52); // Shift based on the exponent and bias. | |
237 | m >> s | |
238 | } else if fbits <= 2047 << 52 { // >= max (incl. inf) | |
239 | u128::MAX | |
240 | } else { // Negative or NaN | |
241 | 0 | |
242 | } | |
5099ac24 FG |
243 | } |
244 | } | |
245 | ||
923072b8 | 246 | // Conversions from floats to signed integers. |
5099ac24 | 247 | intrinsics! { |
923072b8 FG |
248 | #[arm_aeabi_alias = __aeabi_f2iz] |
249 | pub extern "C" fn __fixsfsi(f: f32) -> i32 { | |
250 | let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. | |
251 | if fbits < 127 << 23 { // >= 0, < 1 | |
252 | 0 | |
253 | } else if fbits < 158 << 23 { // >= 1, < max | |
254 | let m = 1 << 31 | fbits << 8; // Mantissa and the implicit 1-bit. | |
255 | let s = 158 - (fbits >> 23); // Shift based on the exponent and bias. | |
256 | let u = (m >> s) as i32; // Unsigned result. | |
257 | if f.is_sign_negative() { -u } else { u } | |
258 | } else if fbits <= 255 << 23 { // >= max (incl. inf) | |
259 | if f.is_sign_negative() { i32::MIN } else { i32::MAX } | |
260 | } else { // NaN | |
261 | 0 | |
262 | } | |
5099ac24 FG |
263 | } |
264 | ||
923072b8 FG |
265 | #[arm_aeabi_alias = __aeabi_f2lz] |
266 | pub extern "C" fn __fixsfdi(f: f32) -> i64 { | |
267 | let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. | |
268 | if fbits < 127 << 23 { // >= 0, < 1 | |
269 | 0 | |
270 | } else if fbits < 190 << 23 { // >= 1, < max | |
271 | let m = 1 << 63 | (fbits as u64) << 40; // Mantissa and the implicit 1-bit. | |
272 | let s = 190 - (fbits >> 23); // Shift based on the exponent and bias. | |
273 | let u = (m >> s) as i64; // Unsigned result. | |
274 | if f.is_sign_negative() { -u } else { u } | |
275 | } else if fbits <= 255 << 23 { // >= max (incl. inf) | |
276 | if f.is_sign_negative() { i64::MIN } else { i64::MAX } | |
277 | } else { // NaN | |
278 | 0 | |
279 | } | |
5099ac24 FG |
280 | } |
281 | ||
923072b8 FG |
282 | #[cfg_attr(target_feature = "llvm14-builtins-abi", win64_128bit_abi_hack)] |
283 | #[cfg_attr(not(target_feature = "llvm14-builtins-abi"), unadjusted_on_win64)] | |
5099ac24 | 284 | pub extern "C" fn __fixsfti(f: f32) -> i128 { |
923072b8 FG |
285 | let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. |
286 | if fbits < 127 << 23 { // >= 0, < 1 | |
287 | 0 | |
288 | } else if fbits < 254 << 23 { // >= 1, < max | |
289 | let m = 1 << 127 | (fbits as u128) << 104; // Mantissa and the implicit 1-bit. | |
290 | let s = 254 - (fbits >> 23); // Shift based on the exponent and bias. | |
291 | let u = (m >> s) as i128; // Unsigned result. | |
292 | if f.is_sign_negative() { -u } else { u } | |
293 | } else if fbits <= 255 << 23 { // >= max (incl. inf) | |
294 | if f.is_sign_negative() { i128::MIN } else { i128::MAX } | |
295 | } else { // NaN | |
296 | 0 | |
297 | } | |
5099ac24 FG |
298 | } |
299 | ||
923072b8 FG |
300 | #[arm_aeabi_alias = __aeabi_d2iz] |
301 | pub extern "C" fn __fixdfsi(f: f64) -> i32 { | |
302 | let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. | |
303 | if fbits < 1023 << 52 { // >= 0, < 1 | |
304 | 0 | |
305 | } else if fbits < 1054 << 52 { // >= 1, < max | |
306 | let m = 1 << 31 | (fbits >> 21) as u32; // Mantissa and the implicit 1-bit. | |
307 | let s = 1054 - (fbits >> 52); // Shift based on the exponent and bias. | |
308 | let u = (m >> s) as i32; // Unsigned result. | |
309 | if f.is_sign_negative() { -u } else { u } | |
310 | } else if fbits <= 2047 << 52 { // >= max (incl. inf) | |
311 | if f.is_sign_negative() { i32::MIN } else { i32::MAX } | |
312 | } else { // NaN | |
313 | 0 | |
314 | } | |
5099ac24 FG |
315 | } |
316 | ||
923072b8 FG |
317 | #[arm_aeabi_alias = __aeabi_d2lz] |
318 | pub extern "C" fn __fixdfdi(f: f64) -> i64 { | |
319 | let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. | |
320 | if fbits < 1023 << 52 { // >= 0, < 1 | |
321 | 0 | |
322 | } else if fbits < 1086 << 52 { // >= 1, < max | |
323 | let m = 1 << 63 | fbits << 11; // Mantissa and the implicit 1-bit. | |
324 | let s = 1086 - (fbits >> 52); // Shift based on the exponent and bias. | |
325 | let u = (m >> s) as i64; // Unsigned result. | |
326 | if f.is_sign_negative() { -u } else { u } | |
327 | } else if fbits <= 2047 << 52 { // >= max (incl. inf) | |
328 | if f.is_sign_negative() { i64::MIN } else { i64::MAX } | |
329 | } else { // NaN | |
330 | 0 | |
331 | } | |
5099ac24 | 332 | } |
041b39d2 | 333 | |
923072b8 FG |
334 | #[cfg_attr(target_feature = "llvm14-builtins-abi", win64_128bit_abi_hack)] |
335 | #[cfg_attr(not(target_feature = "llvm14-builtins-abi"), unadjusted_on_win64)] | |
336 | pub extern "C" fn __fixdfti(f: f64) -> i128 { | |
337 | let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. | |
338 | if fbits < 1023 << 52 { // >= 0, < 1 | |
339 | 0 | |
340 | } else if fbits < 1150 << 52 { // >= 1, < max | |
341 | let m = 1 << 127 | (fbits as u128) << 75; // Mantissa and the implicit 1-bit. | |
342 | let s = 1150 - (fbits >> 52); // Shift based on the exponent and bias. | |
343 | let u = (m >> s) as i128; // Unsigned result. | |
344 | if f.is_sign_negative() { -u } else { u } | |
345 | } else if fbits <= 2047 << 52 { // >= max (incl. inf) | |
346 | if f.is_sign_negative() { i128::MIN } else { i128::MAX } | |
347 | } else { // NaN | |
348 | 0 | |
349 | } | |
041b39d2 XL |
350 | } |
351 | } |