From 0fcb85997db852350c104b40e3d7c78214bb0708 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 7 Sep 2013 17:15:35 +1000 Subject: [PATCH] Moved checked trait impls out of std::num This follows the same pattern as the other numeric trait impls, and reduces the clutter in std::num. --- src/libstd/num/i16.rs | 33 +++- src/libstd/num/i32.rs | 33 +++- src/libstd/num/i64.rs | 35 +++- src/libstd/num/i8.rs | 33 +++- src/libstd/num/int.rs | 70 +++++++- src/libstd/num/num.rs | 379 +---------------------------------------- src/libstd/num/u16.rs | 35 ++++ src/libstd/num/u32.rs | 35 ++++ src/libstd/num/u64.rs | 37 ++++ src/libstd/num/u8.rs | 35 ++++ src/libstd/num/uint.rs | 69 ++++++++ 11 files changed, 411 insertions(+), 383 deletions(-) diff --git a/src/libstd/num/i16.rs b/src/libstd/num/i16.rs index eec20297a53..5c077c7e633 100644 --- a/src/libstd/num/i16.rs +++ b/src/libstd/num/i16.rs @@ -10,7 +10,8 @@ //! Operations and constants for `i16` -use num::BitCount; +use num::{BitCount, CheckedAdd, CheckedSub, CheckedMul}; +use option::{Option, Some, None}; use unstable::intrinsics; pub use self::generated::*; @@ -30,3 +31,33 @@ fn leading_zeros(&self) -> i16 { unsafe { intrinsics::ctlz16(*self) } } #[inline] fn trailing_zeros(&self) -> i16 { unsafe { intrinsics::cttz16(*self) } } } + +impl CheckedAdd for i16 { + #[inline] + fn checked_add(&self, v: &i16) -> Option { + unsafe { + let (x, y) = intrinsics::i16_add_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} + +impl CheckedSub for i16 { + #[inline] + fn checked_sub(&self, v: &i16) -> Option { + unsafe { + let (x, y) = intrinsics::i16_sub_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} + +impl CheckedMul for i16 { + #[inline] + fn checked_mul(&self, v: &i16) -> Option { + unsafe { + let (x, y) = intrinsics::i16_mul_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} diff --git a/src/libstd/num/i32.rs b/src/libstd/num/i32.rs index 769187cc66d..f076e33b3a2 100644 --- a/src/libstd/num/i32.rs +++ b/src/libstd/num/i32.rs @@ -10,7 +10,8 @@ //! Operations and constants for `i32` -use num::BitCount; +use num::{BitCount, CheckedAdd, CheckedSub, CheckedMul}; +use option::{Option, Some, None}; use unstable::intrinsics; pub use self::generated::*; @@ -30,3 +31,33 @@ fn leading_zeros(&self) -> i32 { unsafe { intrinsics::ctlz32(*self) } } #[inline] fn trailing_zeros(&self) -> i32 { unsafe { intrinsics::cttz32(*self) } } } + +impl CheckedAdd for i32 { + #[inline] + fn checked_add(&self, v: &i32) -> Option { + unsafe { + let (x, y) = intrinsics::i32_add_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} + +impl CheckedSub for i32 { + #[inline] + fn checked_sub(&self, v: &i32) -> Option { + unsafe { + let (x, y) = intrinsics::i32_sub_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} + +impl CheckedMul for i32 { + #[inline] + fn checked_mul(&self, v: &i32) -> Option { + unsafe { + let (x, y) = intrinsics::i32_mul_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} diff --git a/src/libstd/num/i64.rs b/src/libstd/num/i64.rs index ae0e59d1661..10df7e37b88 100644 --- a/src/libstd/num/i64.rs +++ b/src/libstd/num/i64.rs @@ -10,7 +10,8 @@ //! Operations and constants for `i64` -use num::BitCount; +use num::{BitCount, CheckedAdd, CheckedSub, CheckedMul}; +use option::{Option, Some, None}; use unstable::intrinsics; pub use self::generated::*; @@ -30,3 +31,35 @@ fn leading_zeros(&self) -> i64 { unsafe { intrinsics::ctlz64(*self) } } #[inline] fn trailing_zeros(&self) -> i64 { unsafe { intrinsics::cttz64(*self) } } } + +impl CheckedAdd for i64 { + #[inline] + fn checked_add(&self, v: &i64) -> Option { + unsafe { + let (x, y) = intrinsics::i64_add_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} + +impl CheckedSub for i64 { + #[inline] + fn checked_sub(&self, v: &i64) -> Option { + unsafe { + let (x, y) = intrinsics::i64_sub_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} + +// FIXME: #8449: should not be disabled on 32-bit +#[cfg(target_word_size = "64")] +impl CheckedMul for i64 { + #[inline] + fn checked_mul(&self, v: &i64) -> Option { + unsafe { + let (x, y) = intrinsics::i64_mul_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} diff --git a/src/libstd/num/i8.rs b/src/libstd/num/i8.rs index 31a1f4241f5..a807f6b9e53 100644 --- a/src/libstd/num/i8.rs +++ b/src/libstd/num/i8.rs @@ -10,7 +10,8 @@ //! Operations and constants for `i8` -use num::BitCount; +use num::{BitCount, CheckedAdd, CheckedSub, CheckedMul}; +use option::{Option, Some, None}; use unstable::intrinsics; pub use self::generated::*; @@ -30,3 +31,33 @@ fn leading_zeros(&self) -> i8 { unsafe { intrinsics::ctlz8(*self) } } #[inline] fn trailing_zeros(&self) -> i8 { unsafe { intrinsics::cttz8(*self) } } } + +impl CheckedAdd for i8 { + #[inline] + fn checked_add(&self, v: &i8) -> Option { + unsafe { + let (x, y) = intrinsics::i8_add_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} + +impl CheckedSub for i8 { + #[inline] + fn checked_sub(&self, v: &i8) -> Option { + unsafe { + let (x, y) = intrinsics::i8_sub_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} + +impl CheckedMul for i8 { + #[inline] + fn checked_mul(&self, v: &i8) -> Option { + unsafe { + let (x, y) = intrinsics::i8_mul_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs index d39b4b2b911..c5364fa3dab 100644 --- a/src/libstd/num/int.rs +++ b/src/libstd/num/int.rs @@ -12,7 +12,9 @@ #[allow(non_uppercase_statics)]; -use num::BitCount; +use num::{BitCount, CheckedAdd, CheckedSub, CheckedMul}; +use option::{Option, Some, None}; +use unstable::intrinsics; pub use self::generated::*; @@ -51,6 +53,72 @@ fn leading_zeros(&self) -> int { (*self as i64).leading_zeros() as int } fn trailing_zeros(&self) -> int { (*self as i64).trailing_zeros() as int } } +#[cfg(target_word_size = "32")] +impl CheckedAdd for int { + #[inline] + fn checked_add(&self, v: &int) -> Option { + unsafe { + let (x, y) = intrinsics::i32_add_with_overflow(*self as i32, *v as i32); + if y { None } else { Some(x as int) } + } + } +} + +#[cfg(target_word_size = "64")] +impl CheckedAdd for int { + #[inline] + fn checked_add(&self, v: &int) -> Option { + unsafe { + let (x, y) = intrinsics::i64_add_with_overflow(*self as i64, *v as i64); + if y { None } else { Some(x as int) } + } + } +} + +#[cfg(target_word_size = "32")] +impl CheckedSub for int { + #[inline] + fn checked_sub(&self, v: &int) -> Option { + unsafe { + let (x, y) = intrinsics::i32_sub_with_overflow(*self as i32, *v as i32); + if y { None } else { Some(x as int) } + } + } +} + +#[cfg(target_word_size = "64")] +impl CheckedSub for int { + #[inline] + fn checked_sub(&self, v: &int) -> Option { + unsafe { + let (x, y) = intrinsics::i64_sub_with_overflow(*self as i64, *v as i64); + if y { None } else { Some(x as int) } + } + } +} + +#[cfg(target_word_size = "32")] +impl CheckedMul for int { + #[inline] + fn checked_mul(&self, v: &int) -> Option { + unsafe { + let (x, y) = intrinsics::i32_mul_with_overflow(*self as i32, *v as i32); + if y { None } else { Some(x as int) } + } + } +} + +#[cfg(target_word_size = "64")] +impl CheckedMul for int { + #[inline] + fn checked_mul(&self, v: &int) -> Option { + unsafe { + let (x, y) = intrinsics::i64_mul_with_overflow(*self as i64, *v as i64); + if y { None } else { Some(x as int) } + } + } +} + /// Returns `base` raised to the power of `exponent` pub fn pow(base: int, exponent: uint) -> int { if exponent == 0u { diff --git a/src/libstd/num/num.rs b/src/libstd/num/num.rs index ac8f0022b95..724bc6dda01 100644 --- a/src/libstd/num/num.rs +++ b/src/libstd/num/num.rs @@ -19,7 +19,6 @@ use ops::{Add, Sub, Mul, Div, Rem, Neg}; use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr}; use option::{Option, Some, None}; -use unstable::intrinsics; pub mod strconv; @@ -493,7 +492,7 @@ pub trait Saturating { fn saturating_sub(self, v: Self) -> Self; } -impl Saturating for T { +impl Saturating for T { #[inline] fn saturating_add(self, v: T) -> T { match self.checked_add(&v) { @@ -523,390 +522,14 @@ pub trait CheckedAdd: Add { fn checked_add(&self, v: &Self) -> Option; } -impl CheckedAdd for i8 { - #[inline] - fn checked_add(&self, v: &i8) -> Option { - unsafe { - let (x, y) = intrinsics::i8_add_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -impl CheckedAdd for i16 { - #[inline] - fn checked_add(&self, v: &i16) -> Option { - unsafe { - let (x, y) = intrinsics::i16_add_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -impl CheckedAdd for i32 { - #[inline] - fn checked_add(&self, v: &i32) -> Option { - unsafe { - let (x, y) = intrinsics::i32_add_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -impl CheckedAdd for i64 { - #[inline] - fn checked_add(&self, v: &i64) -> Option { - unsafe { - let (x, y) = intrinsics::i64_add_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -#[cfg(target_word_size = "32")] -impl CheckedAdd for int { - #[inline] - fn checked_add(&self, v: &int) -> Option { - unsafe { - let (x, y) = intrinsics::i32_add_with_overflow(*self as i32, *v as i32); - if y { None } else { Some(x as int) } - } - } -} - -#[cfg(target_word_size = "64")] -impl CheckedAdd for int { - #[inline] - fn checked_add(&self, v: &int) -> Option { - unsafe { - let (x, y) = intrinsics::i64_add_with_overflow(*self as i64, *v as i64); - if y { None } else { Some(x as int) } - } - } -} - -impl CheckedAdd for u8 { - #[inline] - fn checked_add(&self, v: &u8) -> Option { - unsafe { - let (x, y) = intrinsics::u8_add_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -impl CheckedAdd for u16 { - #[inline] - fn checked_add(&self, v: &u16) -> Option { - unsafe { - let (x, y) = intrinsics::u16_add_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -impl CheckedAdd for u32 { - #[inline] - fn checked_add(&self, v: &u32) -> Option { - unsafe { - let (x, y) = intrinsics::u32_add_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -impl CheckedAdd for u64 { - #[inline] - fn checked_add(&self, v: &u64) -> Option { - unsafe { - let (x, y) = intrinsics::u64_add_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -#[cfg(target_word_size = "32")] -impl CheckedAdd for uint { - #[inline] - fn checked_add(&self, v: &uint) -> Option { - unsafe { - let (x, y) = intrinsics::u32_add_with_overflow(*self as u32, *v as u32); - if y { None } else { Some(x as uint) } - } - } -} - -#[cfg(target_word_size = "64")] -impl CheckedAdd for uint { - #[inline] - fn checked_add(&self, v: &uint) -> Option { - unsafe { - let (x, y) = intrinsics::u64_add_with_overflow(*self as u64, *v as u64); - if y { None } else { Some(x as uint) } - } - } -} - pub trait CheckedSub: Sub { fn checked_sub(&self, v: &Self) -> Option; } -impl CheckedSub for i8 { - #[inline] - fn checked_sub(&self, v: &i8) -> Option { - unsafe { - let (x, y) = intrinsics::i8_sub_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -impl CheckedSub for i16 { - #[inline] - fn checked_sub(&self, v: &i16) -> Option { - unsafe { - let (x, y) = intrinsics::i16_sub_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -impl CheckedSub for i32 { - #[inline] - fn checked_sub(&self, v: &i32) -> Option { - unsafe { - let (x, y) = intrinsics::i32_sub_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -impl CheckedSub for i64 { - #[inline] - fn checked_sub(&self, v: &i64) -> Option { - unsafe { - let (x, y) = intrinsics::i64_sub_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -#[cfg(target_word_size = "32")] -impl CheckedSub for int { - #[inline] - fn checked_sub(&self, v: &int) -> Option { - unsafe { - let (x, y) = intrinsics::i32_sub_with_overflow(*self as i32, *v as i32); - if y { None } else { Some(x as int) } - } - } -} - -#[cfg(target_word_size = "64")] -impl CheckedSub for int { - #[inline] - fn checked_sub(&self, v: &int) -> Option { - unsafe { - let (x, y) = intrinsics::i64_sub_with_overflow(*self as i64, *v as i64); - if y { None } else { Some(x as int) } - } - } -} - -impl CheckedSub for u8 { - #[inline] - fn checked_sub(&self, v: &u8) -> Option { - unsafe { - let (x, y) = intrinsics::u8_sub_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -impl CheckedSub for u16 { - #[inline] - fn checked_sub(&self, v: &u16) -> Option { - unsafe { - let (x, y) = intrinsics::u16_sub_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -impl CheckedSub for u32 { - #[inline] - fn checked_sub(&self, v: &u32) -> Option { - unsafe { - let (x, y) = intrinsics::u32_sub_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -impl CheckedSub for u64 { - #[inline] - fn checked_sub(&self, v: &u64) -> Option { - unsafe { - let (x, y) = intrinsics::u64_sub_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -#[cfg(target_word_size = "32")] -impl CheckedSub for uint { - #[inline] - fn checked_sub(&self, v: &uint) -> Option { - unsafe { - let (x, y) = intrinsics::u32_sub_with_overflow(*self as u32, *v as u32); - if y { None } else { Some(x as uint) } - } - } -} - -#[cfg(target_word_size = "64")] -impl CheckedSub for uint { - #[inline] - fn checked_sub(&self, v: &uint) -> Option { - unsafe { - let (x, y) = intrinsics::u64_sub_with_overflow(*self as u64, *v as u64); - if y { None } else { Some(x as uint) } - } - } -} - pub trait CheckedMul: Mul { fn checked_mul(&self, v: &Self) -> Option; } -impl CheckedMul for i8 { - #[inline] - fn checked_mul(&self, v: &i8) -> Option { - unsafe { - let (x, y) = intrinsics::i8_mul_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -impl CheckedMul for i16 { - #[inline] - fn checked_mul(&self, v: &i16) -> Option { - unsafe { - let (x, y) = intrinsics::i16_mul_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -impl CheckedMul for i32 { - #[inline] - fn checked_mul(&self, v: &i32) -> Option { - unsafe { - let (x, y) = intrinsics::i32_mul_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -// FIXME: #8449: should not be disabled on 32-bit -#[cfg(target_word_size = "64")] -impl CheckedMul for i64 { - #[inline] - fn checked_mul(&self, v: &i64) -> Option { - unsafe { - let (x, y) = intrinsics::i64_mul_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -#[cfg(target_word_size = "32")] -impl CheckedMul for int { - #[inline] - fn checked_mul(&self, v: &int) -> Option { - unsafe { - let (x, y) = intrinsics::i32_mul_with_overflow(*self as i32, *v as i32); - if y { None } else { Some(x as int) } - } - } -} - -#[cfg(target_word_size = "64")] -impl CheckedMul for int { - #[inline] - fn checked_mul(&self, v: &int) -> Option { - unsafe { - let (x, y) = intrinsics::i64_mul_with_overflow(*self as i64, *v as i64); - if y { None } else { Some(x as int) } - } - } -} - -impl CheckedMul for u8 { - #[inline] - fn checked_mul(&self, v: &u8) -> Option { - unsafe { - let (x, y) = intrinsics::u8_mul_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -impl CheckedMul for u16 { - #[inline] - fn checked_mul(&self, v: &u16) -> Option { - unsafe { - let (x, y) = intrinsics::u16_mul_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -impl CheckedMul for u32 { - #[inline] - fn checked_mul(&self, v: &u32) -> Option { - unsafe { - let (x, y) = intrinsics::u32_mul_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -// FIXME: #8449: should not be disabled on 32-bit -#[cfg(target_word_size = "64")] -impl CheckedMul for u64 { - #[inline] - fn checked_mul(&self, v: &u64) -> Option { - unsafe { - let (x, y) = intrinsics::u64_mul_with_overflow(*self, *v); - if y { None } else { Some(x) } - } - } -} - -#[cfg(target_word_size = "32")] -impl CheckedMul for uint { - #[inline] - fn checked_mul(&self, v: &uint) -> Option { - unsafe { - let (x, y) = intrinsics::u32_mul_with_overflow(*self as u32, *v as u32); - if y { None } else { Some(x as uint) } - } - } -} - -#[cfg(target_word_size = "64")] -impl CheckedMul for uint { - #[inline] - fn checked_mul(&self, v: &uint) -> Option { - unsafe { - let (x, y) = intrinsics::u64_mul_with_overflow(*self as u64, *v as u64); - if y { None } else { Some(x as uint) } - } - } -} - pub trait CheckedDiv: Div { fn checked_div(&self, v: &Self) -> Option; } diff --git a/src/libstd/num/u16.rs b/src/libstd/num/u16.rs index 3a4c2420f9e..e227947ca6e 100644 --- a/src/libstd/num/u16.rs +++ b/src/libstd/num/u16.rs @@ -10,5 +10,40 @@ //! Operations and constants for `u16` +use num::{CheckedAdd, CheckedSub, CheckedMul}; +use option::{Option, Some, None}; +use unstable::intrinsics; + pub use self::generated::*; + uint_module!(u16, i16, 16) + +impl CheckedAdd for u16 { + #[inline] + fn checked_add(&self, v: &u16) -> Option { + unsafe { + let (x, y) = intrinsics::u16_add_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} + +impl CheckedSub for u16 { + #[inline] + fn checked_sub(&self, v: &u16) -> Option { + unsafe { + let (x, y) = intrinsics::u16_sub_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} + +impl CheckedMul for u16 { + #[inline] + fn checked_mul(&self, v: &u16) -> Option { + unsafe { + let (x, y) = intrinsics::u16_mul_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} diff --git a/src/libstd/num/u32.rs b/src/libstd/num/u32.rs index f87fa7fcd42..4dbd543da7b 100644 --- a/src/libstd/num/u32.rs +++ b/src/libstd/num/u32.rs @@ -10,5 +10,40 @@ //! Operations and constants for `u32` +use num::{CheckedAdd, CheckedSub, CheckedMul}; +use option::{Option, Some, None}; +use unstable::intrinsics; + pub use self::generated::*; + uint_module!(u32, i32, 32) + +impl CheckedAdd for u32 { + #[inline] + fn checked_add(&self, v: &u32) -> Option { + unsafe { + let (x, y) = intrinsics::u32_add_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} + +impl CheckedSub for u32 { + #[inline] + fn checked_sub(&self, v: &u32) -> Option { + unsafe { + let (x, y) = intrinsics::u32_sub_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} + +impl CheckedMul for u32 { + #[inline] + fn checked_mul(&self, v: &u32) -> Option { + unsafe { + let (x, y) = intrinsics::u32_mul_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} diff --git a/src/libstd/num/u64.rs b/src/libstd/num/u64.rs index 792db155569..b311183ba11 100644 --- a/src/libstd/num/u64.rs +++ b/src/libstd/num/u64.rs @@ -10,5 +10,42 @@ //! Operations and constants for `u64` +use num::{CheckedAdd, CheckedSub, CheckedMul}; +use option::{Option, Some, None}; +use unstable::intrinsics; + pub use self::generated::*; + uint_module!(u64, i64, 64) + +impl CheckedAdd for u64 { + #[inline] + fn checked_add(&self, v: &u64) -> Option { + unsafe { + let (x, y) = intrinsics::u64_add_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} + +impl CheckedSub for u64 { + #[inline] + fn checked_sub(&self, v: &u64) -> Option { + unsafe { + let (x, y) = intrinsics::u64_sub_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} + +// FIXME: #8449: should not be disabled on 32-bit +#[cfg(target_word_size = "64")] +impl CheckedMul for u64 { + #[inline] + fn checked_mul(&self, v: &u64) -> Option { + unsafe { + let (x, y) = intrinsics::u64_mul_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} diff --git a/src/libstd/num/u8.rs b/src/libstd/num/u8.rs index e21e80f8406..ca54af5cecc 100644 --- a/src/libstd/num/u8.rs +++ b/src/libstd/num/u8.rs @@ -10,5 +10,40 @@ //! Operations and constants for `u8` +use num::{CheckedAdd, CheckedSub, CheckedMul}; +use option::{Option, Some, None}; +use unstable::intrinsics; + pub use self::generated::*; + uint_module!(u8, i8, 8) + +impl CheckedAdd for u8 { + #[inline] + fn checked_add(&self, v: &u8) -> Option { + unsafe { + let (x, y) = intrinsics::u8_add_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} + +impl CheckedSub for u8 { + #[inline] + fn checked_sub(&self, v: &u8) -> Option { + unsafe { + let (x, y) = intrinsics::u8_sub_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} + +impl CheckedMul for u8 { + #[inline] + fn checked_mul(&self, v: &u8) -> Option { + unsafe { + let (x, y) = intrinsics::u8_mul_with_overflow(*self, *v); + if y { None } else { Some(x) } + } + } +} diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs index e23bdc576d3..dfdd6cf72f7 100644 --- a/src/libstd/num/uint.rs +++ b/src/libstd/num/uint.rs @@ -11,6 +11,9 @@ //! Operations and constants for `uint` use num; +use num::{CheckedAdd, CheckedSub, CheckedMul}; +use option::{Option, Some, None}; +use unstable::intrinsics; use sys; pub use self::generated::*; @@ -101,6 +104,72 @@ pub fn next_power_of_two(n: uint) -> uint { return tmp + 1u; } +#[cfg(target_word_size = "32")] +impl CheckedAdd for uint { + #[inline] + fn checked_add(&self, v: &uint) -> Option { + unsafe { + let (x, y) = intrinsics::u32_add_with_overflow(*self as u32, *v as u32); + if y { None } else { Some(x as uint) } + } + } +} + +#[cfg(target_word_size = "64")] +impl CheckedAdd for uint { + #[inline] + fn checked_add(&self, v: &uint) -> Option { + unsafe { + let (x, y) = intrinsics::u64_add_with_overflow(*self as u64, *v as u64); + if y { None } else { Some(x as uint) } + } + } +} + +#[cfg(target_word_size = "32")] +impl CheckedSub for uint { + #[inline] + fn checked_sub(&self, v: &uint) -> Option { + unsafe { + let (x, y) = intrinsics::u32_sub_with_overflow(*self as u32, *v as u32); + if y { None } else { Some(x as uint) } + } + } +} + +#[cfg(target_word_size = "64")] +impl CheckedSub for uint { + #[inline] + fn checked_sub(&self, v: &uint) -> Option { + unsafe { + let (x, y) = intrinsics::u64_sub_with_overflow(*self as u64, *v as u64); + if y { None } else { Some(x as uint) } + } + } +} + +#[cfg(target_word_size = "32")] +impl CheckedMul for uint { + #[inline] + fn checked_mul(&self, v: &uint) -> Option { + unsafe { + let (x, y) = intrinsics::u32_mul_with_overflow(*self as u32, *v as u32); + if y { None } else { Some(x as uint) } + } + } +} + +#[cfg(target_word_size = "64")] +impl CheckedMul for uint { + #[inline] + fn checked_mul(&self, v: &uint) -> Option { + unsafe { + let (x, y) = intrinsics::u64_mul_with_overflow(*self as u64, *v as u64); + if y { None } else { Some(x as uint) } + } + } +} + #[test] fn test_next_power_of_two() { assert!((next_power_of_two(0u) == 0u));