From 00d8d7bc04a882926829c65b9d6ff6448b22cfef Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Sat, 17 Oct 2015 16:27:31 -0700 Subject: [PATCH 1/2] Implement conversion traits for primitive float types --- src/libcore/num/mod.rs | 23 +++++++++++++-- src/libcoretest/num/mod.rs | 57 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 8b005b2f8ba7e..38ad19c3cbe13 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1473,14 +1473,14 @@ impl fmt::Display for ParseIntError { pub use num::dec2flt::ParseFloatError; -// Conversion traits for primitive integer types +// Conversion traits for primitive integer and float types // Conversions T -> T are covered by a blanket impl and therefore excluded // Some conversions from and to usize/isize are not implemented due to portability concerns macro_rules! impl_from { ($Small: ty, $Large: ty) => { - #[stable(feature = "lossless_int_conv", since = "1.5.0")] + #[stable(feature = "lossless_prim_conv", since = "1.5.0")] impl From<$Small> for $Large { - #[stable(feature = "lossless_int_conv", since = "1.5.0")] + #[stable(feature = "lossless_prim_conv", since = "1.5.0")] #[inline] fn from(small: $Small) -> $Large { small as $Large @@ -1514,3 +1514,20 @@ impl_from! { u8, i64 } impl_from! { u16, i32 } impl_from! { u16, i64 } impl_from! { u32, i64 } + +// Signed -> Float +impl_from! { i8, f32 } +impl_from! { i8, f64 } +impl_from! { i16, f32 } +impl_from! { i16, f64 } +impl_from! { i32, f64 } + +// Unsigned -> Float +impl_from! { u8, f32 } +impl_from! { u8, f64 } +impl_from! { u16, f32 } +impl_from! { u16, f64 } +impl_from! { u32, f64 } + +// Float -> Float +impl_from! { f32, f64 } diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 5e2ec66bababe..738761f3911b6 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -177,4 +177,61 @@ mod tests { test_impl_from! { test_u16i32, u16, i32 } test_impl_from! { test_u16i64, u16, i64 } test_impl_from! { test_u32i64, u32, i64 } + + // Signed -> Float + test_impl_from! { test_i8f32, i8, f32 } + test_impl_from! { test_i8f64, i8, f64 } + test_impl_from! { test_i16f32, i16, f32 } + test_impl_from! { test_i16f64, i16, f64 } + test_impl_from! { test_i32f64, i32, f64 } + + // Unsigned -> Float + test_impl_from! { test_u8f32, u8, f32 } + test_impl_from! { test_u8f64, u8, f64 } + test_impl_from! { test_u16f32, u16, f32 } + test_impl_from! { test_u16f64, u16, f64 } + test_impl_from! { test_u32f64, u32, f64 } + + // Float -> Float + #[test] + fn test_f32f64() { + use core::f32; + + let max: f64 = f32::MAX.into(); + assert_eq!(max as f32, f32::MAX); + assert!(max.is_normal()); + + let min: f64 = f32::MIN.into(); + assert_eq!(min as f32, f32::MIN); + assert!(min.is_normal()); + + let min_positive: f64 = f32::MIN_POSITIVE.into(); + assert_eq!(min_positive as f32, f32::MIN_POSITIVE); + assert!(min_positive.is_normal()); + + let epsilon: f64 = f32::EPSILON.into(); + assert_eq!(epsilon as f32, f32::EPSILON); + assert!(epsilon.is_normal()); + + let zero: f64 = (0.0f32).into(); + assert_eq!(zero as f32, 0.0f32); + assert!(zero.is_sign_positive()); + + let neg_zero: f64 = (-0.0f32).into(); + assert_eq!(neg_zero as f32, -0.0f32); + assert!(neg_zero.is_sign_negative()); + + let infinity: f64 = f32::INFINITY.into(); + assert_eq!(infinity as f32, f32::INFINITY); + assert!(infinity.is_infinite()); + assert!(infinity.is_sign_positive()); + + let neg_infinity: f64 = f32::NEG_INFINITY.into(); + assert_eq!(neg_infinity as f32, f32::NEG_INFINITY); + assert!(neg_infinity.is_infinite()); + assert!(neg_infinity.is_sign_negative()); + + let nan: f64 = f32::NAN.into(); + assert!(nan.is_nan()); + } } From 1a19f9877ad1d582ac80f8e765eff879e00222ea Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 28 Oct 2015 16:05:51 -0700 Subject: [PATCH 2/2] Comment how the significand limits lossless int->float conversion --- src/libcore/num/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 38ad19c3cbe13..a79bdd5961e96 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1515,6 +1515,10 @@ impl_from! { u16, i32 } impl_from! { u16, i64 } impl_from! { u32, i64 } +// Note: integers can only be represented with full precision in a float if +// they fit in the significand, which is 24 bits in f32 and 53 bits in f64. +// Lossy float conversions are not implemented at this time. + // Signed -> Float impl_from! { i8, f32 } impl_from! { i8, f64 }