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/>
7mod 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.
74intrinsics! {
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.
107intrinsics! {
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.
146intrinsics! {
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.
245intrinsics! {
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