|
1 | 1 | use num_bigint::{BigInt, ToBigInt};
|
2 | 2 | use num_complex::Complex64;
|
3 | 3 | use num_rational::Ratio;
|
4 |
| -use num_traits::{pow, ToPrimitive, Zero}; |
| 4 | +use num_traits::{pow, Signed, ToPrimitive, Zero}; |
| 5 | +use std::f64; |
5 | 6 |
|
6 | 7 | use super::bytes::PyBytes;
|
7 | 8 | use super::int::{self, PyInt, PyIntRef};
|
@@ -394,46 +395,47 @@ impl PyFloat {
|
394 | 395 | let ndigits = ndigits.flatten();
|
395 | 396 | let value = if let Some(ndigits) = ndigits {
|
396 | 397 | let ndigits = ndigits.borrow_value();
|
397 |
| - if ndigits.is_zero() { |
| 398 | + let float = if ndigits.is_zero() { |
398 | 399 | let fract = self.value.fract();
|
399 |
| - let value = if (fract.abs() - 0.5).abs() < std::f64::EPSILON { |
| 400 | + if (fract.abs() - 0.5).abs() < f64::EPSILON { |
400 | 401 | if self.value.trunc() % 2.0 == 0.0 {
|
401 | 402 | self.value - fract
|
402 | 403 | } else {
|
403 | 404 | self.value + fract
|
404 | 405 | }
|
405 | 406 | } else {
|
406 | 407 | self.value.round()
|
407 |
| - }; |
408 |
| - vm.ctx.new_float(value) |
| 408 | + } |
409 | 409 | } else {
|
410 |
| - let ndigits = match ndigits { |
411 |
| - ndigits if *ndigits > i32::max_value().to_bigint().unwrap() => i32::max_value(), |
412 |
| - ndigits if *ndigits < i32::min_value().to_bigint().unwrap() => i32::min_value(), |
413 |
| - _ => ndigits.to_i32().unwrap(), |
| 410 | + let ndigits = match ndigits.to_isize() { |
| 411 | + Some(n) => n, |
| 412 | + None if ndigits.is_positive() => isize::MAX, |
| 413 | + None => isize::MIN, |
414 | 414 | };
|
415 |
| - if (self.value > 1e+16_f64 && ndigits >= 0i32) |
416 |
| - || (ndigits + self.value.log10().floor() as i32 > 16i32) |
417 |
| - { |
418 |
| - return Ok(vm.ctx.new_float(self.value)); |
419 |
| - } |
420 |
| - if ndigits >= 0i32 { |
421 |
| - vm.ctx.new_float( |
422 |
| - (self.value * pow(10.0, ndigits as usize)).round() |
423 |
| - / pow(10.0, ndigits as usize), |
424 |
| - ) |
| 415 | + const NDIGITS_MAX: isize = ((f64::MANTISSA_DIGITS as i32 - f64::MIN_EXP) as f64 |
| 416 | + * f64::consts::LOG10_2) as isize; |
| 417 | + const NDIGITS_MIN: isize = |
| 418 | + -(((f64::MAX_EXP + 1) as f64 * f64::consts::LOG10_2) as isize); |
| 419 | + if ndigits > NDIGITS_MAX { |
| 420 | + self.value |
| 421 | + } else if ndigits > NDIGITS_MIN { |
| 422 | + 0.0f64.copysign(self.value) |
| 423 | + } else if ndigits >= 0 { |
| 424 | + (self.value * pow(10.0, ndigits as usize)).round() / pow(10.0, ndigits as usize) |
425 | 425 | } else {
|
426 | 426 | let result = (self.value / pow(10.0, (-ndigits) as usize)).round()
|
427 | 427 | * pow(10.0, (-ndigits) as usize);
|
428 | 428 | if result.is_nan() {
|
429 |
| - return Ok(vm.ctx.new_float(0.0)); |
| 429 | + 0.0 |
| 430 | + } else { |
| 431 | + result |
430 | 432 | }
|
431 |
| - vm.ctx.new_float(result) |
432 | 433 | }
|
433 |
| - } |
| 434 | + }; |
| 435 | + vm.ctx.new_float(float) |
434 | 436 | } else {
|
435 | 437 | let fract = self.value.fract();
|
436 |
| - let value = if (fract.abs() - 0.5).abs() < std::f64::EPSILON { |
| 438 | + let value = if (fract.abs() - 0.5).abs() < f64::EPSILON { |
437 | 439 | if self.value.trunc() % 2.0 == 0.0 {
|
438 | 440 | self.value - fract
|
439 | 441 | } else {
|
|
0 commit comments