From 48b2141b83bd3afe6aee3adf170ef6e985ab1353 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Mon, 11 Feb 2013 12:33:05 +1100 Subject: [PATCH] Add NumCast trait for generic numeric type casts --- src/libcore/core.rc | 2 +- src/libcore/num/f32.rs | 87 ++++++++++++++++-- src/libcore/num/f64.rs | 83 ++++++++++++++++- src/libcore/num/float.rs | 98 ++++++++++++++++----- src/libcore/num/int-template.rs | 31 ++----- src/libcore/num/int-template/i16.rs | 71 +++++++++++++++ src/libcore/num/int-template/i32.rs | 71 +++++++++++++++ src/libcore/num/int-template/i64.rs | 71 +++++++++++++++ src/libcore/num/int-template/i8.rs | 71 +++++++++++++++ src/libcore/num/int-template/int.rs | 71 +++++++++++++++ src/libcore/num/num.rs | 69 +++++++++++---- src/libcore/num/uint-template.rs | 17 ++-- src/libcore/num/uint-template/u16.rs | 71 +++++++++++++++ src/libcore/num/uint-template/u32.rs | 71 +++++++++++++++ src/libcore/num/uint-template/u64.rs | 71 +++++++++++++++ src/libcore/num/uint-template/u8.rs | 71 +++++++++++++++ src/libcore/num/uint-template/uint.rs | 71 +++++++++++++++ src/libcore/prelude.rs | 2 +- src/test/run-pass/trait-inheritance-num.rs | 8 +- src/test/run-pass/trait-inheritance-num0.rs | 6 +- src/test/run-pass/trait-inheritance-num1.rs | 6 +- src/test/run-pass/trait-inheritance-num2.rs | 4 +- src/test/run-pass/trait-inheritance-num3.rs | 6 +- src/test/run-pass/trait-inheritance-num5.rs | 6 +- 24 files changed, 1044 insertions(+), 91 deletions(-) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 64b480818b1e7..7bf64d5b6684b 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -199,7 +199,7 @@ pub use vec::{OwnedVector, OwnedCopyableVector}; pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter}; pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times}; -pub use num::Num; +pub use num::{Num, 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 738445b5cd946..6bea9e81197d3 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: 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 f09d874803c3d..7cde210265324 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: 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 f5ae05ebffb4e..74bf50737f563 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: 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(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 1856781b1d779..b616a08246b67 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(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 da60b567f665a..572cce92ea1d7 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: 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 1bc45bb71af7e..de2e467d02ab1 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: 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 83d15aa857d95..d7413920a64f1 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: 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 740442ed725be..f2577020128bd 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: 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 224da0dc062d3..4ba1570e1359a 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: 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 05b03a53dcdea..eb722b441c7a6 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(n: T) -> U { + NumCast::from(n) +} + +/** + * An interface for generic numeric type casts + */ +pub trait NumCast { + static pure fn from(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(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(radix: uint, - pow: uint) -> T { +pub pure fn pow_with_uint(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(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( +pub pure fn to_str_bytes_common( 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( let neg = *num < _0 || (negative_zero && *num == _0 && special && is_neg_zero(num)); let mut buf: ~[u8] = ~[]; - let radix_gen = Num::from_int::(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( * `to_str_bytes_common()`, for details see there. */ #[inline(always)] -pub pure fn to_str_common( +pub pure fn to_str_common( 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( +pub pure fn from_str_bytes_common( buf: &[u8], radix: uint, negative: bool, fractional: bool, special: bool, exponent: ExponentFormat, empty_zero: bool ) -> Option { @@ -519,7 +554,7 @@ pub pure fn from_str_bytes_common( 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( // 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( // 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::(digit as int) * power; + accum += digit_t * power; } else { - accum -= Num::from_int::(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( * `from_str_bytes_common()`, for details see there. */ #[inline(always)] -pub pure fn from_str_common( +pub pure fn from_str_common( buf: &str, radix: uint, negative: bool, fractional: bool, special: bool, exponent: ExponentFormat, empty_zero: bool ) -> Option { diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index f8bbb35204add..0a219660fb946 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 { @@ -409,6 +404,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))] diff --git a/src/libcore/num/uint-template/u16.rs b/src/libcore/num/uint-template/u16.rs index b9a007af2f67a..e2e8e2bc9fce2 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: 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 141509c49e555..ac2727bff0996 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: 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 35210eae9a75c..345f81c147c77 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: 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 e273a20321326..71be36d901961 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: 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 93f59cd2d9f97..66689f18dfe99 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: 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 diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index a798d8c866a3f..7ae7d0cd87404 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -29,7 +29,7 @@ pub use container::{Container, Mutable, Map, Set}; pub use hash::Hash; pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter}; pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times}; -pub use num::Num; +pub use num::{Num, NumCast}; pub use path::GenericPath; pub use path::Path; pub use path::PosixPath; diff --git a/src/test/run-pass/trait-inheritance-num.rs b/src/test/run-pass/trait-inheritance-num.rs index ca720c27d77ad..c7a049b2f34e0 100644 --- a/src/test/run-pass/trait-inheritance-num.rs +++ b/src/test/run-pass/trait-inheritance-num.rs @@ -11,16 +11,16 @@ // except according to those terms. use cmp::{Eq, Ord}; -use num::Num::from_int; +use num::NumCast::from; extern mod std; use std::cmp::FuzzyEq; -pub trait NumExt: Num Eq Ord {} +pub trait NumExt: Num NumCast Eq Ord {} pub trait FloatExt: NumExt FuzzyEq {} -fn greater_than_one(n: &T) -> bool { *n > from_int(1) } -fn greater_than_one_float(n: &T) -> bool { *n > from_int(1) } +fn greater_than_one(n: &T) -> bool { *n > from(1) } +fn greater_than_one_float(n: &T) -> bool { *n > from(1) } pub fn main() {} diff --git a/src/test/run-pass/trait-inheritance-num0.rs b/src/test/run-pass/trait-inheritance-num0.rs index c7f43e055a4d3..1996e05618a0d 100644 --- a/src/test/run-pass/trait-inheritance-num0.rs +++ b/src/test/run-pass/trait-inheritance-num0.rs @@ -12,17 +12,17 @@ // Extending Num and using inherited static methods -use Num::from_int; +use num::NumCast::from; trait Num { static fn from_int(i: int) -> Self; fn gt(&self, other: &Self) -> bool; } -pub trait NumExt: Num { } +pub trait NumExt: Num NumCast { } fn greater_than_one(n: &T) -> bool { - n.gt(&from_int(1)) + n.gt(&from(1)) } pub fn main() {} diff --git a/src/test/run-pass/trait-inheritance-num1.rs b/src/test/run-pass/trait-inheritance-num1.rs index 7546735993677..a9cbd4e622c40 100644 --- a/src/test/run-pass/trait-inheritance-num1.rs +++ b/src/test/run-pass/trait-inheritance-num1.rs @@ -11,12 +11,12 @@ // Using the real Num from core use cmp::Ord; -use num::Num::from_int; +use num::NumCast::from; -pub trait NumExt: Num Ord { } +pub trait NumExt: Num NumCast Ord { } fn greater_than_one(n: &T) -> bool { - *n > from_int(1) + *n > from(1) } pub fn main() {} diff --git a/src/test/run-pass/trait-inheritance-num2.rs b/src/test/run-pass/trait-inheritance-num2.rs index ecedaac8daaab..6829990bc5acd 100644 --- a/src/test/run-pass/trait-inheritance-num2.rs +++ b/src/test/run-pass/trait-inheritance-num2.rs @@ -13,7 +13,7 @@ // A more complex example of numeric extensions use cmp::{Eq, Ord}; -use num::Num::from_int; +use num::NumCast::from; extern mod std; use std::cmp::FuzzyEq; @@ -38,7 +38,7 @@ pub impl f64: TypeExt {} pub impl float: TypeExt {} -pub trait NumExt: TypeExt Eq Ord Num {} +pub trait NumExt: TypeExt Eq Ord Num NumCast {} pub impl u8: NumExt {} pub impl u16: NumExt {} diff --git a/src/test/run-pass/trait-inheritance-num3.rs b/src/test/run-pass/trait-inheritance-num3.rs index 939b074e2dd54..32775164d35ef 100644 --- a/src/test/run-pass/trait-inheritance-num3.rs +++ b/src/test/run-pass/trait-inheritance-num3.rs @@ -9,13 +9,13 @@ // except according to those terms. use cmp::{Eq, Ord}; -use num::Num::from_int; +use num::NumCast::from; -pub trait NumExt: Eq Ord Num {} +pub trait NumExt: Eq Ord Num NumCast {} pub impl f32: NumExt {} -fn num_eq_one(n: T) { io::println(fmt!("%?", n == from_int(1))) } +fn num_eq_one(n: T) { io::println(fmt!("%?", n == from(1))) } pub fn main() { num_eq_one(1f32); // you need to actually use the function to trigger the ICE diff --git a/src/test/run-pass/trait-inheritance-num5.rs b/src/test/run-pass/trait-inheritance-num5.rs index bb9b57d4afb67..13c75224e5f88 100644 --- a/src/test/run-pass/trait-inheritance-num5.rs +++ b/src/test/run-pass/trait-inheritance-num5.rs @@ -9,15 +9,15 @@ // except according to those terms. use cmp::{Eq, Ord}; -use num::Num::from_int; +use num::NumCast::from; -pub trait NumExt: Eq Num {} +pub trait NumExt: Eq Num NumCast {} pub impl f32: NumExt {} pub impl int: NumExt {} fn num_eq_one() -> T { - from_int(1) + from(1) } pub fn main() {