bigint: cleanup float conversions
This commit is contained in:
parent
a480c7ca6c
commit
2c235d2dde
|
@ -1178,16 +1178,16 @@ impl ToPrimitive for BigUint {
|
||||||
0 => Some(f32::zero()),
|
0 => Some(f32::zero()),
|
||||||
1 => Some(self.data[0] as f32),
|
1 => Some(self.data[0] as f32),
|
||||||
len => {
|
len => {
|
||||||
// prevent overflow of exponant
|
// this will prevent any overflow of exponent
|
||||||
if len > (f32::MAX_EXP as usize) / big_digit::BITS {
|
if len > (f32::MAX_EXP as usize) / big_digit::BITS {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let exponant = (len - 2) * big_digit::BITS;
|
let exponent = (len - 2) * big_digit::BITS;
|
||||||
// we need 25 significant digits, 24 to be stored and 1 for rounding
|
// we need 25 significant digits, 24 to be stored and 1 for rounding
|
||||||
// this gives at least 33 significant digits
|
// this gives at least 33 significant digits
|
||||||
let mantissa = big_digit::to_doublebigdigit(self.data[len - 1], self.data[len - 2]);
|
let mantissa = big_digit::to_doublebigdigit(self.data[len - 1], self.data[len - 2]);
|
||||||
// this cast handles rounding
|
// this cast handles rounding
|
||||||
let ret = (mantissa as f32) * 2.0.powi(exponant as i32);
|
let ret = (mantissa as f32) * 2.0.powi(exponent as i32);
|
||||||
if ret.is_infinite() {
|
if ret.is_infinite() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
@ -1206,26 +1206,22 @@ impl ToPrimitive for BigUint {
|
||||||
1 => Some(self.data[0] as f64),
|
1 => Some(self.data[0] as f64),
|
||||||
2 => Some(big_digit::to_doublebigdigit(self.data[1], self.data[0]) as f64),
|
2 => Some(big_digit::to_doublebigdigit(self.data[1], self.data[0]) as f64),
|
||||||
len => {
|
len => {
|
||||||
// this will prevent any overflow of exponant
|
// this will prevent any overflow of exponent
|
||||||
if len > (f64::MAX_EXP as usize) / big_digit::BITS {
|
if len > (f64::MAX_EXP as usize) / big_digit::BITS {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let mut exponant = (len - 2) * big_digit::BITS;
|
let mut exponent = (len - 2) * big_digit::BITS;
|
||||||
let mut mantissa = big_digit::to_doublebigdigit(self.data[len - 1], self.data[len - 2]);
|
let mut mantissa = big_digit::to_doublebigdigit(self.data[len - 1], self.data[len - 2]);
|
||||||
// we need at least 54 significant bit digits, 53 to be stored and 1 for rounding
|
// we need at least 54 significant bit digits, 53 to be stored and 1 for rounding
|
||||||
// so we take enough from the next BigDigit to make it up if needed
|
// so we take enough from the next BigDigit to make it up to 64
|
||||||
let needed = (f64::MANTISSA_DIGITS as usize) + 1;
|
let shift = mantissa.leading_zeros() as usize;
|
||||||
let bits = (2 * big_digit::BITS) - (mantissa.leading_zeros() as usize);
|
if shift > 0 {
|
||||||
if needed > bits {
|
mantissa <<= shift;
|
||||||
let diff = needed - bits;
|
mantissa |= self.data[len - 3] as u64 >> (big_digit::BITS - shift);
|
||||||
mantissa <<= diff;
|
exponent -= shift;
|
||||||
exponant -= diff;
|
|
||||||
let mut x = self.data[len - 3];
|
|
||||||
x >>= big_digit::BITS - diff;
|
|
||||||
mantissa |= x as u64;
|
|
||||||
}
|
}
|
||||||
// this cast handles rounding
|
// this cast handles rounding
|
||||||
let ret = (mantissa as f64) * 2.0.powi(exponant as i32);
|
let ret = (mantissa as f64) * 2.0.powi(exponent as i32);
|
||||||
if ret.is_infinite() {
|
if ret.is_infinite() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
@ -1252,11 +1248,6 @@ impl FromPrimitive for BigUint {
|
||||||
Some(BigUint::from(n))
|
Some(BigUint::from(n))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn from_f32(n: f32) -> Option<BigUint> {
|
|
||||||
BigUint::from_f64(n as f64)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_f64(mut n: f64) -> Option<BigUint> {
|
fn from_f64(mut n: f64) -> Option<BigUint> {
|
||||||
// handle NAN, INFINITY, NEG_INFINITY
|
// handle NAN, INFINITY, NEG_INFINITY
|
||||||
|
@ -2250,15 +2241,6 @@ impl FromPrimitive for BigInt {
|
||||||
Some(BigInt::from(n))
|
Some(BigInt::from(n))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn from_f32(n: f32) -> Option<BigInt> {
|
|
||||||
if n >= 0.0 {
|
|
||||||
BigUint::from_f32(n).map(|x| BigInt::from_biguint(Plus, x))
|
|
||||||
} else {
|
|
||||||
BigUint::from_f32(-n).map(|x| BigInt::from_biguint(Minus, x))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_f64(n: f64) -> Option<BigInt> {
|
fn from_f64(n: f64) -> Option<BigInt> {
|
||||||
if n >= 0.0 {
|
if n >= 0.0 {
|
||||||
|
|
Loading…
Reference in New Issue