bigint: cleanup float conversions

This commit is contained in:
Oliver Middleton 2015-12-24 18:15:56 +00:00
parent a480c7ca6c
commit 2c235d2dde
1 changed files with 12 additions and 30 deletions

View File

@ -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 {