about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-04-17 23:45:55 -0700
committerAlex Crichton <alex@alexcrichton.com>2015-04-21 15:23:54 -0700
commita568a7f9f2eb3fa3f3e049df288ef0ad32cc7881 (patch)
tree2d96b295e43de338e7e650110ba00ac2e116b519 /src/libcore
parent0791f9f406053d84dc7136c2be015a469304d7f0 (diff)
downloadrust-a568a7f9f2eb3fa3f3e049df288ef0ad32cc7881.tar.gz
rust-a568a7f9f2eb3fa3f3e049df288ef0ad32cc7881.zip
std: Bring back f32::from_str_radix as an unstable API
This API was exercised in a few tests and mirrors the `from_str_radix`
functionality of the integer types.
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/iter.rs3
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/num/f32.rs9
-rw-r--r--src/libcore/num/f64.rs9
-rw-r--r--src/libcore/num/float_macros.rs142
-rw-r--r--src/libcore/num/mod.rs250
6 files changed, 175 insertions, 239 deletions
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index 651658e4d56..233ed018119 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -2327,9 +2327,8 @@ impl<I: RandomAccessIterator, F> RandomAccessIterator for Inspect<I, F>
 /// An iterator that yields sequential Fibonacci numbers, and stops on overflow.
 ///
 /// ```
-/// # #![feature(core)]
+/// #![feature(core)]
 /// use std::iter::Unfold;
-/// use std::num::Int; // For `.checked_add()`
 ///
 /// // This iterator will yield up to the last Fibonacci number before the max
 /// // value of `u32`. You can simply change `u32` to `u64` in this line if
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 164d3e49385..249f0a0c389 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -108,6 +108,7 @@ mod uint_macros;
 #[path = "num/f32.rs"]   pub mod f32;
 #[path = "num/f64.rs"]   pub mod f64;
 
+#[macro_use]
 pub mod num;
 
 /* The libcore prelude, not as all-encompassing as the libstd prelude */
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index a9afa5078d2..50dd3f1661a 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -16,9 +16,11 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+use prelude::*;
+
 use intrinsics;
 use mem;
-use num::Float;
+use num::{Float, ParseFloatError};
 use num::FpCategory as Fp;
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -153,6 +155,8 @@ impl Float for f32 {
     #[inline]
     fn one() -> f32 { 1.0 }
 
+    from_str_radix_float_impl! { f32 }
+
     /// Returns `true` if the number is NaN.
     #[inline]
     fn is_nan(self) -> bool { self != self }
@@ -234,9 +238,6 @@ impl Float for f32 {
     /// The fractional part of the number, satisfying:
     ///
     /// ```
-    /// # #![feature(core)]
-    /// use std::num::Float;
-    ///
     /// let x = 1.65f32;
     /// assert!(x == x.trunc() + x.fract())
     /// ```
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index fa9660a60e9..62b566e7eb4 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -16,10 +16,12 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+use prelude::*;
+
 use intrinsics;
 use mem;
-use num::Float;
 use num::FpCategory as Fp;
+use num::{Float, ParseFloatError};
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const RADIX: u32 = 2;
@@ -153,6 +155,8 @@ impl Float for f64 {
     #[inline]
     fn one() -> f64 { 1.0 }
 
+    from_str_radix_float_impl! { f64 }
+
     /// Returns `true` if the number is NaN.
     #[inline]
     fn is_nan(self) -> bool { self != self }
@@ -234,9 +238,6 @@ impl Float for f64 {
     /// The fractional part of the number, satisfying:
     ///
     /// ```
-    /// # #![feature(core)]
-    /// use std::num::Float;
-    ///
     /// let x = 1.65f64;
     /// assert!(x == x.trunc() + x.fract())
     /// ```
diff --git a/src/libcore/num/float_macros.rs b/src/libcore/num/float_macros.rs
index b3adef53dab..5ee0dc19f9b 100644
--- a/src/libcore/num/float_macros.rs
+++ b/src/libcore/num/float_macros.rs
@@ -18,3 +18,145 @@ macro_rules! assert_approx_eq {
                 "{} is not approximately equal to {}", *a, *b);
     })
 }
+
+macro_rules! from_str_radix_float_impl {
+    ($T:ty) => {
+        fn from_str_radix(src: &str, radix: u32)
+                          -> Result<$T, ParseFloatError> {
+            use num::FloatErrorKind::*;
+            use num::ParseFloatError as PFE;
+
+            // Special values
+            match src {
+                "inf"   => return Ok(Float::infinity()),
+                "-inf"  => return Ok(Float::neg_infinity()),
+                "NaN"   => return Ok(Float::nan()),
+                _       => {},
+            }
+
+            let (is_positive, src) =  match src.slice_shift_char() {
+                None             => return Err(PFE { kind: Empty }),
+                Some(('-', ""))  => return Err(PFE { kind: Empty }),
+                Some(('-', src)) => (false, src),
+                Some((_, _))     => (true,  src),
+            };
+
+            // The significand to accumulate
+            let mut sig = if is_positive { 0.0 } else { -0.0 };
+            // Necessary to detect overflow
+            let mut prev_sig = sig;
+            let mut cs = src.chars().enumerate();
+            // Exponent prefix and exponent index offset
+            let mut exp_info = None::<(char, usize)>;
+
+            // Parse the integer part of the significand
+            for (i, c) in cs.by_ref() {
+                match c.to_digit(radix) {
+                    Some(digit) => {
+                        // shift significand one digit left
+                        sig = sig * (radix as $T);
+
+                        // add/subtract current digit depending on sign
+                        if is_positive {
+                            sig = sig + ((digit as isize) as $T);
+                        } else {
+                            sig = sig - ((digit as isize) as $T);
+                        }
+
+                        // Detect overflow by comparing to last value, except
+                        // if we've not seen any non-zero digits.
+                        if prev_sig != 0.0 {
+                            if is_positive && sig <= prev_sig
+                                { return Ok(Float::infinity()); }
+                            if !is_positive && sig >= prev_sig
+                                { return Ok(Float::neg_infinity()); }
+
+                            // Detect overflow by reversing the shift-and-add process
+                            if is_positive && (prev_sig != (sig - digit as $T) / radix as $T)
+                                { return Ok(Float::infinity()); }
+                            if !is_positive && (prev_sig != (sig + digit as $T) / radix as $T)
+                                { return Ok(Float::neg_infinity()); }
+                        }
+                        prev_sig = sig;
+                    },
+                    None => match c {
+                        'e' | 'E' | 'p' | 'P' => {
+                            exp_info = Some((c, i + 1));
+                            break;  // start of exponent
+                        },
+                        '.' => {
+                            break;  // start of fractional part
+                        },
+                        _ => {
+                            return Err(PFE { kind: Invalid });
+                        },
+                    },
+                }
+            }
+
+            // If we are not yet at the exponent parse the fractional
+            // part of the significand
+            if exp_info.is_none() {
+                let mut power = 1.0;
+                for (i, c) in cs.by_ref() {
+                    match c.to_digit(radix) {
+                        Some(digit) => {
+                            // Decrease power one order of magnitude
+                            power = power / (radix as $T);
+                            // add/subtract current digit depending on sign
+                            sig = if is_positive {
+                                sig + (digit as $T) * power
+                            } else {
+                                sig - (digit as $T) * power
+                            };
+                            // Detect overflow by comparing to last value
+                            if is_positive && sig < prev_sig
+                                { return Ok(Float::infinity()); }
+                            if !is_positive && sig > prev_sig
+                                { return Ok(Float::neg_infinity()); }
+                            prev_sig = sig;
+                        },
+                        None => match c {
+                            'e' | 'E' | 'p' | 'P' => {
+                                exp_info = Some((c, i + 1));
+                                break; // start of exponent
+                            },
+                            _ => {
+                                return Err(PFE { kind: Invalid });
+                            },
+                        },
+                    }
+                }
+            }
+
+            // Parse and calculate the exponent
+            let exp = match exp_info {
+                Some((c, offset)) => {
+                    let base = match c {
+                        'E' | 'e' if radix == 10 => 10.0,
+                        'P' | 'p' if radix == 16 => 2.0,
+                        _ => return Err(PFE { kind: Invalid }),
+                    };
+
+                    // Parse the exponent as decimal integer
+                    let src = &src[offset..];
+                    let (is_positive, exp) = match src.slice_shift_char() {
+                        Some(('-', src)) => (false, src.parse::<usize>()),
+                        Some(('+', src)) => (true,  src.parse::<usize>()),
+                        Some((_, _))     => (true,  src.parse::<usize>()),
+                        None             => return Err(PFE { kind: Invalid }),
+                    };
+
+                    match (is_positive, exp) {
+                        (true,  Ok(exp)) => base.powi(exp as i32),
+                        (false, Ok(exp)) => 1.0 / base.powi(exp as i32),
+                        (_, Err(_))      => return Err(PFE { kind: Invalid }),
+                    }
+                },
+                None => 1.0, // no exponent
+            };
+
+            Ok(sig * exp)
+        }
+    }
+}
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index cd1ce1f4535..44d5333ce1f 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -19,7 +19,6 @@ use char::CharExt;
 use cmp::{Eq, PartialOrd};
 use fmt;
 use intrinsics;
-use iter::Iterator;
 use marker::Copy;
 use mem::size_of;
 use option::Option::{self, Some, None};
@@ -148,9 +147,6 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```rust
-        /// # #![feature(core)]
-        /// use std::num::Int;
-        ///
         /// let n = 0b01001100u8;
         ///
         /// assert_eq!(n.count_ones(), 3);
@@ -164,9 +160,6 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```rust
-        /// # #![feature(core)]
-        /// use std::num::Int;
-        ///
         /// let n = 0b01001100u8;
         ///
         /// assert_eq!(n.count_zeros(), 5);
@@ -183,9 +176,6 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```rust
-        /// # #![feature(core)]
-        /// use std::num::Int;
-        ///
         /// let n = 0b0101000u16;
         ///
         /// assert_eq!(n.leading_zeros(), 10);
@@ -202,9 +192,6 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```rust
-        /// # #![feature(core)]
-        /// use std::num::Int;
-        ///
         /// let n = 0b0101000u16;
         ///
         /// assert_eq!(n.trailing_zeros(), 3);
@@ -221,9 +208,6 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```rust
-        /// # #![feature(core)]
-        /// use std::num::Int;
-        ///
         /// let n = 0x0123456789ABCDEFu64;
         /// let m = 0x3456789ABCDEF012u64;
         ///
@@ -242,9 +226,6 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```rust
-        /// # #![feature(core)]
-        /// use std::num::Int;
-        ///
         /// let n = 0x0123456789ABCDEFu64;
         /// let m = 0xDEF0123456789ABCu64;
         ///
@@ -261,8 +242,6 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// let n = 0x0123456789ABCDEFu64;
         /// let m = 0xEFCDAB8967452301u64;
         ///
@@ -282,14 +261,12 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// let n = 0x0123456789ABCDEFu64;
         ///
         /// if cfg!(target_endian = "big") {
-        ///     assert_eq!(Int::from_be(n), n)
+        ///     assert_eq!(u64::from_be(n), n)
         /// } else {
-        ///     assert_eq!(Int::from_be(n), n.swap_bytes())
+        ///     assert_eq!(u64::from_be(n), n.swap_bytes())
         /// }
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -306,14 +283,12 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// let n = 0x0123456789ABCDEFu64;
         ///
         /// if cfg!(target_endian = "little") {
-        ///     assert_eq!(Int::from_le(n), n)
+        ///     assert_eq!(u64::from_le(n), n)
         /// } else {
-        ///     assert_eq!(Int::from_le(n), n.swap_bytes())
+        ///     assert_eq!(u64::from_le(n), n.swap_bytes())
         /// }
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -330,8 +305,6 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// let n = 0x0123456789ABCDEFu64;
         ///
         /// if cfg!(target_endian = "big") {
@@ -354,8 +327,6 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// let n = 0x0123456789ABCDEFu64;
         ///
         /// if cfg!(target_endian = "little") {
@@ -376,8 +347,6 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// assert_eq!(5u16.checked_add(65530), Some(65535));
         /// assert_eq!(6u16.checked_add(65530), None);
         /// ```
@@ -393,8 +362,6 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// assert_eq!((-127i8).checked_sub(1), Some(-128));
         /// assert_eq!((-128i8).checked_sub(1), None);
         /// ```
@@ -410,8 +377,6 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// assert_eq!(5u8.checked_mul(51), Some(255));
         /// assert_eq!(5u8.checked_mul(52), None);
         /// ```
@@ -427,8 +392,6 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// assert_eq!((-127i8).checked_div(-1), Some(127));
         /// assert_eq!((-128i8).checked_div(-1), None);
         /// assert_eq!((1i8).checked_div(0), None);
@@ -728,9 +691,6 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```rust
-        /// # #![feature(core)]
-        /// use std::num::Int;
-        ///
         /// let n = 0b01001100u8;
         ///
         /// assert_eq!(n.count_ones(), 3);
@@ -746,9 +706,6 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```rust
-        /// # #![feature(core)]
-        /// use std::num::Int;
-        ///
         /// let n = 0b01001100u8;
         ///
         /// assert_eq!(n.count_zeros(), 5);
@@ -765,9 +722,6 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```rust
-        /// # #![feature(core)]
-        /// use std::num::Int;
-        ///
         /// let n = 0b0101000u16;
         ///
         /// assert_eq!(n.leading_zeros(), 10);
@@ -784,9 +738,6 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```rust
-        /// # #![feature(core)]
-        /// use std::num::Int;
-        ///
         /// let n = 0b0101000u16;
         ///
         /// assert_eq!(n.trailing_zeros(), 3);
@@ -803,9 +754,6 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```rust
-        /// # #![feature(core)]
-        /// use std::num::Int;
-        ///
         /// let n = 0x0123456789ABCDEFu64;
         /// let m = 0x3456789ABCDEF012u64;
         ///
@@ -826,9 +774,6 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```rust
-        /// # #![feature(core)]
-        /// use std::num::Int;
-        ///
         /// let n = 0x0123456789ABCDEFu64;
         /// let m = 0xDEF0123456789ABCu64;
         ///
@@ -847,8 +792,6 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// let n = 0x0123456789ABCDEFu64;
         /// let m = 0xEFCDAB8967452301u64;
         ///
@@ -868,14 +811,12 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// let n = 0x0123456789ABCDEFu64;
         ///
         /// if cfg!(target_endian = "big") {
-        ///     assert_eq!(Int::from_be(n), n)
+        ///     assert_eq!(u64::from_be(n), n)
         /// } else {
-        ///     assert_eq!(Int::from_be(n), n.swap_bytes())
+        ///     assert_eq!(u64::from_be(n), n.swap_bytes())
         /// }
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -892,14 +833,12 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// let n = 0x0123456789ABCDEFu64;
         ///
         /// if cfg!(target_endian = "little") {
-        ///     assert_eq!(Int::from_le(n), n)
+        ///     assert_eq!(u64::from_le(n), n)
         /// } else {
-        ///     assert_eq!(Int::from_le(n), n.swap_bytes())
+        ///     assert_eq!(u64::from_le(n), n.swap_bytes())
         /// }
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -916,8 +855,6 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// let n = 0x0123456789ABCDEFu64;
         ///
         /// if cfg!(target_endian = "big") {
@@ -940,8 +877,6 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// let n = 0x0123456789ABCDEFu64;
         ///
         /// if cfg!(target_endian = "little") {
@@ -962,8 +897,6 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// assert_eq!(5u16.checked_add(65530), Some(65535));
         /// assert_eq!(6u16.checked_add(65530), None);
         /// ```
@@ -979,8 +912,6 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// assert_eq!((-127i8).checked_sub(1), Some(-128));
         /// assert_eq!((-128i8).checked_sub(1), None);
         /// ```
@@ -996,8 +927,6 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// assert_eq!(5u8.checked_mul(51), Some(255));
         /// assert_eq!(5u8.checked_mul(52), None);
         /// ```
@@ -1013,8 +942,6 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```rust
-        /// use std::num::Int;
-        ///
         /// assert_eq!((-127i8).checked_div(-1), Some(127));
         /// assert_eq!((-128i8).checked_div(-1), None);
         /// assert_eq!((1i8).checked_div(0), None);
@@ -1147,10 +1074,7 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```rust
-        /// # #![feature(core)]
-        /// use std::num::Int;
-        ///
-        /// assert_eq!(2.pow(4), 16);
+        /// assert_eq!(2i32.pow(4), 16);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
@@ -1328,6 +1252,8 @@ pub trait Float {
     fn zero() -> Self;
     /// Returns 1.0.
     fn one() -> Self;
+    /// Parses the string `s` with the radix `r` as a float.
+    fn from_str_radix(s: &str, r: u32) -> Result<Self, ParseFloatError>;
 
     /// Returns true if this value is NaN and false otherwise.
     fn is_nan(self) -> bool;
@@ -1412,8 +1338,8 @@ pub trait Float {
     fn to_radians(self) -> Self;
 }
 
-macro_rules! from_str_radix_float_impl {
-    ($T:ty) => {
+macro_rules! from_str_float_impl {
+    ($T:ident) => {
         #[stable(feature = "rust1", since = "1.0.0")]
         impl FromStr for $T {
             type Err = ParseFloatError;
@@ -1441,152 +1367,19 @@ macro_rules! from_str_radix_float_impl {
             ///
             /// # Return value
             ///
-            /// `Err(ParseFloatError)` if the string did not represent a valid number.
-            /// Otherwise, `Ok(n)` where `n` is the floating-point number represented by `src`.
+            /// `Err(ParseFloatError)` if the string did not represent a valid
+            /// number.  Otherwise, `Ok(n)` where `n` is the floating-point
+            /// number represented by `src`.
             #[inline]
             #[allow(deprecated)]
             fn from_str(src: &str) -> Result<$T, ParseFloatError> {
-                use self::FloatErrorKind::*;
-                use self::ParseFloatError as PFE;
-                let radix = 10;
-
-                // Special values
-                match src {
-                    "inf"   => return Ok(Float::infinity()),
-                    "-inf"  => return Ok(Float::neg_infinity()),
-                    "NaN"   => return Ok(Float::nan()),
-                    _       => {},
-                }
-
-                let (is_positive, src) =  match src.slice_shift_char() {
-                    None             => return Err(PFE { kind: Empty }),
-                    Some(('-', ""))  => return Err(PFE { kind: Empty }),
-                    Some(('-', src)) => (false, src),
-                    Some((_, _))     => (true,  src),
-                };
-
-                // The significand to accumulate
-                let mut sig = if is_positive { 0.0 } else { -0.0 };
-                // Necessary to detect overflow
-                let mut prev_sig = sig;
-                let mut cs = src.chars().enumerate();
-                // Exponent prefix and exponent index offset
-                let mut exp_info = None::<(char, usize)>;
-
-                // Parse the integer part of the significand
-                for (i, c) in cs.by_ref() {
-                    match c.to_digit(radix) {
-                        Some(digit) => {
-                            // shift significand one digit left
-                            sig = sig * (radix as $T);
-
-                            // add/subtract current digit depending on sign
-                            if is_positive {
-                                sig = sig + ((digit as isize) as $T);
-                            } else {
-                                sig = sig - ((digit as isize) as $T);
-                            }
-
-                            // Detect overflow by comparing to last value, except
-                            // if we've not seen any non-zero digits.
-                            if prev_sig != 0.0 {
-                                if is_positive && sig <= prev_sig
-                                    { return Ok(Float::infinity()); }
-                                if !is_positive && sig >= prev_sig
-                                    { return Ok(Float::neg_infinity()); }
-
-                                // Detect overflow by reversing the shift-and-add process
-                                if is_positive && (prev_sig != (sig - digit as $T) / radix as $T)
-                                    { return Ok(Float::infinity()); }
-                                if !is_positive && (prev_sig != (sig + digit as $T) / radix as $T)
-                                    { return Ok(Float::neg_infinity()); }
-                            }
-                            prev_sig = sig;
-                        },
-                        None => match c {
-                            'e' | 'E' | 'p' | 'P' => {
-                                exp_info = Some((c, i + 1));
-                                break;  // start of exponent
-                            },
-                            '.' => {
-                                break;  // start of fractional part
-                            },
-                            _ => {
-                                return Err(PFE { kind: Invalid });
-                            },
-                        },
-                    }
-                }
-
-                // If we are not yet at the exponent parse the fractional
-                // part of the significand
-                if exp_info.is_none() {
-                    let mut power = 1.0;
-                    for (i, c) in cs.by_ref() {
-                        match c.to_digit(radix) {
-                            Some(digit) => {
-                                // Decrease power one order of magnitude
-                                power = power / (radix as $T);
-                                // add/subtract current digit depending on sign
-                                sig = if is_positive {
-                                    sig + (digit as $T) * power
-                                } else {
-                                    sig - (digit as $T) * power
-                                };
-                                // Detect overflow by comparing to last value
-                                if is_positive && sig < prev_sig
-                                    { return Ok(Float::infinity()); }
-                                if !is_positive && sig > prev_sig
-                                    { return Ok(Float::neg_infinity()); }
-                                prev_sig = sig;
-                            },
-                            None => match c {
-                                'e' | 'E' | 'p' | 'P' => {
-                                    exp_info = Some((c, i + 1));
-                                    break; // start of exponent
-                                },
-                                _ => {
-                                    return Err(PFE { kind: Invalid });
-                                },
-                            },
-                        }
-                    }
-                }
-
-                // Parse and calculate the exponent
-                let exp = match exp_info {
-                    Some((c, offset)) => {
-                        let base = match c {
-                            'E' | 'e' if radix == 10 => 10.0,
-                            'P' | 'p' if radix == 16 => 2.0,
-                            _ => return Err(PFE { kind: Invalid }),
-                        };
-
-                        // Parse the exponent as decimal integer
-                        let src = &src[offset..];
-                        let (is_positive, exp) = match src.slice_shift_char() {
-                            Some(('-', src)) => (false, src.parse::<usize>()),
-                            Some(('+', src)) => (true,  src.parse::<usize>()),
-                            Some((_, _))     => (true,  src.parse::<usize>()),
-                            None             => return Err(PFE { kind: Invalid }),
-                        };
-
-                        match (is_positive, exp) {
-                            (true,  Ok(exp)) => base.powi(exp as i32),
-                            (false, Ok(exp)) => 1.0 / base.powi(exp as i32),
-                            (_, Err(_))      => return Err(PFE { kind: Invalid }),
-                        }
-                    },
-                    None => 1.0, // no exponent
-                };
-
-                Ok(sig * exp)
+                $T::from_str_radix(src, 10)
             }
         }
     }
 }
-from_str_radix_float_impl! { f32 }
-from_str_radix_float_impl! { f64 }
+from_str_float_impl!(f32);
+from_str_float_impl!(f64);
 
 macro_rules! from_str_radix_int_impl {
     ($($T:ident)*) => {$(
@@ -1716,11 +1509,10 @@ impl fmt::Display for ParseIntError {
 
 /// An error which can be returned when parsing a float.
 #[derive(Debug, Clone, PartialEq)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct ParseFloatError { kind: FloatErrorKind }
+pub struct ParseFloatError { pub kind: FloatErrorKind }
 
 #[derive(Debug, Clone, PartialEq)]
-enum FloatErrorKind {
+pub enum FloatErrorKind {
     Empty,
     Invalid,
 }