issue = "0")]
use prelude::v1::*;
-use num::ParseFloatError as PFE;
-use num::FloatErrorKind;
+use fmt;
+use str::FromStr;
+
use self::parse::{parse_decimal, Decimal, Sign};
use self::parse::ParseResult::{self, Valid, ShortcutToInf, ShortcutToZero};
use self::num::digits_to_big;
pub mod rawfp;
pub mod parse;
-/// Entry point for decimal-to-f32 conversion.
-pub fn to_f32(s: &str) -> Result<f32, PFE> {
- dec2flt(s)
+macro_rules! from_str_float_impl {
+ ($t:ty, $func:ident) => {
+ #[stable(feature = "rust1", since = "1.0.0")]
+ impl FromStr for $t {
+ type Err = ParseFloatError;
+
+ /// Converts a string in base 10 to a float.
+ /// Accepts an optional decimal exponent.
+ ///
+ /// This function accepts strings such as
+ ///
+ /// * '3.14'
+ /// * '-3.14'
+ /// * '2.5E10', or equivalently, '2.5e10'
+ /// * '2.5E-10'
+ /// * '.' (understood as 0)
+ /// * '5.'
+ /// * '.5', or, equivalently, '0.5'
+ /// * 'inf', '-inf', 'NaN'
+ ///
+ /// Leading and trailing whitespace represent an error.
+ ///
+ /// # Arguments
+ ///
+ /// * src - A string
+ ///
+ /// # 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`.
+ #[inline]
+ fn from_str(src: &str) -> Result<Self, ParseFloatError> {
+ dec2flt(src)
+ }
+ }
+ }
+}
+from_str_float_impl!(f32, to_f32);
+from_str_float_impl!(f64, to_f64);
+
+/// 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
+}
+
+#[derive(Debug, Clone, PartialEq)]
+enum FloatErrorKind {
+ Empty,
+ Invalid,
+}
+
+impl ParseFloatError {
+ #[unstable(feature = "int_error_internals",
+ reason = "available through Error trait and this method should \
+ not be exposed publicly",
+ issue = "0")]
+ #[doc(hidden)]
+ pub fn __description(&self) -> &str {
+ match self.kind {
+ FloatErrorKind::Empty => "cannot parse float from empty string",
+ FloatErrorKind::Invalid => "invalid float literal",
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for ParseFloatError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ self.__description().fmt(f)
+ }
+}
+
+pub fn pfe_empty() -> ParseFloatError {
+ ParseFloatError { kind: FloatErrorKind::Empty }
}
-/// Entry point for decimal-to-f64 conversion.
-pub fn to_f64(s: &str) -> Result<f64, PFE> {
- dec2flt(s)
+pub fn pfe_invalid() -> ParseFloatError {
+ ParseFloatError { kind: FloatErrorKind::Invalid }
}
/// Split decimal string into sign and the rest, without inspecting or validating the rest.
}
/// Convert a decimal string into a floating point number.
-fn dec2flt<T: RawFloat>(s: &str) -> Result<T, PFE> {
+fn dec2flt<T: RawFloat>(s: &str) -> Result<T, ParseFloatError> {
if s.is_empty() {
- return Err(PFE { __kind: FloatErrorKind::Empty });
+ return Err(pfe_empty())
}
let (sign, s) = extract_sign(s);
let flt = match parse_decimal(s) {
ParseResult::Invalid => match s {
"inf" => T::infinity(),
"NaN" => T::nan(),
- _ => { return Err(PFE { __kind: FloatErrorKind::Invalid }); }
+ _ => { return Err(pfe_invalid()); }
}
};
/// 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> {
+fn convert<T: RawFloat>(mut decimal: Decimal) -> Result<T, ParseFloatError> {
simplify(&mut decimal);
if let Some(x) = trivial_cases(&decimal) {
return Ok(x);
// 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 });
+ return Err(pfe_invalid());
}
let f = digits_to_big(decimal.integral, decimal.fractional);
($T:ty) => {
fn from_str_radix(src: &str, radix: u32)
-> Result<$T, ParseFloatError> {
- use num::FloatErrorKind::*;
- use num::ParseFloatError as PFE;
+ use num::dec2flt::{pfe_empty, pfe_invalid};
// Special values
match src {
}
let (is_positive, src) = match src.slice_shift_char() {
- None => return Err(PFE { __kind: Empty }),
- Some(('-', "")) => return Err(PFE { __kind: Empty }),
+ None => return Err(pfe_empty()),
+ Some(('-', "")) => return Err(pfe_empty()),
Some(('-', src)) => (false, src),
Some((_, _)) => (true, src),
};
break; // start of fractional part
},
_ => {
- return Err(PFE { __kind: Invalid });
+ return Err(pfe_invalid())
},
},
}
break; // start of exponent
},
_ => {
- return Err(PFE { __kind: Invalid });
+ return Err(pfe_invalid())
},
},
}
let base = match c {
'E' | 'e' if radix == 10 => 10.0,
'P' | 'p' if radix == 16 => 2.0,
- _ => return Err(PFE { __kind: Invalid }),
+ _ => return Err(pfe_invalid()),
};
// Parse the exponent as decimal integer
Some(('-', src)) => (false, src.parse::<usize>()),
Some(('+', src)) => (true, src.parse::<usize>()),
Some((_, _)) => (true, src.parse::<usize>()),
- None => return Err(PFE { __kind: Invalid }),
+ None => return Err(pfe_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 }),
+ (_, Err(_)) => return Err(pfe_invalid()),
}
},
None => 1.0, // no exponent
fn to_radians(self) -> Self;
}
-macro_rules! from_str_float_impl {
- ($t:ty, $func:ident) => {
- #[stable(feature = "rust1", since = "1.0.0")]
- impl FromStr for $t {
- type Err = ParseFloatError;
-
- /// Converts a string in base 10 to a float.
- /// Accepts an optional decimal exponent.
- ///
- /// This function accepts strings such as
- ///
- /// * '3.14'
- /// * '-3.14'
- /// * '2.5E10', or equivalently, '2.5e10'
- /// * '2.5E-10'
- /// * '.' (understood as 0)
- /// * '5.'
- /// * '.5', or, equivalently, '0.5'
- /// * 'inf', '-inf', 'NaN'
- ///
- /// Leading and trailing whitespace represent an error.
- ///
- /// # Arguments
- ///
- /// * src - A string
- ///
- /// # 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`.
- #[inline]
- fn from_str(src: &str) -> Result<Self, ParseFloatError> {
- dec2flt::$func(src)
- }
- }
- }
-}
-from_str_float_impl!(f32, to_f32);
-from_str_float_impl!(f64, to_f64);
-
macro_rules! from_str_radix_int_impl {
($($t:ty)*) => {$(
#[stable(feature = "rust1", since = "1.0.0")]
}
}
-/// An error which can be returned when parsing a float.
-#[derive(Debug, Clone, PartialEq)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct ParseFloatError {
- #[doc(hidden)]
- #[unstable(feature = "float_error_internals",
- reason = "should not be exposed publicly",
- issue = "0")]
- pub __kind: FloatErrorKind
-}
-
-#[derive(Debug, Clone, PartialEq)]
-#[unstable(feature = "float_error_internals",
- reason = "should not be exposed publicly",
- issue = "0")]
-#[doc(hidden)]
-pub enum FloatErrorKind {
- Empty,
- Invalid,
-}
-
-impl ParseFloatError {
- #[doc(hidden)]
- pub fn __description(&self) -> &str {
- match self.__kind {
- FloatErrorKind::Empty => "cannot parse float from empty string",
- FloatErrorKind::Invalid => "invalid float literal",
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Display for ParseFloatError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- self.__description().fmt(f)
- }
-}
+pub use num::dec2flt::ParseFloatError;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::atomic::*;
-use core::atomic::Ordering::SeqCst;
+use core::sync::atomic::*;
+use core::sync::atomic::Ordering::SeqCst;
#[test]
fn bool_() {
use std::{i64, f32, f64};
use test;
-use core::num::dec2flt::{to_f32, to_f64};
mod parse;
mod rawfp;
let inputs = &[stringify!($x).into(), format!("{:?}", x64), format!("{:e}", x64)];
for input in inputs {
if input != "inf" {
- assert_eq!(to_f64(input), Ok(x64));
- assert_eq!(to_f32(input), Ok(x32));
+ assert_eq!(input.parse(), Ok(x64));
+ assert_eq!(input.parse(), Ok(x32));
let neg_input = &format!("-{}", input);
- assert_eq!(to_f64(neg_input), Ok(-x64));
- assert_eq!(to_f32(neg_input), Ok(-x32));
+ assert_eq!(neg_input.parse(), Ok(-x64));
+ assert_eq!(neg_input.parse(), Ok(-x32));
}
}
})
#[test]
fn lonely_dot() {
- assert_eq!(to_f64("."), Ok(0.0));
+ assert_eq!(".".parse(), Ok(0.0));
}
#[test]
fn nan() {
- assert!(to_f64("NaN").unwrap().is_nan());
- assert!(to_f32("NaN").unwrap().is_nan());
+ assert!("NaN".parse::<f32>().unwrap().is_nan());
+ assert!("NaN".parse::<f64>().unwrap().is_nan());
}
#[test]
fn inf() {
- assert_eq!(to_f64("inf"), Ok(f64::INFINITY));
- assert_eq!(to_f64("-inf"), Ok(f64::NEG_INFINITY));
- assert_eq!(to_f32("inf"), Ok(f32::INFINITY));
- assert_eq!(to_f32("-inf"), Ok(f32::NEG_INFINITY));
+ assert_eq!("inf".parse(), Ok(f64::INFINITY));
+ assert_eq!("-inf".parse(), Ok(f64::NEG_INFINITY));
+ assert_eq!("inf".parse(), Ok(f32::INFINITY));
+ assert_eq!("-inf".parse(), Ok(f32::NEG_INFINITY));
}
#[test]
fn massive_exponent() {
let max = i64::MAX;
- assert_eq!(to_f64(&format!("1e{}000", max)), Ok(f64::INFINITY));
- assert_eq!(to_f64(&format!("1e-{}000", max)), Ok(0.0));
- assert_eq!(to_f64(&format!("1e{}000", max)), Ok(f64::INFINITY));
+ assert_eq!(format!("1e{}000", max).parse(), Ok(f64::INFINITY));
+ assert_eq!(format!("1e-{}000", max).parse(), Ok(0.0));
+ assert_eq!(format!("1e{}000", max).parse(), Ok(f64::INFINITY));
}
#[bench]
fn bench_0(b: &mut test::Bencher) {
- b.iter(|| to_f64("0.0"));
+ b.iter(|| "0.0".parse::<f64>());
}
#[bench]
fn bench_42(b: &mut test::Bencher) {
- b.iter(|| to_f64("42"));
+ b.iter(|| "42".parse::<f64>());
}
#[bench]
fn bench_huge_int(b: &mut test::Bencher) {
// 2^128 - 1
- b.iter(|| to_f64("170141183460469231731687303715884105727"));
+ b.iter(|| "170141183460469231731687303715884105727".parse::<f64>());
}
#[bench]
fn bench_short_decimal(b: &mut test::Bencher) {
- b.iter(|| to_f64("1234.5678"));
+ b.iter(|| "1234.5678".parse::<f64>());
}
#[bench]
fn bench_pi_long(b: &mut test::Bencher) {
- b.iter(|| to_f64("3.14159265358979323846264338327950288"));
+ b.iter(|| "3.14159265358979323846264338327950288".parse::<f64>());
}
#[bench]
fn bench_pi_short(b: &mut test::Bencher) {
- b.iter(|| to_f64("3.141592653589793"))
+ b.iter(|| "3.141592653589793".parse::<f64>())
}
#[bench]
fn bench_1e150(b: &mut test::Bencher) {
- b.iter(|| to_f64("1e150"));
+ b.iter(|| "1e150".parse::<f64>());
}
#[bench]
fn bench_long_decimal_and_exp(b: &mut test::Bencher) {
- b.iter(|| to_f64("727501488517303786137132964064381141071e-123"));
+ b.iter(|| "727501488517303786137132964064381141071e-123".parse::<f64>());
}
#[bench]
fn bench_min_subnormal(b: &mut test::Bencher) {
- b.iter(|| to_f64("5e-324"));
+ b.iter(|| "5e-324".parse::<f64>());
}
#[bench]
fn bench_min_normal(b: &mut test::Bencher) {
- b.iter(|| to_f64("2.2250738585072014e-308"));
+ b.iter(|| "2.2250738585072014e-308".parse::<f64>());
}
#[bench]
fn bench_max(b: &mut test::Bencher) {
- b.iter(|| to_f64("1.7976931348623157e308"));
+ b.iter(|| "1.7976931348623157e308".parse::<f64>());
}
use core::$T_i::*;
use num;
use core::ops::{BitOr, BitAnd, BitXor, Shl, Shr, Not};
- use std::str;
+ use std::str::FromStr;
#[test]
fn test_overflows() {
assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>);
assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>);
}
-
+}
)}
fn assert_clone<T>() where T : Clone { }
fn main() {
- assert_clone::<foo::core::atomic::AtomicBool>();
+ assert_clone::<foo::core::sync::atomic::AtomicBool>();
//~^ ERROR the trait `foo::core::clone::Clone` is not implemented for the type `foo::core::
-}
\ No newline at end of file
+}
fn assert_clone<T>() where T : Clone { }
fn main() {
- assert_clone::<bar::atomic::AtomicBool>();
- //~^ ERROR the trait `bar::clone::Clone` is not implemented for the type `bar::atomic::
-}
\ No newline at end of file
+ assert_clone::<bar::sync::atomic::AtomicBool>();
+ //~^ ERROR the trait `bar::clone::Clone` is not implemented for the type `bar::sync::atomic::
+}
fn assert_clone<T>() where T : Clone { }
fn main() {
- assert_clone::<foo::core::atomic::AtomicBool>();
- //~^ ERROR the trait `core::clone::Clone` is not implemented for the type `core::atomic::
-}
\ No newline at end of file
+ assert_clone::<foo::core::sync::atomic::AtomicBool>();
+ //~^ ERROR the trait `core::clone::Clone` is not implemented for the type `core::sync::atomic::
+}