1 | use crate::float::Float; |
2 | use crate::int::{CastInto, Int, MinInt}; |
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 | R::Int: CastInto<u32>, |
11 | u32: 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_exp_bias = F::EXP_BIAS; |
18 | |
19 | let src_min_normal = F::IMPLICIT_BIT; |
20 | let src_sig_mask = F::SIG_MASK; |
21 | let src_infinity = F::EXP_MASK; |
22 | let src_sign_mask = F::SIGN_MASK; |
23 | let src_abs_mask = src_sign_mask - src_one; |
24 | let round_mask = (src_one << (F::SIG_BITS - R::SIG_BITS)) - src_one; |
25 | let halfway = src_one << (F::SIG_BITS - R::SIG_BITS - 1); |
26 | let src_qnan = src_one << (F::SIG_BITS - 1); |
27 | let src_nan_code = src_qnan - src_one; |
28 | |
29 | let dst_zero = R::Int::ZERO; |
30 | let dst_one = R::Int::ONE; |
31 | let dst_bits = R::BITS; |
32 | let dst_inf_exp = R::EXP_SAT; |
33 | let dst_exp_bias = R::EXP_BIAS; |
34 | |
35 | let underflow_exponent: F::Int = (src_exp_bias + 1 - dst_exp_bias).cast(); |
36 | let overflow_exponent: F::Int = (src_exp_bias + dst_inf_exp - dst_exp_bias).cast(); |
37 | let underflow: F::Int = underflow_exponent << F::SIG_BITS; |
38 | let overflow: F::Int = overflow_exponent << F::SIG_BITS; |
39 | |
40 | let dst_qnan = R::Int::ONE << (R::SIG_BITS - 1); |
41 | let dst_nan_code = dst_qnan - dst_one; |
42 | |
43 | let sig_bits_delta = F::SIG_BITS - R::SIG_BITS; |
44 | // Break a into a sign and representation of the absolute value. |
45 | let a_abs = a.to_bits() & src_abs_mask; |
46 | let sign = a.to_bits() & src_sign_mask; |
47 | let mut abs_result: R::Int; |
48 | |
49 | if a_abs.wrapping_sub(underflow) < a_abs.wrapping_sub(overflow) { |
50 | // The exponent of a is within the range of normal numbers in the |
51 | // destination format. We can convert by simply right-shifting with |
52 | // rounding and adjusting the exponent. |
53 | abs_result = (a_abs >> sig_bits_delta).cast_lossy(); |
54 | // Cast before shifting to prevent overflow. |
55 | let bias_diff: R::Int = src_exp_bias.wrapping_sub(dst_exp_bias).cast(); |
56 | let tmp = bias_diff << R::SIG_BITS; |
57 | abs_result = abs_result.wrapping_sub(tmp); |
58 | |
59 | let round_bits = a_abs & round_mask; |
60 | if round_bits > halfway { |
61 | // Round to nearest. |
62 | abs_result += dst_one; |
63 | } else if round_bits == halfway { |
64 | // Tie to even. |
65 | abs_result += abs_result & dst_one; |
66 | }; |
67 | } else if a_abs > src_infinity { |
68 | // a is NaN. |
69 | // Conjure the result by beginning with infinity, setting the qNaN |
70 | // bit and inserting the (truncated) trailing NaN field. |
71 | // Cast before shifting to prevent overflow. |
72 | let dst_inf_exp: R::Int = dst_inf_exp.cast(); |
73 | abs_result = dst_inf_exp << R::SIG_BITS; |
74 | abs_result |= dst_qnan; |
75 | abs_result |= dst_nan_code & ((a_abs & src_nan_code) >> (F::SIG_BITS - R::SIG_BITS)).cast(); |
76 | } else if a_abs >= overflow { |
77 | // a overflows to infinity. |
78 | // Cast before shifting to prevent overflow. |
79 | let dst_inf_exp: R::Int = dst_inf_exp.cast(); |
80 | abs_result = dst_inf_exp << R::SIG_BITS; |
81 | } else { |
82 | // a underflows on conversion to the destination type or is an exact |
83 | // zero. The result may be a denormal or zero. Extract the exponent |
84 | // to get the shift amount for the denormalization. |
85 | let a_exp: u32 = (a_abs >> F::SIG_BITS).cast(); |
86 | let shift = src_exp_bias - dst_exp_bias - a_exp + 1; |
87 | |
88 | let significand = (a.to_bits() & src_sig_mask) | src_min_normal; |
89 | |
90 | // Right shift by the denormalization amount with sticky. |
91 | if shift > F::SIG_BITS { |
92 | abs_result = dst_zero; |
93 | } else { |
94 | let sticky = if (significand << (src_bits - shift)) != src_zero { |
95 | src_one |
96 | } else { |
97 | src_zero |
98 | }; |
99 | let denormalized_significand: F::Int = (significand >> shift) | sticky; |
100 | abs_result = (denormalized_significand >> (F::SIG_BITS - R::SIG_BITS)).cast(); |
101 | let round_bits = denormalized_significand & round_mask; |
102 | // Round to nearest |
103 | if round_bits > halfway { |
104 | abs_result += dst_one; |
105 | } |
106 | // Ties to even |
107 | else if round_bits == halfway { |
108 | abs_result += abs_result & dst_one; |
109 | }; |
110 | } |
111 | } |
112 | |
113 | // Apply the signbit to the absolute value. |
114 | R::from_bits(abs_result | sign.wrapping_shr(src_bits - dst_bits).cast()) |
115 | } |
116 | |
117 | intrinsics! { |
118 | #[aapcs_on_arm] |
119 | #[arm_aeabi_alias = __aeabi_d2f] |
120 | pub extern "C" fn __truncdfsf2(a: f64) -> f32 { |
121 | trunc(a) |
122 | } |
123 | } |
124 | |
125 | intrinsics! { |
126 | #[aapcs_on_arm] |
127 | #[apple_f16_ret_abi] |
128 | #[arm_aeabi_alias = __aeabi_f2h] |
129 | #[cfg (f16_enabled)] |
130 | pub extern "C" fn __truncsfhf2(a: f32) -> f16 { |
131 | trunc(a) |
132 | } |
133 | |
134 | #[aapcs_on_arm] |
135 | #[apple_f16_ret_abi] |
136 | #[cfg (f16_enabled)] |
137 | pub extern "C" fn __gnu_f2h_ieee(a: f32) -> f16 { |
138 | trunc(a) |
139 | } |
140 | |
141 | #[aapcs_on_arm] |
142 | #[apple_f16_ret_abi] |
143 | #[arm_aeabi_alias = __aeabi_d2h] |
144 | #[cfg (f16_enabled)] |
145 | pub extern "C" fn __truncdfhf2(a: f64) -> f16 { |
146 | trunc(a) |
147 | } |
148 | |
149 | #[aapcs_on_arm] |
150 | #[ppc_alias = __trunckfhf2] |
151 | #[cfg (all(f16_enabled, f128_enabled))] |
152 | pub extern "C" fn __trunctfhf2(a: f128) -> f16 { |
153 | trunc(a) |
154 | } |
155 | |
156 | #[aapcs_on_arm] |
157 | #[ppc_alias = __trunckfsf2] |
158 | #[cfg (f128_enabled)] |
159 | pub extern "C" fn __trunctfsf2(a: f128) -> f32 { |
160 | trunc(a) |
161 | } |
162 | |
163 | #[aapcs_on_arm] |
164 | #[ppc_alias = __trunckfdf2] |
165 | #[cfg (f128_enabled)] |
166 | pub extern "C" fn __trunctfdf2(a: f128) -> f64 { |
167 | trunc(a) |
168 | } |
169 | } |
170 | |