1use core::ops::Neg;
2
3use crate::int::{CastFrom, CastInto, Int, MinInt};
4
5use super::Float;
6
7/// Conversions from integers to floats.
8///
9/// The algorithm is explained here: <https://blog.m-ou.se/floats/>. It roughly does the following:
10/// - Calculate a base mantissa by shifting the integer into mantissa position. This gives us a
11/// mantissa _with the implicit bit set_!
12/// - Figure out if rounding needs to occur by classifying the bits that are to be truncated. Some
13/// patterns are used to simplify this. Adjust the mantissa with the result if needed.
14/// - Calculate the exponent based on the base-2 logarithm of `i` (leading zeros). Subtract one.
15/// - Shift the exponent and add the mantissa to create the final representation. Subtracting one
16/// from the exponent (above) accounts for the explicit bit being set in the mantissa.
17///
18/// # Terminology
19///
20/// - `i`: the original integer
21/// - `i_m`: the integer, shifted fully left (no leading zeros)
22/// - `n`: number of leading zeroes
23/// - `e`: the resulting exponent. Usually 1 is subtracted to offset the mantissa implicit bit.
24/// - `m_base`: the mantissa before adjusting for truncated bits. Implicit bit is usually set.
25/// - `adj`: the bits that will be truncated, possibly compressed in some way.
26/// - `m`: the resulting mantissa. Implicit bit is usually set.
27mod int_to_float {
28 use super::*;
29
30 /// Calculate the exponent from the number of leading zeros.
31 ///
32 /// Usually 1 is subtracted from this function's result, so that a mantissa with the implicit
33 /// bit set can be added back later.
34 fn exp<I: Int, F: Float<Int: CastFrom<u32>>>(n: u32) -> F::Int {
35 F::Int::cast_from(F::EXP_BIAS - 1 + I::BITS - n)
36 }
37
38 /// Adjust a mantissa with dropped bits to perform correct rounding.
39 ///
40 /// The dropped bits should be exactly the bits that get truncated (left-aligned), but they
41 /// can be combined or compressed in some way that simplifies operations.
42 fn m_adj<F: Float>(m_base: F::Int, dropped_bits: F::Int) -> F::Int {
43 // Branchlessly extract a `1` if rounding up should happen, 0 otherwise
44 // This accounts for rounding to even.
45 let adj = (dropped_bits - ((dropped_bits >> (F::BITS - 1)) & !m_base)) >> (F::BITS - 1);
46
47 // Add one when we need to round up. Break ties to even.
48 m_base + adj
49 }
50
51 /// Shift the exponent to its position and add the mantissa.
52 ///
53 /// If the mantissa has the implicit bit set, the exponent should be one less than its actual
54 /// value to cancel it out.
55 fn repr<F: Float>(e: F::Int, m: F::Int) -> F::Int {
56 // + rather than | so the mantissa can overflow into the exponent
57 (e << F::SIG_BITS) + m
58 }
59
60 /// Shift distance from a left-aligned integer to a smaller float.
61 fn shift_f_lt_i<I: Int, F: Float>() -> u32 {
62 (I::BITS - F::BITS) + F::EXP_BITS
63 }
64
65 /// Shift distance from an integer with `n` leading zeros to a smaller float.
66 fn shift_f_gt_i<I: Int, F: Float>(n: u32) -> u32 {
67 F::SIG_BITS - I::BITS + 1 + n
68 }
69
70 /// Perform a signed operation as unsigned, then add the sign back.
71 pub fn signed<I, F, Conv>(i: I, conv: Conv) -> F
72 where
73 F: Float,
74 I: Int,
75 F::Int: CastFrom<I>,
76 Conv: Fn(I::UnsignedInt) -> F::Int,
77 {
78 let sign_bit = F::Int::cast_from(i >> (I::BITS - 1)) << (F::BITS - 1);
79 F::from_bits(conv(i.unsigned_abs()) | sign_bit)
80 }
81
82 pub fn u32_to_f32_bits(i: u32) -> u32 {
83 if i == 0 {
84 return 0;
85 }
86 let n = i.leading_zeros();
87 // Mantissa with implicit bit set (significant bits)
88 let m_base = (i << n) >> f32::EXP_BITS;
89 // Bits that will be dropped (insignificant bits)
90 let adj = (i << n) << (f32::SIG_BITS + 1);
91 let m = m_adj::<f32>(m_base, adj);
92 let e = exp::<u32, f32>(n) - 1;
93 repr::<f32>(e, m)
94 }
95
96 pub fn u32_to_f64_bits(i: u32) -> u64 {
97 if i == 0 {
98 return 0;
99 }
100 let n = i.leading_zeros();
101 // Mantissa with implicit bit set
102 let m = (i as u64) << shift_f_gt_i::<u32, f64>(n);
103 let e = exp::<u32, f64>(n) - 1;
104 repr::<f64>(e, m)
105 }
106
107 #[cfg(f128_enabled)]
108 pub fn u32_to_f128_bits(i: u32) -> u128 {
109 if i == 0 {
110 return 0;
111 }
112 let n = i.leading_zeros();
113
114 // Shift into mantissa position that is correct for the type, but shifted into the lower
115 // 64 bits over so can can avoid 128-bit math.
116 let m = (i as u64) << (shift_f_gt_i::<u32, f128>(n) - 64);
117 let e = exp::<u32, f128>(n) as u64 - 1;
118 // High 64 bits of f128 representation.
119 let h = (e << (f128::SIG_BITS - 64)) + m;
120
121 // Shift back to the high bits, the rest of the mantissa will always be 0.
122 (h as u128) << 64
123 }
124
125 pub fn u64_to_f32_bits(i: u64) -> u32 {
126 let n = i.leading_zeros();
127 let i_m = i.wrapping_shl(n);
128 // Mantissa with implicit bit set
129 let m_base: u32 = (i_m >> shift_f_lt_i::<u64, f32>()) as u32;
130 // The entire lower half of `i` will be truncated (masked portion), plus the
131 // next `EXP_BITS` bits.
132 let adj = ((i_m >> f32::EXP_BITS) | i_m & 0xFFFF) as u32;
133 let m = m_adj::<f32>(m_base, adj);
134 let e = if i == 0 { 0 } else { exp::<u64, f32>(n) - 1 };
135 repr::<f32>(e, m)
136 }
137
138 pub fn u64_to_f64_bits(i: u64) -> u64 {
139 if i == 0 {
140 return 0;
141 }
142 let n = i.leading_zeros();
143 // Mantissa with implicit bit set
144 let m_base = (i << n) >> f64::EXP_BITS;
145 let adj = (i << n) << (f64::SIG_BITS + 1);
146 let m = m_adj::<f64>(m_base, adj);
147 let e = exp::<u64, f64>(n) - 1;
148 repr::<f64>(e, m)
149 }
150
151 #[cfg(f128_enabled)]
152 pub fn u64_to_f128_bits(i: u64) -> u128 {
153 if i == 0 {
154 return 0;
155 }
156 let n = i.leading_zeros();
157 // Mantissa with implicit bit set
158 let m = (i as u128) << shift_f_gt_i::<u64, f128>(n);
159 let e = exp::<u64, f128>(n) - 1;
160 repr::<f128>(e, m)
161 }
162
163 pub fn u128_to_f32_bits(i: u128) -> u32 {
164 let n = i.leading_zeros();
165 let i_m = i.wrapping_shl(n); // Mantissa, shifted so the first bit is nonzero
166 let m_base: u32 = (i_m >> shift_f_lt_i::<u128, f32>()) as u32;
167
168 // Within the upper `F::BITS`, everything except for the signifcand
169 // gets truncated
170 let d1: u32 = (i_m >> (u128::BITS - f32::BITS - f32::SIG_BITS - 1)).cast();
171
172 // The entire rest of `i_m` gets truncated. Zero the upper `F::BITS` then just
173 // check if it is nonzero.
174 let d2: u32 = (i_m << f32::BITS >> f32::BITS != 0).into();
175 let adj = d1 | d2;
176
177 // Mantissa with implicit bit set
178 let m = m_adj::<f32>(m_base, adj);
179 let e = if i == 0 { 0 } else { exp::<u128, f32>(n) - 1 };
180 repr::<f32>(e, m)
181 }
182
183 pub fn u128_to_f64_bits(i: u128) -> u64 {
184 let n = i.leading_zeros();
185 let i_m = i.wrapping_shl(n);
186 // Mantissa with implicit bit set
187 let m_base: u64 = (i_m >> shift_f_lt_i::<u128, f64>()) as u64;
188 // The entire lower half of `i` will be truncated (masked portion), plus the
189 // next `EXP_BITS` bits.
190 let adj = ((i_m >> f64::EXP_BITS) | i_m & 0xFFFF_FFFF) as u64;
191 let m = m_adj::<f64>(m_base, adj);
192 let e = if i == 0 { 0 } else { exp::<u128, f64>(n) - 1 };
193 repr::<f64>(e, m)
194 }
195
196 #[cfg(f128_enabled)]
197 pub fn u128_to_f128_bits(i: u128) -> u128 {
198 if i == 0 {
199 return 0;
200 }
201 let n = i.leading_zeros();
202 // Mantissa with implicit bit set
203 let m_base = (i << n) >> f128::EXP_BITS;
204 let adj = (i << n) << (f128::SIG_BITS + 1);
205 let m = m_adj::<f128>(m_base, adj);
206 let e = exp::<u128, f128>(n) - 1;
207 repr::<f128>(e, m)
208 }
209}
210
211// Conversions from unsigned integers to floats.
212intrinsics! {
213 #[arm_aeabi_alias = __aeabi_ui2f]
214 pub extern "C" fn __floatunsisf(i: u32) -> f32 {
215 f32::from_bits(int_to_float::u32_to_f32_bits(i))
216 }
217
218 #[arm_aeabi_alias = __aeabi_ui2d]
219 pub extern "C" fn __floatunsidf(i: u32) -> f64 {
220 f64::from_bits(int_to_float::u32_to_f64_bits(i))
221 }
222
223 #[arm_aeabi_alias = __aeabi_ul2f]
224 pub extern "C" fn __floatundisf(i: u64) -> f32 {
225 f32::from_bits(int_to_float::u64_to_f32_bits(i))
226 }
227
228 #[arm_aeabi_alias = __aeabi_ul2d]
229 pub extern "C" fn __floatundidf(i: u64) -> f64 {
230 f64::from_bits(int_to_float::u64_to_f64_bits(i))
231 }
232
233 #[cfg_attr(target_os = "uefi", unadjusted_on_win64)]
234 pub extern "C" fn __floatuntisf(i: u128) -> f32 {
235 f32::from_bits(int_to_float::u128_to_f32_bits(i))
236 }
237
238 #[cfg_attr(target_os = "uefi", unadjusted_on_win64)]
239 pub extern "C" fn __floatuntidf(i: u128) -> f64 {
240 f64::from_bits(int_to_float::u128_to_f64_bits(i))
241 }
242
243 #[ppc_alias = __floatunsikf]
244 #[cfg(f128_enabled)]
245 pub extern "C" fn __floatunsitf(i: u32) -> f128 {
246 f128::from_bits(int_to_float::u32_to_f128_bits(i))
247 }
248
249 #[ppc_alias = __floatundikf]
250 #[cfg(f128_enabled)]
251 pub extern "C" fn __floatunditf(i: u64) -> f128 {
252 f128::from_bits(int_to_float::u64_to_f128_bits(i))
253 }
254
255 #[ppc_alias = __floatuntikf]
256 #[cfg(f128_enabled)]
257 pub extern "C" fn __floatuntitf(i: u128) -> f128 {
258 f128::from_bits(int_to_float::u128_to_f128_bits(i))
259 }
260}
261
262// Conversions from signed integers to floats.
263intrinsics! {
264 #[arm_aeabi_alias = __aeabi_i2f]
265 pub extern "C" fn __floatsisf(i: i32) -> f32 {
266 int_to_float::signed(i, int_to_float::u32_to_f32_bits)
267 }
268
269 #[arm_aeabi_alias = __aeabi_i2d]
270 pub extern "C" fn __floatsidf(i: i32) -> f64 {
271 int_to_float::signed(i, int_to_float::u32_to_f64_bits)
272 }
273
274 #[arm_aeabi_alias = __aeabi_l2f]
275 pub extern "C" fn __floatdisf(i: i64) -> f32 {
276 int_to_float::signed(i, int_to_float::u64_to_f32_bits)
277 }
278
279 #[arm_aeabi_alias = __aeabi_l2d]
280 pub extern "C" fn __floatdidf(i: i64) -> f64 {
281 int_to_float::signed(i, int_to_float::u64_to_f64_bits)
282 }
283
284 #[cfg_attr(target_os = "uefi", unadjusted_on_win64)]
285 pub extern "C" fn __floattisf(i: i128) -> f32 {
286 int_to_float::signed(i, int_to_float::u128_to_f32_bits)
287 }
288
289 #[cfg_attr(target_os = "uefi", unadjusted_on_win64)]
290 pub extern "C" fn __floattidf(i: i128) -> f64 {
291 int_to_float::signed(i, int_to_float::u128_to_f64_bits)
292 }
293
294 #[ppc_alias = __floatsikf]
295 #[cfg(f128_enabled)]
296 pub extern "C" fn __floatsitf(i: i32) -> f128 {
297 int_to_float::signed(i, int_to_float::u32_to_f128_bits)
298 }
299
300 #[ppc_alias = __floatdikf]
301 #[cfg(f128_enabled)]
302 pub extern "C" fn __floatditf(i: i64) -> f128 {
303 int_to_float::signed(i, int_to_float::u64_to_f128_bits)
304 }
305
306 #[ppc_alias = __floattikf]
307 #[cfg(f128_enabled)]
308 pub extern "C" fn __floattitf(i: i128) -> f128 {
309 int_to_float::signed(i, int_to_float::u128_to_f128_bits)
310 }
311}
312
313/// Generic float to unsigned int conversions.
314fn float_to_unsigned_int<F, U>(f: F) -> U
315where
316 F: Float,
317 U: Int<UnsignedInt = U>,
318 F::Int: CastInto<U>,
319 F::Int: CastFrom<u32>,
320 F::Int: CastInto<U::UnsignedInt>,
321 u32: CastFrom<F::Int>,
322{
323 float_to_int_inner::<F, U, _, _>(fbits:f.to_bits(), |i: U| i, || U::MAX)
324}
325
326/// Generic float to signed int conversions.
327fn float_to_signed_int<F, I>(f: F) -> I
328where
329 F: Float,
330 I: Int + Neg<Output = I>,
331 I::UnsignedInt: Int,
332 F::Int: CastInto<I::UnsignedInt>,
333 F::Int: CastFrom<u32>,
334 u32: CastFrom<F::Int>,
335{
336 float_to_int_inner::<F, I, _, _>(
337 fbits:f.to_bits() & !F::SIGN_MASK,
338 |i: I| if f.is_sign_negative() { -i } else { i },
339 || if f.is_sign_negative() { I::MIN } else { I::MAX },
340 )
341}
342
343/// Float to int conversions, generic for both signed and unsigned.
344///
345/// Parameters:
346/// - `fbits`: `abg(f)` bitcasted to an integer.
347/// - `map_inbounds`: apply this transformation to integers that are within range (add the sign back).
348/// - `out_of_bounds`: return value when out of range for `I`.
349fn float_to_int_inner<F, I, FnFoo, FnOob>(
350 fbits: F::Int,
351 map_inbounds: FnFoo,
352 out_of_bounds: FnOob,
353) -> I
354where
355 F: Float,
356 I: Int,
357 FnFoo: FnOnce(I) -> I,
358 FnOob: FnOnce() -> I,
359 I::UnsignedInt: Int,
360 F::Int: CastInto<I::UnsignedInt>,
361 F::Int: CastFrom<u32>,
362 u32: CastFrom<F::Int>,
363{
364 let int_max_exp = F::EXP_BIAS + I::MAX.ilog2() + 1;
365 let foobar = F::EXP_BIAS + I::UnsignedInt::BITS - 1;
366
367 if fbits < F::ONE.to_bits() {
368 // < 0 gets rounded to 0
369 I::ZERO
370 } else if fbits < F::Int::cast_from(int_max_exp) << F::SIG_BITS {
371 // >= 1, < integer max
372 let m_base = if I::UnsignedInt::BITS >= F::Int::BITS {
373 I::UnsignedInt::cast_from(fbits) << (I::BITS - F::SIG_BITS - 1)
374 } else {
375 I::UnsignedInt::cast_from(fbits >> (F::SIG_BITS - I::BITS + 1))
376 };
377
378 // Set the implicit 1-bit.
379 let m: I::UnsignedInt = (I::UnsignedInt::ONE << (I::BITS - 1)) | m_base;
380
381 // Shift based on the exponent and bias.
382 let s: u32 = (foobar) - u32::cast_from(fbits >> F::SIG_BITS);
383
384 let unsigned = m >> s;
385 map_inbounds(I::from_unsigned(unsigned))
386 } else if fbits <= F::EXP_MASK {
387 // >= max (incl. inf)
388 out_of_bounds()
389 } else {
390 I::ZERO
391 }
392}
393
394// Conversions from floats to unsigned integers.
395intrinsics! {
396 #[arm_aeabi_alias = __aeabi_f2uiz]
397 pub extern "C" fn __fixunssfsi(f: f32) -> u32 {
398 float_to_unsigned_int(f)
399 }
400
401 #[arm_aeabi_alias = __aeabi_f2ulz]
402 pub extern "C" fn __fixunssfdi(f: f32) -> u64 {
403 float_to_unsigned_int(f)
404 }
405
406 pub extern "C" fn __fixunssfti(f: f32) -> u128 {
407 float_to_unsigned_int(f)
408 }
409
410 #[arm_aeabi_alias = __aeabi_d2uiz]
411 pub extern "C" fn __fixunsdfsi(f: f64) -> u32 {
412 float_to_unsigned_int(f)
413 }
414
415 #[arm_aeabi_alias = __aeabi_d2ulz]
416 pub extern "C" fn __fixunsdfdi(f: f64) -> u64 {
417 float_to_unsigned_int(f)
418 }
419
420 pub extern "C" fn __fixunsdfti(f: f64) -> u128 {
421 float_to_unsigned_int(f)
422 }
423
424 #[ppc_alias = __fixunskfsi]
425 #[cfg(f128_enabled)]
426 pub extern "C" fn __fixunstfsi(f: f128) -> u32 {
427 float_to_unsigned_int(f)
428 }
429
430 #[ppc_alias = __fixunskfdi]
431 #[cfg(f128_enabled)]
432 pub extern "C" fn __fixunstfdi(f: f128) -> u64 {
433 float_to_unsigned_int(f)
434 }
435
436 #[ppc_alias = __fixunskfti]
437 #[cfg(f128_enabled)]
438 pub extern "C" fn __fixunstfti(f: f128) -> u128 {
439 float_to_unsigned_int(f)
440 }
441}
442
443// Conversions from floats to signed integers.
444intrinsics! {
445 #[arm_aeabi_alias = __aeabi_f2iz]
446 pub extern "C" fn __fixsfsi(f: f32) -> i32 {
447 float_to_signed_int(f)
448 }
449
450 #[arm_aeabi_alias = __aeabi_f2lz]
451 pub extern "C" fn __fixsfdi(f: f32) -> i64 {
452 float_to_signed_int(f)
453 }
454
455 pub extern "C" fn __fixsfti(f: f32) -> i128 {
456 float_to_signed_int(f)
457 }
458
459 #[arm_aeabi_alias = __aeabi_d2iz]
460 pub extern "C" fn __fixdfsi(f: f64) -> i32 {
461 float_to_signed_int(f)
462 }
463
464 #[arm_aeabi_alias = __aeabi_d2lz]
465 pub extern "C" fn __fixdfdi(f: f64) -> i64 {
466 float_to_signed_int(f)
467 }
468
469 pub extern "C" fn __fixdfti(f: f64) -> i128 {
470 float_to_signed_int(f)
471 }
472
473 #[ppc_alias = __fixkfsi]
474 #[cfg(f128_enabled)]
475 pub extern "C" fn __fixtfsi(f: f128) -> i32 {
476 float_to_signed_int(f)
477 }
478
479 #[ppc_alias = __fixkfdi]
480 #[cfg(f128_enabled)]
481 pub extern "C" fn __fixtfdi(f: f128) -> i64 {
482 float_to_signed_int(f)
483 }
484
485 #[ppc_alias = __fixkfti]
486 #[cfg(f128_enabled)]
487 pub extern "C" fn __fixtfti(f: f128) -> i128 {
488 float_to_signed_int(f)
489 }
490}
491