about summary refs log tree commit diff
path: root/src/libstd/num/num.rs
diff options
context:
space:
mode:
authorErick Tryzelaar <erick.tryzelaar@gmail.com>2013-09-15 09:50:17 -0700
committerErick Tryzelaar <erick.tryzelaar@gmail.com>2013-10-02 07:55:41 -0700
commitd9d1dfc1955fabb7ee3a55e9c84cdcd5aad67417 (patch)
tree44ee6031936df55eb8d34db48298b2a67b21cc3b /src/libstd/num/num.rs
parent17548378a707fae752dc722e2fb767a65195e422 (diff)
downloadrust-d9d1dfc1955fabb7ee3a55e9c84cdcd5aad67417.tar.gz
rust-d9d1dfc1955fabb7ee3a55e9c84cdcd5aad67417.zip
std: Replace num::IntConvertible with {To,From}Primitive
Diffstat (limited to 'src/libstd/num/num.rs')
-rw-r--r--src/libstd/num/num.rs424
1 files changed, 341 insertions, 83 deletions
diff --git a/src/libstd/num/num.rs b/src/libstd/num/num.rs
index 95b1057dfd0..a8c85184664 100644
--- a/src/libstd/num/num.rs
+++ b/src/libstd/num/num.rs
@@ -32,11 +32,6 @@ pub trait Num: Eq + Zero + One
              + Div<Self,Self>
              + Rem<Self,Self> {}
 
-pub trait IntConvertible {
-    fn to_int(&self) -> int;
-    fn from_int(n: int) -> Self;
-}
-
 pub trait Orderable: Ord {
     // These should be methods on `Ord`, with overridable default implementations. We don't want
     // to encumber all implementors of Ord by requiring them to implement these functions, but at
@@ -353,6 +348,298 @@ pub trait Float: Real
 #[inline(always)] pub fn ln_1p<T: Float>(value: T) -> T { value.ln_1p() }
 #[inline(always)] pub fn mul_add<T: Float>(a: T, b: T, c: T) -> T { a.mul_add(b, c) }
 
+/// A generic trait for converting a value to a number.
+pub trait ToPrimitive {
+    /// Converts the value of `self` to an `int`.
+    fn to_int(&self) -> Option<int>;
+
+    /// Converts the value of `self` to an `i8`.
+    #[inline]
+    fn to_i8(&self) -> Option<i8> {
+        // XXX: Check for range.
+        self.to_int().and_then(|x| Some(x as i8))
+    }
+
+    /// Converts the value of `self` to an `i16`.
+    #[inline]
+    fn to_i16(&self) -> Option<i16> {
+        // XXX: Check for range.
+        self.to_int().and_then(|x| Some(x as i16))
+    }
+
+    /// Converts the value of `self` to an `i32`.
+    #[inline]
+    fn to_i32(&self) -> Option<i32> {
+        // XXX: Check for range.
+        self.to_int().and_then(|x| Some(x as i32))
+    }
+
+    /// Converts the value of `self` to an `i64`.
+    #[inline]
+    fn to_i64(&self) -> Option<i64> {
+        // XXX: Check for range.
+        self.to_int().and_then(|x| Some(x as i64))
+    }
+
+    /// Converts the value of `self` to an `uint`.
+    fn to_uint(&self) -> Option<uint>;
+
+    /// Converts the value of `self` to an `u8`.
+    #[inline]
+    fn to_u8(&self) -> Option<u8> {
+        // XXX: Check for range.
+        self.to_uint().and_then(|x| Some(x as u8))
+    }
+
+    /// Converts the value of `self` to an `u16`.
+    #[inline]
+    fn to_u16(&self) -> Option<u16> {
+        // XXX: Check for range.
+        self.to_uint().and_then(|x| Some(x as u16))
+    }
+
+    /// Converts the value of `self` to an `u32`.
+    #[inline]
+    fn to_u32(&self) -> Option<u32> {
+        // XXX: Check for range.
+        self.to_uint().and_then(|x| Some(x as u32))
+    }
+
+    /// Converts the value of `self` to an `u64`.
+    #[inline]
+    fn to_u64(&self) -> Option<u64> {
+        // XXX: Check for range.
+        self.to_uint().and_then(|x| Some(x as u64))
+    }
+
+    /// Converts the value of `self` to an `f32`.
+    #[inline]
+    fn to_f32(&self) -> Option<f32> {
+        // XXX: Check for range.
+        self.to_float().and_then(|x| Some(x as f32))
+    }
+
+    /// Converts the value of `self` to an `f64`.
+    #[inline]
+    fn to_f64(&self) -> Option<f64> {
+        // XXX: Check for range.
+        self.to_float().and_then(|x| Some(x as f64))
+    }
+}
+
+macro_rules! impl_to_primitive(
+    ($T:ty) => (
+        impl ToPrimitive for $T {
+            #[inline] fn to_int(&self)   -> Option<int>   { Some(*self as int)   }
+            #[inline] fn to_i8(&self)    -> Option<i8>    { Some(*self as i8)    }
+            #[inline] fn to_i16(&self)   -> Option<i16>   { Some(*self as i16)   }
+            #[inline] fn to_i32(&self)   -> Option<i32>   { Some(*self as i32)   }
+            #[inline] fn to_i64(&self)   -> Option<i64>   { Some(*self as i64)   }
+
+            #[inline] fn to_uint(&self)  -> Option<uint>  { Some(*self as uint)  }
+            #[inline] fn to_u8(&self)    -> Option<u8>    { Some(*self as u8)    }
+            #[inline] fn to_u16(&self)   -> Option<u16>   { Some(*self as u16)   }
+            #[inline] fn to_u32(&self)   -> Option<u32>   { Some(*self as u32)   }
+            #[inline] fn to_u64(&self)   -> Option<u64>   { Some(*self as u64)   }
+
+            #[inline] fn to_float(&self) -> Option<float> { Some(*self as float) }
+            #[inline] fn to_f32(&self)   -> Option<f32>   { Some(*self as f32)   }
+            #[inline] fn to_f64(&self)   -> Option<f64>   { Some(*self as f64)   }
+        }
+    )
+)
+
+impl_to_primitive!(u8)
+impl_to_primitive!(u16)
+impl_to_primitive!(u32)
+impl_to_primitive!(u64)
+impl_to_primitive!(uint)
+impl_to_primitive!(i8)
+impl_to_primitive!(i16)
+impl_to_primitive!(i32)
+impl_to_primitive!(i64)
+impl_to_primitive!(int)
+impl_to_primitive!(f32)
+impl_to_primitive!(f64)
+impl_to_primitive!(float)
+
+/// A generic trait for converting a number to a value.
+pub trait FromPrimitive {
+    /// Convert an `int` to return an optional value of this type. If the
+    /// value cannot be represented by this value, the `None` is returned.
+    fn from_int(n: int) -> Option<Self>;
+
+    /// Convert an `i8` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_i8(n: i8) -> Option<Self> {
+        FromPrimitive::from_int(n as int)
+    }
+
+    /// Convert an `i16` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_i16(n: i16) -> Option<Self> {
+        FromPrimitive::from_int(n as int)
+    }
+
+    /// Convert an `i32` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_i32(n: i32) -> Option<Self> {
+        FromPrimitive::from_int(n as int)
+    }
+
+    /// Convert an `i64` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_i64(n: i64) -> Option<Self> {
+        FromPrimitive::from_int(n as int)
+    }
+
+    /// Convert an `uint` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    fn from_uint(n: uint) -> Option<Self>;
+
+    /// Convert an `u8` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_u8(n: u8) -> Option<Self> {
+        FromPrimitive::from_uint(n as uint)
+    }
+
+    /// Convert an `u16` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_u16(n: u16) -> Option<Self> {
+        FromPrimitive::from_uint(n as uint)
+    }
+
+    /// Convert an `u32` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_u32(n: u32) -> Option<Self> {
+        FromPrimitive::from_uint(n as uint)
+    }
+
+    /// Convert an `u64` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_u64(n: u64) -> Option<Self> {
+        FromPrimitive::from_uint(n as uint)
+    }
+
+    /// Convert a `f32` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_f32(n: f32) -> Option<Self> {
+        FromPrimitive::from_float(n as float)
+    }
+
+    /// Convert a `f64` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_f64(n: f64) -> Option<Self> {
+        FromPrimitive::from_float(n as float)
+    }
+}
+
+/// A utility function that just calls `FromPrimitive::from_int`.
+pub fn from_int<A: FromPrimitive>(n: int) -> Option<A> {
+    FromPrimitive::from_int(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_i8`.
+pub fn from_i8<A: FromPrimitive>(n: i8) -> Option<A> {
+    FromPrimitive::from_i8(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_i16`.
+pub fn from_i16<A: FromPrimitive>(n: i16) -> Option<A> {
+    FromPrimitive::from_i16(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_i32`.
+pub fn from_i32<A: FromPrimitive>(n: i32) -> Option<A> {
+    FromPrimitive::from_i32(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_i64`.
+pub fn from_i64<A: FromPrimitive>(n: i64) -> Option<A> {
+    FromPrimitive::from_i64(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_uint`.
+pub fn from_uint<A: FromPrimitive>(n: uint) -> Option<A> {
+    FromPrimitive::from_uint(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_u8`.
+pub fn from_u8<A: FromPrimitive>(n: u8) -> Option<A> {
+    FromPrimitive::from_u8(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_u16`.
+pub fn from_u16<A: FromPrimitive>(n: u16) -> Option<A> {
+    FromPrimitive::from_u16(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_u32`.
+pub fn from_u32<A: FromPrimitive>(n: u32) -> Option<A> {
+    FromPrimitive::from_u32(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_u64`.
+pub fn from_u64<A: FromPrimitive>(n: u64) -> Option<A> {
+    FromPrimitive::from_u64(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_f32`.
+pub fn from_f32<A: FromPrimitive>(n: f32) -> Option<A> {
+    FromPrimitive::from_f32(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_f64`.
+pub fn from_f64<A: FromPrimitive>(n: f64) -> Option<A> {
+    FromPrimitive::from_f64(n)
+}
+
+macro_rules! impl_from_primitive(
+    ($T:ty) => (
+        impl FromPrimitive for $T {
+            #[inline] fn from_int(n: int)     -> Option<$T> { Some(n as $T) }
+            #[inline] fn from_i8(n: i8)       -> Option<$T> { Some(n as $T) }
+            #[inline] fn from_i16(n: i16)     -> Option<$T> { Some(n as $T) }
+            #[inline] fn from_i32(n: i32)     -> Option<$T> { Some(n as $T) }
+            #[inline] fn from_i64(n: i64)     -> Option<$T> { Some(n as $T) }
+
+            #[inline] fn from_uint(n: uint)   -> Option<$T> { Some(n as $T) }
+            #[inline] fn from_u8(n: u8)       -> Option<$T> { Some(n as $T) }
+            #[inline] fn from_u16(n: u16)     -> Option<$T> { Some(n as $T) }
+            #[inline] fn from_u32(n: u32)     -> Option<$T> { Some(n as $T) }
+            #[inline] fn from_u64(n: u64)     -> Option<$T> { Some(n as $T) }
+
+            #[inline] fn from_float(n: float) -> Option<$T> { Some(n as $T) }
+            #[inline] fn from_f32(n: f32)     -> Option<$T> { Some(n as $T) }
+            #[inline] fn from_f64(n: f64)     -> Option<$T> { Some(n as $T) }
+        }
+    )
+)
+
+impl_from_primitive!(u8)
+impl_from_primitive!(u16)
+impl_from_primitive!(u32)
+impl_from_primitive!(u64)
+impl_from_primitive!(uint)
+impl_from_primitive!(i8)
+impl_from_primitive!(i16)
+impl_from_primitive!(i32)
+impl_from_primitive!(i64)
+impl_from_primitive!(int)
+impl_from_primitive!(f32)
+impl_from_primitive!(f64)
+impl_from_primitive!(float)
+
 /// Cast from one machine scalar to another
 ///
 /// # Example
@@ -363,54 +650,24 @@ pub trait Float: Real
 /// ```
 ///
 #[inline]
-pub fn cast<T:NumCast,U:NumCast>(n: T) -> U {
+pub fn cast<T: NumCast,U: NumCast>(n: T) -> Option<U> {
     NumCast::from(n)
 }
 
 /// An interface for casting between machine scalars
-pub trait NumCast {
-    fn from<T:NumCast>(n: T) -> Self;
-
-    fn to_u8(&self) -> u8;
-    fn to_u16(&self) -> u16;
-    fn to_u32(&self) -> u32;
-    fn to_u64(&self) -> u64;
-    fn to_uint(&self) -> uint;
-
-    fn to_i8(&self) -> i8;
-    fn to_i16(&self) -> i16;
-    fn to_i32(&self) -> i32;
-    fn to_i64(&self) -> i64;
-    fn to_int(&self) -> int;
-
-    fn to_f32(&self) -> f32;
-    fn to_f64(&self) -> f64;
+pub trait NumCast: ToPrimitive {
+    fn from<T: ToPrimitive>(n: T) -> Option<Self>;
 }
 
 macro_rules! impl_num_cast(
     ($T:ty, $conv:ident) => (
         impl NumCast for $T {
             #[inline]
-            fn from<N:NumCast>(n: N) -> $T {
+            fn from<N: ToPrimitive>(n: N) -> Option<$T> {
                 // `$conv` could be generated using `concat_idents!`, but that
                 // macro seems to be broken at the moment
                 n.$conv()
             }
-
-            #[inline] fn to_u8(&self)    -> u8    { *self as u8    }
-            #[inline] fn to_u16(&self)   -> u16   { *self as u16   }
-            #[inline] fn to_u32(&self)   -> u32   { *self as u32   }
-            #[inline] fn to_u64(&self)   -> u64   { *self as u64   }
-            #[inline] fn to_uint(&self)  -> uint  { *self as uint  }
-
-            #[inline] fn to_i8(&self)    -> i8    { *self as i8    }
-            #[inline] fn to_i16(&self)   -> i16   { *self as i16   }
-            #[inline] fn to_i32(&self)   -> i32   { *self as i32   }
-            #[inline] fn to_i64(&self)   -> i64   { *self as i64   }
-            #[inline] fn to_int(&self)   -> int   { *self as int   }
-
-            #[inline] fn to_f32(&self)   -> f32   { *self as f32   }
-            #[inline] fn to_f64(&self)   -> f64   { *self as f64   }
         }
     )
 )
@@ -461,7 +718,7 @@ pub fn pow_with_uint<T:NumCast+One+Zero+Div<T,T>+Mul<T,T>>(radix: uint, pow: uin
     if radix == 0u { return _0; }
     let mut my_pow     = pow;
     let mut total      = _1;
-    let mut multiplier = cast(radix);
+    let mut multiplier = cast(radix).unwrap();
     while (my_pow > 0u) {
         if my_pow % 2u == 1u {
             total = total * multiplier;
@@ -543,11 +800,11 @@ pub trait CheckedDiv: Div<Self, Self> {
 /// Helper function for testing numeric operations
 #[cfg(test)]
 pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
-    assert_eq!(ten.add(&two),  cast(12));
-    assert_eq!(ten.sub(&two),  cast(8));
-    assert_eq!(ten.mul(&two),  cast(20));
-    assert_eq!(ten.div(&two),  cast(5));
-    assert_eq!(ten.rem(&two),  cast(0));
+    assert_eq!(ten.add(&two),  cast(12).unwrap());
+    assert_eq!(ten.sub(&two),  cast(8).unwrap());
+    assert_eq!(ten.mul(&two),  cast(20).unwrap());
+    assert_eq!(ten.div(&two),  cast(5).unwrap());
+    assert_eq!(ten.rem(&two),  cast(0).unwrap());
 
     assert_eq!(ten.add(&two),  ten + two);
     assert_eq!(ten.sub(&two),  ten - two);
@@ -566,44 +823,45 @@ mod tests {
         ($_20:expr) => ({
             let _20 = $_20;
 
-            assert_eq!(20u,   _20.to_uint());
-            assert_eq!(20u8,  _20.to_u8());
-            assert_eq!(20u16, _20.to_u16());
-            assert_eq!(20u32, _20.to_u32());
-            assert_eq!(20u64, _20.to_u64());
-            assert_eq!(20i,   _20.to_int());
-            assert_eq!(20i8,  _20.to_i8());
-            assert_eq!(20i16, _20.to_i16());
-            assert_eq!(20i32, _20.to_i32());
-            assert_eq!(20i64, _20.to_i64());
-            assert_eq!(20f32, _20.to_f32());
-            assert_eq!(20f64, _20.to_f64());
-
-            assert_eq!(_20, NumCast::from(20u));
-            assert_eq!(_20, NumCast::from(20u8));
-            assert_eq!(_20, NumCast::from(20u16));
-            assert_eq!(_20, NumCast::from(20u32));
-            assert_eq!(_20, NumCast::from(20u64));
-            assert_eq!(_20, NumCast::from(20i));
-            assert_eq!(_20, NumCast::from(20i8));
-            assert_eq!(_20, NumCast::from(20i16));
-            assert_eq!(_20, NumCast::from(20i32));
-            assert_eq!(_20, NumCast::from(20i64));
-            assert_eq!(_20, NumCast::from(20f32));
-            assert_eq!(_20, NumCast::from(20f64));
-
-            assert_eq!(_20, cast(20u));
-            assert_eq!(_20, cast(20u8));
-            assert_eq!(_20, cast(20u16));
-            assert_eq!(_20, cast(20u32));
-            assert_eq!(_20, cast(20u64));
-            assert_eq!(_20, cast(20i));
-            assert_eq!(_20, cast(20i8));
-            assert_eq!(_20, cast(20i16));
-            assert_eq!(_20, cast(20i32));
-            assert_eq!(_20, cast(20i64));
-            assert_eq!(_20, cast(20f32));
-            assert_eq!(_20, cast(20f64));
+            assert_eq!(20u,   _20.to_uint().unwrap());
+            assert_eq!(20u8,  _20.to_u8().unwrap());
+            assert_eq!(20u16, _20.to_u16().unwrap());
+            assert_eq!(20u32, _20.to_u32().unwrap());
+            assert_eq!(20u64, _20.to_u64().unwrap());
+            assert_eq!(20i,   _20.to_int().unwrap());
+            assert_eq!(20i8,  _20.to_i8().unwrap());
+            assert_eq!(20i16, _20.to_i16().unwrap());
+            assert_eq!(20i32, _20.to_i32().unwrap());
+            assert_eq!(20i64, _20.to_i64().unwrap());
+            assert_eq!(20f,   _20.to_float().unwrap());
+            assert_eq!(20f32, _20.to_f32().unwrap());
+            assert_eq!(20f64, _20.to_f64().unwrap());
+
+            assert_eq!(_20, NumCast::from(20u).unwrap());
+            assert_eq!(_20, NumCast::from(20u8).unwrap());
+            assert_eq!(_20, NumCast::from(20u16).unwrap());
+            assert_eq!(_20, NumCast::from(20u32).unwrap());
+            assert_eq!(_20, NumCast::from(20u64).unwrap());
+            assert_eq!(_20, NumCast::from(20i).unwrap());
+            assert_eq!(_20, NumCast::from(20i8).unwrap());
+            assert_eq!(_20, NumCast::from(20i16).unwrap());
+            assert_eq!(_20, NumCast::from(20i32).unwrap());
+            assert_eq!(_20, NumCast::from(20i64).unwrap());
+            assert_eq!(_20, NumCast::from(20f32).unwrap());
+            assert_eq!(_20, NumCast::from(20f64).unwrap());
+
+            assert_eq!(_20, cast(20u).unwrap());
+            assert_eq!(_20, cast(20u8).unwrap());
+            assert_eq!(_20, cast(20u16).unwrap());
+            assert_eq!(_20, cast(20u32).unwrap());
+            assert_eq!(_20, cast(20u64).unwrap());
+            assert_eq!(_20, cast(20i).unwrap());
+            assert_eq!(_20, cast(20i8).unwrap());
+            assert_eq!(_20, cast(20i16).unwrap());
+            assert_eq!(_20, cast(20i32).unwrap());
+            assert_eq!(_20, cast(20i64).unwrap());
+            assert_eq!(_20, cast(20f32).unwrap());
+            assert_eq!(_20, cast(20f64).unwrap());
         })
     )