|
1 | 1 | use float::Float;
|
2 |
| -use int::{Int, CastInto}; |
| 2 | +use int::Int; |
3 | 3 |
|
4 | 4 | macro_rules! int_to_float {
|
5 | 5 | ($i:expr, $ity:ty, $fty:ty) => ({
|
@@ -137,116 +137,115 @@ enum Sign {
|
137 | 137 | Negative
|
138 | 138 | }
|
139 | 139 |
|
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 |
| - } |
| 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 | + }) |
190 | 189 | }
|
191 | 190 |
|
192 | 191 | intrinsics! {
|
193 | 192 | #[arm_aeabi_alias = __aeabi_f2iz]
|
194 | 193 | pub extern "C" fn __fixsfsi(f: f32) -> i32 {
|
195 |
| - float_to_int(f) |
| 194 | + float_to_int!(f, f32, i32) |
196 | 195 | }
|
197 | 196 |
|
198 | 197 | #[arm_aeabi_alias = __aeabi_f2lz]
|
199 | 198 | pub extern "C" fn __fixsfdi(f: f32) -> i64 {
|
200 |
| - float_to_int(f) |
| 199 | + float_to_int!(f, f32, i64) |
201 | 200 | }
|
202 | 201 |
|
203 | 202 | #[unadjusted_on_win64]
|
204 | 203 | pub extern "C" fn __fixsfti(f: f32) -> i128 {
|
205 |
| - float_to_int(f) |
| 204 | + float_to_int!(f, f32, i128) |
206 | 205 | }
|
207 | 206 |
|
208 | 207 | #[arm_aeabi_alias = __aeabi_d2iz]
|
209 | 208 | pub extern "C" fn __fixdfsi(f: f64) -> i32 {
|
210 |
| - float_to_int(f) |
| 209 | + float_to_int!(f, f64, i32) |
211 | 210 | }
|
212 | 211 |
|
213 | 212 | #[arm_aeabi_alias = __aeabi_d2lz]
|
214 | 213 | pub extern "C" fn __fixdfdi(f: f64) -> i64 {
|
215 |
| - float_to_int(f) |
| 214 | + float_to_int!(f, f64, i64) |
216 | 215 | }
|
217 | 216 |
|
218 | 217 | #[unadjusted_on_win64]
|
219 | 218 | pub extern "C" fn __fixdfti(f: f64) -> i128 {
|
220 |
| - float_to_int(f) |
| 219 | + float_to_int!(f, f64, i128) |
221 | 220 | }
|
222 | 221 |
|
223 | 222 | #[arm_aeabi_alias = __aeabi_f2uiz]
|
224 | 223 | pub extern "C" fn __fixunssfsi(f: f32) -> u32 {
|
225 |
| - float_to_int(f) |
| 224 | + float_to_int!(f, f32, u32) |
226 | 225 | }
|
227 | 226 |
|
228 | 227 | #[arm_aeabi_alias = __aeabi_f2ulz]
|
229 | 228 | pub extern "C" fn __fixunssfdi(f: f32) -> u64 {
|
230 |
| - float_to_int(f) |
| 229 | + float_to_int!(f, f32, u64) |
231 | 230 | }
|
232 | 231 |
|
233 | 232 | #[unadjusted_on_win64]
|
234 | 233 | pub extern "C" fn __fixunssfti(f: f32) -> u128 {
|
235 |
| - float_to_int(f) |
| 234 | + float_to_int!(f, f32, u128) |
236 | 235 | }
|
237 | 236 |
|
238 | 237 | #[arm_aeabi_alias = __aeabi_d2uiz]
|
239 | 238 | pub extern "C" fn __fixunsdfsi(f: f64) -> u32 {
|
240 |
| - float_to_int(f) |
| 239 | + float_to_int!(f, f64, u32) |
241 | 240 | }
|
242 | 241 |
|
243 | 242 | #[arm_aeabi_alias = __aeabi_d2ulz]
|
244 | 243 | pub extern "C" fn __fixunsdfdi(f: f64) -> u64 {
|
245 |
| - float_to_int(f) |
| 244 | + float_to_int!(f, f64, u64) |
246 | 245 | }
|
247 | 246 |
|
248 | 247 | #[unadjusted_on_win64]
|
249 | 248 | pub extern "C" fn __fixunsdfti(f: f64) -> u128 {
|
250 |
| - float_to_int(f) |
| 249 | + float_to_int!(f, f64, u128) |
251 | 250 | }
|
252 | 251 | }
|
0 commit comments