Add Int, Uint and Float traits for primitive numbers

This commit is contained in:
Brendan Zabarauskas 2013-04-26 10:22:08 +10:00
parent b62421000c
commit 4c07f5e457
8 changed files with 122 additions and 48 deletions

View File

@ -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;

View File

@ -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::<f32>() / 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());

View File

@ -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::<f64>() / 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());

View File

@ -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::<f64>() }
}
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

View File

@ -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.

View File

@ -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
///

View File

@ -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.

View File

@ -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;