about summary refs log tree commit diff
path: root/src/libcore/num
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
parentb7e39a1c2dd24fd4110c22c70cad254365b0ffd3 (diff)
downloadrust-ba792a4baa856d83c3001afa181db91c5b4c9732.tar.gz
rust-ba792a4baa856d83c3001afa181db91c5b4c9732.zip
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')
-rw-r--r--src/libcore/num/dec2flt/algorithm.rs353
-rw-r--r--src/libcore/num/dec2flt/mod.rs234
-rw-r--r--src/libcore/num/dec2flt/num.rs95
-rw-r--r--src/libcore/num/dec2flt/parse.rs128
-rw-r--r--src/libcore/num/dec2flt/rawfp.rs356
-rw-r--r--src/libcore/num/dec2flt/table.rs1239
-rw-r--r--src/libcore/num/flt2dec/bignum.rs21
-rw-r--r--src/libcore/num/mod.rs9
8 files changed, 2420 insertions, 15 deletions
diff --git a/src/libcore/num/dec2flt/algorithm.rs b/src/libcore/num/dec2flt/algorithm.rs
new file mode 100644
index 00000000000..97019090b56
--- /dev/null
+++ b/src/libcore/num/dec2flt/algorithm.rs
@@ -0,0 +1,353 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! The various algorithms from the paper.
+
+use num::flt2dec::strategy::grisu::Fp;
+use prelude::v1::*;
+use cmp::min;
+use cmp::Ordering::{Less, Equal, Greater};
+use super::table;
+use super::rawfp::{self, Unpacked, RawFloat, fp_to_float, next_float, prev_float};
+use super::num::{self, Big};
+
+/// Number of significand bits in Fp
+const P: u32 = 64;
+
+// We simply store the best approximation for *all* exponents, so
+// the variable "h" and the associated conditions can be omitted.
+// This trades performance for space (11 KiB versus... 5 KiB or so?)
+
+fn power_of_ten(e: i16) -> Fp {
+    assert!(e >= table::MIN_E);
+    let i = e - table::MIN_E;
+    let sig = table::POWERS.0[i as usize];
+    let exp = table::POWERS.1[i as usize];
+    Fp { f: sig, e: exp }
+}
+
+/// The fast path of Bellerophon using machine-sized integers and floats.
+///
+/// This is extracted into a separate function so that it can be attempted before constructing
+/// a bignum.
+pub fn fast_path<T: RawFloat>(integral: &[u8], fractional: &[u8], e: i64) -> Option<T> {
+    let num_digits = integral.len() + fractional.len();
+    // log_10(f64::max_sig) ~ 15.95. We compare the exact value to max_sig near the end,
+    // this is just a quick, cheap rejection (and also frees the rest of the code from
+    // worrying about underflow).
+    if num_digits > 16 {
+        return None;
+    }
+    if e.abs() >= T::ceil_log5_of_max_sig() as i64 {
+        return None;
+    }
+    let f = num::from_str_unchecked(integral.iter().chain(fractional.iter()));
+    if f > T::max_sig() {
+        return None;
+    }
+    let e = e as i16; // Can't overflow because e.abs() <= LOG5_OF_EXP_N
+    // The case e < 0 cannot be folded into the other branch. Negative powers result in
+    // a repeating fractional part in binary, which are rounded, which causes real
+    // (and occasioally quite significant!) errors in the final result.
+    // The case `e == 0`, however, is unnecessary for correctness. It's just measurably faster.
+    if e == 0 {
+        Some(T::from_int(f))
+    } else if e > 0 {
+        Some(T::from_int(f) * fp_to_float(power_of_ten(e)))
+    } else {
+        Some(T::from_int(f) / fp_to_float(power_of_ten(-e)))
+    }
+}
+
+/// Algorithm Bellerophon is trivial code justified by non-trivial numeric analysis.
+///
+/// It rounds ``f`` to a float with 64 bit significand and multiplies it by the best approximation
+/// of `10^e` (in the same floating point format). This is often enough to get the correct result.
+/// However, when the result is close to halfway between two adjecent (ordinary) floats, the
+/// compound rounding error from multiplying two approximation means the result may be off by a
+/// few bits. When this happens, the iterative Algorithm R fixes things up.
+///
+/// The hand-wavy "close to halfway" is made precise by the numeric analysis in the paper.
+/// In the words of Clinger:
+///
+/// > Slop, expressed in units of the least significant bit, is an inclusive bound for the error
+/// > accumulated during the floating point calculation of the approximation to f * 10^e. (Slop is
+/// > not a bound for the true error, but bounds the difference between the approximation z and
+/// > the best possible approximation that uses p bits of significand.)
+pub fn bellerophon<T: RawFloat>(f: &Big, e: i16) -> T {
+    let slop;
+    if f <= &Big::from_u64(T::max_sig()) {
+        // The cases abs(e) < log5(2^N) are in fast_path()
+        slop = if e >= 0 { 0 } else { 3 };
+    } else {
+        slop = if e >= 0 { 1 } else { 4 };
+    }
+    let z = rawfp::big_to_fp(f).mul(&power_of_ten(e)).normalize();
+    let exp_p_n = 1 << (P - T::sig_bits() as u32);
+    let lowbits: i64 = (z.f % exp_p_n) as i64;
+    // Is the slop large enough to make a difference when
+    // rounding to n bits?
+    if (lowbits - exp_p_n as i64 / 2).abs() <= slop {
+        algorithm_r(f, e, fp_to_float(z))
+    } else {
+        fp_to_float(z)
+    }
+}
+
+/// An iterative algorithm that improves a floating point approximation of `f * 10^e`.
+///
+/// Each iteration gets one unit in the last place closer, which of course takes terribly long to
+/// converge if `z0` is even mildly off. Luckily, when used as fallback for Bellerophon, the
+/// starting approximation is off by at most one ULP.
+fn algorithm_r<T: RawFloat>(f: &Big, e: i16, z0: T) -> T {
+    let mut z = z0;
+    loop {
+        let raw = z.unpack();
+        let (m, k) = (raw.sig, raw.k);
+        let mut x = f.clone();
+        let mut y = Big::from_u64(m);
+
+        // Find positive integers `x`, `y` such that `x / y` is exactly `(f * 10^e) / (m * 2^k)`.
+        // This not only avoids dealing with the signs of `e` and `k`, we also eliminate the
+        // power of two common to `10^e` and `2^k` to make the numbers smaller.
+        make_ratio(&mut x, &mut y, e, k);
+
+        let m_digits = [(m & 0xFF_FF_FF_FF) as u32, (m >> 32) as u32];
+        // This is written a bit awkwardly because our bignums don't support
+        // negative numbers, so we use the absolute value + sign information.
+        // The multiplication with m_digits can't overflow. If `x` or `y` are large enough that
+        // we need to worry about overflow, then they are also large enough that`make_ratio` has
+        // reduced the fraction by a factor of 2^64 or more.
+        let (d2, d_negative) = if x >= y {
+            // Don't need x any more, save a clone().
+            x.sub(&y).mul_pow2(1).mul_digits(&m_digits);
+            (x, false)
+        } else {
+            // Still need y - make a copy.
+            let mut y = y.clone();
+            y.sub(&x).mul_pow2(1).mul_digits(&m_digits);
+            (y, true)
+        };
+
+        if d2 < y {
+            let mut d2_double = d2;
+            d2_double.mul_pow2(1);
+            if m == T::min_sig() && d_negative && d2_double > y {
+                z = prev_float(z);
+            } else {
+                return z;
+            }
+        } else if d2 == y {
+            if m % 2 == 0 {
+                if m == T::min_sig() && d_negative {
+                    z = prev_float(z);
+                } else {
+                    return z;
+                }
+            } else if d_negative {
+                z = prev_float(z);
+            } else {
+                z = next_float(z);
+            }
+        } else if d_negative {
+            z = prev_float(z);
+        } else {
+            z = next_float(z);
+        }
+    }
+}
+
+/// Given `x = f` and `y = m` where `f` represent input decimal digits as usual and `m` is the
+/// significand of a floating point approximation, make the ratio `x / y` equal to
+/// `(f * 10^e) / (m * 2^k)`, possibly reduced by a power of two both have in common.
+fn make_ratio(x: &mut Big, y: &mut Big, e: i16, k: i16) {
+    let (e_abs, k_abs) = (e.abs() as usize, k.abs() as usize);
+    if e >= 0 {
+        if k >= 0 {
+            // x = f * 10^e, y = m * 2^k, except that we reduce the fraction by some power of two.
+            let common = min(e_abs, k_abs);
+            x.mul_pow5(e_abs).mul_pow2(e_abs - common);
+            y.mul_pow2(k_abs - common);
+        } else {
+            // x = f * 10^e * 2^abs(k), y = m
+            // This can't overflow because it requires positive `e` and negative `k`, which can
+            // only happen for values extremely close to 1, which means that `e` and `k` will be
+            // comparatively tiny.
+            x.mul_pow5(e_abs).mul_pow2(e_abs + k_abs);
+        }
+    } else {
+        if k >= 0 {
+            // x = f, y = m * 10^abs(e) * 2^k
+            // This can't overflow either, see above.
+            y.mul_pow5(e_abs).mul_pow2(k_abs + e_abs);
+        } else {
+            // x = f * 2^abs(k), y = m * 10^abs(e), again reducing by a common power of two.
+            let common = min(e_abs, k_abs);
+            x.mul_pow2(k_abs - common);
+            y.mul_pow5(e_abs).mul_pow2(e_abs - common);
+        }
+    }
+}
+
+/// Conceptually, Algorithm M is the simplest way to convert a decimal to a float.
+///
+/// We form a ratio that is equal to `f * 10^e`, then throwing in powers of two until it gives
+/// a valid float significand. The binary exponent `k` is the number of times we multiplied
+/// numerator or denominator by two, i.e., at all times `f * 10^e` equals `(u / v) * 2^k`.
+/// When we have found out significand, we only need to round by inspecting the remainder of the
+/// division, which is done in helper functions further below.
+///
+/// This algorithm is super slow, even with the optimization described in `quick_start()`.
+/// However, it's the simplest of the algorithms to adapt for overflow, underflow, and subnormal
+/// results. This implementation takes over when Bellerophon and Algorithm R are overwhelmed.
+/// Detecting underflow and overflow is easy: The ratio still isn't an in-range significand,
+/// yet the minimum/maximum exponent has been reached. In the case of overflow, we simply return
+/// infinity.
+///
+/// Handling underflow and subnormals is trickier. One big problem is that, with the minimum
+/// exponent, the ratio might still be too large for a significand. See underflow() for details.
+pub fn algorithm_m<T: RawFloat>(f: &Big, e: i16) -> T {
+    let mut u;
+    let mut v;
+    let e_abs = e.abs() as usize;
+    let mut k = 0;
+    if e < 0 {
+        u = f.clone();
+        v = Big::from_small(1);
+        v.mul_pow5(e_abs).mul_pow2(e_abs);
+    } else {
+        // FIXME possible optimization: generalize big_to_fp so that we can do the equivalent of
+        // fp_to_float(big_to_fp(u)) here, only without the double rounding.
+        u = f.clone();
+        u.mul_pow5(e_abs).mul_pow2(e_abs);
+        v = Big::from_small(1);
+    }
+    quick_start::<T>(&mut u, &mut v, &mut k);
+    let mut rem = Big::from_small(0);
+    let mut x = Big::from_small(0);
+    let min_sig = Big::from_u64(T::min_sig());
+    let max_sig = Big::from_u64(T::max_sig());
+    loop {
+        u.div_rem(&v, &mut x, &mut rem);
+        if k == T::min_exp_int() {
+            // We have to stop at the minimum exponent, if we wait until `k < T::min_exp_int()`,
+            // then we'd be off by a factor of two. Unfortunately this means we have to special-
+            // case normal numbers with the minimum exponent.
+            // FIXME find a more elegant formulation, but run the `tiny-pow10` test to make sure
+            // that it's actually correct!
+            if x >= min_sig && x <= max_sig {
+                break;
+            }
+            return underflow(x, v, rem);
+        }
+        if k > T::max_exp_int() {
+            return T::infinity();
+        }
+        if x < min_sig {
+            u.mul_pow2(1);
+            k -= 1;
+        } else if x > max_sig {
+            v.mul_pow2(1);
+            k += 1;
+        } else {
+            break;
+        }
+    }
+    let q = num::to_u64(&x);
+    let z = rawfp::encode_normal(Unpacked::new(q, k));
+    round_by_remainder(v, rem, q, z)
+}
+
+/// Skip over most AlgorithmM iterations by checking the bit length.
+fn quick_start<T: RawFloat>(u: &mut Big, v: &mut Big, k: &mut i16) {
+    // The bit length is an estimate of the base two logarithm, and log(u / v) = log(u) - log(v).
+    // The estimate is off by at most 1, but always an under-estimate, so the error on log(u)
+    // and log(v) are of the same sign and cancel out (if both are large). Therefore the error
+    // for log(u / v) is at most one as well.
+    // The target ratio is one where u/v is in an in-range significand. Thus our termination
+    // condition is log2(u / v) being the significand bits, plus/minus one.
+    // FIXME Looking at the second bit could improve the estimate and avoid some more divisions.
+    let target_ratio = f64::sig_bits() as i16;
+    let log2_u = u.bit_length() as i16;
+    let log2_v = v.bit_length() as i16;
+    let mut u_shift: i16 = 0;
+    let mut v_shift: i16 = 0;
+    assert!(*k == 0);
+    loop {
+        if *k == T::min_exp_int() {
+            // Underflow or subnormal. Leave it to the main function.
+            break;
+        }
+        if *k == T::max_exp_int() {
+            // Overflow. Leave it to the main function.
+            break;
+        }
+        let log2_ratio = (log2_u + u_shift) - (log2_v + v_shift);
+        if log2_ratio < target_ratio - 1 {
+            u_shift += 1;
+            *k -= 1;
+        } else if log2_ratio > target_ratio + 1 {
+            v_shift += 1;
+            *k += 1;
+        } else {
+            break;
+        }
+    }
+    u.mul_pow2(u_shift as usize);
+    v.mul_pow2(v_shift as usize);
+}
+
+fn underflow<T: RawFloat>(x: Big, v: Big, rem: Big) -> T {
+    if x < Big::from_u64(T::min_sig()) {
+        let q = num::to_u64(&x);
+        let z = rawfp::encode_subnormal(q);
+        return round_by_remainder(v, rem, q, z);
+    }
+    // Ratio isn't an in-range significand with the minimum exponent, so we need to round off
+    // excess bits and adjust the exponent accordingly. The real value now looks like this:
+    //
+    //        x        lsb
+    // /--------------\/
+    // 1010101010101010.10101010101010 * 2^k
+    // \-----/\-------/ \------------/
+    //    q     trunc.    (represented by rem)
+    //
+    // Therefore, when the rounded-off bits are != 0.5 ULP, they decide the rounding
+    // on their own. When they are equal and the remainder is non-zero, the value still
+    // needs to be rounded up. Only when the rounded off bits are 1/2 and the remainer
+    // is zero, we have a half-to-even situation.
+    let bits = x.bit_length();
+    let lsb = bits - T::sig_bits() as usize;
+    let q = num::get_bits(&x, lsb, bits);
+    let k = T::min_exp_int() + lsb as i16;
+    let z = rawfp::encode_normal(Unpacked::new(q, k));
+    let q_even = q % 2 == 0;
+    match num::compare_with_half_ulp(&x, lsb) {
+        Greater => next_float(z),
+        Less => z,
+        Equal if rem.is_zero() && q_even => z,
+        Equal => next_float(z),
+    }
+}
+
+/// Ordinary round-to-even, obfuscated by having to round based on the remainder of a division.
+fn round_by_remainder<T: RawFloat>(v: Big, r: Big, q: u64, z: T) -> T {
+    let mut v_minus_r = v;
+    v_minus_r.sub(&r);
+    if r < v_minus_r {
+        z
+    } else if r > v_minus_r {
+        next_float(z)
+    } else if q % 2 == 0 {
+        z
+    } else {
+        next_float(z)
+    }
+}
diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs
new file mode 100644
index 00000000000..413a67b2563
--- /dev/null
+++ b/src/libcore/num/dec2flt/mod.rs
@@ -0,0 +1,234 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Converting decimal strings into IEEE 754 binary floating point numbers.
+//!
+//! # Problem statement
+//!
+//! We are given a decimal string such as `12.34e56`. This string consists of integral (`12`),
+//! fractional (`45`), and exponent (`56`) parts. All parts are optional and interpreted as zero
+//! when missing.
+//!
+//! We seek the IEEE 754 floating point number that is closest to the exact value of the decimal
+//! string. It is well-known that many decimal strings do not have terminating representations in
+//! base two, so we round to 0.5 units in the last place (in other words, as well as possible).
+//! Ties, decimal values exactly half-way between two consecutive floats, are resolved with the
+//! half-to-even strategy, also known as banker's rounding.
+//!
+//! Needless to say, this is quite hard, both in terms of implementation complexity and in terms
+//! of CPU cycles taken.
+//!
+//! # Implementation
+//!
+//! First, we ignore signs. Or rather, we remove it at the very beginning of the conversion
+//! process and re-apply it at the very end. This is correct in all edge cases since IEEE
+//! floats are symmetric around zero, negating one simply flips the first bit.
+//!
+//! Then we remove the decimal point by adjusting the exponent: Conceptually, `12.34e56` turns
+//! into `1234e54`, which we describe with a positive integer `f = 1234` and an integer `e = 54`.
+//! The `(f, e)` representation is used by almost all code past the parsing stage.
+//!
+//! We then try a long chain of progressively more general and expensive special cases using
+//! machine-sized integers and small, fixed-sized floating point numbers (first `f32`/`f64`, then
+//! a type with 64 bit significand, `Fp`). When all these fail, we bite the bullet and resort to a
+//! simple but very slow algorithm that involved computing `f * 10^e` fully and doing an iterative
+//! search for the best approximation.
+//!
+//! Primarily, this module and its children implement the algorithms described in:
+//! "How to Read Floating Point Numbers Accurately" by William D. Clinger,
+//! available online: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.45.4152
+//!
+//! In addition, there are numerous helper functions that are used in the paper but not available
+//! in Rust (or at least in core). Our version is additionally complicated by the need to handle
+//! overflow and underflow and the desire to handle subnormal numbers.  Bellerophon and
+//! Algorithm R have trouble with overflow, subnormals, and underflow. We conservatively switch to
+//! Algorithm M (with the modifications described in section 8 of the paper) well before the
+//! inputs get into the critical region.
+//!
+//! Another aspect that needs attention is the ``RawFloat`` trait by which almost all functions
+//! are parametrized. One might think that it's enough to parse to `f64` and cast the result to
+//! `f32`. Unfortunately this is not the world we live in, and this has nothing to do with using
+//! base two or half-to-even rounding.
+//!
+//! Consider for example two types `d2` and `d4` representing a decimal type with two decimal
+//! digits and four decimal digits each and take "0.01499" as input. Let's use half-up rounding.
+//! Going directly to two decimal digits gives `0.01`, but if we round to four digits first,
+//! we get `0.0150`, which is then rounded up to `0.02`. The same principle applies to other
+//! operations as well, if you want 0.5 ULP accuracy you need to do *everything* in full precision
+//! and round *exactly once, at the end*, by considering all truncated bits at once.
+//!
+//! FIXME Although some code duplication is necessary, perhaps parts of the code could be shuffled
+//! around such that less code is duplicated. Large parts of the algorithms are independent of the
+//! float type to output, or only needs access to a few constants, which could be passed in as
+//! parameters.
+//!
+//! # Other
+//!
+//! The conversion should *never* panic. There are assertions and explicit panics in the code,
+//! but they should never be triggered and only serve as internal sanity checks. Any panics should
+//! be considered a bug.
+//!
+//! There are unit tests but they are woefully inadequate at ensuring correctness, they only cover
+//! a small percentage of possible errors. Far more extensive tests are located in the directory
+//! `src/etc/test-float-parse` as a Python script.
+//!
+//! A note on integer overflow: Many parts of this file perform arithmetic with the decimal
+//! exponent `e`. Primarily, we shift the decimal point around: Before the first decimal digit,
+//! after the last decimal digit, and so on. This could overflow if done carelessly. We rely on
+//! the parsing submodule to only hand out sufficiently small exponents, where "sufficient" means
+//! "such that the exponent +/- the number of decimal digits fits into a 64 bit integer".
+//! Larger exponents are accepted, but we don't do arithmetic with them, they are immediately
+//! turned into {positive,negative} {zero,infinity}.
+//!
+//! FIXME: this uses several things from core::num::flt2dec, which is nonsense. Those things
+//! should be moved into core::num::<something else>.
+
+#![doc(hidden)]
+#![unstable(feature = "dec2flt",
+            reason = "internal routines only exposed for testing")]
+
+use prelude::v1::*;
+use num::ParseFloatError as PFE;
+use num::FloatErrorKind;
+use self::parse::{parse_decimal, Decimal, Sign};
+use self::parse::ParseResult::{self, Valid, ShortcutToInf, ShortcutToZero};
+use self::num::digits_to_big;
+use self::rawfp::RawFloat;
+
+mod algorithm;
+mod table;
+mod num;
+// These two have their own tests.
+pub mod rawfp;
+pub mod parse;
+
+/// Entry point for decimal-to-f32 conversion.
+pub fn to_f32(s: &str) -> Result<f32, PFE> {
+    dec2flt(s)
+}
+
+/// Entry point for decimal-to-f64 conversion.
+pub fn to_f64(s: &str) -> Result<f64, PFE> {
+    dec2flt(s)
+}
+
+/// Split decimal string into sign and the rest, without inspecting or validating the rest.
+fn extract_sign(s: &str) -> (Sign, &str) {
+    match s.as_bytes()[0] {
+        b'+' => (Sign::Positive, &s[1..]),
+        b'-' => (Sign::Negative, &s[1..]),
+        // If the string is invalid, we never use the sign, so we don't need to validate here.
+        _ => (Sign::Positive, s),
+    }
+}
+
+/// Convert a decimal string into a floating point number.
+fn dec2flt<T: RawFloat>(s: &str) -> Result<T, PFE> {
+    if s.is_empty() {
+        return Err(PFE { __kind: FloatErrorKind::Empty });
+    }
+    let (sign, s) = extract_sign(s);
+    let flt = match parse_decimal(s) {
+        Valid(decimal) => try!(convert(decimal)),
+        ShortcutToInf => T::infinity(),
+        ShortcutToZero => T::zero(),
+        ParseResult::Invalid => match s {
+            "inf" => T::infinity(),
+            "NaN" => T::nan(),
+            _ => { return Err(PFE { __kind: FloatErrorKind::Invalid }); }
+        }
+    };
+
+    match sign {
+        Sign::Positive => Ok(flt),
+        Sign::Negative => Ok(-flt),
+    }
+}
+
+/// The main workhorse for the decimal-to-float conversion: Orchestrate all the preprocessing
+/// and figure out which algorithm should do the actual conversion.
+fn convert<T: RawFloat>(mut decimal: Decimal) -> Result<T, PFE> {
+    simplify(&mut decimal);
+    if let Some(x) = trivial_cases(&decimal) {
+        return Ok(x);
+    }
+    // AlgorithmM and AlgorithmR both compute approximately `f * 10^e`.
+    let max_digits = decimal.integral.len() + decimal.fractional.len() +
+                     decimal.exp.abs() as usize;
+    // Remove/shift out the decimal point.
+    let e = decimal.exp - decimal.fractional.len() as i64;
+    if let Some(x) = algorithm::fast_path(decimal.integral, decimal.fractional, e) {
+        return Ok(x);
+    }
+    // Big32x40 is limited to 1280 bits, which translates to about 385 decimal digits.
+    // If we exceed this, perhaps while calculating `f * 10^e` in Algorithm R or Algorithm M,
+    // we'll crash. So we error out before getting too close, with a generous safety margin.
+    if max_digits > 375 {
+        return Err(PFE { __kind: FloatErrorKind::Invalid });
+    }
+    let f = digits_to_big(decimal.integral, decimal.fractional);
+
+    // Now the exponent certainly fits in 16 bit, which is used throughout the main algorithms.
+    let e = e as i16;
+    // FIXME These bounds are rather conservative. A more careful analysis of the failure modes
+    // of Bellerophon could allow using it in more cases for a massive speed up.
+    let exponent_in_range = table::MIN_E <= e && e <= table::MAX_E;
+    let value_in_range = max_digits <= T::max_normal_digits();
+    if exponent_in_range && value_in_range {
+        Ok(algorithm::bellerophon(&f, e))
+    } else {
+        Ok(algorithm::algorithm_m(&f, e))
+    }
+}
+
+// As written, this optimizes badly (see #27130, though it refers to an old version of the code).
+// `inline(always)` is a workaround for that. There are only two call sites overall and it doesn't
+// make code size worse.
+
+/// Strip zeros where possible, even when this requires changing the exponent
+#[inline(always)]
+fn simplify(decimal: &mut Decimal) {
+    let is_zero = &|&&d: &&u8| -> bool { d == b'0' };
+    // Trimming these zeros does not change anything but may enable the fast path (< 15 digits).
+    let leading_zeros = decimal.integral.iter().take_while(is_zero).count();
+    decimal.integral = &decimal.integral[leading_zeros..];
+    let trailing_zeros = decimal.fractional.iter().rev().take_while(is_zero).count();
+    let end = decimal.fractional.len() - trailing_zeros;
+    decimal.fractional = &decimal.fractional[..end];
+    // Simplify numbers of the form 0.0...x and x...0.0, adjusting the exponent accordingly.
+    // This may not always be a win (possibly pushes some numbers out of the fast path), but it
+    // simplifies other parts significantly (notably, approximating the magnitude of the value).
+    if decimal.integral.is_empty() {
+        let leading_zeros = decimal.fractional.iter().take_while(is_zero).count();
+        decimal.fractional = &decimal.fractional[leading_zeros..];
+        decimal.exp -= leading_zeros as i64;
+    } else if decimal.fractional.is_empty() {
+        let trailing_zeros = decimal.integral.iter().rev().take_while(is_zero).count();
+        let end = decimal.integral.len() - trailing_zeros;
+        decimal.integral = &decimal.integral[..end];
+        decimal.exp += trailing_zeros as i64;
+    }
+}
+
+/// Detect obvious overflows and underflows without even looking at the decimal digits.
+fn trivial_cases<T: RawFloat>(decimal: &Decimal) -> Option<T> {
+    // There were zeros but they were stripped by simplify()
+    if decimal.integral.is_empty() && decimal.fractional.is_empty() {
+        return Some(T::zero());
+    }
+    // This is a crude approximation of ceil(log10(the real value)).
+    let max_place = decimal.exp + decimal.integral.len() as i64;
+    if max_place > T::inf_cutoff() {
+        return Some(T::infinity());
+    } else if max_place < T::zero_cutoff() {
+        return Some(T::zero());
+    }
+    None
+}
diff --git a/src/libcore/num/dec2flt/num.rs b/src/libcore/num/dec2flt/num.rs
new file mode 100644
index 00000000000..dcba73d7c93
--- /dev/null
+++ b/src/libcore/num/dec2flt/num.rs
@@ -0,0 +1,95 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Utility functions for bignums that don't make too much sense to turn into methods.
+
+// FIXME This module's name is a bit unfortunate, since other modules also import `core::num`.
+
+use prelude::v1::*;
+use cmp::Ordering::{self, Less, Equal, Greater};
+use num::flt2dec::bignum::Big32x40;
+
+pub type Big = Big32x40;
+
+/// Test whether truncating all bits less significant than `ones_place` introduces
+/// a relative error less, equal, or greater than 0.5 ULP.
+pub fn compare_with_half_ulp(f: &Big, ones_place: usize) -> Ordering {
+    if ones_place == 0 {
+        return Less;
+    }
+    let half_bit = ones_place - 1;
+    if f.get_bit(half_bit) == 0 {
+        // < 0.5 ULP
+        return Less;
+    }
+    // If all remaining bits are zero, it's = 0.5 ULP, otherwise > 0.5
+    // If there are no more bits (half_bit == 0), the below also correctly returns Equal.
+    for i in 0..half_bit {
+        if f.get_bit(i) == 1 {
+            return Greater;
+        }
+    }
+    Equal
+}
+
+/// Convert an ASCII string containing only decimal digits to a `u64`.
+///
+/// Does not perform checks for overflow or invalid characters, so if the caller is not careful,
+/// the result is bogus and can panic (though it won't be `unsafe`). Additionally, empty strings
+/// are treated as zero. This function exists because
+///
+/// 1. using `FromStr` on `&[u8]` requires `from_utf8_unchecked`, which is bad, and
+/// 2. piecing together the results of `integral.parse()` and `fractional.parse()` is
+///    more complicated than this entire function.
+pub fn from_str_unchecked<'a, T>(bytes: T) -> u64 where T : IntoIterator<Item=&'a u8> {
+    let mut result = 0;
+    for &c in bytes {
+        result = result * 10 + (c - b'0') as u64;
+    }
+    result
+}
+
+/// Convert a string of ASCII digits into a bignum.
+///
+/// Like `from_str_unchecked`, this function relies on the parser to weed out non-digits.
+pub fn digits_to_big(integral: &[u8], fractional: &[u8]) -> Big {
+    let mut f = Big::from_small(0);
+    for &c in integral.iter().chain(fractional) {
+        let n = (c - b'0') as u32;
+        f.mul_small(10);
+        f.add_small(n);
+    }
+    f
+}
+
+/// Unwraps a bignum into a 64 bit integer. Panics if the number is too large.
+pub fn to_u64(x: &Big) -> u64 {
+    assert!(x.bit_length() < 64);
+    let d = x.digits();
+    if d.len() < 2 {
+        d[0] as u64
+    } else {
+        (d[1] as u64) << 32 | d[0] as u64
+    }
+}
+
+
+/// Extract a range of bits.
+
+/// Index 0 is the least significant bit and the range is half-open as usual.
+/// Panics if asked to extract more bits than fit into the return type.
+pub fn get_bits(x: &Big, start: usize, end: usize) -> u64 {
+    assert!(end - start <= 64);
+    let mut result: u64 = 0;
+    for i in (start..end).rev() {
+        result = result << 1 | x.get_bit(i) as u64;
+    }
+    result
+}
diff --git a/src/libcore/num/dec2flt/parse.rs b/src/libcore/num/dec2flt/parse.rs
new file mode 100644
index 00000000000..58e2a6e9bba
--- /dev/null
+++ b/src/libcore/num/dec2flt/parse.rs
@@ -0,0 +1,128 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Validating and decomposing a decimal string of the form:
+//!
+//! `(digits | digits? '.'? digits?) (('e' | 'E') ('+' | '-')? digits)?`
+//!
+//! In other words, standard floating-point syntax, with two exceptions: No sign, and no
+//! handling of "inf" and "NaN". These are handled by the driver function (super::dec2flt).
+//!
+//! Although recognizing valid inputs is relatively easy, this module also has to reject the
+//! countless invalid variations, never panic, and perform numerous checks that the other
+//! modules rely on to not panic (or overflow) in turn.
+//! To make matters worse, all that happens in a single pass over the input.
+//! So, be careful when modifying anything, and double-check with the other modules.
+use prelude::v1::*;
+use super::num;
+use self::ParseResult::{Valid, ShortcutToInf, ShortcutToZero, Invalid};
+
+#[derive(Debug)]
+pub enum Sign {
+    Positive,
+    Negative,
+}
+
+#[derive(Debug, PartialEq, Eq)]
+/// The interesting parts of a decimal string.
+pub struct Decimal<'a> {
+    pub integral: &'a [u8],
+    pub fractional: &'a [u8],
+    /// The decimal exponent, guaranteed to have fewer than 18 decimal digits.
+    pub exp: i64,
+}
+
+impl<'a> Decimal<'a> {
+    pub fn new(integral: &'a [u8], fractional: &'a [u8], exp: i64) -> Decimal<'a> {
+        Decimal { integral: integral, fractional: fractional, exp: exp }
+    }
+}
+
+#[derive(Debug, PartialEq, Eq)]
+pub enum ParseResult<'a> {
+    Valid(Decimal<'a>),
+    ShortcutToInf,
+    ShortcutToZero,
+    Invalid,
+}
+
+/// Check if the input string is a valid floating point number and if so, locate the integral
+/// part, the fractional part, and the exponent in it. Does not handle signs.
+pub fn parse_decimal(s: &str) -> ParseResult {
+    let s = s.as_bytes();
+    let (integral, s) = eat_digits(s);
+    match s.first() {
+        None => Valid(Decimal::new(integral, b"", 0)),
+        Some(&b'e') | Some(&b'E') => {
+            if integral.is_empty() {
+                return Invalid; // No digits before 'e'
+            }
+            parse_exp(integral, b"", &s[1..])
+        }
+        Some(&b'.') => {
+            let (fractional, s) = eat_digits(&s[1..]);
+            if integral.is_empty() && fractional.is_empty() && s.is_empty() {
+                // For historic reasons "." is a valid input.
+                return Valid(Decimal::new(b"", b"", 0));
+            }
+            match s.first() {
+                None => Valid(Decimal::new(integral, fractional, 0)),
+                Some(&b'e') | Some(&b'E') => parse_exp(integral, fractional, &s[1..]),
+                _ => Invalid, // Trailing junk after fractional part
+            }
+        }
+        _ => Invalid, // Trailing junk after first digit string
+    }
+}
+
+/// Carve off decimal digits up to the first non-digit character.
+fn eat_digits(s: &[u8]) -> (&[u8], &[u8]) {
+    let mut i = 0;
+    while i < s.len() && b'0' <= s[i] && s[i] <= b'9' {
+        i += 1;
+    }
+    (&s[..i], &s[i..])
+}
+
+/// Exponent extraction and error checking.
+fn parse_exp<'a>(integral: &'a [u8], fractional: &'a [u8], rest: &'a [u8]) -> ParseResult<'a> {
+    let (sign, rest) = match rest.first() {
+        Some(&b'-') => (Sign::Negative, &rest[1..]),
+        Some(&b'+') => (Sign::Positive, &rest[1..]),
+        _ => (Sign::Positive, rest),
+    };
+    let (mut number, trailing) = eat_digits(rest);
+    if !trailing.is_empty() {
+        return Invalid; // Trailing junk after exponent
+    }
+    if number.is_empty() {
+        return Invalid; // Empty exponent
+    }
+    // At this point, we certainly have a valid string of digits. It may be too long to put into
+    // an `i64`, but if it's that huge, the input is certainly zero or infinity. Since each zero
+    // in the decimal digits only adjusts the exponent by +/- 1, at exp = 10^18 the input would
+    // have to be 17 exabyte (!) of zeros to get even remotely close to being finite.
+    // This is not exactly a use case we need to cater to.
+    while number.first() == Some(&b'0') {
+        number = &number[1..];
+    }
+    if number.len() >= 18 {
+        return match sign {
+            Sign::Positive => ShortcutToInf,
+            Sign::Negative => ShortcutToZero,
+        };
+    }
+    let abs_exp = num::from_str_unchecked(number);
+    let e = match sign {
+        Sign::Positive => abs_exp as i64,
+        Sign::Negative => -(abs_exp as i64),
+    };
+    Valid(Decimal::new(integral, fractional, e))
+}
diff --git a/src/libcore/num/dec2flt/rawfp.rs b/src/libcore/num/dec2flt/rawfp.rs
new file mode 100644
index 00000000000..830d2dad42f
--- /dev/null
+++ b/src/libcore/num/dec2flt/rawfp.rs
@@ -0,0 +1,356 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Bit fiddling on positive IEEE 754 floats. Negative numbers aren't and needn't be handled.
+//! Normal floating point numbers have a canonical representation as (frac, exp) such that the
+//! value is 2^exp * (1 + sum(frac[N-i] / 2^i)) where N is the number of bits. Subnormals are
+//! slightly different and weird, but the same principle applies.
+//!
+//! Here, however, we represent them as (sig, k) with f positive, such that the value is f * 2^e.
+//! Besides making the "hidden bit" explicit, this changes the exponent by the so-called
+//! mantissa shift.
+//!
+//! Put another way, normally floats are written as (1) but here they are written as (2):
+//!
+//! 1. `1.101100...11 * 2^m`
+//! 2. `1101100...11 * 2^n`
+//!
+//! We call (1) the **fractional representation** and (2) the **integral representation**.
+//!
+//! Many functions in this module only handle normal numbers. The dec2flt routines conservatively
+//! take the universally-correct slow path (Algorithm M) for very small and very large numbers.
+//! That algorithm needs only next_float() which does handle subnormals and zeros.
+use prelude::v1::*;
+use u32;
+use cmp::Ordering::{Less, Equal, Greater};
+use ops::{Mul, Div, Neg};
+use fmt::{Debug, LowerExp};
+use mem::transmute;
+use num::flt2dec::strategy::grisu::Fp;
+use num::FpCategory::{Infinite, Zero, Subnormal, Normal, Nan};
+use num::Float;
+use super::num::{self, Big};
+
+#[derive(Copy, Clone, Debug)]
+pub struct Unpacked {
+    pub sig: u64,
+    pub k: i16,
+}
+
+impl Unpacked {
+    pub fn new(sig: u64, k: i16) -> Self {
+        Unpacked { sig: sig, k: k }
+    }
+}
+
+/// A helper trait to avoid duplicating basically all the conversion code for `f32` and `f64`.
+///
+/// See the parent module's doc comment for why this is necessary.
+///
+/// Should **never ever** be implemented for other types or be used outside the dec2flt module.
+/// Inherits from `Float` because there is some overlap, but all the reused methods are trivial.
+/// The "methods" (pseudo-constants) with default implementation should not be overriden.
+pub trait RawFloat : Float + Copy + Debug + LowerExp
+                    + Mul<Output=Self> + Div<Output=Self> + Neg<Output=Self>
+{
+    /// Get the raw binary representation of the float.
+    fn transmute(self) -> u64;
+
+    /// Transmute the raw binary representation into a float.
+    fn from_bits(bits: u64) -> Self;
+
+    /// Decode the float.
+    fn unpack(self) -> Unpacked;
+
+    /// Cast from a small integer that can be represented exactly.  Panic if the integer can't be
+    /// represented, the other code in this module makes sure to never let that happen.
+    fn from_int(x: u64) -> Self;
+
+    // FIXME Everything that follows should be associated constants, but taking the value of an
+    // associated constant from a type parameter does not work (yet?)
+    // A possible workaround is having a `FloatInfo` struct for all the constants, but so far
+    // the methods aren't painful enough to rewrite.
+
+    /// What the name says. It's easier to hard code than juggling intrinsics and
+    /// hoping LLVM constant folds it.
+    fn ceil_log5_of_max_sig() -> i16;
+
+    // A conservative bound on the decimal digits of inputs that can't produce overflow or zero or
+    /// subnormals. Probably the decimal exponent of the maximum normal value, hence the name.
+    fn max_normal_digits() -> usize;
+
+    /// When the most significant decimal digit has a place value greater than this, the number
+    /// is certainly rounded to infinity.
+    fn inf_cutoff() -> i64;
+
+    /// When the most significant decimal digit has a place value less than this, the number
+    /// is certainly rounded to zero.
+    fn zero_cutoff() -> i64;
+
+    /// The number of bits in the exponent.
+    fn exp_bits() -> u8;
+
+    /// The number of bits in the singificand, *including* the hidden bit.
+    fn sig_bits() -> u8;
+
+    /// The number of bits in the singificand, *excluding* the hidden bit.
+    fn explicit_sig_bits() -> u8 {
+        Self::sig_bits() - 1
+    }
+
+    /// The maximum legal exponent in fractional representation.
+    fn max_exp() -> i16 {
+        (1 << (Self::exp_bits() - 1)) - 1
+    }
+
+    /// The minimum legal exponent in fractional representation, excluding subnormals.
+    fn min_exp() -> i16 {
+        -Self::max_exp() + 1
+    }
+
+    /// `MAX_EXP` for integral representation, i.e., with the shift applied.
+    fn max_exp_int() -> i16 {
+        Self::max_exp() - (Self::sig_bits() as i16 - 1)
+    }
+
+    /// `MAX_EXP` encoded (i.e., with offset bias)
+    fn max_encoded_exp() -> i16 {
+        (1 << Self::exp_bits()) - 1
+    }
+
+    /// `MIN_EXP` for integral representation, i.e., with the shift applied.
+    fn min_exp_int() -> i16 {
+        Self::min_exp() - (Self::sig_bits() as i16 - 1)
+    }
+
+    /// The maximum normalized singificand in integral representation.
+    fn max_sig() -> u64 {
+        (1 << Self::sig_bits()) - 1
+    }
+
+    /// The minimal normalized significand in integral representation.
+    fn min_sig() -> u64 {
+        1 << (Self::sig_bits() - 1)
+    }
+}
+
+impl RawFloat for f32 {
+    fn sig_bits() -> u8 {
+        24
+    }
+
+    fn exp_bits() -> u8 {
+        8
+    }
+
+    fn ceil_log5_of_max_sig() -> i16 {
+        11
+    }
+
+    fn transmute(self) -> u64 {
+        let bits: u32 = unsafe { transmute(self) };
+        bits as u64
+    }
+
+    fn from_bits(bits: u64) -> f32 {
+        assert!(bits < u32::MAX as u64, "f32::from_bits: too many bits");
+        unsafe { transmute(bits as u32) }
+    }
+
+    fn unpack(self) -> Unpacked {
+        let (sig, exp, _sig) = self.integer_decode();
+        Unpacked::new(sig, exp)
+    }
+
+    fn from_int(x: u64) -> f32 {
+        // rkruppe is uncertain whether `as` rounds correctly on all platforms.
+        debug_assert!(x as f32 == fp_to_float(Fp { f: x, e: 0 }));
+        x as f32
+    }
+
+    fn max_normal_digits() -> usize {
+        35
+    }
+
+    fn inf_cutoff() -> i64 {
+        40
+    }
+
+    fn zero_cutoff() -> i64 {
+        -48
+    }
+}
+
+
+impl RawFloat for f64 {
+    fn sig_bits() -> u8 {
+        53
+    }
+
+    fn exp_bits() -> u8 {
+        11
+    }
+
+    fn ceil_log5_of_max_sig() -> i16 {
+        23
+    }
+
+    fn transmute(self) -> u64 {
+        let bits: u64 = unsafe { transmute(self) };
+        bits
+    }
+
+    fn from_bits(bits: u64) -> f64 {
+        unsafe { transmute(bits) }
+    }
+
+    fn unpack(self) -> Unpacked {
+        let (sig, exp, _sig) = self.integer_decode();
+        Unpacked::new(sig, exp)
+    }
+
+    fn from_int(x: u64) -> f64 {
+        // rkruppe is uncertain whether `as` rounds correctly on all platforms.
+        debug_assert!(x as f64 == fp_to_float(Fp { f: x, e: 0 }));
+        x as f64
+    }
+
+    fn max_normal_digits() -> usize {
+        305
+    }
+
+    fn inf_cutoff() -> i64 {
+        310
+    }
+
+    fn zero_cutoff() -> i64 {
+        -326
+    }
+
+}
+
+/// Convert an Fp to the closest f64. Only handles number that fit into a normalized f64.
+pub fn fp_to_float<T: RawFloat>(x: Fp) -> T {
+    let x = x.normalize();
+    // x.f is 64 bit, so x.e has a mantissa shift of 63
+    let e = x.e + 63;
+    if e > T::max_exp() {
+        panic!("fp_to_float: exponent {} too large", e)
+    }  else if e > T::min_exp() {
+        encode_normal(round_normal::<T>(x))
+    } else {
+        panic!("fp_to_float: exponent {} too small", e)
+    }
+}
+
+/// Round the 64-bit significand to 53 bit with half-to-even. Does not handle exponent overflow.
+pub fn round_normal<T: RawFloat>(x: Fp) -> Unpacked {
+    let excess = 64 - T::sig_bits() as i16;
+    let half: u64 = 1 << (excess - 1);
+    let (q, rem) = (x.f >> excess, x.f & ((1 << excess) - 1));
+    assert_eq!(q << excess | rem, x.f);
+    // Adjust mantissa shift
+    let k = x.e + excess;
+    if rem < half {
+        Unpacked::new(q, k)
+    } else if rem == half && (q % 2) == 0 {
+        Unpacked::new(q, k)
+    } else if q == T::max_sig() {
+        Unpacked::new(T::min_sig(), k + 1)
+    } else {
+        Unpacked::new(q + 1, k)
+    }
+}
+
+/// Inverse of `RawFloat::unpack()` for normalized numbers.
+/// Panics if the significand or exponent are not valid for normalized numbers.
+pub fn encode_normal<T: RawFloat>(x: Unpacked) -> T {
+    debug_assert!(T::min_sig() <= x.sig && x.sig <= T::max_sig(),
+        "encode_normal: significand not normalized");
+    // Remove the hidden bit
+    let sig_enc = x.sig & !(1 << T::explicit_sig_bits());
+    // Adjust the exponent for exponent bias and mantissa shift
+    let k_enc = x.k + T::max_exp() + T::explicit_sig_bits() as i16;
+    debug_assert!(k_enc != 0 && k_enc < T::max_encoded_exp(),
+        "encode_normal: exponent out of range");
+    // Leave sign bit at 0 ("+"), our numbers are all positive
+    let bits = (k_enc as u64) << T::explicit_sig_bits() | sig_enc;
+    T::from_bits(bits)
+}
+
+/// Construct the subnormal. A mantissa of 0 is allowed and constructs zero.
+pub fn encode_subnormal<T: RawFloat>(significand: u64) -> T {
+    assert!(significand < T::min_sig(), "encode_subnormal: not actually subnormal");
+    // Êncoded exponent is 0, the sign bit is 0, so we just have to reinterpret the bits.
+    T::from_bits(significand)
+}
+
+/// Approximate a bignum with an Fp. Rounds within 0.5 ULP with half-to-even.
+pub fn big_to_fp(f: &Big) -> Fp {
+    let end = f.bit_length();
+    assert!(end != 0, "big_to_fp: unexpectedly, input is zero");
+    let start = end.saturating_sub(64);
+    let leading = num::get_bits(f, start, end);
+    // We cut off all bits prior to the index `start`, i.e., we effectively right-shift by
+    // an amount of `start`, so this is also the exponent we need.
+    let e = start as i16;
+    let rounded_down = Fp { f: leading, e: e }.normalize();
+    // Round (half-to-even) depending on the truncated bits.
+    match num::compare_with_half_ulp(f, start) {
+        Less => rounded_down,
+        Equal if leading % 2 == 0 => rounded_down,
+        Equal | Greater => match leading.checked_add(1) {
+            Some(f) => Fp { f: f, e: e }.normalize(),
+            None => Fp { f: 1 << 63, e: e + 1 },
+        }
+    }
+}
+
+/// Find the largest floating point number strictly smaller than the argument.
+/// Does not handle subnormals, zero, or exponent underflow.
+pub fn prev_float<T: RawFloat>(x: T) -> T {
+    match x.classify() {
+        Infinite => panic!("prev_float: argument is infinite"),
+        Nan => panic!("prev_float: argument is NaN"),
+        Subnormal => panic!("prev_float: argument is subnormal"),
+        Zero => panic!("prev_float: argument is zero"),
+        Normal => {
+            let Unpacked { sig, k } = x.unpack();
+            if sig == T::min_sig() {
+                encode_normal(Unpacked::new(T::max_sig(), k - 1))
+            } else {
+                encode_normal(Unpacked::new(sig - 1, k))
+            }
+        }
+    }
+}
+
+// Find the smallest floating point number strictly larger than the argument.
+// This operation is saturating, i.e. next_float(inf) == inf.
+// Unlike most code in this module, this function does handle zero, subnormals, and infinities.
+// However, like all other code here, it does not deal with NaN and negative numbers.
+pub fn next_float<T: RawFloat>(x: T) -> T {
+    match x.classify() {
+        Nan => panic!("next_float: argument is NaN"),
+        Infinite => T::infinity(),
+        // This seems too good to be true, but it works.
+        // 0.0 is encoded as the all-zero word. Subnormals are 0x000m...m where m is the mantissa.
+        // In particular, the smallest subnormal is 0x0...01 and the largest is 0x000F...F.
+        // The smallest normal number is 0x0010...0, so this corner case works as well.
+        // If the increment overflows the mantissa, the carry bit increments the exponent as we
+        // want, and the mantissa bits become zero. Because of the hidden bit convention, this
+        // too is exactly what we want!
+        // Finally, f64::MAX + 1 = 7eff...f + 1 = 7ff0...0 = f64::INFINITY.
+        Zero | Subnormal | Normal => {
+            let bits: u64 = x.transmute();
+            T::from_bits(bits + 1)
+        }
+    }
+}
diff --git a/src/libcore/num/dec2flt/table.rs b/src/libcore/num/dec2flt/table.rs
new file mode 100644
index 00000000000..dd985fd155b
--- /dev/null
+++ b/src/libcore/num/dec2flt/table.rs
@@ -0,0 +1,1239 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+// Table of approximations of powers of ten.
+// DO NOT MODIFY: Generated by a src/etc/dec2flt_table.py
+pub const MIN_E: i16 = -305;
+pub const MAX_E: i16 = 305;
+
+pub const POWERS: ([u64; 611], [i16; 611]) = ([
+    0xe0b62e2929aba83c,
+    0x8c71dcd9ba0b4926,
+    0xaf8e5410288e1b6f,
+    0xdb71e91432b1a24b,
+    0x892731ac9faf056f,
+    0xab70fe17c79ac6ca,
+    0xd64d3d9db981787d,
+    0x85f0468293f0eb4e,
+    0xa76c582338ed2622,
+    0xd1476e2c07286faa,
+    0x82cca4db847945ca,
+    0xa37fce126597973d,
+    0xcc5fc196fefd7d0c,
+    0xff77b1fcbebcdc4f,
+    0x9faacf3df73609b1,
+    0xc795830d75038c1e,
+    0xf97ae3d0d2446f25,
+    0x9becce62836ac577,
+    0xc2e801fb244576d5,
+    0xf3a20279ed56d48a,
+    0x9845418c345644d7,
+    0xbe5691ef416bd60c,
+    0xedec366b11c6cb8f,
+    0x94b3a202eb1c3f39,
+    0xb9e08a83a5e34f08,
+    0xe858ad248f5c22ca,
+    0x91376c36d99995be,
+    0xb58547448ffffb2e,
+    0xe2e69915b3fff9f9,
+    0x8dd01fad907ffc3c,
+    0xb1442798f49ffb4b,
+    0xdd95317f31c7fa1d,
+    0x8a7d3eef7f1cfc52,
+    0xad1c8eab5ee43b67,
+    0xd863b256369d4a41,
+    0x873e4f75e2224e68,
+    0xa90de3535aaae202,
+    0xd3515c2831559a83,
+    0x8412d9991ed58092,
+    0xa5178fff668ae0b6,
+    0xce5d73ff402d98e4,
+    0x80fa687f881c7f8e,
+    0xa139029f6a239f72,
+    0xc987434744ac874f,
+    0xfbe9141915d7a922,
+    0x9d71ac8fada6c9b5,
+    0xc4ce17b399107c23,
+    0xf6019da07f549b2b,
+    0x99c102844f94e0fb,
+    0xc0314325637a193a,
+    0xf03d93eebc589f88,
+    0x96267c7535b763b5,
+    0xbbb01b9283253ca3,
+    0xea9c227723ee8bcb,
+    0x92a1958a7675175f,
+    0xb749faed14125d37,
+    0xe51c79a85916f485,
+    0x8f31cc0937ae58d3,
+    0xb2fe3f0b8599ef08,
+    0xdfbdcece67006ac9,
+    0x8bd6a141006042be,
+    0xaecc49914078536d,
+    0xda7f5bf590966849,
+    0x888f99797a5e012d,
+    0xaab37fd7d8f58179,
+    0xd5605fcdcf32e1d7,
+    0x855c3be0a17fcd26,
+    0xa6b34ad8c9dfc070,
+    0xd0601d8efc57b08c,
+    0x823c12795db6ce57,
+    0xa2cb1717b52481ed,
+    0xcb7ddcdda26da269,
+    0xfe5d54150b090b03,
+    0x9efa548d26e5a6e2,
+    0xc6b8e9b0709f109a,
+    0xf867241c8cc6d4c1,
+    0x9b407691d7fc44f8,
+    0xc21094364dfb5637,
+    0xf294b943e17a2bc4,
+    0x979cf3ca6cec5b5b,
+    0xbd8430bd08277231,
+    0xece53cec4a314ebe,
+    0x940f4613ae5ed137,
+    0xb913179899f68584,
+    0xe757dd7ec07426e5,
+    0x9096ea6f3848984f,
+    0xb4bca50b065abe63,
+    0xe1ebce4dc7f16dfc,
+    0x8d3360f09cf6e4bd,
+    0xb080392cc4349ded,
+    0xdca04777f541c568,
+    0x89e42caaf9491b61,
+    0xac5d37d5b79b6239,
+    0xd77485cb25823ac7,
+    0x86a8d39ef77164bd,
+    0xa8530886b54dbdec,
+    0xd267caa862a12d67,
+    0x8380dea93da4bc60,
+    0xa46116538d0deb78,
+    0xcd795be870516656,
+    0x806bd9714632dff6,
+    0xa086cfcd97bf97f4,
+    0xc8a883c0fdaf7df0,
+    0xfad2a4b13d1b5d6c,
+    0x9cc3a6eec6311a64,
+    0xc3f490aa77bd60fd,
+    0xf4f1b4d515acb93c,
+    0x991711052d8bf3c5,
+    0xbf5cd54678eef0b7,
+    0xef340a98172aace5,
+    0x9580869f0e7aac0f,
+    0xbae0a846d2195713,
+    0xe998d258869facd7,
+    0x91ff83775423cc06,
+    0xb67f6455292cbf08,
+    0xe41f3d6a7377eeca,
+    0x8e938662882af53e,
+    0xb23867fb2a35b28e,
+    0xdec681f9f4c31f31,
+    0x8b3c113c38f9f37f,
+    0xae0b158b4738705f,
+    0xd98ddaee19068c76,
+    0x87f8a8d4cfa417ca,
+    0xa9f6d30a038d1dbc,
+    0xd47487cc8470652b,
+    0x84c8d4dfd2c63f3b,
+    0xa5fb0a17c777cf0a,
+    0xcf79cc9db955c2cc,
+    0x81ac1fe293d599c0,
+    0xa21727db38cb0030,
+    0xca9cf1d206fdc03c,
+    0xfd442e4688bd304b,
+    0x9e4a9cec15763e2f,
+    0xc5dd44271ad3cdba,
+    0xf7549530e188c129,
+    0x9a94dd3e8cf578ba,
+    0xc13a148e3032d6e8,
+    0xf18899b1bc3f8ca2,
+    0x96f5600f15a7b7e5,
+    0xbcb2b812db11a5de,
+    0xebdf661791d60f56,
+    0x936b9fcebb25c996,
+    0xb84687c269ef3bfb,
+    0xe65829b3046b0afa,
+    0x8ff71a0fe2c2e6dc,
+    0xb3f4e093db73a093,
+    0xe0f218b8d25088b8,
+    0x8c974f7383725573,
+    0xafbd2350644eead0,
+    0xdbac6c247d62a584,
+    0x894bc396ce5da772,
+    0xab9eb47c81f5114f,
+    0xd686619ba27255a3,
+    0x8613fd0145877586,
+    0xa798fc4196e952e7,
+    0xd17f3b51fca3a7a1,
+    0x82ef85133de648c5,
+    0xa3ab66580d5fdaf6,
+    0xcc963fee10b7d1b3,
+    0xffbbcfe994e5c620,
+    0x9fd561f1fd0f9bd4,
+    0xc7caba6e7c5382c9,
+    0xf9bd690a1b68637b,
+    0x9c1661a651213e2d,
+    0xc31bfa0fe5698db8,
+    0xf3e2f893dec3f126,
+    0x986ddb5c6b3a76b8,
+    0xbe89523386091466,
+    0xee2ba6c0678b597f,
+    0x94db483840b717f0,
+    0xba121a4650e4ddec,
+    0xe896a0d7e51e1566,
+    0x915e2486ef32cd60,
+    0xb5b5ada8aaff80b8,
+    0xe3231912d5bf60e6,
+    0x8df5efabc5979c90,
+    0xb1736b96b6fd83b4,
+    0xddd0467c64bce4a1,
+    0x8aa22c0dbef60ee4,
+    0xad4ab7112eb3929e,
+    0xd89d64d57a607745,
+    0x87625f056c7c4a8b,
+    0xa93af6c6c79b5d2e,
+    0xd389b47879823479,
+    0x843610cb4bf160cc,
+    0xa54394fe1eedb8ff,
+    0xce947a3da6a9273e,
+    0x811ccc668829b887,
+    0xa163ff802a3426a9,
+    0xc9bcff6034c13053,
+    0xfc2c3f3841f17c68,
+    0x9d9ba7832936edc1,
+    0xc5029163f384a931,
+    0xf64335bcf065d37d,
+    0x99ea0196163fa42e,
+    0xc06481fb9bcf8d3a,
+    0xf07da27a82c37088,
+    0x964e858c91ba2655,
+    0xbbe226efb628afeb,
+    0xeadab0aba3b2dbe5,
+    0x92c8ae6b464fc96f,
+    0xb77ada0617e3bbcb,
+    0xe55990879ddcaabe,
+    0x8f57fa54c2a9eab7,
+    0xb32df8e9f3546564,
+    0xdff9772470297ebd,
+    0x8bfbea76c619ef36,
+    0xaefae51477a06b04,
+    0xdab99e59958885c5,
+    0x88b402f7fd75539b,
+    0xaae103b5fcd2a882,
+    0xd59944a37c0752a2,
+    0x857fcae62d8493a5,
+    0xa6dfbd9fb8e5b88f,
+    0xd097ad07a71f26b2,
+    0x825ecc24c8737830,
+    0xa2f67f2dfa90563b,
+    0xcbb41ef979346bca,
+    0xfea126b7d78186bd,
+    0x9f24b832e6b0f436,
+    0xc6ede63fa05d3144,
+    0xf8a95fcf88747d94,
+    0x9b69dbe1b548ce7d,
+    0xc24452da229b021c,
+    0xf2d56790ab41c2a3,
+    0x97c560ba6b0919a6,
+    0xbdb6b8e905cb600f,
+    0xed246723473e3813,
+    0x9436c0760c86e30c,
+    0xb94470938fa89bcf,
+    0xe7958cb87392c2c3,
+    0x90bd77f3483bb9ba,
+    0xb4ecd5f01a4aa828,
+    0xe2280b6c20dd5232,
+    0x8d590723948a535f,
+    0xb0af48ec79ace837,
+    0xdcdb1b2798182245,
+    0x8a08f0f8bf0f156b,
+    0xac8b2d36eed2dac6,
+    0xd7adf884aa879177,
+    0x86ccbb52ea94baeb,
+    0xa87fea27a539e9a5,
+    0xd29fe4b18e88640f,
+    0x83a3eeeef9153e89,
+    0xa48ceaaab75a8e2b,
+    0xcdb02555653131b6,
+    0x808e17555f3ebf12,
+    0xa0b19d2ab70e6ed6,
+    0xc8de047564d20a8c,
+    0xfb158592be068d2f,
+    0x9ced737bb6c4183d,
+    0xc428d05aa4751e4d,
+    0xf53304714d9265e0,
+    0x993fe2c6d07b7fac,
+    0xbf8fdb78849a5f97,
+    0xef73d256a5c0f77d,
+    0x95a8637627989aae,
+    0xbb127c53b17ec159,
+    0xe9d71b689dde71b0,
+    0x9226712162ab070e,
+    0xb6b00d69bb55c8d1,
+    0xe45c10c42a2b3b06,
+    0x8eb98a7a9a5b04e3,
+    0xb267ed1940f1c61c,
+    0xdf01e85f912e37a3,
+    0x8b61313bbabce2c6,
+    0xae397d8aa96c1b78,
+    0xd9c7dced53c72256,
+    0x881cea14545c7575,
+    0xaa242499697392d3,
+    0xd4ad2dbfc3d07788,
+    0x84ec3c97da624ab5,
+    0xa6274bbdd0fadd62,
+    0xcfb11ead453994ba,
+    0x81ceb32c4b43fcf5,
+    0xa2425ff75e14fc32,
+    0xcad2f7f5359a3b3e,
+    0xfd87b5f28300ca0e,
+    0x9e74d1b791e07e48,
+    0xc612062576589ddb,
+    0xf79687aed3eec551,
+    0x9abe14cd44753b53,
+    0xc16d9a0095928a27,
+    0xf1c90080baf72cb1,
+    0x971da05074da7bef,
+    0xbce5086492111aeb,
+    0xec1e4a7db69561a5,
+    0x9392ee8e921d5d07,
+    0xb877aa3236a4b449,
+    0xe69594bec44de15b,
+    0x901d7cf73ab0acd9,
+    0xb424dc35095cd80f,
+    0xe12e13424bb40e13,
+    0x8cbccc096f5088cc,
+    0xafebff0bcb24aaff,
+    0xdbe6fecebdedd5bf,
+    0x89705f4136b4a597,
+    0xabcc77118461cefd,
+    0xd6bf94d5e57a42bc,
+    0x8637bd05af6c69b6,
+    0xa7c5ac471b478423,
+    0xd1b71758e219652c,
+    0x83126e978d4fdf3b,
+    0xa3d70a3d70a3d70a,
+    0xcccccccccccccccd,
+    0x8000000000000000,
+    0xa000000000000000,
+    0xc800000000000000,
+    0xfa00000000000000,
+    0x9c40000000000000,
+    0xc350000000000000,
+    0xf424000000000000,
+    0x9896800000000000,
+    0xbebc200000000000,
+    0xee6b280000000000,
+    0x9502f90000000000,
+    0xba43b74000000000,
+    0xe8d4a51000000000,
+    0x9184e72a00000000,
+    0xb5e620f480000000,
+    0xe35fa931a0000000,
+    0x8e1bc9bf04000000,
+    0xb1a2bc2ec5000000,
+    0xde0b6b3a76400000,
+    0x8ac7230489e80000,
+    0xad78ebc5ac620000,
+    0xd8d726b7177a8000,
+    0x878678326eac9000,
+    0xa968163f0a57b400,
+    0xd3c21bcecceda100,
+    0x84595161401484a0,
+    0xa56fa5b99019a5c8,
+    0xcecb8f27f4200f3a,
+    0x813f3978f8940984,
+    0xa18f07d736b90be5,
+    0xc9f2c9cd04674edf,
+    0xfc6f7c4045812296,
+    0x9dc5ada82b70b59e,
+    0xc5371912364ce305,
+    0xf684df56c3e01bc7,
+    0x9a130b963a6c115c,
+    0xc097ce7bc90715b3,
+    0xf0bdc21abb48db20,
+    0x96769950b50d88f4,
+    0xbc143fa4e250eb31,
+    0xeb194f8e1ae525fd,
+    0x92efd1b8d0cf37be,
+    0xb7abc627050305ae,
+    0xe596b7b0c643c719,
+    0x8f7e32ce7bea5c70,
+    0xb35dbf821ae4f38c,
+    0xe0352f62a19e306f,
+    0x8c213d9da502de45,
+    0xaf298d050e4395d7,
+    0xdaf3f04651d47b4c,
+    0x88d8762bf324cd10,
+    0xab0e93b6efee0054,
+    0xd5d238a4abe98068,
+    0x85a36366eb71f041,
+    0xa70c3c40a64e6c52,
+    0xd0cf4b50cfe20766,
+    0x82818f1281ed44a0,
+    0xa321f2d7226895c8,
+    0xcbea6f8ceb02bb3a,
+    0xfee50b7025c36a08,
+    0x9f4f2726179a2245,
+    0xc722f0ef9d80aad6,
+    0xf8ebad2b84e0d58c,
+    0x9b934c3b330c8577,
+    0xc2781f49ffcfa6d5,
+    0xf316271c7fc3908b,
+    0x97edd871cfda3a57,
+    0xbde94e8e43d0c8ec,
+    0xed63a231d4c4fb27,
+    0x945e455f24fb1cf9,
+    0xb975d6b6ee39e437,
+    0xe7d34c64a9c85d44,
+    0x90e40fbeea1d3a4b,
+    0xb51d13aea4a488dd,
+    0xe264589a4dcdab15,
+    0x8d7eb76070a08aed,
+    0xb0de65388cc8ada8,
+    0xdd15fe86affad912,
+    0x8a2dbf142dfcc7ab,
+    0xacb92ed9397bf996,
+    0xd7e77a8f87daf7fc,
+    0x86f0ac99b4e8dafd,
+    0xa8acd7c0222311bd,
+    0xd2d80db02aabd62c,
+    0x83c7088e1aab65db,
+    0xa4b8cab1a1563f52,
+    0xcde6fd5e09abcf27,
+    0x80b05e5ac60b6178,
+    0xa0dc75f1778e39d6,
+    0xc913936dd571c84c,
+    0xfb5878494ace3a5f,
+    0x9d174b2dcec0e47b,
+    0xc45d1df942711d9a,
+    0xf5746577930d6501,
+    0x9968bf6abbe85f20,
+    0xbfc2ef456ae276e9,
+    0xefb3ab16c59b14a3,
+    0x95d04aee3b80ece6,
+    0xbb445da9ca61281f,
+    0xea1575143cf97227,
+    0x924d692ca61be758,
+    0xb6e0c377cfa2e12e,
+    0xe498f455c38b997a,
+    0x8edf98b59a373fec,
+    0xb2977ee300c50fe7,
+    0xdf3d5e9bc0f653e1,
+    0x8b865b215899f46d,
+    0xae67f1e9aec07188,
+    0xda01ee641a708dea,
+    0x884134fe908658b2,
+    0xaa51823e34a7eedf,
+    0xd4e5e2cdc1d1ea96,
+    0x850fadc09923329e,
+    0xa6539930bf6bff46,
+    0xcfe87f7cef46ff17,
+    0x81f14fae158c5f6e,
+    0xa26da3999aef774a,
+    0xcb090c8001ab551c,
+    0xfdcb4fa002162a63,
+    0x9e9f11c4014dda7e,
+    0xc646d63501a1511e,
+    0xf7d88bc24209a565,
+    0x9ae757596946075f,
+    0xc1a12d2fc3978937,
+    0xf209787bb47d6b85,
+    0x9745eb4d50ce6333,
+    0xbd176620a501fc00,
+    0xec5d3fa8ce427b00,
+    0x93ba47c980e98ce0,
+    0xb8a8d9bbe123f018,
+    0xe6d3102ad96cec1e,
+    0x9043ea1ac7e41393,
+    0xb454e4a179dd1877,
+    0xe16a1dc9d8545e95,
+    0x8ce2529e2734bb1d,
+    0xb01ae745b101e9e4,
+    0xdc21a1171d42645d,
+    0x899504ae72497eba,
+    0xabfa45da0edbde69,
+    0xd6f8d7509292d603,
+    0x865b86925b9bc5c2,
+    0xa7f26836f282b733,
+    0xd1ef0244af2364ff,
+    0x8335616aed761f1f,
+    0xa402b9c5a8d3a6e7,
+    0xcd036837130890a1,
+    0x802221226be55a65,
+    0xa02aa96b06deb0fe,
+    0xc83553c5c8965d3d,
+    0xfa42a8b73abbf48d,
+    0x9c69a97284b578d8,
+    0xc38413cf25e2d70e,
+    0xf46518c2ef5b8cd1,
+    0x98bf2f79d5993803,
+    0xbeeefb584aff8604,
+    0xeeaaba2e5dbf6785,
+    0x952ab45cfa97a0b3,
+    0xba756174393d88e0,
+    0xe912b9d1478ceb17,
+    0x91abb422ccb812ef,
+    0xb616a12b7fe617aa,
+    0xe39c49765fdf9d95,
+    0x8e41ade9fbebc27d,
+    0xb1d219647ae6b31c,
+    0xde469fbd99a05fe3,
+    0x8aec23d680043bee,
+    0xada72ccc20054aea,
+    0xd910f7ff28069da4,
+    0x87aa9aff79042287,
+    0xa99541bf57452b28,
+    0xd3fa922f2d1675f2,
+    0x847c9b5d7c2e09b7,
+    0xa59bc234db398c25,
+    0xcf02b2c21207ef2f,
+    0x8161afb94b44f57d,
+    0xa1ba1ba79e1632dc,
+    0xca28a291859bbf93,
+    0xfcb2cb35e702af78,
+    0x9defbf01b061adab,
+    0xc56baec21c7a1916,
+    0xf6c69a72a3989f5c,
+    0x9a3c2087a63f6399,
+    0xc0cb28a98fcf3c80,
+    0xf0fdf2d3f3c30b9f,
+    0x969eb7c47859e744,
+    0xbc4665b596706115,
+    0xeb57ff22fc0c795a,
+    0x9316ff75dd87cbd8,
+    0xb7dcbf5354e9bece,
+    0xe5d3ef282a242e82,
+    0x8fa475791a569d11,
+    0xb38d92d760ec4455,
+    0xe070f78d3927556b,
+    0x8c469ab843b89563,
+    0xaf58416654a6babb,
+    0xdb2e51bfe9d0696a,
+    0x88fcf317f22241e2,
+    0xab3c2fddeeaad25b,
+    0xd60b3bd56a5586f2,
+    0x85c7056562757457,
+    0xa738c6bebb12d16d,
+    0xd106f86e69d785c8,
+    0x82a45b450226b39d,
+    0xa34d721642b06084,
+    0xcc20ce9bd35c78a5,
+    0xff290242c83396ce,
+    0x9f79a169bd203e41,
+    0xc75809c42c684dd1,
+    0xf92e0c3537826146,
+    0x9bbcc7a142b17ccc,
+    0xc2abf989935ddbfe,
+    0xf356f7ebf83552fe,
+    0x98165af37b2153df,
+    0xbe1bf1b059e9a8d6,
+    0xeda2ee1c7064130c,
+    0x9485d4d1c63e8be8,
+    0xb9a74a0637ce2ee1,
+    0xe8111c87c5c1ba9a,
+    0x910ab1d4db9914a0,
+    0xb54d5e4a127f59c8,
+    0xe2a0b5dc971f303a,
+    0x8da471a9de737e24,
+    0xb10d8e1456105dad,
+    0xdd50f1996b947519,
+    0x8a5296ffe33cc930,
+    0xace73cbfdc0bfb7b,
+    0xd8210befd30efa5a,
+    0x8714a775e3e95c78,
+    0xa8d9d1535ce3b396,
+    0xd31045a8341ca07c,
+    0x83ea2b892091e44e,
+    0xa4e4b66b68b65d61,
+    0xce1de40642e3f4b9,
+    0x80d2ae83e9ce78f4,
+    0xa1075a24e4421731,
+    0xc94930ae1d529cfd,
+    0xfb9b7cd9a4a7443c,
+    0x9d412e0806e88aa6,
+    0xc491798a08a2ad4f,
+    0xf5b5d7ec8acb58a3,
+    0x9991a6f3d6bf1766,
+    0xbff610b0cc6edd3f,
+    0xeff394dcff8a948f,
+    0x95f83d0a1fb69cd9,
+    0xbb764c4ca7a44410,
+    0xea53df5fd18d5514,
+    0x92746b9be2f8552c,
+    0xb7118682dbb66a77,
+    0xe4d5e82392a40515,
+    0x8f05b1163ba6832d,
+    0xb2c71d5bca9023f8,
+    0xdf78e4b2bd342cf7,
+    0x8bab8eefb6409c1a,
+    0xae9672aba3d0c321,
+    0xda3c0f568cc4f3e9,
+    0x8865899617fb1871,
+    0xaa7eebfb9df9de8e,
+    0xd51ea6fa85785631,
+    0x8533285c936b35df,
+    0xa67ff273b8460357,
+    0xd01fef10a657842c,
+    0x8213f56a67f6b29c,
+    0xa298f2c501f45f43,
+    0xcb3f2f7642717713,
+    0xfe0efb53d30dd4d8,
+    0x9ec95d1463e8a507,
+    0xc67bb4597ce2ce49,
+    0xf81aa16fdc1b81db,
+    0x9b10a4e5e9913129,
+    0xc1d4ce1f63f57d73,
+    0xf24a01a73cf2dcd0,
+    0x976e41088617ca02,
+    0xbd49d14aa79dbc82,
+    0xec9c459d51852ba3,
+    0x93e1ab8252f33b46,
+    0xb8da1662e7b00a17,
+    0xe7109bfba19c0c9d,
+    0x906a617d450187e2,
+    0xb484f9dc9641e9db,
+    0xe1a63853bbd26451,
+    0x8d07e33455637eb3,
+    0xb049dc016abc5e60,
+    0xdc5c5301c56b75f7,
+    0x89b9b3e11b6329bb,
+    0xac2820d9623bf429,
+    0xd732290fbacaf134,
+    0x867f59a9d4bed6c0,
+    0xa81f301449ee8c70,
+    0xd226fc195c6a2f8c,
+    0x83585d8fd9c25db8,
+    0xa42e74f3d032f526,
+    0xcd3a1230c43fb26f,
+    0x80444b5e7aa7cf85,
+    0xa0555e361951c367,
+    0xc86ab5c39fa63441,
+    0xfa856334878fc151,
+    0x9c935e00d4b9d8d2,
+    0xc3b8358109e84f07,
+    0xf4a642e14c6262c9,
+    0x98e7e9cccfbd7dbe,
+    0xbf21e44003acdd2d,
+    0xeeea5d5004981478,
+    0x95527a5202df0ccb,
+    0xbaa718e68396cffe,
+    0xe950df20247c83fd,
+    0x91d28b7416cdd27e,
+], [
+    -1077,
+    -1073,
+    -1070,
+    -1067,
+    -1063,
+    -1060,
+    -1057,
+    -1053,
+    -1050,
+    -1047,
+    -1043,
+    -1040,
+    -1037,
+    -1034,
+    -1030,
+    -1027,
+    -1024,
+    -1020,
+    -1017,
+    -1014,
+    -1010,
+    -1007,
+    -1004,
+    -1000,
+    -997,
+    -994,
+    -990,
+    -987,
+    -984,
+    -980,
+    -977,
+    -974,
+    -970,
+    -967,
+    -964,
+    -960,
+    -957,
+    -954,
+    -950,
+    -947,
+    -944,
+    -940,
+    -937,
+    -934,
+    -931,
+    -927,
+    -924,
+    -921,
+    -917,
+    -914,
+    -911,
+    -907,
+    -904,
+    -901,
+    -897,
+    -894,
+    -891,
+    -887,
+    -884,
+    -881,
+    -877,
+    -874,
+    -871,
+    -867,
+    -864,
+    -861,
+    -857,
+    -854,
+    -851,
+    -847,
+    -844,
+    -841,
+    -838,
+    -834,
+    -831,
+    -828,
+    -824,
+    -821,
+    -818,
+    -814,
+    -811,
+    -808,
+    -804,
+    -801,
+    -798,
+    -794,
+    -791,
+    -788,
+    -784,
+    -781,
+    -778,
+    -774,
+    -771,
+    -768,
+    -764,
+    -761,
+    -758,
+    -754,
+    -751,
+    -748,
+    -744,
+    -741,
+    -738,
+    -735,
+    -731,
+    -728,
+    -725,
+    -721,
+    -718,
+    -715,
+    -711,
+    -708,
+    -705,
+    -701,
+    -698,
+    -695,
+    -691,
+    -688,
+    -685,
+    -681,
+    -678,
+    -675,
+    -671,
+    -668,
+    -665,
+    -661,
+    -658,
+    -655,
+    -651,
+    -648,
+    -645,
+    -642,
+    -638,
+    -635,
+    -632,
+    -628,
+    -625,
+    -622,
+    -618,
+    -615,
+    -612,
+    -608,
+    -605,
+    -602,
+    -598,
+    -595,
+    -592,
+    -588,
+    -585,
+    -582,
+    -578,
+    -575,
+    -572,
+    -568,
+    -565,
+    -562,
+    -558,
+    -555,
+    -552,
+    -549,
+    -545,
+    -542,
+    -539,
+    -535,
+    -532,
+    -529,
+    -525,
+    -522,
+    -519,
+    -515,
+    -512,
+    -509,
+    -505,
+    -502,
+    -499,
+    -495,
+    -492,
+    -489,
+    -485,
+    -482,
+    -479,
+    -475,
+    -472,
+    -469,
+    -465,
+    -462,
+    -459,
+    -455,
+    -452,
+    -449,
+    -446,
+    -442,
+    -439,
+    -436,
+    -432,
+    -429,
+    -426,
+    -422,
+    -419,
+    -416,
+    -412,
+    -409,
+    -406,
+    -402,
+    -399,
+    -396,
+    -392,
+    -389,
+    -386,
+    -382,
+    -379,
+    -376,
+    -372,
+    -369,
+    -366,
+    -362,
+    -359,
+    -356,
+    -353,
+    -349,
+    -346,
+    -343,
+    -339,
+    -336,
+    -333,
+    -329,
+    -326,
+    -323,
+    -319,
+    -316,
+    -313,
+    -309,
+    -306,
+    -303,
+    -299,
+    -296,
+    -293,
+    -289,
+    -286,
+    -283,
+    -279,
+    -276,
+    -273,
+    -269,
+    -266,
+    -263,
+    -259,
+    -256,
+    -253,
+    -250,
+    -246,
+    -243,
+    -240,
+    -236,
+    -233,
+    -230,
+    -226,
+    -223,
+    -220,
+    -216,
+    -213,
+    -210,
+    -206,
+    -203,
+    -200,
+    -196,
+    -193,
+    -190,
+    -186,
+    -183,
+    -180,
+    -176,
+    -173,
+    -170,
+    -166,
+    -163,
+    -160,
+    -157,
+    -153,
+    -150,
+    -147,
+    -143,
+    -140,
+    -137,
+    -133,
+    -130,
+    -127,
+    -123,
+    -120,
+    -117,
+    -113,
+    -110,
+    -107,
+    -103,
+    -100,
+    -97,
+    -93,
+    -90,
+    -87,
+    -83,
+    -80,
+    -77,
+    -73,
+    -70,
+    -67,
+    -63,
+    -60,
+    -57,
+    -54,
+    -50,
+    -47,
+    -44,
+    -40,
+    -37,
+    -34,
+    -30,
+    -27,
+    -24,
+    -20,
+    -17,
+    -14,
+    -10,
+    -7,
+    -4,
+    0,
+    3,
+    6,
+    10,
+    13,
+    16,
+    20,
+    23,
+    26,
+    30,
+    33,
+    36,
+    39,
+    43,
+    46,
+    49,
+    53,
+    56,
+    59,
+    63,
+    66,
+    69,
+    73,
+    76,
+    79,
+    83,
+    86,
+    89,
+    93,
+    96,
+    99,
+    103,
+    106,
+    109,
+    113,
+    116,
+    119,
+    123,
+    126,
+    129,
+    132,
+    136,
+    139,
+    142,
+    146,
+    149,
+    152,
+    156,
+    159,
+    162,
+    166,
+    169,
+    172,
+    176,
+    179,
+    182,
+    186,
+    189,
+    192,
+    196,
+    199,
+    202,
+    206,
+    209,
+    212,
+    216,
+    219,
+    222,
+    226,
+    229,
+    232,
+    235,
+    239,
+    242,
+    245,
+    249,
+    252,
+    255,
+    259,
+    262,
+    265,
+    269,
+    272,
+    275,
+    279,
+    282,
+    285,
+    289,
+    292,
+    295,
+    299,
+    302,
+    305,
+    309,
+    312,
+    315,
+    319,
+    322,
+    325,
+    328,
+    332,
+    335,
+    338,
+    342,
+    345,
+    348,
+    352,
+    355,
+    358,
+    362,
+    365,
+    368,
+    372,
+    375,
+    378,
+    382,
+    385,
+    388,
+    392,
+    395,
+    398,
+    402,
+    405,
+    408,
+    412,
+    415,
+    418,
+    422,
+    425,
+    428,
+    431,
+    435,
+    438,
+    441,
+    445,
+    448,
+    451,
+    455,
+    458,
+    461,
+    465,
+    468,
+    471,
+    475,
+    478,
+    481,
+    485,
+    488,
+    491,
+    495,
+    498,
+    501,
+    505,
+    508,
+    511,
+    515,
+    518,
+    521,
+    524,
+    528,
+    531,
+    534,
+    538,
+    541,
+    544,
+    548,
+    551,
+    554,
+    558,
+    561,
+    564,
+    568,
+    571,
+    574,
+    578,
+    581,
+    584,
+    588,
+    591,
+    594,
+    598,
+    601,
+    604,
+    608,
+    611,
+    614,
+    617,
+    621,
+    624,
+    627,
+    631,
+    634,
+    637,
+    641,
+    644,
+    647,
+    651,
+    654,
+    657,
+    661,
+    664,
+    667,
+    671,
+    674,
+    677,
+    681,
+    684,
+    687,
+    691,
+    694,
+    697,
+    701,
+    704,
+    707,
+    711,
+    714,
+    717,
+    720,
+    724,
+    727,
+    730,
+    734,
+    737,
+    740,
+    744,
+    747,
+    750,
+    754,
+    757,
+    760,
+    764,
+    767,
+    770,
+    774,
+    777,
+    780,
+    784,
+    787,
+    790,
+    794,
+    797,
+    800,
+    804,
+    807,
+    810,
+    813,
+    817,
+    820,
+    823,
+    827,
+    830,
+    833,
+    837,
+    840,
+    843,
+    847,
+    850,
+    853,
+    857,
+    860,
+    863,
+    867,
+    870,
+    873,
+    877,
+    880,
+    883,
+    887,
+    890,
+    893,
+    897,
+    900,
+    903,
+    907,
+    910,
+    913,
+    916,
+    920,
+    923,
+    926,
+    930,
+    933,
+    936,
+    940,
+    943,
+    946,
+    950,
+]);
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;
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index ad891bf8fa6..19ca83b6ea4 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -44,6 +44,7 @@ pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T);
 
 pub mod wrapping;
 pub mod flt2dec;
+pub mod dec2flt;
 
 /// Types that have a "zero" value.
 ///
@@ -1364,7 +1365,7 @@ pub trait Float {
 }
 
 macro_rules! from_str_float_impl {
-    ($t:ty) => {
+    ($t:ty, $func:ident) => {
         #[stable(feature = "rust1", since = "1.0.0")]
         impl FromStr for $t {
             type Err = ParseFloatError;
@@ -1397,13 +1398,13 @@ macro_rules! from_str_float_impl {
             #[inline]
             #[allow(deprecated)]
             fn from_str(src: &str) -> Result<Self, ParseFloatError> {
-                Self::from_str_radix(src, 10)
+                dec2flt::$func(src)
             }
         }
     }
 }
-from_str_float_impl!(f32);
-from_str_float_impl!(f64);
+from_str_float_impl!(f32, to_f32);
+from_str_float_impl!(f64, to_f64);
 
 macro_rules! from_str_radix_int_impl {
     ($($t:ty)*) => {$(