From 4c07f5e457102d52042735e277959f7e1a55491e Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Fri, 26 Apr 2013 10:22:08 +1000 Subject: [PATCH] Add Int, Uint and Float traits for primitive numbers --- src/libcore/core.rc | 1 + src/libcore/num/f32.rs | 50 ++++++++++++++++++++------------ src/libcore/num/f64.rs | 50 ++++++++++++++++++++------------ src/libcore/num/float.rs | 46 +++++++++++++++++++++-------- src/libcore/num/int-template.rs | 2 ++ src/libcore/num/num.rs | 18 ++++++++++++ src/libcore/num/uint-template.rs | 2 ++ src/libcore/prelude.rs | 1 + 8 files changed, 122 insertions(+), 48 deletions(-) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 8b9ba22f330..55cabad7412 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -108,6 +108,7 @@ pub use num::{Signed, Unsigned, Integer}; pub use num::{Round, Fractional, Real, RealExt}; pub use num::{Bitwise, Bounded}; pub use num::{Primitive, PrimitiveInt}; +pub use num::{Int, Uint, Float}; pub use ptr::Ptr; pub use to_str::ToStr; pub use clone::Clone; diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index d1369b929f6..f6330df9f9e 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -114,9 +114,6 @@ pub static infinity: f32 = 1.0_f32/0.0_f32; pub static neg_infinity: f32 = -1.0_f32/0.0_f32; -#[inline(always)] -pub fn is_NaN(f: f32) -> bool { f != f } - #[inline(always)] pub fn add(x: f32, y: f32) -> f32 { return x + y; } @@ -154,18 +151,6 @@ pub fn gt(x: f32, y: f32) -> bool { return x > y; } // FIXME (#1999): replace the predicates below with llvm intrinsics or // calls to the libmath macros in the rust runtime for performance. -/// Returns true if `x`is an infinite number -#[inline(always)] -pub fn is_infinite(x: f32) -> bool { - return x == infinity || x == neg_infinity; -} - -/// Returns true if `x`is a finite number -#[inline(always)] -pub fn is_finite(x: f32) -> bool { - return !(is_NaN(x) || is_infinite(x)); -} - // FIXME (#1999): add is_normal, is_subnormal, and fpclassify. /* Module: consts */ @@ -313,7 +298,7 @@ impl Signed for f32 { /// #[inline(always)] fn signum(&self) -> f32 { - if is_NaN(*self) { NaN } else { copysign(1.0, *self) } + if self.is_NaN() { NaN } else { copysign(1.0, *self) } } /// Returns `true` if the number is positive, including `+0.0` and `infinity` @@ -517,6 +502,35 @@ impl Primitive for f32 { fn bytes() -> uint { Primitive::bits::() / 8 } } +impl Float for f32 { + #[inline(always)] + fn NaN() -> f32 { 0.0 / 0.0 } + + #[inline(always)] + fn infinity() -> f32 { 1.0 / 0.0 } + + #[inline(always)] + fn neg_infinity() -> f32 { -1.0 / 0.0 } + + #[inline(always)] + fn neg_zero() -> f32 { -0.0 } + + #[inline(always)] + fn is_NaN(&self) -> bool { *self != *self } + + /// Returns `true` if the number is infinite + #[inline(always)] + fn is_infinite(&self) -> bool { + *self == Float::infinity() || *self == Float::neg_infinity() + } + + /// Returns `true` if the number is finite + #[inline(always)] + fn is_finite(&self) -> bool { + !(self.is_NaN() || self.is_infinite()) + } +} + // // Section: String Conversions // @@ -852,7 +866,7 @@ mod tests { assert_eq!((-1f32).abs(), 1f32); assert_eq!(neg_infinity.abs(), infinity); assert_eq!((1f32/neg_infinity).abs(), 0f32); - assert!(is_NaN(NaN.abs())); + assert!(NaN.abs().is_NaN()); assert_eq!(infinity.signum(), 1f32); assert_eq!(1f32.signum(), 1f32); @@ -861,7 +875,7 @@ mod tests { assert_eq!((-1f32).signum(), -1f32); assert_eq!(neg_infinity.signum(), -1f32); assert_eq!((1f32/neg_infinity).signum(), -1f32); - assert!(is_NaN(NaN.signum())); + assert!(NaN.signum().is_NaN()); assert!(infinity.is_positive()); assert!(1f32.is_positive()); diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 4e0030b5421..d40c402b464 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -138,9 +138,6 @@ pub static infinity: f64 = 1.0_f64/0.0_f64; pub static neg_infinity: f64 = -1.0_f64/0.0_f64; -#[inline(always)] -pub fn is_NaN(f: f64) -> bool { f != f } - #[inline(always)] pub fn add(x: f64, y: f64) -> f64 { return x + y; } @@ -174,18 +171,6 @@ pub fn ge(x: f64, y: f64) -> bool { return x >= y; } #[inline(always)] pub fn gt(x: f64, y: f64) -> bool { return x > y; } -/// Returns true if `x`is an infinite number -#[inline(always)] -pub fn is_infinite(x: f64) -> bool { - return x == infinity || x == neg_infinity; -} - -/// Returns true if `x` is a finite number -#[inline(always)] -pub fn is_finite(x: f64) -> bool { - return !(is_NaN(x) || is_infinite(x)); -} - // FIXME (#1999): add is_normal, is_subnormal, and fpclassify @@ -323,7 +308,7 @@ impl Signed for f64 { /// #[inline(always)] fn signum(&self) -> f64 { - if is_NaN(*self) { NaN } else { copysign(1.0, *self) } + if self.is_NaN() { NaN } else { copysign(1.0, *self) } } /// Returns `true` if the number is positive, including `+0.0` and `infinity` @@ -557,6 +542,35 @@ impl Primitive for f64 { fn bytes() -> uint { Primitive::bits::() / 8 } } +impl Float for f64 { + #[inline(always)] + fn NaN() -> f64 { 0.0 / 0.0 } + + #[inline(always)] + fn infinity() -> f64 { 1.0 / 0.0 } + + #[inline(always)] + fn neg_infinity() -> f64 { -1.0 / 0.0 } + + #[inline(always)] + fn neg_zero() -> f64 { -0.0 } + + #[inline(always)] + fn is_NaN(&self) -> bool { *self != *self } + + /// Returns `true` if the number is infinite + #[inline(always)] + fn is_infinite(&self) -> bool { + *self == Float::infinity() || *self == Float::neg_infinity() + } + + /// Returns `true` if the number is finite + #[inline(always)] + fn is_finite(&self) -> bool { + !(self.is_NaN() || self.is_infinite()) + } +} + // // Section: String Conversions // @@ -893,7 +907,7 @@ mod tests { assert_eq!((-1f64).abs(), 1f64); assert_eq!(neg_infinity.abs(), infinity); assert_eq!((1f64/neg_infinity).abs(), 0f64); - assert!(is_NaN(NaN.abs())); + assert!(NaN.abs().is_NaN()); assert_eq!(infinity.signum(), 1f64); assert_eq!(1f64.signum(), 1f64); @@ -902,7 +916,7 @@ mod tests { assert_eq!((-1f64).signum(), -1f64); assert_eq!(neg_infinity.signum(), -1f64); assert_eq!((1f64/neg_infinity).signum(), -1f64); - assert!(is_NaN(NaN.signum())); + assert!(NaN.signum().is_NaN()); assert!(infinity.is_positive()); assert!(1f64.is_positive()); diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index a409639f9e6..9852e05c0b8 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -337,13 +337,6 @@ pub fn pow_with_uint(base: uint, pow: uint) -> float { return total; } -#[inline(always)] -pub fn is_infinite(x: float) -> bool { f64::is_infinite(x as f64) } -#[inline(always)] -pub fn is_finite(x: float) -> bool { f64::is_finite(x as f64) } -#[inline(always)] -pub fn is_NaN(x: float) -> bool { f64::is_NaN(x as f64) } - #[inline(always)] pub fn abs(x: float) -> float { f64::abs(x as f64) as float @@ -677,7 +670,7 @@ impl Signed for float { /// #[inline(always)] fn signum(&self) -> float { - if is_NaN(*self) { NaN } else { f64::copysign(1.0, *self as f64) as float } + if self.is_NaN() { NaN } else { f64::copysign(1.0, *self as f64) as float } } /// Returns `true` if the number is positive, including `+0.0` and `infinity` @@ -697,6 +690,35 @@ impl Primitive for float { fn bytes() -> uint { Primitive::bytes::() } } +impl Float for float { + #[inline(always)] + fn NaN() -> float { 0.0 / 0.0 } + + #[inline(always)] + fn infinity() -> float { 1.0 / 0.0 } + + #[inline(always)] + fn neg_infinity() -> float { -1.0 / 0.0 } + + #[inline(always)] + fn neg_zero() -> float { -0.0 } + + #[inline(always)] + fn is_NaN(&self) -> bool { *self != *self } + + /// Returns `true` if the number is infinite + #[inline(always)] + fn is_infinite(&self) -> bool { + *self == Float::infinity() || *self == Float::neg_infinity() + } + + /// Returns `true` if the number is finite + #[inline(always)] + fn is_finite(&self) -> bool { + !(self.is_NaN() || self.is_infinite()) + } +} + #[cfg(test)] mod tests { use super::*; @@ -814,7 +836,7 @@ mod tests { assert_eq!((-1f).abs(), 1f); assert_eq!(neg_infinity.abs(), infinity); assert_eq!((1f/neg_infinity).abs(), 0f); - assert!(is_NaN(NaN.abs())); + assert!(NaN.abs().is_NaN()); assert_eq!(infinity.signum(), 1f); assert_eq!(1f.signum(), 1f); @@ -823,7 +845,7 @@ mod tests { assert_eq!((-1f).signum(), -1f); assert_eq!(neg_infinity.signum(), -1f); assert_eq!((1f/neg_infinity).signum(), -1f); - assert!(is_NaN(NaN.signum())); + assert!(NaN.signum().is_NaN()); assert!(infinity.is_positive()); assert!(1f.is_positive()); @@ -878,7 +900,7 @@ mod tests { assert_eq!(from_str(~"-inf"), Some(neg_infinity)); // note: NaN != NaN, hence this slightly complex test match from_str(~"NaN") { - Some(f) => assert!(is_NaN(f)), + Some(f) => assert!(f.is_NaN()), None => fail!() } // note: -0 == 0, hence these slightly more complex tests @@ -925,7 +947,7 @@ mod tests { assert_eq!(from_str_hex(~"-inf"), Some(neg_infinity)); // note: NaN != NaN, hence this slightly complex test match from_str_hex(~"NaN") { - Some(f) => assert!(is_NaN(f)), + Some(f) => assert!(f.is_NaN()), None => fail!() } // note: -0 == 0, hence these slightly more complex tests diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index 32ae19bec41..877767b5cbf 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -447,6 +447,8 @@ impl Bounded for T { impl PrimitiveInt for T {} +impl Int for T {} + // String conversion functions and impl str -> num /// Parse a string as a number in base 10. diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 5b524a42c25..8e6128ceb97 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -228,6 +228,24 @@ pub trait Uint: PrimitiveInt pub trait Int: PrimitiveInt + Signed {} +/// +/// Primitive floating point numbers. This trait should only be implemented +/// for the `f32`, `f64`, and `float` types. +/// +pub trait Float: Real + + Signed + + Primitive { + // FIXME (#5527): These should be associated constants + fn NaN() -> Self; + fn infinity() -> Self; + fn neg_infinity() -> Self; + fn neg_zero() -> Self; + + fn is_NaN(&self) -> bool; + fn is_infinite(&self) -> bool; + fn is_finite(&self) -> bool; +} + /// /// Cast from one machine scalar to another /// diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index a89a6faec28..67a930c72a4 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -279,6 +279,8 @@ impl Bounded for T { impl PrimitiveInt for T {} +impl Uint for T {} + // String conversion functions and impl str -> num /// Parse a string as a number in base 10. diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 2ab1347f578..fdae5298d7c 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -42,6 +42,7 @@ pub use num::{Signed, Unsigned, Integer}; pub use num::{Round, Fractional, Real, RealExt}; pub use num::{Bitwise, Bounded}; pub use num::{Primitive, PrimitiveInt}; +pub use num::{Int, Uint, Float}; pub use path::GenericPath; pub use path::Path; pub use path::PosixPath;