1 | use crate::float::Float; |
2 | use crate::int::{CastInto, Int}; |
3 | |
4 | fn trunc<F: Float, R: Float>(a: F) -> R |
5 | where |
6 | F::Int: CastInto<u64>, |
7 | F::Int: CastInto<u32>, |
8 | u64: CastInto<F::Int>, |
9 | u32: CastInto<F::Int>, |
10 | |
11 | R::Int: CastInto<u32>, |
12 | u32: 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_exp_bias = F::EXPONENT_BIAS; |
19 | |
20 | let src_min_normal = F::IMPLICIT_BIT; |
21 | let src_significand_mask = F::SIGNIFICAND_MASK; |
22 | let src_infinity = F::EXPONENT_MASK; |
23 | let src_sign_mask = F::SIGN_MASK; |
24 | let src_abs_mask = src_sign_mask - src_one; |
25 | let round_mask = (src_one << (F::SIGNIFICAND_BITS - R::SIGNIFICAND_BITS)) - src_one; |
26 | let halfway = src_one << (F::SIGNIFICAND_BITS - R::SIGNIFICAND_BITS - 1); |
27 | let src_qnan = src_one << (F::SIGNIFICAND_BITS - 1); |
28 | let src_nan_code = src_qnan - src_one; |
29 | |
30 | let dst_zero = R::Int::ZERO; |
31 | let dst_one = R::Int::ONE; |
32 | let dst_bits = R::BITS; |
33 | let dst_inf_exp = R::EXPONENT_MAX; |
34 | let dst_exp_bias = R::EXPONENT_BIAS; |
35 | |
36 | let underflow_exponent: F::Int = (src_exp_bias + 1 - dst_exp_bias).cast(); |
37 | let overflow_exponent: F::Int = (src_exp_bias + dst_inf_exp - dst_exp_bias).cast(); |
38 | let underflow: F::Int = underflow_exponent << F::SIGNIFICAND_BITS; |
39 | let overflow: F::Int = overflow_exponent << F::SIGNIFICAND_BITS; |
40 | |
41 | let dst_qnan = R::Int::ONE << (R::SIGNIFICAND_BITS - 1); |
42 | let dst_nan_code = dst_qnan - dst_one; |
43 | |
44 | let sign_bits_delta = F::SIGNIFICAND_BITS - R::SIGNIFICAND_BITS; |
45 | // Break a into a sign and representation of the absolute value. |
46 | let a_abs = a.repr() & src_abs_mask; |
47 | let sign = a.repr() & src_sign_mask; |
48 | let mut abs_result: R::Int; |
49 | |
50 | if a_abs.wrapping_sub(underflow) < a_abs.wrapping_sub(overflow) { |
51 | // The exponent of a is within the range of normal numbers in the |
52 | // destination format. We can convert by simply right-shifting with |
53 | // rounding and adjusting the exponent. |
54 | abs_result = (a_abs >> sign_bits_delta).cast(); |
55 | let tmp = src_exp_bias.wrapping_sub(dst_exp_bias) << R::SIGNIFICAND_BITS; |
56 | abs_result = abs_result.wrapping_sub(tmp.cast()); |
57 | |
58 | let round_bits = a_abs & round_mask; |
59 | if round_bits > halfway { |
60 | // Round to nearest. |
61 | abs_result += dst_one; |
62 | } else if round_bits == halfway { |
63 | // Tie to even. |
64 | abs_result += abs_result & dst_one; |
65 | }; |
66 | } else if a_abs > src_infinity { |
67 | // a is NaN. |
68 | // Conjure the result by beginning with infinity, setting the qNaN |
69 | // bit and inserting the (truncated) trailing NaN field. |
70 | abs_result = (dst_inf_exp << R::SIGNIFICAND_BITS).cast(); |
71 | abs_result |= dst_qnan; |
72 | abs_result |= dst_nan_code |
73 | & ((a_abs & src_nan_code) >> (F::SIGNIFICAND_BITS - R::SIGNIFICAND_BITS)).cast(); |
74 | } else if a_abs >= overflow { |
75 | // a overflows to infinity. |
76 | abs_result = (dst_inf_exp << R::SIGNIFICAND_BITS).cast(); |
77 | } else { |
78 | // a underflows on conversion to the destination type or is an exact |
79 | // zero. The result may be a denormal or zero. Extract the exponent |
80 | // to get the shift amount for the denormalization. |
81 | let a_exp: u32 = (a_abs >> F::SIGNIFICAND_BITS).cast(); |
82 | let shift = src_exp_bias - dst_exp_bias - a_exp + 1; |
83 | |
84 | let significand = (a.repr() & src_significand_mask) | src_min_normal; |
85 | |
86 | // Right shift by the denormalization amount with sticky. |
87 | if shift > F::SIGNIFICAND_BITS { |
88 | abs_result = dst_zero; |
89 | } else { |
90 | let sticky = if (significand << (src_bits - shift)) != src_zero { |
91 | src_one |
92 | } else { |
93 | src_zero |
94 | }; |
95 | let denormalized_significand: F::Int = significand >> shift | sticky; |
96 | abs_result = |
97 | (denormalized_significand >> (F::SIGNIFICAND_BITS - R::SIGNIFICAND_BITS)).cast(); |
98 | let round_bits = denormalized_significand & round_mask; |
99 | // Round to nearest |
100 | if round_bits > halfway { |
101 | abs_result += dst_one; |
102 | } |
103 | // Ties to even |
104 | else if round_bits == halfway { |
105 | abs_result += abs_result & dst_one; |
106 | }; |
107 | } |
108 | } |
109 | |
110 | // Apply the signbit to the absolute value. |
111 | R::from_repr(abs_result | sign.wrapping_shr(src_bits - dst_bits).cast()) |
112 | } |
113 | |
114 | intrinsics! { |
115 | #[avr_skip] |
116 | #[aapcs_on_arm] |
117 | #[arm_aeabi_alias = __aeabi_d2f] |
118 | pub extern "C" fn __truncdfsf2(a: f64) -> f32 { |
119 | trunc(a) |
120 | } |
121 | |
122 | #[cfg (target_arch = "arm" )] |
123 | pub extern "C" fn __truncdfsf2vfp(a: f64) -> f32 { |
124 | a as f32 |
125 | } |
126 | } |
127 | |