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; |
11 | } |
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. |
16 | let e = 157 - n; // Exponent plus 127, minus one. |
17 | (e << 23) + m // + not |, so the mantissa can overflow into the exponent. |
18 | } |
19 | |
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. |
28 | } |
29 | |
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. |
38 | } |
39 | |
40 | pub fn u64_to_f64_bits(i: u64) -> u64 { |
41 | if i == 0 { |
42 | return 0; |
43 | } |
44 | let n = i.leading_zeros(); |
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. |
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. |
70 | } |
71 | } |
72 | |
73 | // Conversions from unsigned integers to floats. |
74 | intrinsics! { |
75 | #[arm_aeabi_alias = __aeabi_ui2f] |
76 | pub extern "C" fn __floatunsisf(i: u32) -> f32 { |
77 | f32::from_bits(int_to_float::u32_to_f32_bits(i)) |
78 | } |
79 | |
80 | #[arm_aeabi_alias = __aeabi_ui2d] |
81 | pub extern "C" fn __floatunsidf(i: u32) -> f64 { |
82 | f64::from_bits(int_to_float::u32_to_f64_bits(i)) |
83 | } |
84 | |
85 | #[arm_aeabi_alias = __aeabi_ul2f] |
86 | pub extern "C" fn __floatundisf(i: u64) -> f32 { |
87 | f32::from_bits(int_to_float::u64_to_f32_bits(i)) |
88 | } |
89 | |
90 | #[arm_aeabi_alias = __aeabi_ul2d] |
91 | pub extern "C" fn __floatundidf(i: u64) -> f64 { |
92 | f64::from_bits(int_to_float::u64_to_f64_bits(i)) |
93 | } |
94 | |
95 | #[cfg_attr(target_os = "uefi" , unadjusted_on_win64)] |
96 | pub extern "C" fn __floatuntisf(i: u128) -> f32 { |
97 | f32::from_bits(int_to_float::u128_to_f32_bits(i)) |
98 | } |
99 | |
100 | #[cfg_attr(target_os = "uefi" , unadjusted_on_win64)] |
101 | pub extern "C" fn __floatuntidf(i: u128) -> f64 { |
102 | f64::from_bits(int_to_float::u128_to_f64_bits(i)) |
103 | } |
104 | } |
105 | |
106 | // Conversions from signed integers to floats. |
107 | intrinsics! { |
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) |
112 | } |
113 | |
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) |
118 | } |
119 | |
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) |
124 | } |
125 | |
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) |
130 | } |
131 | |
132 | #[cfg_attr(target_os = "uefi" , unadjusted_on_win64)] |
133 | pub extern "C" fn __floattisf(i: i128) -> f32 { |
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) |
136 | } |
137 | |
138 | #[cfg_attr(target_os = "uefi" , unadjusted_on_win64)] |
139 | pub extern "C" fn __floattidf(i: i128) -> f64 { |
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) |
142 | } |
143 | } |
144 | |
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 | } |
161 | } |
162 | |
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 | } |
177 | } |
178 | |
179 | #[win64_128bit_abi_hack] |
180 | pub extern "C" fn __fixunssfti(f: f32) -> u128 { |
181 | let fbits = f.to_bits(); |
182 | if fbits < 127 << 23 { // >= 0, < 1 |
183 | 0 |
184 | } else if fbits < 255 << 23 { // >= 1, < inf |
185 | let m = 1 << 127 | (fbits as u128) << 104; // Mantissa and the implicit 1-bit. |
186 | let s = 254 - (fbits >> 23); // Shift based on the exponent and bias. |
187 | m >> s |
188 | } else if fbits == 255 << 23 { // == inf |
189 | u128::MAX |
190 | } else { // Negative or NaN |
191 | 0 |
192 | } |
193 | } |
194 | |
195 | #[arm_aeabi_alias = __aeabi_d2uiz] |
196 | pub extern "C" fn __fixunsdfsi(f: f64) -> u32 { |
197 | let fbits = f.to_bits(); |
198 | if fbits < 1023 << 52 { // >= 0, < 1 |
199 | 0 |
200 | } else if fbits < 1055 << 52 { // >= 1, < max |
201 | let m = 1 << 31 | (fbits >> 21) as u32; // Mantissa and the implicit 1-bit. |
202 | let s = 1054 - (fbits >> 52); // Shift based on the exponent and bias. |
203 | m >> s |
204 | } else if fbits <= 2047 << 52 { // >= max (incl. inf) |
205 | u32::MAX |
206 | } else { // Negative or NaN |
207 | 0 |
208 | } |
209 | } |
210 | |
211 | #[arm_aeabi_alias = __aeabi_d2ulz] |
212 | pub extern "C" fn __fixunsdfdi(f: f64) -> u64 { |
213 | let fbits = f.to_bits(); |
214 | if fbits < 1023 << 52 { // >= 0, < 1 |
215 | 0 |
216 | } else if fbits < 1087 << 52 { // >= 1, < max |
217 | let m = 1 << 63 | fbits << 11; // Mantissa and the implicit 1-bit. |
218 | let s = 1086 - (fbits >> 52); // Shift based on the exponent and bias. |
219 | m >> s |
220 | } else if fbits <= 2047 << 52 { // >= max (incl. inf) |
221 | u64::MAX |
222 | } else { // Negative or NaN |
223 | 0 |
224 | } |
225 | } |
226 | |
227 | #[win64_128bit_abi_hack] |
228 | pub extern "C" fn __fixunsdfti(f: f64) -> u128 { |
229 | let fbits = f.to_bits(); |
230 | if fbits < 1023 << 52 { // >= 0, < 1 |
231 | 0 |
232 | } else if fbits < 1151 << 52 { // >= 1, < max |
233 | let m = 1 << 127 | (fbits as u128) << 75; // Mantissa and the implicit 1-bit. |
234 | let s = 1150 - (fbits >> 52); // Shift based on the exponent and bias. |
235 | m >> s |
236 | } else if fbits <= 2047 << 52 { // >= max (incl. inf) |
237 | u128::MAX |
238 | } else { // Negative or NaN |
239 | 0 |
240 | } |
241 | } |
242 | } |
243 | |
244 | // Conversions from floats to signed integers. |
245 | intrinsics! { |
246 | #[arm_aeabi_alias = __aeabi_f2iz] |
247 | pub extern "C" fn __fixsfsi(f: f32) -> i32 { |
248 | let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. |
249 | if fbits < 127 << 23 { // >= 0, < 1 |
250 | 0 |
251 | } else if fbits < 158 << 23 { // >= 1, < max |
252 | let m = 1 << 31 | fbits << 8; // Mantissa and the implicit 1-bit. |
253 | let s = 158 - (fbits >> 23); // Shift based on the exponent and bias. |
254 | let u = (m >> s) as i32; // Unsigned result. |
255 | if f.is_sign_negative() { -u } else { u } |
256 | } else if fbits <= 255 << 23 { // >= max (incl. inf) |
257 | if f.is_sign_negative() { i32::MIN } else { i32::MAX } |
258 | } else { // NaN |
259 | 0 |
260 | } |
261 | } |
262 | |
263 | #[arm_aeabi_alias = __aeabi_f2lz] |
264 | pub extern "C" fn __fixsfdi(f: f32) -> i64 { |
265 | let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. |
266 | if fbits < 127 << 23 { // >= 0, < 1 |
267 | 0 |
268 | } else if fbits < 190 << 23 { // >= 1, < max |
269 | let m = 1 << 63 | (fbits as u64) << 40; // Mantissa and the implicit 1-bit. |
270 | let s = 190 - (fbits >> 23); // Shift based on the exponent and bias. |
271 | let u = (m >> s) as i64; // Unsigned result. |
272 | if f.is_sign_negative() { -u } else { u } |
273 | } else if fbits <= 255 << 23 { // >= max (incl. inf) |
274 | if f.is_sign_negative() { i64::MIN } else { i64::MAX } |
275 | } else { // NaN |
276 | 0 |
277 | } |
278 | } |
279 | |
280 | #[win64_128bit_abi_hack] |
281 | pub extern "C" fn __fixsfti(f: f32) -> i128 { |
282 | let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. |
283 | if fbits < 127 << 23 { // >= 0, < 1 |
284 | 0 |
285 | } else if fbits < 254 << 23 { // >= 1, < max |
286 | let m = 1 << 127 | (fbits as u128) << 104; // Mantissa and the implicit 1-bit. |
287 | let s = 254 - (fbits >> 23); // Shift based on the exponent and bias. |
288 | let u = (m >> s) as i128; // Unsigned result. |
289 | if f.is_sign_negative() { -u } else { u } |
290 | } else if fbits <= 255 << 23 { // >= max (incl. inf) |
291 | if f.is_sign_negative() { i128::MIN } else { i128::MAX } |
292 | } else { // NaN |
293 | 0 |
294 | } |
295 | } |
296 | |
297 | #[arm_aeabi_alias = __aeabi_d2iz] |
298 | pub extern "C" fn __fixdfsi(f: f64) -> i32 { |
299 | let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. |
300 | if fbits < 1023 << 52 { // >= 0, < 1 |
301 | 0 |
302 | } else if fbits < 1054 << 52 { // >= 1, < max |
303 | let m = 1 << 31 | (fbits >> 21) as u32; // Mantissa and the implicit 1-bit. |
304 | let s = 1054 - (fbits >> 52); // Shift based on the exponent and bias. |
305 | let u = (m >> s) as i32; // Unsigned result. |
306 | if f.is_sign_negative() { -u } else { u } |
307 | } else if fbits <= 2047 << 52 { // >= max (incl. inf) |
308 | if f.is_sign_negative() { i32::MIN } else { i32::MAX } |
309 | } else { // NaN |
310 | 0 |
311 | } |
312 | } |
313 | |
314 | #[arm_aeabi_alias = __aeabi_d2lz] |
315 | pub extern "C" fn __fixdfdi(f: f64) -> i64 { |
316 | let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. |
317 | if fbits < 1023 << 52 { // >= 0, < 1 |
318 | 0 |
319 | } else if fbits < 1086 << 52 { // >= 1, < max |
320 | let m = 1 << 63 | fbits << 11; // Mantissa and the implicit 1-bit. |
321 | let s = 1086 - (fbits >> 52); // Shift based on the exponent and bias. |
322 | let u = (m >> s) as i64; // Unsigned result. |
323 | if f.is_sign_negative() { -u } else { u } |
324 | } else if fbits <= 2047 << 52 { // >= max (incl. inf) |
325 | if f.is_sign_negative() { i64::MIN } else { i64::MAX } |
326 | } else { // NaN |
327 | 0 |
328 | } |
329 | } |
330 | |
331 | #[win64_128bit_abi_hack] |
332 | pub extern "C" fn __fixdfti(f: f64) -> i128 { |
333 | let fbits = f.to_bits() & !0 >> 1; // Remove sign bit. |
334 | if fbits < 1023 << 52 { // >= 0, < 1 |
335 | 0 |
336 | } else if fbits < 1150 << 52 { // >= 1, < max |
337 | let m = 1 << 127 | (fbits as u128) << 75; // Mantissa and the implicit 1-bit. |
338 | let s = 1150 - (fbits >> 52); // Shift based on the exponent and bias. |
339 | let u = (m >> s) as i128; // Unsigned result. |
340 | if f.is_sign_negative() { -u } else { u } |
341 | } else if fbits <= 2047 << 52 { // >= max (incl. inf) |
342 | if f.is_sign_negative() { i128::MIN } else { i128::MAX } |
343 | } else { // NaN |
344 | 0 |
345 | } |
346 | } |
347 | } |
348 | |