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