1 | use crate::float::Float; |
2 | use crate::int::{CastInto, Int}; |
3 | |
4 | /// Generic conversion from a narrower to a wider IEEE-754 floating-point type |
5 | fn extend<F: Float, R: Float>(a: F) -> R |
6 | where |
7 | F::Int: CastInto<u64>, |
8 | u64: CastInto<F::Int>, |
9 | u32: CastInto<R::Int>, |
10 | R::Int: CastInto<u32>, |
11 | R::Int: CastInto<u64>, |
12 | u64: CastInto<R::Int>, |
13 | F::Int: CastInto<R::Int>, |
14 | { |
15 | let src_zero = F::Int::ZERO; |
16 | let src_one = F::Int::ONE; |
17 | let src_bits = F::BITS; |
18 | let src_sign_bits = F::SIGNIFICAND_BITS; |
19 | let src_exp_bias = F::EXPONENT_BIAS; |
20 | let src_min_normal = F::IMPLICIT_BIT; |
21 | let src_infinity = F::EXPONENT_MASK; |
22 | let src_sign_mask = F::SIGN_MASK as F::Int; |
23 | let src_abs_mask = src_sign_mask - src_one; |
24 | let src_qnan = F::SIGNIFICAND_MASK; |
25 | let src_nan_code = src_qnan - src_one; |
26 | |
27 | let dst_bits = R::BITS; |
28 | let dst_sign_bits = R::SIGNIFICAND_BITS; |
29 | let dst_inf_exp = R::EXPONENT_MAX; |
30 | let dst_exp_bias = R::EXPONENT_BIAS; |
31 | let dst_min_normal = R::IMPLICIT_BIT; |
32 | |
33 | let sign_bits_delta = dst_sign_bits - src_sign_bits; |
34 | let exp_bias_delta = dst_exp_bias - src_exp_bias; |
35 | let a_abs = a.repr() & src_abs_mask; |
36 | let mut abs_result = R::Int::ZERO; |
37 | |
38 | if a_abs.wrapping_sub(src_min_normal) < src_infinity.wrapping_sub(src_min_normal) { |
39 | // a is a normal number. |
40 | // Extend to the destination type by shifting the significand and |
41 | // exponent into the proper position and rebiasing the exponent. |
42 | let abs_dst: R::Int = a_abs.cast(); |
43 | let bias_dst: R::Int = exp_bias_delta.cast(); |
44 | abs_result = abs_dst.wrapping_shl(sign_bits_delta); |
45 | abs_result += bias_dst.wrapping_shl(dst_sign_bits); |
46 | } else if a_abs >= src_infinity { |
47 | // a is NaN or infinity. |
48 | // Conjure the result by beginning with infinity, then setting the qNaN |
49 | // bit (if needed) and right-aligning the rest of the trailing NaN |
50 | // payload field. |
51 | let qnan_dst: R::Int = (a_abs & src_qnan).cast(); |
52 | let nan_code_dst: R::Int = (a_abs & src_nan_code).cast(); |
53 | let inf_exp_dst: R::Int = dst_inf_exp.cast(); |
54 | abs_result = inf_exp_dst.wrapping_shl(dst_sign_bits); |
55 | abs_result |= qnan_dst.wrapping_shl(sign_bits_delta); |
56 | abs_result |= nan_code_dst.wrapping_shl(sign_bits_delta); |
57 | } else if a_abs != src_zero { |
58 | // a is denormal. |
59 | // Renormalize the significand and clear the leading bit, then insert |
60 | // the correct adjusted exponent in the destination type. |
61 | let scale = a_abs.leading_zeros() - src_min_normal.leading_zeros(); |
62 | let abs_dst: R::Int = a_abs.cast(); |
63 | let bias_dst: R::Int = (exp_bias_delta - scale + 1).cast(); |
64 | abs_result = abs_dst.wrapping_shl(sign_bits_delta + scale); |
65 | abs_result = (abs_result ^ dst_min_normal) | (bias_dst.wrapping_shl(dst_sign_bits)); |
66 | } |
67 | |
68 | let sign_result: R::Int = (a.repr() & src_sign_mask).cast(); |
69 | R::from_repr(abs_result | (sign_result.wrapping_shl(dst_bits - src_bits))) |
70 | } |
71 | |
72 | intrinsics! { |
73 | #[avr_skip] |
74 | #[aapcs_on_arm] |
75 | #[arm_aeabi_alias = __aeabi_f2d] |
76 | pub extern "C" fn __extendsfdf2(a: f32) -> f64 { |
77 | extend(a) |
78 | } |
79 | |
80 | #[cfg (target_arch = "arm" )] |
81 | pub extern "C" fn __extendsfdf2vfp(a: f32) -> f64 { |
82 | a as f64 // LLVM generate 'fcvtds' |
83 | } |
84 | } |
85 | |