about summary refs log tree commit diff
path: root/src/libcore/num/flt2dec
diff options
context:
space:
mode:
authorRobin Kruppe <robin.kruppe@gmail.com>2015-07-26 17:50:29 +0200
committerRobin Kruppe <robin.kruppe@gmail.com>2015-08-08 17:15:31 +0200
commitba792a4baa856d83c3001afa181db91c5b4c9732 (patch)
tree7d2096c3a3aed1829069b5e21d90e74e03da578c /src/libcore/num/flt2dec
parentb7e39a1c2dd24fd4110c22c70cad254365b0ffd3 (diff)
Accurate decimal-to-float parsing routines.
This commit primarily adds implementations of the algorithms from William
Clinger's paper "How to Read Floating Point Numbers Accurately". It also
includes a lot of infrastructure necessary for those algorithms, and some
unit tests.

Since these algorithms reject a few (extreme) inputs that were previously
accepted, this could be seen as a [breaking-change]
Diffstat (limited to 'src/libcore/num/flt2dec')
-rw-r--r--src/libcore/num/flt2dec/bignum.rs21
1 files changed, 10 insertions, 11 deletions
diff --git a/src/libcore/num/flt2dec/bignum.rs b/src/libcore/num/flt2dec/bignum.rs
index 15980f925fa..ee1f6ffdd0a 100644
--- a/src/libcore/num/flt2dec/bignum.rs
+++ b/src/libcore/num/flt2dec/bignum.rs
@@ -171,20 +171,19 @@ macro_rules! define_bignum {
             pub fn bit_length(&self) -> usize {
                 use mem;
 
-                let digitbits = mem::size_of::<$ty>()* 8;
                 // Skip over the most significant digits which are zero.
-                let nonzero = match self.digits().iter().rposition(|&x| x != 0) {
-                    Some(n) => {
-                        let end = self.size - n;
-                        &self.digits()[..end]
-                    }
-                    None => {
-                        // There are no non-zero digits, i.e. the number is zero.
-                        return 0;
-                    }
-                };
+                let digits = self.digits();
+                let zeros = digits.iter().rev().take_while(|&&x| x == 0).count();
+                let end = digits.len() - zeros;
+                let nonzero = &digits[..end];
+
+                if nonzero.is_empty() {
+                    // There are no non-zero digits, i.e. the number is zero.
+                    return 0;
+                }
                 // This could be optimized with leading_zeros() and bit shifts, but that's
                 // probably not worth the hassle.
+                let digitbits = mem::size_of::<$ty>()* 8;
                 let mut i = nonzero.len() * digitbits - 1;
                 while self.get_bit(i) == 0 {
                     i -= 1;