aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/eval.rs23
1 files changed, 18 insertions, 5 deletions
diff --git a/src/eval.rs b/src/eval.rs
index d9fb184..beda22b 100644
--- a/src/eval.rs
+++ b/src/eval.rs
@@ -14,26 +14,31 @@ fn int_to_float(i: &BigInt) -> f64 {
}
let mut fraction;
if exponent <= 52 {
+ // The number can be represented exactly without rounding.
fraction = i.to_u64().unwrap() << 52 - exponent;
} else {
+ // We need to round.
let power = BigInt::from(1) << exponent - 52;
- let (fraction_big, rem) = i.div_rem(&power);
- fraction = fraction_big.to_u64().unwrap();
+ let (rounded_fraction, rem) = i.div_rem(&power);
+ fraction = rounded_fraction.to_u64().unwrap();
let half = power >> 1;
+ // Round up?
if rem > half || rem == half && fraction % 2 == 1 {
fraction += 1;
+ // Check for overflow.
if fraction == 1 << 53 {
exponent += 1;
+ fraction >>= 1;
if exponent > 1023 {
return f64::INFINITY;
}
- fraction = 1 << 53;
}
}
}
- let u = (exponent + 1023) << 52 | fraction & !(1 << 52);
- f64::from_bits(u)
+ // Build the float from exponent and fraction
+ // https://en.wikipedia.org/wiki/IEEE_754
+ f64::from_bits(((exponent + 1023) << 52) + (fraction & !(1 << 52)))
}
#[derive(Debug, PartialEq)]
@@ -302,6 +307,14 @@ mod tests {
}
#[test]
+ fn int_to_float_round_up_overflow() {
+ assert_eq!(
+ int_to_float(&BigInt::from(0x1ff_ffff_ffff_fff9u64)),
+ 0x200_0000_0000_0000u64 as f64
+ );
+ }
+
+ #[test]
fn int_to_float_round_down() {
assert_eq!(
int_to_float(&BigInt::from(0x40_0000_0000_0001u64)),