|
1 | 1 | use float::Float;
|
2 |
| -use int::Int; |
| 2 | +use int::{Int, CastInto}; |
3 | 3 |
|
4 | 4 | macro_rules! int_to_float {
|
5 | 5 | ($i:expr, $ity:ty, $fty:ty) => ({
|
@@ -137,115 +137,116 @@ enum Sign {
|
137 | 137 | Negative
|
138 | 138 | }
|
139 | 139 |
|
140 |
| -macro_rules! float_to_int { |
141 |
| - ($f:expr, $fty:ty, $ity:ty) => ({ |
142 |
| - let f = $f; |
143 |
| - let fixint_min = <$ity>::min_value(); |
144 |
| - let fixint_max = <$ity>::max_value(); |
145 |
| - let fixint_bits = <$ity>::BITS as usize; |
146 |
| - let fixint_unsigned = fixint_min == 0; |
147 |
| - |
148 |
| - let sign_bit = <$fty>::SIGN_MASK; |
149 |
| - let significand_bits = <$fty>::SIGNIFICAND_BITS as usize; |
150 |
| - let exponent_bias = <$fty>::EXPONENT_BIAS as usize; |
151 |
| - //let exponent_max = <$fty>::exponent_max() as usize; |
152 |
| - |
153 |
| - // Break a into sign, exponent, significand |
154 |
| - let a_rep = <$fty>::repr(f); |
155 |
| - let a_abs = a_rep & !sign_bit; |
156 |
| - |
157 |
| - // this is used to work around -1 not being available for unsigned |
158 |
| - let sign = if (a_rep & sign_bit) == 0 { Sign::Positive } else { Sign::Negative }; |
159 |
| - let mut exponent = (a_abs >> significand_bits) as usize; |
160 |
| - let significand = (a_abs & <$fty>::SIGNIFICAND_MASK) | <$fty>::IMPLICIT_BIT; |
161 |
| - |
162 |
| - // if < 1 or unsigned & negative |
163 |
| - if exponent < exponent_bias || |
164 |
| - fixint_unsigned && sign == Sign::Negative { |
165 |
| - return 0 |
166 |
| - } |
167 |
| - exponent -= exponent_bias; |
168 |
| - |
169 |
| - // If the value is infinity, saturate. |
170 |
| - // If the value is too large for the integer type, 0. |
171 |
| - if exponent >= (if fixint_unsigned {fixint_bits} else {fixint_bits -1}) { |
172 |
| - return if sign == Sign::Positive {fixint_max} else {fixint_min} |
173 |
| - } |
174 |
| - // If 0 <= exponent < significand_bits, right shift to get the result. |
175 |
| - // Otherwise, shift left. |
176 |
| - // (sign - 1) will never overflow as negative signs are already returned as 0 for unsigned |
177 |
| - let r = if exponent < significand_bits { |
178 |
| - (significand >> (significand_bits - exponent)) as $ity |
179 |
| - } else { |
180 |
| - (significand as $ity) << (exponent - significand_bits) |
181 |
| - }; |
182 |
| - |
183 |
| - if sign == Sign::Negative { |
184 |
| - (!r).wrapping_add(1) |
185 |
| - } else { |
186 |
| - r |
187 |
| - } |
188 |
| - }) |
| 140 | +fn float_to_int<F: Float, I: Int>(f: F) -> I where |
| 141 | + F::Int: CastInto<u32>, |
| 142 | + F::Int: CastInto<I>, |
| 143 | +{ |
| 144 | + let f = f; |
| 145 | + let fixint_min = I::min_value(); |
| 146 | + let fixint_max = I::max_value(); |
| 147 | + let fixint_bits = I::BITS; |
| 148 | + let fixint_unsigned = fixint_min == I::ZERO; |
| 149 | + |
| 150 | + let sign_bit = F::SIGN_MASK; |
| 151 | + let significand_bits = F::SIGNIFICAND_BITS; |
| 152 | + let exponent_bias = F::EXPONENT_BIAS; |
| 153 | + //let exponent_max = F::exponent_max() as usize; |
| 154 | + |
| 155 | + // Break a into sign, exponent, significand |
| 156 | + let a_rep = F::repr(f); |
| 157 | + let a_abs = a_rep & !sign_bit; |
| 158 | + |
| 159 | + // this is used to work around -1 not being available for unsigned |
| 160 | + let sign = if (a_rep & sign_bit) == F::Int::ZERO { Sign::Positive } else { Sign::Negative }; |
| 161 | + let mut exponent: u32 = (a_abs >> significand_bits).cast(); |
| 162 | + let significand = (a_abs & F::SIGNIFICAND_MASK) | F::IMPLICIT_BIT; |
| 163 | + |
| 164 | + // if < 1 or unsigned & negative |
| 165 | + if exponent < exponent_bias || |
| 166 | + fixint_unsigned && sign == Sign::Negative { |
| 167 | + return I::ZERO; |
| 168 | + } |
| 169 | + exponent -= exponent_bias; |
| 170 | + |
| 171 | + // If the value is infinity, saturate. |
| 172 | + // If the value is too large for the integer type, 0. |
| 173 | + if exponent >= (if fixint_unsigned {fixint_bits} else {fixint_bits -1}) { |
| 174 | + return if sign == Sign::Positive {fixint_max} else {fixint_min} |
| 175 | + } |
| 176 | + // If 0 <= exponent < significand_bits, right shift to get the result. |
| 177 | + // Otherwise, shift left. |
| 178 | + // (sign - 1) will never overflow as negative signs are already returned as 0 for unsigned |
| 179 | + let r: I = if exponent < significand_bits { |
| 180 | + (significand >> (significand_bits - exponent)).cast() |
| 181 | + } else { |
| 182 | + (significand << (exponent - significand_bits)).cast() |
| 183 | + }; |
| 184 | + |
| 185 | + if sign == Sign::Negative { |
| 186 | + (!r).wrapping_add(I::ONE) |
| 187 | + } else { |
| 188 | + r |
| 189 | + } |
189 | 190 | }
|
190 | 191 |
|
191 | 192 | intrinsics! {
|
192 | 193 | #[arm_aeabi_alias = __aeabi_f2iz]
|
193 | 194 | pub extern "C" fn __fixsfsi(f: f32) -> i32 {
|
194 |
| - float_to_int!(f, f32, i32) |
| 195 | + float_to_int(f) |
195 | 196 | }
|
196 | 197 |
|
197 | 198 | #[arm_aeabi_alias = __aeabi_f2lz]
|
198 | 199 | pub extern "C" fn __fixsfdi(f: f32) -> i64 {
|
199 |
| - float_to_int!(f, f32, i64) |
| 200 | + float_to_int(f) |
200 | 201 | }
|
201 | 202 |
|
202 | 203 | #[unadjusted_on_win64]
|
203 | 204 | pub extern "C" fn __fixsfti(f: f32) -> i128 {
|
204 |
| - float_to_int!(f, f32, i128) |
| 205 | + float_to_int(f) |
205 | 206 | }
|
206 | 207 |
|
207 | 208 | #[arm_aeabi_alias = __aeabi_d2iz]
|
208 | 209 | pub extern "C" fn __fixdfsi(f: f64) -> i32 {
|
209 |
| - float_to_int!(f, f64, i32) |
| 210 | + float_to_int(f) |
210 | 211 | }
|
211 | 212 |
|
212 | 213 | #[arm_aeabi_alias = __aeabi_d2lz]
|
213 | 214 | pub extern "C" fn __fixdfdi(f: f64) -> i64 {
|
214 |
| - float_to_int!(f, f64, i64) |
| 215 | + float_to_int(f) |
215 | 216 | }
|
216 | 217 |
|
217 | 218 | #[unadjusted_on_win64]
|
218 | 219 | pub extern "C" fn __fixdfti(f: f64) -> i128 {
|
219 |
| - float_to_int!(f, f64, i128) |
| 220 | + float_to_int(f) |
220 | 221 | }
|
221 | 222 |
|
222 | 223 | #[arm_aeabi_alias = __aeabi_f2uiz]
|
223 | 224 | pub extern "C" fn __fixunssfsi(f: f32) -> u32 {
|
224 |
| - float_to_int!(f, f32, u32) |
| 225 | + float_to_int(f) |
225 | 226 | }
|
226 | 227 |
|
227 | 228 | #[arm_aeabi_alias = __aeabi_f2ulz]
|
228 | 229 | pub extern "C" fn __fixunssfdi(f: f32) -> u64 {
|
229 |
| - float_to_int!(f, f32, u64) |
| 230 | + float_to_int(f) |
230 | 231 | }
|
231 | 232 |
|
232 | 233 | #[unadjusted_on_win64]
|
233 | 234 | pub extern "C" fn __fixunssfti(f: f32) -> u128 {
|
234 |
| - float_to_int!(f, f32, u128) |
| 235 | + float_to_int(f) |
235 | 236 | }
|
236 | 237 |
|
237 | 238 | #[arm_aeabi_alias = __aeabi_d2uiz]
|
238 | 239 | pub extern "C" fn __fixunsdfsi(f: f64) -> u32 {
|
239 |
| - float_to_int!(f, f64, u32) |
| 240 | + float_to_int(f) |
240 | 241 | }
|
241 | 242 |
|
242 | 243 | #[arm_aeabi_alias = __aeabi_d2ulz]
|
243 | 244 | pub extern "C" fn __fixunsdfdi(f: f64) -> u64 {
|
244 |
| - float_to_int!(f, f64, u64) |
| 245 | + float_to_int(f) |
245 | 246 | }
|
246 | 247 |
|
247 | 248 | #[unadjusted_on_win64]
|
248 | 249 | pub extern "C" fn __fixunsdfti(f: f64) -> u128 {
|
249 |
| - float_to_int!(f, f64, u128) |
| 250 | + float_to_int(f) |
250 | 251 | }
|
251 | 252 | }
|
0 commit comments