summary refs log tree commit diff
path: root/src/libcore/num
diff options
context:
space:
mode:
authorBrendan Zabarauskas <bjzaba@yahoo.com.au>2013-02-11 12:33:05 +1100
committerBrendan Zabarauskas <bjzaba@yahoo.com.au>2013-02-11 12:33:05 +1100
commit48b2141b83bd3afe6aee3adf170ef6e985ab1353 (patch)
tree2f7645e008ff316d7b1d12b24a4a96e3f8e8b17d /src/libcore/num
parent0f04df8522cc93dfcdc0eb49f8403d305a508e58 (diff)
downloadrust-48b2141b83bd3afe6aee3adf170ef6e985ab1353.tar.gz
rust-48b2141b83bd3afe6aee3adf170ef6e985ab1353.zip
Add NumCast trait for generic numeric type casts
Diffstat (limited to 'src/libcore/num')
-rw-r--r--src/libcore/num/f32.rs87
-rw-r--r--src/libcore/num/f64.rs83
-rw-r--r--src/libcore/num/float.rs98
-rw-r--r--src/libcore/num/int-template.rs31
-rw-r--r--src/libcore/num/int-template/i16.rs71
-rw-r--r--src/libcore/num/int-template/i32.rs71
-rw-r--r--src/libcore/num/int-template/i64.rs71
-rw-r--r--src/libcore/num/int-template/i8.rs71
-rw-r--r--src/libcore/num/int-template/int.rs71
-rw-r--r--src/libcore/num/num.rs69
-rw-r--r--src/libcore/num/uint-template.rs17
-rw-r--r--src/libcore/num/uint-template/u16.rs71
-rw-r--r--src/libcore/num/uint-template/u32.rs71
-rw-r--r--src/libcore/num/uint-template/u64.rs71
-rw-r--r--src/libcore/num/uint-template/u8.rs71
-rw-r--r--src/libcore/num/uint-template/uint.rs71
16 files changed, 1024 insertions, 71 deletions
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index 738445b5cd9..6bea9e81197 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -14,6 +14,7 @@ use cmath;
 use cmp;
 use libc::{c_float, c_int};
 use num;
+use num::NumCast;
 use option::Option;
 use from_str;
 use to_str;
@@ -283,11 +284,6 @@ impl f32: num::Num {
     pure fn modulo(&self, other: &f32) -> f32 { return *self % *other; }
     #[inline(always)]
     pure fn neg(&self)                -> f32 { return -*self;        }
-
-    #[inline(always)]
-    pure fn to_int(&self)         -> int { return *self as int; }
-    #[inline(always)]
-    static pure fn from_int(n: int) -> f32 { return n as f32;    }
 }
 
 impl f32: num::Zero {
@@ -300,6 +296,30 @@ impl f32: num::One {
     static pure fn one() -> f32 { 1.0 }
 }
 
+pub impl f32: NumCast {
+    /**
+     * Cast `n` to an `f32`
+     */
+    #[inline(always)]
+    static pure fn from<N:NumCast>(n: N) -> f32 { n.to_f32() }
+
+    #[inline(always)] pure fn to_u8(&self)    -> u8    { *self as u8    }
+    #[inline(always)] pure fn to_u16(&self)   -> u16   { *self as u16   }
+    #[inline(always)] pure fn to_u32(&self)   -> u32   { *self as u32   }
+    #[inline(always)] pure fn to_u64(&self)   -> u64   { *self as u64   }
+    #[inline(always)] pure fn to_uint(&self)  -> uint  { *self as uint  }
+
+    #[inline(always)] pure fn to_i8(&self)    -> i8    { *self as i8    }
+    #[inline(always)] pure fn to_i16(&self)   -> i16   { *self as i16   }
+    #[inline(always)] pure fn to_i32(&self)   -> i32   { *self as i32   }
+    #[inline(always)] pure fn to_i64(&self)   -> i64   { *self as i64   }
+    #[inline(always)] pure fn to_int(&self)   -> int   { *self as int   }
+
+    #[inline(always)] pure fn to_f32(&self)   -> f32   { *self          }
+    #[inline(always)] pure fn to_f64(&self)   -> f64   { *self as f64   }
+    #[inline(always)] pure fn to_float(&self) -> float { *self as float }
+}
+
 #[abi="rust-intrinsic"]
 pub extern {
     fn floorf32(val: f32) -> f32;
@@ -545,6 +565,63 @@ impl f32: num::FromStrRadix {
     }
 }
 
+#[test]
+pub fn test_num() {
+    let ten: f32 = num::cast(10);
+    let two: f32 = num::cast(2);
+
+    assert (ten.add(&two)    == num::cast(12));
+    assert (ten.sub(&two)    == num::cast(8));
+    assert (ten.mul(&two)    == num::cast(20));
+    assert (ten.div(&two)    == num::cast(5));
+    assert (ten.modulo(&two) == num::cast(0));
+}
+
+#[test]
+fn test_numcast() {
+    assert (20u     == 20f32.to_uint());
+    assert (20u8    == 20f32.to_u8());
+    assert (20u16   == 20f32.to_u16());
+    assert (20u32   == 20f32.to_u32());
+    assert (20u64   == 20f32.to_u64());
+    assert (20i     == 20f32.to_int());
+    assert (20i8    == 20f32.to_i8());
+    assert (20i16   == 20f32.to_i16());
+    assert (20i32   == 20f32.to_i32());
+    assert (20i64   == 20f32.to_i64());
+    assert (20f     == 20f32.to_float());
+    assert (20f32   == 20f32.to_f32());
+    assert (20f64   == 20f32.to_f64());
+
+    assert (20f32 == NumCast::from(20u));
+    assert (20f32 == NumCast::from(20u8));
+    assert (20f32 == NumCast::from(20u16));
+    assert (20f32 == NumCast::from(20u32));
+    assert (20f32 == NumCast::from(20u64));
+    assert (20f32 == NumCast::from(20i));
+    assert (20f32 == NumCast::from(20i8));
+    assert (20f32 == NumCast::from(20i16));
+    assert (20f32 == NumCast::from(20i32));
+    assert (20f32 == NumCast::from(20i64));
+    assert (20f32 == NumCast::from(20f));
+    assert (20f32 == NumCast::from(20f32));
+    assert (20f32 == NumCast::from(20f64));
+
+    assert (20f32 == num::cast(20u));
+    assert (20f32 == num::cast(20u8));
+    assert (20f32 == num::cast(20u16));
+    assert (20f32 == num::cast(20u32));
+    assert (20f32 == num::cast(20u64));
+    assert (20f32 == num::cast(20i));
+    assert (20f32 == num::cast(20i8));
+    assert (20f32 == num::cast(20i16));
+    assert (20f32 == num::cast(20i32));
+    assert (20f32 == num::cast(20i64));
+    assert (20f32 == num::cast(20f));
+    assert (20f32 == num::cast(20f32));
+    assert (20f32 == num::cast(20f64));
+}
+
 //
 // Local Variables:
 // mode: rust
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index f09d874803c..7cde2102653 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -15,6 +15,7 @@ use cmp;
 use libc::{c_double, c_int};
 use libc;
 use num;
+use num::NumCast;
 use option::Option;
 use to_str;
 use from_str;
@@ -307,11 +308,30 @@ impl f64: num::Num {
     pure fn modulo(&self, other: &f64) -> f64 { return *self % *other; }
     #[inline(always)]
     pure fn neg(&self)                -> f64 { return -*self;        }
+}
 
+pub impl f64: NumCast {
+    /**
+     * Cast `n` to an `f64`
+     */
     #[inline(always)]
-    pure fn to_int(&self)         -> int { return *self as int; }
-    #[inline(always)]
-    static pure fn from_int(n: int) -> f64 { return n as f64;    }
+    static pure fn from<N:NumCast>(n: N) -> f64 { n.to_f64() }
+
+    #[inline(always)] pure fn to_u8(&self)    -> u8    { *self as u8    }
+    #[inline(always)] pure fn to_u16(&self)   -> u16   { *self as u16   }
+    #[inline(always)] pure fn to_u32(&self)   -> u32   { *self as u32   }
+    #[inline(always)] pure fn to_u64(&self)   -> u64   { *self as u64   }
+    #[inline(always)] pure fn to_uint(&self)  -> uint  { *self as uint  }
+
+    #[inline(always)] pure fn to_i8(&self)    -> i8    { *self as i8    }
+    #[inline(always)] pure fn to_i16(&self)   -> i16   { *self as i16   }
+    #[inline(always)] pure fn to_i32(&self)   -> i32   { *self as i32   }
+    #[inline(always)] pure fn to_i64(&self)   -> i64   { *self as i64   }
+    #[inline(always)] pure fn to_int(&self)   -> int   { *self as int   }
+
+    #[inline(always)] pure fn to_f32(&self)   -> f32   { *self as f32   }
+    #[inline(always)] pure fn to_f64(&self)   -> f64   { *self          }
+    #[inline(always)] pure fn to_float(&self) -> float { *self as float }
 }
 
 impl f64: num::Zero {
@@ -569,6 +589,63 @@ impl f64: num::FromStrRadix {
     }
 }
 
+#[test]
+pub fn test_num() {
+    let ten: f64 = num::cast(10);
+    let two: f64 = num::cast(2);
+
+    assert (ten.add(&two)    == num::cast(12));
+    assert (ten.sub(&two)    == num::cast(8));
+    assert (ten.mul(&two)    == num::cast(20));
+    assert (ten.div(&two)    == num::cast(5));
+    assert (ten.modulo(&two) == num::cast(0));
+}
+
+#[test]
+fn test_numcast() {
+    assert (20u   == 20f64.to_uint());
+    assert (20u8  == 20f64.to_u8());
+    assert (20u16 == 20f64.to_u16());
+    assert (20u32 == 20f64.to_u32());
+    assert (20u64 == 20f64.to_u64());
+    assert (20i   == 20f64.to_int());
+    assert (20i8  == 20f64.to_i8());
+    assert (20i16 == 20f64.to_i16());
+    assert (20i32 == 20f64.to_i32());
+    assert (20i64 == 20f64.to_i64());
+    assert (20f   == 20f64.to_float());
+    assert (20f32 == 20f64.to_f32());
+    assert (20f64 == 20f64.to_f64());
+
+    assert (20f64 == NumCast::from(20u));
+    assert (20f64 == NumCast::from(20u8));
+    assert (20f64 == NumCast::from(20u16));
+    assert (20f64 == NumCast::from(20u32));
+    assert (20f64 == NumCast::from(20u64));
+    assert (20f64 == NumCast::from(20i));
+    assert (20f64 == NumCast::from(20i8));
+    assert (20f64 == NumCast::from(20i16));
+    assert (20f64 == NumCast::from(20i32));
+    assert (20f64 == NumCast::from(20i64));
+    assert (20f64 == NumCast::from(20f));
+    assert (20f64 == NumCast::from(20f32));
+    assert (20f64 == NumCast::from(20f64));
+
+    assert (20f64 == num::cast(20u));
+    assert (20f64 == num::cast(20u8));
+    assert (20f64 == num::cast(20u16));
+    assert (20f64 == num::cast(20u32));
+    assert (20f64 == num::cast(20u64));
+    assert (20f64 == num::cast(20i));
+    assert (20f64 == num::cast(20i8));
+    assert (20f64 == num::cast(20i16));
+    assert (20f64 == num::cast(20i32));
+    assert (20f64 == num::cast(20i64));
+    assert (20f64 == num::cast(20f));
+    assert (20f64 == num::cast(20f32));
+    assert (20f64 == num::cast(20f64));
+}
+
 //
 // Local Variables:
 // mode: rust
diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs
index f5ae05ebffb..74bf50737f5 100644
--- a/src/libcore/num/float.rs
+++ b/src/libcore/num/float.rs
@@ -26,7 +26,7 @@ use cmp::{Eq, Ord};
 use cmp;
 use f64;
 use num;
-use num::Num::from_int;
+use num::NumCast;
 use option::{None, Option, Some};
 use str;
 use uint;
@@ -417,11 +417,6 @@ impl float: num::Num {
     pure fn modulo(&self, other: &float) -> float { return *self % *other; }
     #[inline(always)]
     pure fn neg(&self)                  -> float { return -*self;        }
-
-    #[inline(always)]
-    pure fn to_int(&self)         -> int   { return *self as int; }
-    #[inline(always)]
-    static pure fn from_int(&self, n: int) -> float { return n as float;  }
 }
 
 impl float: num::Zero {
@@ -434,6 +429,30 @@ impl float: num::One {
     static pure fn one() -> float { 1.0 }
 }
 
+pub impl float: NumCast {
+    /**
+     * Cast `n` to a `float`
+     */
+    #[inline(always)]
+    static pure fn from<N:NumCast>(n: N) -> float { n.to_float() }
+
+    #[inline(always)] pure fn to_u8(&self)    -> u8    { *self as u8    }
+    #[inline(always)] pure fn to_u16(&self)   -> u16   { *self as u16   }
+    #[inline(always)] pure fn to_u32(&self)   -> u32   { *self as u32   }
+    #[inline(always)] pure fn to_u64(&self)   -> u64   { *self as u64   }
+    #[inline(always)] pure fn to_uint(&self)  -> uint  { *self as uint  }
+
+    #[inline(always)] pure fn to_i8(&self)    -> i8    { *self as i8    }
+    #[inline(always)] pure fn to_i16(&self)   -> i16   { *self as i16   }
+    #[inline(always)] pure fn to_i32(&self)   -> i32   { *self as i32   }
+    #[inline(always)] pure fn to_i64(&self)   -> i64   { *self as i64   }
+    #[inline(always)] pure fn to_int(&self)   -> int   { *self as int   }
+
+    #[inline(always)] pure fn to_f32(&self)   -> f32   { *self as f32   }
+    #[inline(always)] pure fn to_f64(&self)   -> f64   { *self as f64   }
+    #[inline(always)] pure fn to_float(&self) -> float { *self          }
+}
+
 impl float: num::Round {
     #[inline(always)]
     pure fn round(&self, mode: num::RoundMode) -> float {
@@ -657,21 +676,60 @@ pub fn test_round() {
 }
 
 #[test]
-pub fn test_traits() {
-    fn test<U:num::Num cmp::Eq>(ten: &U) {
-        assert (ten.to_int() == 10);
-
-        let two: U = from_int(2);
-        assert (two.to_int() == 2);
-
-        assert (ten.add(&two) == from_int(12));
-        assert (ten.sub(&two) == from_int(8));
-        assert (ten.mul(&two) == from_int(20));
-        assert (ten.div(&two) == from_int(5));
-        assert (ten.modulo(&two) == from_int(0));
-    }
+pub fn test_num() {
+    let ten: float = num::cast(10);
+    let two: float = num::cast(2);
 
-    test(&10.0);
+    assert (ten.add(&two)    == num::cast(12));
+    assert (ten.sub(&two)    == num::cast(8));
+    assert (ten.mul(&two)    == num::cast(20));
+    assert (ten.div(&two)    == num::cast(5));
+    assert (ten.modulo(&two) == num::cast(0));
+}
+
+#[test]
+fn test_numcast() {
+    assert (20u   == 20f.to_uint());
+    assert (20u8  == 20f.to_u8());
+    assert (20u16 == 20f.to_u16());
+    assert (20u32 == 20f.to_u32());
+    assert (20u64 == 20f.to_u64());
+    assert (20i   == 20f.to_int());
+    assert (20i8  == 20f.to_i8());
+    assert (20i16 == 20f.to_i16());
+    assert (20i32 == 20f.to_i32());
+    assert (20i64 == 20f.to_i64());
+    assert (20f   == 20f.to_float());
+    assert (20f32 == 20f.to_f32());
+    assert (20f64 == 20f.to_f64());
+
+    assert (20f == NumCast::from(20u));
+    assert (20f == NumCast::from(20u8));
+    assert (20f == NumCast::from(20u16));
+    assert (20f == NumCast::from(20u32));
+    assert (20f == NumCast::from(20u64));
+    assert (20f == NumCast::from(20i));
+    assert (20f == NumCast::from(20i8));
+    assert (20f == NumCast::from(20i16));
+    assert (20f == NumCast::from(20i32));
+    assert (20f == NumCast::from(20i64));
+    assert (20f == NumCast::from(20f));
+    assert (20f == NumCast::from(20f32));
+    assert (20f == NumCast::from(20f64));
+
+    assert (20f == num::cast(20u));
+    assert (20f == num::cast(20u8));
+    assert (20f == num::cast(20u16));
+    assert (20f == num::cast(20u32));
+    assert (20f == num::cast(20u64));
+    assert (20f == num::cast(20i));
+    assert (20f == num::cast(20i8));
+    assert (20f == num::cast(20i16));
+    assert (20f == num::cast(20i32));
+    assert (20f == num::cast(20i64));
+    assert (20f == num::cast(20f));
+    assert (20f == num::cast(20f32));
+    assert (20f == num::cast(20f64));
 }
 
 
diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs
index 1856781b1d7..b616a08246b 100644
--- a/src/libcore/num/int-template.rs
+++ b/src/libcore/num/int-template.rs
@@ -17,7 +17,6 @@ use to_str::ToStr;
 use from_str::FromStr;
 use num::{ToStrRadix, FromStrRadix};
 use num;
-use num::Num::from_int;
 use prelude::*;
 use str;
 use uint;
@@ -184,11 +183,6 @@ impl T: num::Num {
     pure fn modulo(&self, other: &T) -> T { return *self % *other; }
     #[inline(always)]
     pure fn neg(&self)              -> T { return -*self;        }
-
-    #[inline(always)]
-    pure fn to_int(&self)         -> int { return *self as int; }
-    #[inline(always)]
-    static pure fn from_int(n: int) -> T   { return n as T;      }
 }
 
 impl T: num::Zero {
@@ -411,22 +405,15 @@ fn test_int_from_str_overflow() {
 }
 
 #[test]
-fn test_interfaces() {
-    fn test<U:num::Num cmp::Eq>(ten: U) {
-        assert (ten.to_int() == 10);
-
-        let two: U = from_int(2);
-        assert (two.to_int() == 2);
-
-        assert (ten.add(&two) == from_int(12));
-        assert (ten.sub(&two) == from_int(8));
-        assert (ten.mul(&two) == from_int(20));
-        assert (ten.div(&two) == from_int(5));
-        assert (ten.modulo(&two) == from_int(0));
-        assert (ten.neg() == from_int(-10));
-    }
-
-    test(10 as T);
+pub fn test_num() {
+    let ten: T = num::cast(10);
+    let two: T = num::cast(2);
+
+    assert (ten.add(&two)    == num::cast(12));
+    assert (ten.sub(&two)    == num::cast(8));
+    assert (ten.mul(&two)    == num::cast(20));
+    assert (ten.div(&two)    == num::cast(5));
+    assert (ten.modulo(&two) == num::cast(0));
 }
 
 #[test]
diff --git a/src/libcore/num/int-template/i16.rs b/src/libcore/num/int-template/i16.rs
index da60b567f66..572cce92ea1 100644
--- a/src/libcore/num/int-template/i16.rs
+++ b/src/libcore/num/int-template/i16.rs
@@ -10,7 +10,78 @@
 
 //! Operations and constants for `i16`
 
+use num::NumCast;
+
 mod inst {
     pub type T = i16;
     pub const bits: uint = ::u16::bits;
 }
+
+pub impl i16: NumCast {
+    /**
+     * Cast `n` to a `i16`
+     */
+    #[inline(always)]
+    static pure fn from<N:NumCast>(n: N) -> i16 { n.to_i16() }
+
+    #[inline(always)] pure fn to_u8(&self)    -> u8    { *self as u8    }
+    #[inline(always)] pure fn to_u16(&self)   -> u16   { *self as u16   }
+    #[inline(always)] pure fn to_u32(&self)   -> u32   { *self as u32   }
+    #[inline(always)] pure fn to_u64(&self)   -> u64   { *self as u64   }
+    #[inline(always)] pure fn to_uint(&self)  -> uint  { *self as uint  }
+
+    #[inline(always)] pure fn to_i8(&self)    -> i8    { *self as i8    }
+    #[inline(always)] pure fn to_i16(&self)   -> i16   { *self          }
+    #[inline(always)] pure fn to_i32(&self)   -> i32   { *self as i32   }
+    #[inline(always)] pure fn to_i64(&self)   -> i64   { *self as i64   }
+    #[inline(always)] pure fn to_int(&self)   -> int   { *self as int   }
+
+    #[inline(always)] pure fn to_f32(&self)   -> f32   { *self as f32   }
+    #[inline(always)] pure fn to_f64(&self)   -> f64   { *self as f64   }
+    #[inline(always)] pure fn to_float(&self) -> float { *self as float }
+}
+
+#[test]
+fn test_numcast() {
+    assert (20u   == 20i16.to_uint());
+    assert (20u8  == 20i16.to_u8());
+    assert (20u16 == 20i16.to_u16());
+    assert (20u32 == 20i16.to_u32());
+    assert (20u64 == 20i16.to_u64());
+    assert (20i   == 20i16.to_int());
+    assert (20i8  == 20i16.to_i8());
+    assert (20i16 == 20i16.to_i16());
+    assert (20i32 == 20i16.to_i32());
+    assert (20i64 == 20i16.to_i64());
+    assert (20f   == 20i16.to_float());
+    assert (20f32 == 20i16.to_f32());
+    assert (20f64 == 20i16.to_f64());
+
+    assert (20i16 == NumCast::from(20u));
+    assert (20i16 == NumCast::from(20u8));
+    assert (20i16 == NumCast::from(20u16));
+    assert (20i16 == NumCast::from(20u32));
+    assert (20i16 == NumCast::from(20u64));
+    assert (20i16 == NumCast::from(20i));
+    assert (20i16 == NumCast::from(20i8));
+    assert (20i16 == NumCast::from(20i16));
+    assert (20i16 == NumCast::from(20i32));
+    assert (20i16 == NumCast::from(20i64));
+    assert (20i16 == NumCast::from(20f));
+    assert (20i16 == NumCast::from(20f32));
+    assert (20i16 == NumCast::from(20f64));
+
+    assert (20i16 == num::cast(20u));
+    assert (20i16 == num::cast(20u8));
+    assert (20i16 == num::cast(20u16));
+    assert (20i16 == num::cast(20u32));
+    assert (20i16 == num::cast(20u64));
+    assert (20i16 == num::cast(20i));
+    assert (20i16 == num::cast(20i8));
+    assert (20i16 == num::cast(20i16));
+    assert (20i16 == num::cast(20i32));
+    assert (20i16 == num::cast(20i64));
+    assert (20i16 == num::cast(20f));
+    assert (20i16 == num::cast(20f32));
+    assert (20i16 == num::cast(20f64));
+}
\ No newline at end of file
diff --git a/src/libcore/num/int-template/i32.rs b/src/libcore/num/int-template/i32.rs
index 1bc45bb71af..de2e467d02a 100644
--- a/src/libcore/num/int-template/i32.rs
+++ b/src/libcore/num/int-template/i32.rs
@@ -10,7 +10,78 @@
 
 //! Operations and constants for `i32`
 
+use num::NumCast;
+
 mod inst {
     pub type T = i32;
     pub const bits: uint = ::u32::bits;
 }
+
+pub impl i32: NumCast {
+    /**
+     * Cast `n` to a `i32`
+     */
+    #[inline(always)]
+    static pure fn from<N:NumCast>(n: N) -> i32 { n.to_i32() }
+
+    #[inline(always)] pure fn to_u8(&self)    -> u8    { *self as u8    }
+    #[inline(always)] pure fn to_u16(&self)   -> u16   { *self as u16   }
+    #[inline(always)] pure fn to_u32(&self)   -> u32   { *self as u32   }
+    #[inline(always)] pure fn to_u64(&self)   -> u64   { *self as u64   }
+    #[inline(always)] pure fn to_uint(&self)  -> uint  { *self as uint  }
+
+    #[inline(always)] pure fn to_i8(&self)    -> i8    { *self as i8    }
+    #[inline(always)] pure fn to_i16(&self)   -> i16   { *self as i16   }
+    #[inline(always)] pure fn to_i32(&self)   -> i32   { *self          }
+    #[inline(always)] pure fn to_i64(&self)   -> i64   { *self as i64   }
+    #[inline(always)] pure fn to_int(&self)   -> int   { *self as int   }
+
+    #[inline(always)] pure fn to_f32(&self)   -> f32   { *self as f32   }
+    #[inline(always)] pure fn to_f64(&self)   -> f64   { *self as f64   }
+    #[inline(always)] pure fn to_float(&self) -> float { *self as float }
+}
+
+#[test]
+fn test_numcast() {
+    assert (20u   == 20i32.to_uint());
+    assert (20u8  == 20i32.to_u8());
+    assert (20u16 == 20i32.to_u16());
+    assert (20u32 == 20i32.to_u32());
+    assert (20u64 == 20i32.to_u64());
+    assert (20i   == 20i32.to_int());
+    assert (20i8  == 20i32.to_i8());
+    assert (20i16 == 20i32.to_i16());
+    assert (20i32 == 20i32.to_i32());
+    assert (20i64 == 20i32.to_i64());
+    assert (20f   == 20i32.to_float());
+    assert (20f32 == 20i32.to_f32());
+    assert (20f64 == 20i32.to_f64());
+
+    assert (20i32 == NumCast::from(20u));
+    assert (20i32 == NumCast::from(20u8));
+    assert (20i32 == NumCast::from(20u16));
+    assert (20i32 == NumCast::from(20u32));
+    assert (20i32 == NumCast::from(20u64));
+    assert (20i32 == NumCast::from(20i));
+    assert (20i32 == NumCast::from(20i8));
+    assert (20i32 == NumCast::from(20i16));
+    assert (20i32 == NumCast::from(20i32));
+    assert (20i32 == NumCast::from(20i64));
+    assert (20i32 == NumCast::from(20f));
+    assert (20i32 == NumCast::from(20f32));
+    assert (20i32 == NumCast::from(20f64));
+
+    assert (20i32 == num::cast(20u));
+    assert (20i32 == num::cast(20u8));
+    assert (20i32 == num::cast(20u16));
+    assert (20i32 == num::cast(20u32));
+    assert (20i32 == num::cast(20u64));
+    assert (20i32 == num::cast(20i));
+    assert (20i32 == num::cast(20i8));
+    assert (20i32 == num::cast(20i16));
+    assert (20i32 == num::cast(20i32));
+    assert (20i32 == num::cast(20i64));
+    assert (20i32 == num::cast(20f));
+    assert (20i32 == num::cast(20f32));
+    assert (20i32 == num::cast(20f64));
+}
\ No newline at end of file
diff --git a/src/libcore/num/int-template/i64.rs b/src/libcore/num/int-template/i64.rs
index 83d15aa857d..d7413920a64 100644
--- a/src/libcore/num/int-template/i64.rs
+++ b/src/libcore/num/int-template/i64.rs
@@ -10,7 +10,78 @@
 
 //! Operations and constants for `i64`
 
+use num::NumCast;
+
 mod inst {
     pub type T = i64;
     pub const bits: uint = ::u64::bits;
 }
+
+pub impl i64: NumCast {
+    /**
+     * Cast `n` to a `i64`
+     */
+    #[inline(always)]
+    static pure fn from<N:NumCast>(n: N) -> i64 { n.to_i64() }
+
+    #[inline(always)] pure fn to_u8(&self)    -> u8    { *self as u8    }
+    #[inline(always)] pure fn to_u16(&self)   -> u16   { *self as u16   }
+    #[inline(always)] pure fn to_u32(&self)   -> u32   { *self as u32   }
+    #[inline(always)] pure fn to_u64(&self)   -> u64   { *self as u64   }
+    #[inline(always)] pure fn to_uint(&self)  -> uint  { *self as uint  }
+
+    #[inline(always)] pure fn to_i8(&self)    -> i8    { *self as i8    }
+    #[inline(always)] pure fn to_i16(&self)   -> i16   { *self as i16   }
+    #[inline(always)] pure fn to_i32(&self)   -> i32   { *self as i32   }
+    #[inline(always)] pure fn to_i64(&self)   -> i64   { *self          }
+    #[inline(always)] pure fn to_int(&self)   -> int   { *self as int   }
+
+    #[inline(always)] pure fn to_f32(&self)   -> f32   { *self as f32   }
+    #[inline(always)] pure fn to_f64(&self)   -> f64   { *self as f64   }
+    #[inline(always)] pure fn to_float(&self) -> float { *self as float }
+}
+
+#[test]
+fn test_numcast() {
+    assert (20u   == 20i64.to_uint());
+    assert (20u8  == 20i64.to_u8());
+    assert (20u16 == 20i64.to_u16());
+    assert (20u32 == 20i64.to_u32());
+    assert (20u64 == 20i64.to_u64());
+    assert (20i   == 20i64.to_int());
+    assert (20i8  == 20i64.to_i8());
+    assert (20i16 == 20i64.to_i16());
+    assert (20i32 == 20i64.to_i32());
+    assert (20i64 == 20i64.to_i64());
+    assert (20f   == 20i64.to_float());
+    assert (20f32 == 20i64.to_f32());
+    assert (20f64 == 20i64.to_f64());
+
+    assert (20i64 == NumCast::from(20u));
+    assert (20i64 == NumCast::from(20u8));
+    assert (20i64 == NumCast::from(20u16));
+    assert (20i64 == NumCast::from(20u32));
+    assert (20i64 == NumCast::from(20u64));
+    assert (20i64 == NumCast::from(20i));
+    assert (20i64 == NumCast::from(20i8));
+    assert (20i64 == NumCast::from(20i16));
+    assert (20i64 == NumCast::from(20i32));
+    assert (20i64 == NumCast::from(20i64));
+    assert (20i64 == NumCast::from(20f));
+    assert (20i64 == NumCast::from(20f32));
+    assert (20i64 == NumCast::from(20f64));
+
+    assert (20i64 == num::cast(20u));
+    assert (20i64 == num::cast(20u8));
+    assert (20i64 == num::cast(20u16));
+    assert (20i64 == num::cast(20u32));
+    assert (20i64 == num::cast(20u64));
+    assert (20i64 == num::cast(20i));
+    assert (20i64 == num::cast(20i8));
+    assert (20i64 == num::cast(20i16));
+    assert (20i64 == num::cast(20i32));
+    assert (20i64 == num::cast(20i64));
+    assert (20i64 == num::cast(20f));
+    assert (20i64 == num::cast(20f32));
+    assert (20i64 == num::cast(20f64));
+}
diff --git a/src/libcore/num/int-template/i8.rs b/src/libcore/num/int-template/i8.rs
index 740442ed725..f2577020128 100644
--- a/src/libcore/num/int-template/i8.rs
+++ b/src/libcore/num/int-template/i8.rs
@@ -10,7 +10,78 @@
 
 //! Operations and constants for `i8`
 
+use num::NumCast;
+
 mod inst {
     pub type T = i8;
     pub const bits: uint = ::u8::bits;
 }
+
+pub impl i8: NumCast {
+    /**
+     * Cast `n` to a `i8`
+     */
+    #[inline(always)]
+    static pure fn from<N:NumCast>(n: N) -> i8 { n.to_i8() }
+
+    #[inline(always)] pure fn to_u8(&self)    -> u8    { *self as u8    }
+    #[inline(always)] pure fn to_u16(&self)   -> u16   { *self as u16   }
+    #[inline(always)] pure fn to_u32(&self)   -> u32   { *self as u32   }
+    #[inline(always)] pure fn to_u64(&self)   -> u64   { *self as u64   }
+    #[inline(always)] pure fn to_uint(&self)  -> uint  { *self as uint  }
+
+    #[inline(always)] pure fn to_i8(&self)    -> i8    { *self          }
+    #[inline(always)] pure fn to_i16(&self)   -> i16   { *self as i16   }
+    #[inline(always)] pure fn to_i32(&self)   -> i32   { *self as i32   }
+    #[inline(always)] pure fn to_i64(&self)   -> i64   { *self as i64   }
+    #[inline(always)] pure fn to_int(&self)   -> int   { *self as int   }
+
+    #[inline(always)] pure fn to_f32(&self)   -> f32   { *self as f32   }
+    #[inline(always)] pure fn to_f64(&self)   -> f64   { *self as f64   }
+    #[inline(always)] pure fn to_float(&self) -> float { *self as float }
+}
+
+#[test]
+fn test_numcast() {
+    assert (20u   == 20i8.to_uint());
+    assert (20u8  == 20i8.to_u8());
+    assert (20u16 == 20i8.to_u16());
+    assert (20u32 == 20i8.to_u32());
+    assert (20u64 == 20i8.to_u64());
+    assert (20i   == 20i8.to_int());
+    assert (20i8  == 20i8.to_i8());
+    assert (20i16 == 20i8.to_i16());
+    assert (20i32 == 20i8.to_i32());
+    assert (20i64 == 20i8.to_i64());
+    assert (20f   == 20i8.to_float());
+    assert (20f32 == 20i8.to_f32());
+    assert (20f64 == 20i8.to_f64());
+
+    assert (20i8 == NumCast::from(20u));
+    assert (20i8 == NumCast::from(20u8));
+    assert (20i8 == NumCast::from(20u16));
+    assert (20i8 == NumCast::from(20u32));
+    assert (20i8 == NumCast::from(20u64));
+    assert (20i8 == NumCast::from(20i));
+    assert (20i8 == NumCast::from(20i8));
+    assert (20i8 == NumCast::from(20i16));
+    assert (20i8 == NumCast::from(20i32));
+    assert (20i8 == NumCast::from(20i64));
+    assert (20i8 == NumCast::from(20f));
+    assert (20i8 == NumCast::from(20f32));
+    assert (20i8 == NumCast::from(20f64));
+
+    assert (20i8 == num::cast(20u));
+    assert (20i8 == num::cast(20u8));
+    assert (20i8 == num::cast(20u16));
+    assert (20i8 == num::cast(20u32));
+    assert (20i8 == num::cast(20u64));
+    assert (20i8 == num::cast(20i));
+    assert (20i8 == num::cast(20i8));
+    assert (20i8 == num::cast(20i16));
+    assert (20i8 == num::cast(20i32));
+    assert (20i8 == num::cast(20i64));
+    assert (20i8 == num::cast(20f));
+    assert (20i8 == num::cast(20f32));
+    assert (20i8 == num::cast(20f64));
+}
diff --git a/src/libcore/num/int-template/int.rs b/src/libcore/num/int-template/int.rs
index 224da0dc062..4ba1570e135 100644
--- a/src/libcore/num/int-template/int.rs
+++ b/src/libcore/num/int-template/int.rs
@@ -10,6 +10,8 @@
 
 //! Operations and constants for `int`
 
+use num::NumCast;
+
 pub use self::inst::pow;
 
 mod inst {
@@ -55,3 +57,72 @@ mod inst {
         assert (::int::min_value + ::int::max_value + 1 == 0);
     }
 }
+
+pub impl int: NumCast {
+    /**
+     * Cast `n` to a `int`
+     */
+    #[inline(always)]
+    static pure fn from<N:NumCast>(n: N) -> int { n.to_int() }
+
+    #[inline(always)] pure fn to_u8(&self)    -> u8    { *self as u8    }
+    #[inline(always)] pure fn to_u16(&self)   -> u16   { *self as u16   }
+    #[inline(always)] pure fn to_u32(&self)   -> u32   { *self as u32   }
+    #[inline(always)] pure fn to_u64(&self)   -> u64   { *self as u64   }
+    #[inline(always)] pure fn to_uint(&self)  -> uint  { *self as uint  }
+
+    #[inline(always)] pure fn to_i8(&self)    -> i8    { *self as i8    }
+    #[inline(always)] pure fn to_i16(&self)   -> i16   { *self as i16   }
+    #[inline(always)] pure fn to_i32(&self)   -> i32   { *self as i32   }
+    #[inline(always)] pure fn to_i64(&self)   -> i64   { *self as i64   }
+    #[inline(always)] pure fn to_int(&self)   -> int   { *self          }
+
+    #[inline(always)] pure fn to_f32(&self)   -> f32   { *self as f32   }
+    #[inline(always)] pure fn to_f64(&self)   -> f64   { *self as f64   }
+    #[inline(always)] pure fn to_float(&self) -> float { *self as float }
+}
+
+#[test]
+fn test_numcast() {
+    assert (20u   == 20i.to_uint());
+    assert (20u8  == 20i.to_u8());
+    assert (20u16 == 20i.to_u16());
+    assert (20u32 == 20i.to_u32());
+    assert (20u64 == 20i.to_u64());
+    assert (20i   == 20i.to_int());
+    assert (20i8  == 20i.to_i8());
+    assert (20i16 == 20i.to_i16());
+    assert (20i32 == 20i.to_i32());
+    assert (20i64 == 20i.to_i64());
+    assert (20f   == 20i.to_float());
+    assert (20f32 == 20i.to_f32());
+    assert (20f64 == 20i.to_f64());
+
+    assert (20i == NumCast::from(20u));
+    assert (20i == NumCast::from(20u8));
+    assert (20i == NumCast::from(20u16));
+    assert (20i == NumCast::from(20u32));
+    assert (20i == NumCast::from(20u64));
+    assert (20i == NumCast::from(20i));
+    assert (20i == NumCast::from(20i8));
+    assert (20i == NumCast::from(20i16));
+    assert (20i == NumCast::from(20i32));
+    assert (20i == NumCast::from(20i64));
+    assert (20i == NumCast::from(20f));
+    assert (20i == NumCast::from(20f32));
+    assert (20i == NumCast::from(20f64));
+
+    assert (20i == num::cast(20u));
+    assert (20i == num::cast(20u8));
+    assert (20i == num::cast(20u16));
+    assert (20i == num::cast(20u32));
+    assert (20i == num::cast(20u64));
+    assert (20i == num::cast(20i));
+    assert (20i == num::cast(20i8));
+    assert (20i == num::cast(20i16));
+    assert (20i == num::cast(20i32));
+    assert (20i == num::cast(20i64));
+    assert (20i == num::cast(20f));
+    assert (20i == num::cast(20f32));
+    assert (20i == num::cast(20f64));
+}
diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs
index 05b03a53dcd..eb722b441c7 100644
--- a/src/libcore/num/num.rs
+++ b/src/libcore/num/num.rs
@@ -24,9 +24,6 @@ pub trait Num {
     pure fn div(&self, other: &Self) -> Self;
     pure fn modulo(&self, other: &Self) -> Self;
     pure fn neg(&self) -> Self;
-
-    pure fn to_int(&self) -> int;
-    static pure fn from_int(n: int) -> Self;
 }
 
 pub trait IntConvertible {
@@ -50,6 +47,44 @@ pub trait Round {
     pure fn fract(&self) -> Self;
 }
 
+/**
+ * Cast a number the the enclosing type
+ *
+ * # Example
+ *
+ * ~~~
+ * let twenty: f32 = num::cast(0x14);
+ * assert twenty == 20f32;
+ * ~~~
+ */
+#[inline(always)]
+pub pure fn cast<T:NumCast, U:NumCast>(n: T) -> U {
+    NumCast::from(n)
+}
+
+/**
+ * An interface for generic numeric type casts
+ */
+pub trait NumCast {
+    static pure fn from<T:NumCast>(n: T) -> Self;
+
+    pure fn to_u8(&self) -> u8;
+    pure fn to_u16(&self) -> u16;
+    pure fn to_u32(&self) -> u32;
+    pure fn to_u64(&self) -> u64;
+    pure fn to_uint(&self) -> uint;
+
+    pure fn to_i8(&self) -> i8;
+    pure fn to_i16(&self) -> i16;
+    pure fn to_i32(&self) -> i32;
+    pure fn to_i64(&self) -> i64;
+    pure fn to_int(&self) -> int;
+
+    pure fn to_f32(&self) -> f32;
+    pure fn to_f64(&self) -> f64;
+    pure fn to_float(&self) -> float;
+}
+
 pub enum RoundMode {
     RoundDown,
     RoundUp,
@@ -135,8 +170,8 @@ pub pure fn is_neg_zero<T: Num One Zero Eq>(num: &T) -> bool {
  * - If code written to use this function doesn't care about it, it's
  *   probably assuming that `x^0` always equals `1`.
  */
-pub pure fn pow_with_uint<T: Num One Zero Copy>(radix: uint,
-                                                pow: uint) -> T {
+pub pure fn pow_with_uint<T: Num NumCast One Zero Copy>(radix: uint,
+                                                        pow: uint) -> T {
     let _0: T = Zero::zero();
     let _1: T = One::one();
 
@@ -144,7 +179,7 @@ pub pure fn pow_with_uint<T: Num One Zero Copy>(radix: uint,
     if radix == 0u { return _0; }
     let mut my_pow     = pow;
     let mut total      = _1;
-    let mut multiplier = Num::from_int(radix as int);
+    let mut multiplier = cast(radix as int);
     while (my_pow > 0u) {
         if my_pow % 2u == 1u {
             total *= multiplier;
@@ -217,7 +252,7 @@ pub enum SignFormat {
  * those special values, and `special` is `false`, because then the
  * algorithm just does normal calculations on them.
  */
-pub pure fn to_str_bytes_common<T: Num Zero One Eq Ord Round Copy>(
+pub pure fn to_str_bytes_common<T: Num NumCast Zero One Eq Ord Round Copy>(
         num: &T, radix: uint, special: bool, negative_zero: bool,
         sign: SignFormat, digits: SignificantDigits) -> (~[u8], bool) {
     if radix as int <  2 {
@@ -250,7 +285,7 @@ pub pure fn to_str_bytes_common<T: Num Zero One Eq Ord Round Copy>(
     let neg = *num < _0 || (negative_zero && *num == _0
                             && special && is_neg_zero(num));
     let mut buf: ~[u8] = ~[];
-    let radix_gen      = Num::from_int::<T>(radix as int);
+    let radix_gen: T   = cast(radix as int);
 
     let mut deccum;
 
@@ -439,7 +474,7 @@ pub pure fn to_str_bytes_common<T: Num Zero One Eq Ord Round Copy>(
  * `to_str_bytes_common()`, for details see there.
  */
 #[inline(always)]
-pub pure fn to_str_common<T: Num Zero One Eq Ord Round Copy>(
+pub pure fn to_str_common<T: Num NumCast Zero One Eq Ord Round Copy>(
         num: &T, radix: uint, special: bool, negative_zero: bool,
         sign: SignFormat, digits: SignificantDigits) -> (~str, bool) {
     let (bytes, special) = to_str_bytes_common(num, radix, special,
@@ -494,7 +529,7 @@ priv const DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u;
  * - Could accept option to allow ignoring underscores, allowing for numbers
  *   formated like `FF_AE_FF_FF`.
  */
-pub pure fn from_str_bytes_common<T: Num Zero One Ord Copy>(
+pub pure fn from_str_bytes_common<T: Num NumCast Zero One Ord Copy>(
         buf: &[u8], radix: uint, negative: bool, fractional: bool,
         special: bool, exponent: ExponentFormat, empty_zero: bool
         ) -> Option<T> {
@@ -519,7 +554,7 @@ pub pure fn from_str_bytes_common<T: Num Zero One Ord Copy>(
 
     let _0: T = Zero::zero();
     let _1: T = One::one();
-    let radix_gen: T = Num::from_int(radix as int);
+    let radix_gen: T = cast(radix as int);
 
     let len = buf.len();
 
@@ -570,9 +605,9 @@ pub pure fn from_str_bytes_common<T: Num Zero One Ord Copy>(
 
                 // add/subtract current digit depending on sign
                 if accum_positive {
-                    accum += Num::from_int(digit as int);
+                    accum += cast(digit as int);
                 } else {
-                    accum -= Num::from_int(digit as int);
+                    accum -= cast(digit as int);
                 }
 
                 // Detect overflow by comparing to last value
@@ -609,11 +644,13 @@ pub pure fn from_str_bytes_common<T: Num Zero One Ord Copy>(
                     // Decrease power one order of magnitude
                     power /= radix_gen;
 
+                    let digit_t: T = cast(digit);
+
                     // add/subtract current digit depending on sign
                     if accum_positive {
-                        accum += Num::from_int::<T>(digit as int) * power;
+                        accum += digit_t * power;
                     } else {
-                        accum -= Num::from_int::<T>(digit as int) * power;
+                        accum -= digit_t * power;
                     }
 
                     // Detect overflow by comparing to last value
@@ -679,7 +716,7 @@ pub pure fn from_str_bytes_common<T: Num Zero One Ord Copy>(
  * `from_str_bytes_common()`, for details see there.
  */
 #[inline(always)]
-pub pure fn from_str_common<T: Num Zero One Ord Copy>(
+pub pure fn from_str_common<T: Num NumCast Zero One Ord Copy>(
         buf: &str, radix: uint, negative: bool, fractional: bool,
         special: bool, exponent: ExponentFormat, empty_zero: bool
         ) -> Option<T> {
diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs
index f8bbb35204a..0a219660fb9 100644
--- a/src/libcore/num/uint-template.rs
+++ b/src/libcore/num/uint-template.rs
@@ -146,11 +146,6 @@ impl T: num::Num {
     pure fn modulo(&self, other: &T) -> T { return *self % *other; }
     #[inline(always)]
     pure fn neg(&self)              -> T { return -*self;        }
-
-    #[inline(always)]
-    pure fn to_int(&self)         -> int { return *self as int; }
-    #[inline(always)]
-    static pure fn from_int(n: int) -> T   { return n as T;      }
 }
 
 impl T: num::Zero {
@@ -410,6 +405,18 @@ pub fn test_ranges() {
 }
 
 #[test]
+pub fn test_num() {
+    let ten: T = num::cast(10);
+    let two: T = num::cast(2);
+
+    assert (ten.add(&two)    == num::cast(12));
+    assert (ten.sub(&two)    == num::cast(8));
+    assert (ten.mul(&two)    == num::cast(20));
+    assert (ten.div(&two)    == num::cast(5));
+    assert (ten.modulo(&two) == num::cast(0));
+}
+
+#[test]
 #[should_fail]
 #[ignore(cfg(windows))]
 fn test_range_step_zero_step_up() {
diff --git a/src/libcore/num/uint-template/u16.rs b/src/libcore/num/uint-template/u16.rs
index b9a007af2f6..e2e8e2bc9fc 100644
--- a/src/libcore/num/uint-template/u16.rs
+++ b/src/libcore/num/uint-template/u16.rs
@@ -10,9 +10,80 @@
 
 //! Operations and constants for `u16`
 
+use num::NumCast;
+
 mod inst {
     pub type T = u16;
     #[allow(non_camel_case_types)]
     pub type T_SIGNED = i16;
     pub const bits: uint = 16;
 }
+
+pub impl u16: NumCast {
+    /**
+     * Cast `n` to a `u16`
+     */
+    #[inline(always)]
+    static pure fn from<N:NumCast>(n: N) -> u16 { n.to_u16() }
+
+    #[inline(always)] pure fn to_u8(&self)    -> u8    { *self as u8    }
+    #[inline(always)] pure fn to_u16(&self)   -> u16   { *self          }
+    #[inline(always)] pure fn to_u32(&self)   -> u32   { *self as u32   }
+    #[inline(always)] pure fn to_u64(&self)   -> u64   { *self as u64   }
+    #[inline(always)] pure fn to_uint(&self)  -> uint  { *self as uint  }
+
+    #[inline(always)] pure fn to_i8(&self)    -> i8    { *self as i8    }
+    #[inline(always)] pure fn to_i16(&self)   -> i16   { *self as i16   }
+    #[inline(always)] pure fn to_i32(&self)   -> i32   { *self as i32   }
+    #[inline(always)] pure fn to_i64(&self)   -> i64   { *self as i64   }
+    #[inline(always)] pure fn to_int(&self)   -> int   { *self as int   }
+
+    #[inline(always)] pure fn to_f32(&self)   -> f32   { *self as f32   }
+    #[inline(always)] pure fn to_f64(&self)   -> f64   { *self as f64   }
+    #[inline(always)] pure fn to_float(&self) -> float { *self as float }
+}
+
+#[test]
+fn test_numcast() {
+    assert (20u   == 20u16.to_uint());
+    assert (20u8  == 20u16.to_u8());
+    assert (20u16 == 20u16.to_u16());
+    assert (20u32 == 20u16.to_u32());
+    assert (20u64 == 20u16.to_u64());
+    assert (20i   == 20u16.to_int());
+    assert (20i8  == 20u16.to_i8());
+    assert (20i16 == 20u16.to_i16());
+    assert (20i32 == 20u16.to_i32());
+    assert (20i64 == 20u16.to_i64());
+    assert (20f   == 20u16.to_float());
+    assert (20f32 == 20u16.to_f32());
+    assert (20f64 == 20u16.to_f64());
+
+    assert (20u16 == NumCast::from(20u));
+    assert (20u16 == NumCast::from(20u8));
+    assert (20u16 == NumCast::from(20u16));
+    assert (20u16 == NumCast::from(20u32));
+    assert (20u16 == NumCast::from(20u64));
+    assert (20u16 == NumCast::from(20i));
+    assert (20u16 == NumCast::from(20i8));
+    assert (20u16 == NumCast::from(20i16));
+    assert (20u16 == NumCast::from(20i32));
+    assert (20u16 == NumCast::from(20i64));
+    assert (20u16 == NumCast::from(20f));
+    assert (20u16 == NumCast::from(20f32));
+    assert (20u16 == NumCast::from(20f64));
+
+    assert (20u16 == num::cast(20u));
+    assert (20u16 == num::cast(20u8));
+    assert (20u16 == num::cast(20u16));
+    assert (20u16 == num::cast(20u32));
+    assert (20u16 == num::cast(20u64));
+    assert (20u16 == num::cast(20i));
+    assert (20u16 == num::cast(20i8));
+    assert (20u16 == num::cast(20i16));
+    assert (20u16 == num::cast(20i32));
+    assert (20u16 == num::cast(20i64));
+    assert (20u16 == num::cast(20f));
+    assert (20u16 == num::cast(20f32));
+    assert (20u16 == num::cast(20f64));
+}
\ No newline at end of file
diff --git a/src/libcore/num/uint-template/u32.rs b/src/libcore/num/uint-template/u32.rs
index 141509c49e5..ac2727bff09 100644
--- a/src/libcore/num/uint-template/u32.rs
+++ b/src/libcore/num/uint-template/u32.rs
@@ -10,9 +10,80 @@
 
 //! Operations and constants for `u32`
 
+use num::NumCast;
+
 mod inst {
     pub type T = u32;
     #[allow(non_camel_case_types)]
     pub type T_SIGNED = i32;
     pub const bits: uint = 32;
+}
+
+pub impl u32: NumCast {
+    /**
+     * Cast `n` to a `u32`
+     */
+    #[inline(always)]
+    static pure fn from<N:NumCast>(n: N) -> u32 { n.to_u32() }
+
+    #[inline(always)] pure fn to_u8(&self)    -> u8    { *self as u8    }
+    #[inline(always)] pure fn to_u16(&self)   -> u16   { *self as u16   }
+    #[inline(always)] pure fn to_u32(&self)   -> u32   { *self          }
+    #[inline(always)] pure fn to_u64(&self)   -> u64   { *self as u64   }
+    #[inline(always)] pure fn to_uint(&self)  -> uint  { *self as uint  }
+
+    #[inline(always)] pure fn to_i8(&self)    -> i8    { *self as i8    }
+    #[inline(always)] pure fn to_i16(&self)   -> i16   { *self as i16   }
+    #[inline(always)] pure fn to_i32(&self)   -> i32   { *self as i32   }
+    #[inline(always)] pure fn to_i64(&self)   -> i64   { *self as i64   }
+    #[inline(always)] pure fn to_int(&self)   -> int   { *self as int   }
+
+    #[inline(always)] pure fn to_f32(&self)   -> f32   { *self as f32   }
+    #[inline(always)] pure fn to_f64(&self)   -> f64   { *self as f64   }
+    #[inline(always)] pure fn to_float(&self) -> float { *self as float }
+}
+
+#[test]
+fn test_numcast() {
+    assert (20u   == 20u64.to_uint());
+    assert (20u8  == 20u64.to_u8());
+    assert (20u16 == 20u64.to_u16());
+    assert (20u32 == 20u64.to_u32());
+    assert (20u64 == 20u64.to_u64());
+    assert (20i   == 20u64.to_int());
+    assert (20i8  == 20u64.to_i8());
+    assert (20i16 == 20u64.to_i16());
+    assert (20i32 == 20u64.to_i32());
+    assert (20i64 == 20u64.to_i64());
+    assert (20f   == 20u64.to_float());
+    assert (20f32 == 20u64.to_f32());
+    assert (20f64 == 20u64.to_f64());
+
+    assert (20u64 == NumCast::from(20u));
+    assert (20u64 == NumCast::from(20u8));
+    assert (20u64 == NumCast::from(20u16));
+    assert (20u64 == NumCast::from(20u32));
+    assert (20u64 == NumCast::from(20u64));
+    assert (20u64 == NumCast::from(20i));
+    assert (20u64 == NumCast::from(20i8));
+    assert (20u64 == NumCast::from(20i16));
+    assert (20u64 == NumCast::from(20i32));
+    assert (20u64 == NumCast::from(20i64));
+    assert (20u64 == NumCast::from(20f));
+    assert (20u64 == NumCast::from(20f32));
+    assert (20u64 == NumCast::from(20f64));
+
+    assert (20u64 == num::cast(20u));
+    assert (20u64 == num::cast(20u8));
+    assert (20u64 == num::cast(20u16));
+    assert (20u64 == num::cast(20u32));
+    assert (20u64 == num::cast(20u64));
+    assert (20u64 == num::cast(20i));
+    assert (20u64 == num::cast(20i8));
+    assert (20u64 == num::cast(20i16));
+    assert (20u64 == num::cast(20i32));
+    assert (20u64 == num::cast(20i64));
+    assert (20u64 == num::cast(20f));
+    assert (20u64 == num::cast(20f32));
+    assert (20u64 == num::cast(20f64));
 }
\ No newline at end of file
diff --git a/src/libcore/num/uint-template/u64.rs b/src/libcore/num/uint-template/u64.rs
index 35210eae9a7..345f81c147c 100644
--- a/src/libcore/num/uint-template/u64.rs
+++ b/src/libcore/num/uint-template/u64.rs
@@ -10,9 +10,80 @@
 
 //! Operations and constants for `u64`
 
+use num::NumCast;
+
 mod inst {
     pub type T = u64;
     #[allow(non_camel_case_types)]
     pub type T_SIGNED = i64;
     pub const bits: uint = 64;
+}
+
+pub impl u64: num::NumCast {
+    /**
+     * Cast `n` to a `u64`
+     */
+    #[inline(always)]
+    static pure fn from<N:NumCast>(n: N) -> u64 { n.to_u64() }
+
+    #[inline(always)] pure fn to_u8(&self)    -> u8    { *self as u8    }
+    #[inline(always)] pure fn to_u16(&self)   -> u16   { *self as u16   }
+    #[inline(always)] pure fn to_u32(&self)   -> u32   { *self as u32   }
+    #[inline(always)] pure fn to_u64(&self)   -> u64   { *self          }
+    #[inline(always)] pure fn to_uint(&self)  -> uint  { *self as uint  }
+
+    #[inline(always)] pure fn to_i8(&self)    -> i8    { *self as i8    }
+    #[inline(always)] pure fn to_i16(&self)   -> i16   { *self as i16   }
+    #[inline(always)] pure fn to_i32(&self)   -> i32   { *self as i32   }
+    #[inline(always)] pure fn to_i64(&self)   -> i64   { *self as i64   }
+    #[inline(always)] pure fn to_int(&self)   -> int   { *self as int   }
+
+    #[inline(always)] pure fn to_f32(&self)   -> f32   { *self as f32   }
+    #[inline(always)] pure fn to_f64(&self)   -> f64   { *self as f64   }
+    #[inline(always)] pure fn to_float(&self) -> float { *self as float }
+}
+
+#[test]
+fn test_numcast() {
+    assert (20u   == 20u64.to_uint());
+    assert (20u8  == 20u64.to_u8());
+    assert (20u16 == 20u64.to_u16());
+    assert (20u32 == 20u64.to_u32());
+    assert (20u64 == 20u64.to_u64());
+    assert (20i   == 20u64.to_int());
+    assert (20i8  == 20u64.to_i8());
+    assert (20i16 == 20u64.to_i16());
+    assert (20i32 == 20u64.to_i32());
+    assert (20i64 == 20u64.to_i64());
+    assert (20f   == 20u64.to_float());
+    assert (20f32 == 20u64.to_f32());
+    assert (20f64 == 20u64.to_f64());
+
+    assert (20u64 == NumCast::from(20u));
+    assert (20u64 == NumCast::from(20u8));
+    assert (20u64 == NumCast::from(20u16));
+    assert (20u64 == NumCast::from(20u32));
+    assert (20u64 == NumCast::from(20u64));
+    assert (20u64 == NumCast::from(20i));
+    assert (20u64 == NumCast::from(20i8));
+    assert (20u64 == NumCast::from(20i16));
+    assert (20u64 == NumCast::from(20i32));
+    assert (20u64 == NumCast::from(20i64));
+    assert (20u64 == NumCast::from(20f));
+    assert (20u64 == NumCast::from(20f32));
+    assert (20u64 == NumCast::from(20f64));
+
+    assert (20u64 == num::cast(20u));
+    assert (20u64 == num::cast(20u8));
+    assert (20u64 == num::cast(20u16));
+    assert (20u64 == num::cast(20u32));
+    assert (20u64 == num::cast(20u64));
+    assert (20u64 == num::cast(20i));
+    assert (20u64 == num::cast(20i8));
+    assert (20u64 == num::cast(20i16));
+    assert (20u64 == num::cast(20i32));
+    assert (20u64 == num::cast(20i64));
+    assert (20u64 == num::cast(20f));
+    assert (20u64 == num::cast(20f32));
+    assert (20u64 == num::cast(20f64));
 }
\ No newline at end of file
diff --git a/src/libcore/num/uint-template/u8.rs b/src/libcore/num/uint-template/u8.rs
index e273a203213..71be36d9019 100644
--- a/src/libcore/num/uint-template/u8.rs
+++ b/src/libcore/num/uint-template/u8.rs
@@ -12,6 +12,8 @@
 
 pub use self::inst::is_ascii;
 
+use num::NumCast;
+
 mod inst {
     pub type T = u8;
     #[allow(non_camel_case_types)]
@@ -23,3 +25,72 @@ mod inst {
 
     pub pure fn is_ascii(x: T) -> bool { return 0 as T == x & 128 as T; }
 }
+
+pub impl u8: NumCast {
+    /**
+     * Cast `n` to a `u8`
+     */
+    #[inline(always)]
+    static pure fn from<N:NumCast>(n: N) -> u8 { n.to_u8() }
+
+    #[inline(always)] pure fn to_u8(&self)    -> u8    { *self          }
+    #[inline(always)] pure fn to_u16(&self)   -> u16   { *self as u16   }
+    #[inline(always)] pure fn to_u32(&self)   -> u32   { *self as u32   }
+    #[inline(always)] pure fn to_u64(&self)   -> u64   { *self as u64   }
+    #[inline(always)] pure fn to_uint(&self)  -> uint  { *self as uint  }
+
+    #[inline(always)] pure fn to_i8(&self)    -> i8    { *self as i8    }
+    #[inline(always)] pure fn to_i16(&self)   -> i16   { *self as i16   }
+    #[inline(always)] pure fn to_i32(&self)   -> i32   { *self as i32   }
+    #[inline(always)] pure fn to_i64(&self)   -> i64   { *self as i64   }
+    #[inline(always)] pure fn to_int(&self)   -> int   { *self as int   }
+
+    #[inline(always)] pure fn to_f32(&self)   -> f32   { *self as f32   }
+    #[inline(always)] pure fn to_f64(&self)   -> f64   { *self as f64   }
+    #[inline(always)] pure fn to_float(&self) -> float { *self as float }
+}
+
+#[test]
+fn test_numcast() {
+    assert (20u     == 20u8.to_uint());
+    assert (20u8    == 20u8.to_u8());
+    assert (20u16   == 20u8.to_u16());
+    assert (20u32   == 20u8.to_u32());
+    assert (20u64   == 20u8.to_u64());
+    assert (20i     == 20u8.to_int());
+    assert (20i8    == 20u8.to_i8());
+    assert (20i16   == 20u8.to_i16());
+    assert (20i32   == 20u8.to_i32());
+    assert (20i64   == 20u8.to_i64());
+    assert (20f     == 20u8.to_float());
+    assert (20f32   == 20u8.to_f32());
+    assert (20f64   == 20u8.to_f64());
+
+    assert (20u8 == NumCast::from(20u));
+    assert (20u8 == NumCast::from(20u8));
+    assert (20u8 == NumCast::from(20u16));
+    assert (20u8 == NumCast::from(20u32));
+    assert (20u8 == NumCast::from(20u64));
+    assert (20u8 == NumCast::from(20i));
+    assert (20u8 == NumCast::from(20i8));
+    assert (20u8 == NumCast::from(20i16));
+    assert (20u8 == NumCast::from(20i32));
+    assert (20u8 == NumCast::from(20i64));
+    assert (20u8 == NumCast::from(20f));
+    assert (20u8 == NumCast::from(20f32));
+    assert (20u8 == NumCast::from(20f64));
+
+    assert (20u8 == num::cast(20u));
+    assert (20u8 == num::cast(20u8));
+    assert (20u8 == num::cast(20u16));
+    assert (20u8 == num::cast(20u32));
+    assert (20u8 == num::cast(20u64));
+    assert (20u8 == num::cast(20i));
+    assert (20u8 == num::cast(20i8));
+    assert (20u8 == num::cast(20i16));
+    assert (20u8 == num::cast(20i32));
+    assert (20u8 == num::cast(20i64));
+    assert (20u8 == num::cast(20f));
+    assert (20u8 == num::cast(20f32));
+    assert (20u8 == num::cast(20f64));
+}
\ No newline at end of file
diff --git a/src/libcore/num/uint-template/uint.rs b/src/libcore/num/uint-template/uint.rs
index 93f59cd2d9f..66689f18dfe 100644
--- a/src/libcore/num/uint-template/uint.rs
+++ b/src/libcore/num/uint-template/uint.rs
@@ -10,6 +10,8 @@
 
 //! Operations and constants for `uint`
 
+use num::NumCast;
+
 pub use self::inst::{
     div_ceil, div_round, div_floor, iterate,
     next_power_of_two
@@ -206,3 +208,72 @@ pub mod inst {
         assert (accum == 10);
     }
 }
+
+pub impl uint: NumCast {
+    /**
+     * Cast `n` to a `uint`
+     */
+    #[inline(always)]
+    static pure fn from<N:NumCast>(n: N) -> uint { n.to_uint() }
+
+    #[inline(always)] pure fn to_u8(&self)    -> u8    { *self as u8    }
+    #[inline(always)] pure fn to_u16(&self)   -> u16   { *self as u16   }
+    #[inline(always)] pure fn to_u32(&self)   -> u32   { *self as u32   }
+    #[inline(always)] pure fn to_u64(&self)   -> u64   { *self as u64   }
+    #[inline(always)] pure fn to_uint(&self)  -> uint  { *self          }
+
+    #[inline(always)] pure fn to_i8(&self)    -> i8    { *self as i8    }
+    #[inline(always)] pure fn to_i16(&self)   -> i16   { *self as i16   }
+    #[inline(always)] pure fn to_i32(&self)   -> i32   { *self as i32   }
+    #[inline(always)] pure fn to_i64(&self)   -> i64   { *self as i64   }
+    #[inline(always)] pure fn to_int(&self)   -> int   { *self as int   }
+
+    #[inline(always)] pure fn to_f32(&self)   -> f32   { *self as f32   }
+    #[inline(always)] pure fn to_f64(&self)   -> f64   { *self as f64   }
+    #[inline(always)] pure fn to_float(&self) -> float { *self as float }
+}
+
+#[test]
+fn test_numcast() {
+    assert (20u   == 20u.to_uint());
+    assert (20u8  == 20u.to_u8());
+    assert (20u16 == 20u.to_u16());
+    assert (20u32 == 20u.to_u32());
+    assert (20u64 == 20u.to_u64());
+    assert (20i   == 20u.to_int());
+    assert (20i8  == 20u.to_i8());
+    assert (20i16 == 20u.to_i16());
+    assert (20i32 == 20u.to_i32());
+    assert (20i64 == 20u.to_i64());
+    assert (20f   == 20u.to_float());
+    assert (20f32 == 20u.to_f32());
+    assert (20f64 == 20u.to_f64());
+
+    assert (20u == NumCast::from(20u));
+    assert (20u == NumCast::from(20u8));
+    assert (20u == NumCast::from(20u16));
+    assert (20u == NumCast::from(20u32));
+    assert (20u == NumCast::from(20u64));
+    assert (20u == NumCast::from(20i));
+    assert (20u == NumCast::from(20i8));
+    assert (20u == NumCast::from(20i16));
+    assert (20u == NumCast::from(20i32));
+    assert (20u == NumCast::from(20i64));
+    assert (20u == NumCast::from(20f));
+    assert (20u == NumCast::from(20f32));
+    assert (20u == NumCast::from(20f64));
+
+    assert (20u == num::cast(20u));
+    assert (20u == num::cast(20u8));
+    assert (20u == num::cast(20u16));
+    assert (20u == num::cast(20u32));
+    assert (20u == num::cast(20u64));
+    assert (20u == num::cast(20i));
+    assert (20u == num::cast(20i8));
+    assert (20u == num::cast(20i16));
+    assert (20u == num::cast(20i32));
+    assert (20u == num::cast(20i64));
+    assert (20u == num::cast(20f));
+    assert (20u == num::cast(20f32));
+    assert (20u == num::cast(20f64));
+}
\ No newline at end of file