about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorBrendan Zabarauskas <bjzaba@yahoo.com.au>2013-04-23 17:59:49 +1000
committerBrendan Zabarauskas <bjzaba@yahoo.com.au>2013-04-24 12:46:26 +1000
commitaef249056e55ad2bf3d658609c440fad4a9255eb (patch)
treec1e1251fd77c46270d4889ac27c91f1ce1126045 /src/libcore
parent706096b31960143fb1eb957a882f170ae4a8b4e9 (diff)
downloadrust-aef249056e55ad2bf3d658609c440fad4a9255eb.tar.gz
rust-aef249056e55ad2bf3d658609c440fad4a9255eb.zip
Implement Signed and Unsigned traits and remove related predicate functions
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/core.rc2
-rw-r--r--src/libcore/num/f32.rs114
-rw-r--r--src/libcore/num/f64.rs112
-rw-r--r--src/libcore/num/float.rs134
-rw-r--r--src/libcore/num/int-template.rs68
-rw-r--r--src/libcore/num/num.rs11
-rw-r--r--src/libcore/num/uint-template.rs12
-rw-r--r--src/libcore/prelude.rs2
8 files changed, 294 insertions, 161 deletions
diff --git a/src/libcore/core.rc b/src/libcore/core.rc
index b0a3939db73..123fbcca9d5 100644
--- a/src/libcore/core.rc
+++ b/src/libcore/core.rc
@@ -105,7 +105,7 @@ pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter};
 pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times};
 pub use iter::{ExtendedMutableIter};
 
-pub use num::{Num, NumCast};
+pub use num::{Num, Signed, Unsigned, NumCast};
 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 62004710196..5d663844e5b 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -11,6 +11,7 @@
 //! Operations and constants for `f32`
 
 use num::strconv;
+use num::Signed;
 use num;
 use option::Option;
 use from_str;
@@ -163,38 +164,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 a positive number, including +0.0f320 and +Infinity
-#[inline(always)]
-pub fn is_positive(x: f32) -> bool {
-    x > 0.0f32 || (1.0f32/x) == infinity
-}
-
-/// Returns true if `x` is a negative number, including -0.0f320 and -Infinity
-#[inline(always)]
-pub fn is_negative(x: f32) -> bool {
-    x < 0.0f32 || (1.0f32/x) == neg_infinity
-}
-
-/**
- * Returns true if `x` is a negative number, including -0.0f320 and -Infinity
- *
- * This is the same as `f32::is_negative`.
- */
-#[inline(always)]
-pub fn is_nonpositive(x: f32) -> bool {
-  return x < 0.0f32 || (1.0f32/x) == neg_infinity;
-}
-
-/**
- * Returns true if `x` is a positive number, including +0.0f320 and +Infinity
- *
- * This is the same as `f32::is_positive`.)
- */
-#[inline(always)]
-pub fn is_nonnegative(x: f32) -> bool {
-  return x > 0.0f32 || (1.0f32/x) == infinity;
-}
-
 /// Returns true if `x` is a zero number (positive or negative zero)
 #[inline(always)]
 pub fn is_zero(x: f32) -> bool {
@@ -260,11 +229,6 @@ pub mod consts {
 }
 
 #[inline(always)]
-pub fn signbit(x: f32) -> int {
-    if is_negative(x) { return 1; } else { return 0; }
-}
-
-#[inline(always)]
 pub fn logarithm(n: f32, b: f32) -> f32 {
     return log2(n) / log2(b);
 }
@@ -351,15 +315,41 @@ impl Neg<f32> for f32 {
     fn neg(&self) -> f32 { -*self }
 }
 
+impl Signed for f32 {
+    /// Computes the absolute value. Returns `NaN` if the number is `NaN`.
+    #[inline(always)]
+    fn abs(&self) -> f32 { abs(*self) }
+
+    /**
+     * # Returns
+     *
+     * - `1.0` if the number is positive, `+0.0` or `infinity`
+     * - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
+     * - `NaN` if the number is `NaN`
+     */
+    #[inline(always)]
+    fn signum(&self) -> f32 {
+        if is_NaN(*self) { NaN } else { copysign(1.0, *self) }
+    }
+
+    /// Returns `true` if the number is positive, including `+0.0` and `infinity`
+    #[inline(always)]
+    fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity }
+
+    /// Returns `true` if the number is negative, including `-0.0` and `neg_infinity`
+    #[inline(always)]
+    fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
+}
+
 impl num::Round for f32 {
     #[inline(always)]
     fn round(&self, mode: num::RoundMode) -> f32 {
         match mode {
             num::RoundDown                           => floor(*self),
             num::RoundUp                             => ceil(*self),
-            num::RoundToZero   if is_negative(*self) => ceil(*self),
+            num::RoundToZero   if self.is_negative() => ceil(*self),
             num::RoundToZero                         => floor(*self),
-            num::RoundFromZero if is_negative(*self) => floor(*self),
+            num::RoundFromZero if self.is_negative() => floor(*self),
             num::RoundFromZero                       => ceil(*self)
         }
     }
@@ -370,7 +360,7 @@ impl num::Round for f32 {
     fn ceil(&self) -> f32 { ceil(*self) }
     #[inline(always)]
     fn fract(&self) -> f32 {
-        if is_negative(*self) {
+        if self.is_negative() {
             (*self) - ceil(*self)
         } else {
             (*self) - floor(*self)
@@ -595,6 +585,50 @@ impl num::FromStrRadix for f32 {
     }
 }
 
+#[cfg(test)]
+mod tests {
+    use f32::*;
+
+    #[test]
+    pub fn test_signed() {
+        assert_eq!(infinity.abs(), infinity);
+        assert_eq!(1f32.abs(), 1f32);
+        assert_eq!(0f32.abs(), 0f32);
+        assert_eq!((-0f32).abs(), 0f32);
+        assert_eq!((-1f32).abs(), 1f32);
+        assert_eq!(neg_infinity.abs(), infinity);
+        assert_eq!((1f32/neg_infinity).abs(), 0f32);
+        assert!(is_NaN(NaN.abs()));
+
+        assert_eq!(infinity.signum(), 1f32);
+        assert_eq!(1f32.signum(), 1f32);
+        assert_eq!(0f32.signum(), 1f32);
+        assert_eq!((-0f32).signum(), -1f32);
+        assert_eq!((-1f32).signum(), -1f32);
+        assert_eq!(neg_infinity.signum(), -1f32);
+        assert_eq!((1f32/neg_infinity).signum(), -1f32);
+        assert!(is_NaN(NaN.signum()));
+
+        assert!(infinity.is_positive());
+        assert!(1f32.is_positive());
+        assert!(0f32.is_positive());
+        assert!(!(-0f32).is_positive());
+        assert!(!(-1f32).is_positive());
+        assert!(!neg_infinity.is_positive());
+        assert!(!(1f32/neg_infinity).is_positive());
+        assert!(!NaN.is_positive());
+
+        assert!(!infinity.is_negative());
+        assert!(!1f32.is_negative());
+        assert!(!0f32.is_negative());
+        assert!((-0f32).is_negative());
+        assert!((-1f32).is_negative());
+        assert!(neg_infinity.is_negative());
+        assert!((1f32/neg_infinity).is_negative());
+        assert!(!NaN.is_negative());
+    }
+}
+
 //
 // Local Variables:
 // mode: rust
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index 4762c395a25..48f23fe8ba9 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -11,6 +11,7 @@
 //! Operations and constants for `f64`
 
 use num::strconv;
+use num::Signed;
 use num;
 use option::Option;
 use to_str;
@@ -183,36 +184,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 a positive number, including +0.0f640 and +Infinity
-#[inline(always)]
-pub fn is_positive(x: f64) -> bool
-    { return x > 0.0f64 || (1.0f64/x) == infinity; }
-
-/// Returns true if `x` is a negative number, including -0.0f640 and -Infinity
-#[inline(always)]
-pub fn is_negative(x: f64) -> bool
-    { return x < 0.0f64 || (1.0f64/x) == neg_infinity; }
-
-/**
- * Returns true if `x` is a negative number, including -0.0f640 and -Infinity
- *
- * This is the same as `f64::is_negative`.
- */
-#[inline(always)]
-pub fn is_nonpositive(x: f64) -> bool {
-  return x < 0.0f64 || (1.0f64/x) == neg_infinity;
-}
-
-/**
- * Returns true if `x` is a positive number, including +0.0f640 and +Infinity
- *
- * This is the same as `f64::positive`.
- */
-#[inline(always)]
-pub fn is_nonnegative(x: f64) -> bool {
-  return x > 0.0f64 || (1.0f64/x) == infinity;
-}
-
 /// Returns true if `x` is a zero number (positive or negative zero)
 #[inline(always)]
 pub fn is_zero(x: f64) -> bool {
@@ -279,11 +250,6 @@ pub mod consts {
 }
 
 #[inline(always)]
-pub fn signbit(x: f64) -> int {
-    if is_negative(x) { return 1; } else { return 0; }
-}
-
-#[inline(always)]
 pub fn logarithm(n: f64, b: f64) -> f64 {
     return log2(n) / log2(b);
 }
@@ -357,15 +323,41 @@ impl Neg<f64> for f64 {
     fn neg(&self) -> f64 { -*self }
 }
 
+impl Signed for f64 {
+    /// Computes the absolute value. Returns `NaN` if the number is `NaN`.
+    #[inline(always)]
+    fn abs(&self) -> f64 { abs(*self) }
+
+    /**
+     * # Returns
+     *
+     * - `1.0` if the number is positive, `+0.0` or `infinity`
+     * - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
+     * - `NaN` if the number is `NaN`
+     */
+    #[inline(always)]
+    fn signum(&self) -> f64 {
+        if is_NaN(*self) { NaN } else { copysign(1.0, *self) }
+    }
+
+    /// Returns `true` if the number is positive, including `+0.0` and `infinity`
+    #[inline(always)]
+    fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity }
+
+    /// Returns `true` if the number is negative, including `-0.0` and `neg_infinity`
+    #[inline(always)]
+    fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
+}
+
 impl num::Round for f64 {
     #[inline(always)]
     fn round(&self, mode: num::RoundMode) -> f64 {
         match mode {
             num::RoundDown                           => floor(*self),
             num::RoundUp                             => ceil(*self),
-            num::RoundToZero   if is_negative(*self) => ceil(*self),
+            num::RoundToZero   if self.is_negative() => ceil(*self),
             num::RoundToZero                         => floor(*self),
-            num::RoundFromZero if is_negative(*self) => floor(*self),
+            num::RoundFromZero if self.is_negative() => floor(*self),
             num::RoundFromZero                       => ceil(*self)
         }
     }
@@ -376,7 +368,7 @@ impl num::Round for f64 {
     fn ceil(&self) -> f64 { ceil(*self) }
     #[inline(always)]
     fn fract(&self) -> f64 {
-        if is_negative(*self) {
+        if self.is_negative() {
             (*self) - ceil(*self)
         } else {
             (*self) - floor(*self)
@@ -601,6 +593,50 @@ impl num::FromStrRadix for f64 {
     }
 }
 
+#[cfg(test)]
+mod tests {
+    use f64::*;
+
+    #[test]
+    pub fn test_signed() {
+        assert_eq!(infinity.abs(), infinity);
+        assert_eq!(1f64.abs(), 1f64);
+        assert_eq!(0f64.abs(), 0f64);
+        assert_eq!((-0f64).abs(), 0f64);
+        assert_eq!((-1f64).abs(), 1f64);
+        assert_eq!(neg_infinity.abs(), infinity);
+        assert_eq!((1f64/neg_infinity).abs(), 0f64);
+        assert!(is_NaN(NaN.abs()));
+
+        assert_eq!(infinity.signum(), 1f64);
+        assert_eq!(1f64.signum(), 1f64);
+        assert_eq!(0f64.signum(), 1f64);
+        assert_eq!((-0f64).signum(), -1f64);
+        assert_eq!((-1f64).signum(), -1f64);
+        assert_eq!(neg_infinity.signum(), -1f64);
+        assert_eq!((1f64/neg_infinity).signum(), -1f64);
+        assert!(is_NaN(NaN.signum()));
+
+        assert!(infinity.is_positive());
+        assert!(1f64.is_positive());
+        assert!(0f64.is_positive());
+        assert!(!(-0f64).is_positive());
+        assert!(!(-1f64).is_positive());
+        assert!(!neg_infinity.is_positive());
+        assert!(!(1f64/neg_infinity).is_positive());
+        assert!(!NaN.is_positive());
+
+        assert!(!infinity.is_negative());
+        assert!(!1f64.is_negative());
+        assert!(!0f64.is_negative());
+        assert!((-0f64).is_negative());
+        assert!((-1f64).is_negative());
+        assert!(neg_infinity.is_negative());
+        assert!((1f64/neg_infinity).is_negative());
+        assert!(!NaN.is_negative());
+    }
+}
+
 //
 // Local Variables:
 // mode: rust
diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs
index c5c1e52a14c..036d295943c 100644
--- a/src/libcore/num/float.rs
+++ b/src/libcore/num/float.rs
@@ -22,6 +22,7 @@
 
 use f64;
 use num::strconv;
+use num::Signed;
 use num;
 use option::Option;
 use to_str;
@@ -42,7 +43,6 @@ pub use f64::{erf, erfc, exp, expm1, exp2, abs_sub};
 pub use f64::{mul_add, fmax, fmin, nextafter, frexp, hypot, ldexp};
 pub use f64::{lgamma, ln, log_radix, ln1p, log10, log2, ilog_radix};
 pub use f64::{modf, pow, powi, round, sinh, tanh, tgamma, trunc};
-pub use f64::signbit;
 pub use f64::{j0, j1, jn, y0, y1, yn};
 
 pub static NaN: float = 0.0/0.0;
@@ -349,14 +349,6 @@ pub fn pow_with_uint(base: uint, pow: uint) -> float {
 }
 
 #[inline(always)]
-pub fn is_positive(x: float) -> bool { f64::is_positive(x as f64) }
-#[inline(always)]
-pub fn is_negative(x: float) -> bool { f64::is_negative(x as f64) }
-#[inline(always)]
-pub fn is_nonpositive(x: float) -> bool { f64::is_nonpositive(x as f64) }
-#[inline(always)]
-pub fn is_nonnegative(x: float) -> bool { f64::is_nonnegative(x as f64) }
-#[inline(always)]
 pub fn is_zero(x: float) -> bool { f64::is_zero(x as f64) }
 #[inline(always)]
 pub fn is_infinite(x: float) -> bool { f64::is_infinite(x as f64) }
@@ -428,11 +420,11 @@ impl num::Round for float {
                 => f64::floor(*self as f64) as float,
             num::RoundUp
                 => f64::ceil(*self as f64) as float,
-            num::RoundToZero   if is_negative(*self)
+            num::RoundToZero   if self.is_negative()
                 => f64::ceil(*self as f64) as float,
             num::RoundToZero
                 => f64::floor(*self as f64) as float,
-            num::RoundFromZero if is_negative(*self)
+            num::RoundFromZero if self.is_negative()
                 => f64::floor(*self as f64) as float,
             num::RoundFromZero
                 => f64::ceil(*self as f64) as float
@@ -445,7 +437,7 @@ impl num::Round for float {
     fn ceil(&self) -> float { f64::ceil(*self as f64) as float}
     #[inline(always)]
     fn fract(&self) -> float {
-        if is_negative(*self) {
+        if self.is_negative() {
             (*self) - (f64::ceil(*self as f64) as float)
         } else {
             (*self) - (f64::floor(*self as f64) as float)
@@ -501,10 +493,76 @@ impl Neg<float> for float {
     fn neg(&self) -> float { -*self }
 }
 
+impl Signed for float {
+    /// Computes the absolute value. Returns `NaN` if the number is `NaN`.
+    #[inline(always)]
+    fn abs(&self) -> float { abs(*self) }
+
+    /**
+     * # Returns
+     *
+     * - `1.0` if the number is positive, `+0.0` or `infinity`
+     * - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
+     * - `NaN` if the number is NaN
+     */
+    #[inline(always)]
+    fn signum(&self) -> float {
+        if is_NaN(*self) { NaN } else { f64::copysign(1.0, *self as f64) as float }
+    }
+
+    /// Returns `true` if the number is positive, including `+0.0` and `infinity`
+    #[inline(always)]
+    fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity }
+
+    /// Returns `true` if the number is negative, including `-0.0` and `neg_infinity`
+    #[inline(always)]
+    fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
     use prelude::*;
+
+    #[test]
+    pub fn test_signed() {
+        assert_eq!(infinity.abs(), infinity);
+        assert_eq!(1f.abs(), 1f);
+        assert_eq!(0f.abs(), 0f);
+        assert_eq!((-0f).abs(), 0f);
+        assert_eq!((-1f).abs(), 1f);
+        assert_eq!(neg_infinity.abs(), infinity);
+        assert_eq!((1f/neg_infinity).abs(), 0f);
+        assert!(is_NaN(NaN.abs()));
+
+        assert_eq!(infinity.signum(), 1f);
+        assert_eq!(1f.signum(), 1f);
+        assert_eq!(0f.signum(), 1f);
+        assert_eq!((-0f).signum(), -1f);
+        assert_eq!((-1f).signum(), -1f);
+        assert_eq!(neg_infinity.signum(), -1f);
+        assert_eq!((1f/neg_infinity).signum(), -1f);
+        assert!(is_NaN(NaN.signum()));
+
+        assert!(infinity.is_positive());
+        assert!(1f.is_positive());
+        assert!(0f.is_positive());
+        assert!(!(-0f).is_positive());
+        assert!(!(-1f).is_positive());
+        assert!(!neg_infinity.is_positive());
+        assert!(!(1f/neg_infinity).is_positive());
+        assert!(!NaN.is_positive());
+
+        assert!(!infinity.is_negative());
+        assert!(!1f.is_negative());
+        assert!(!0f.is_negative());
+        assert!((-0f).is_negative());
+        assert!((-1f).is_negative());
+        assert!(neg_infinity.is_negative());
+        assert!((1f/neg_infinity).is_negative());
+        assert!(!NaN.is_negative());
+    }
+
     #[test]
     pub fn test_to_str_exact_do_decimal() {
         let s = to_str_exact(5.0, 4u);
@@ -538,11 +596,11 @@ mod tests {
         }
         // note: -0 == 0, hence these slightly more complex tests
         match from_str(~"-0") {
-            Some(v) if is_zero(v) => assert!(is_negative(v)),
+            Some(v) if is_zero(v) => assert!(v.is_negative()),
             _ => fail!()
         }
         match from_str(~"0") {
-            Some(v) if is_zero(v) => assert!(is_positive(v)),
+            Some(v) if is_zero(v) => assert!(v.is_positive()),
             _ => fail!()
         }
 
@@ -585,11 +643,11 @@ mod tests {
         }
         // note: -0 == 0, hence these slightly more complex tests
         match from_str_hex(~"-0") {
-            Some(v) if is_zero(v) => assert!(is_negative(v)),
+            Some(v) if is_zero(v) => assert!(v.is_negative()),
             _ => fail!()
         }
         match from_str_hex(~"0") {
-            Some(v) if is_zero(v) => assert!(is_positive(v)),
+            Some(v) if is_zero(v) => assert!(v.is_positive()),
             _ => fail!()
         }
         assert_eq!(from_str_hex(~"e"), Some(14.));
@@ -642,50 +700,6 @@ mod tests {
     }
 
     #[test]
-    pub fn test_positive() {
-        assert!(is_positive(infinity));
-        assert!(is_positive(1.));
-        assert!(is_positive(0.));
-        assert!(!is_positive(-1.));
-        assert!(!is_positive(neg_infinity));
-        assert!(!is_positive(1./neg_infinity));
-        assert!(!is_positive(NaN));
-    }
-
-    #[test]
-    pub fn test_negative() {
-        assert!(!is_negative(infinity));
-        assert!(!is_negative(1.));
-        assert!(!is_negative(0.));
-        assert!(is_negative(-1.));
-        assert!(is_negative(neg_infinity));
-        assert!(is_negative(1./neg_infinity));
-        assert!(!is_negative(NaN));
-    }
-
-    #[test]
-    pub fn test_nonpositive() {
-        assert!(!is_nonpositive(infinity));
-        assert!(!is_nonpositive(1.));
-        assert!(!is_nonpositive(0.));
-        assert!(is_nonpositive(-1.));
-        assert!(is_nonpositive(neg_infinity));
-        assert!(is_nonpositive(1./neg_infinity));
-        assert!(!is_nonpositive(NaN));
-    }
-
-    #[test]
-    pub fn test_nonnegative() {
-        assert!(is_nonnegative(infinity));
-        assert!(is_nonnegative(1.));
-        assert!(is_nonnegative(0.));
-        assert!(!is_nonnegative(-1.));
-        assert!(!is_nonnegative(neg_infinity));
-        assert!(!is_nonnegative(1./neg_infinity));
-        assert!(!is_nonnegative(NaN));
-    }
-
-    #[test]
     pub fn test_to_str_inf() {
         assert_eq!(to_str_digits(infinity, 10u), ~"inf");
         assert_eq!(to_str_digits(-infinity, 10u), ~"-inf");
diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs
index 684083f53e9..d65cbb4cf92 100644
--- a/src/libcore/num/int-template.rs
+++ b/src/libcore/num/int-template.rs
@@ -14,6 +14,7 @@ use to_str::ToStr;
 use from_str::FromStr;
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
+use num::Signed;
 use num;
 use prelude::*;
 
@@ -70,15 +71,6 @@ pub fn ge(x: T, y: T) -> bool { x >= y }
 #[inline(always)]
 pub fn gt(x: T, y: T) -> bool { x > y }
 
-#[inline(always)]
-pub fn is_positive(x: T) -> bool { x > 0 as T }
-#[inline(always)]
-pub fn is_negative(x: T) -> bool { x < 0 as T }
-#[inline(always)]
-pub fn is_nonpositive(x: T) -> bool { x <= 0 as T }
-#[inline(always)]
-pub fn is_nonnegative(x: T) -> bool { x >= 0 as T }
-
 /**
  * Iterate over the range [`lo`..`hi`)
  *
@@ -139,9 +131,7 @@ pub fn compl(i: T) -> T {
 
 /// Computes the absolute value
 #[inline(always)]
-pub fn abs(i: T) -> T {
-    if is_negative(i) { -i } else { i }
-}
+pub fn abs(i: T) -> T { i.abs() }
 
 #[cfg(notest)]
 impl Ord for T {
@@ -225,6 +215,38 @@ impl Neg<T> for T {
     fn neg(&self) -> T { -*self }
 }
 
+impl Signed for T {
+    /// Computes the absolute value
+    #[inline(always)]
+    fn abs(&self) -> T {
+        if self.is_negative() { -*self } else { *self }
+    }
+
+    /**
+     * # Returns
+     *
+     * - `0` if the number is zero
+     * - `1` if the number is positive
+     * - `-1` if the number is negative
+     */
+    #[inline(always)]
+    fn signum(&self) -> T {
+        match *self {
+            n if n > 0 =>  1,
+            0          =>  0,
+            _          => -1,
+        }
+    }
+
+    /// Returns true if the number is positive
+    #[inline(always)]
+    fn is_positive(&self) -> bool { *self > 0 }
+
+    /// Returns true if the number is negative
+    #[inline(always)]
+    fn is_negative(&self) -> bool { *self < 0 }
+}
+
 #[cfg(notest)]
 impl BitOr<T,T> for T {
     #[inline(always)]
@@ -345,6 +367,28 @@ mod tests {
     use prelude::*;
 
     #[test]
+    pub fn test_signed() {
+        assert_eq!((1 as T).abs(), 1 as T);
+        assert_eq!((0 as T).abs(), 0 as T);
+        assert_eq!((-1 as T).abs(), 1 as T);
+
+        assert_eq!((1 as T).signum(), 1 as T);
+        assert_eq!((0 as T).signum(), 0 as T);
+        assert_eq!((-0 as T).signum(), 0 as T);
+        assert_eq!((-1 as T).signum(), -1 as T);
+
+        assert!((1 as T).is_positive());
+        assert!(!(0 as T).is_positive());
+        assert!(!(-0 as T).is_positive());
+        assert!(!(-1 as T).is_positive());
+
+        assert!(!(1 as T).is_negative());
+        assert!(!(0 as T).is_negative());
+        assert!(!(-0 as T).is_negative());
+        assert!((-1 as T).is_negative());
+    }
+
+    #[test]
     fn test_bitwise_ops() {
         assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T)));
         assert_eq!(0b1000 as T, (0b1100 as T).bitand(&(0b1010 as T)));
diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs
index a0ff510cde7..ea0b290aac2 100644
--- a/src/libcore/num/num.rs
+++ b/src/libcore/num/num.rs
@@ -60,6 +60,17 @@ pub trait One {
     fn one() -> Self;
 }
 
+pub trait Signed: Num
+                + Neg<Self> {
+    fn abs(&self) -> Self;
+    fn signum(&self) -> Self;
+    fn is_positive(&self) -> bool;
+    fn is_negative(&self) -> bool;
+}
+
+pub trait Unsigned: Num {}
+
+// This should be moved into the default implementation for Signed::abs
 pub fn abs<T:Ord + Zero + Neg<T>>(v: T) -> T {
     if v < Zero::zero() { v.neg() } else { v }
 }
diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs
index 4bb93907a3a..41205145f17 100644
--- a/src/libcore/num/uint-template.rs
+++ b/src/libcore/num/uint-template.rs
@@ -15,6 +15,7 @@ use to_str::ToStr;
 use from_str::FromStr;
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
+use num::Unsigned;
 use num;
 use option::Option;
 use prelude::*;
@@ -52,15 +53,6 @@ pub fn ge(x: T, y: T) -> bool { x >= y }
 pub fn gt(x: T, y: T) -> bool { x > y }
 
 #[inline(always)]
-pub fn is_positive(x: T) -> bool { x > 0 as T }
-#[inline(always)]
-pub fn is_negative(x: T) -> bool { x < 0 as T }
-#[inline(always)]
-pub fn is_nonpositive(x: T) -> bool { x <= 0 as T }
-#[inline(always)]
-pub fn is_nonnegative(x: T) -> bool { x >= 0 as T }
-
-#[inline(always)]
 /**
  * Iterate over the range [`start`,`start`+`step`..`stop`)
  *
@@ -190,6 +182,8 @@ impl Neg<T> for T {
     fn neg(&self) -> T { -*self }
 }
 
+impl Unsigned for T {}
+
 #[cfg(notest)]
 impl BitOr<T,T> for T {
     #[inline(always)]
diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs
index 15aa6c78ed6..157a0e3752d 100644
--- a/src/libcore/prelude.rs
+++ b/src/libcore/prelude.rs
@@ -39,7 +39,7 @@ pub use hash::Hash;
 pub use iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};
 pub use iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter};
 pub use iter::{Times, ExtendedMutableIter};
-pub use num::{Num, NumCast};
+pub use num::{Num, Signed, Unsigned, NumCast};
 pub use path::GenericPath;
 pub use path::Path;
 pub use path::PosixPath;