about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/num/wrapping.rs147
2 files changed, 148 insertions, 0 deletions
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 7cc963bed35..94d37cee5b3 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -69,6 +69,7 @@
 #![feature(unboxed_closures)]
 #![feature(rustc_attrs)]
 #![feature(optin_builtin_traits)]
+#![feature(concat_idents)]
 
 #[macro_use]
 mod macros;
diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs
index 30478a8f09f..707e41a948b 100644
--- a/src/libcore/num/wrapping.rs
+++ b/src/libcore/num/wrapping.rs
@@ -14,12 +14,32 @@ use ops::*;
 #[cfg(not(stage0))]
 use intrinsics::{overflowing_add, overflowing_sub, overflowing_mul};
 
+use intrinsics::{i8_add_with_overflow, u8_add_with_overflow};
+use intrinsics::{i16_add_with_overflow, u16_add_with_overflow};
+use intrinsics::{i32_add_with_overflow, u32_add_with_overflow};
+use intrinsics::{i64_add_with_overflow, u64_add_with_overflow};
+use intrinsics::{i8_sub_with_overflow, u8_sub_with_overflow};
+use intrinsics::{i16_sub_with_overflow, u16_sub_with_overflow};
+use intrinsics::{i32_sub_with_overflow, u32_sub_with_overflow};
+use intrinsics::{i64_sub_with_overflow, u64_sub_with_overflow};
+use intrinsics::{i8_mul_with_overflow, u8_mul_with_overflow};
+use intrinsics::{i16_mul_with_overflow, u16_mul_with_overflow};
+use intrinsics::{i32_mul_with_overflow, u32_mul_with_overflow};
+use intrinsics::{i64_mul_with_overflow, u64_mul_with_overflow};
+
 pub trait WrappingOps {
     fn wrapping_add(self, rhs: Self) -> Self;
     fn wrapping_sub(self, rhs: Self) -> Self;
     fn wrapping_mul(self, rhs: Self) -> Self;
 }
 
+#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
+pub trait OverflowingOps {
+    fn overflowing_add(self, rhs: Self) -> (Self, bool);
+    fn overflowing_sub(self, rhs: Self) -> (Self, bool);
+    fn overflowing_mul(self, rhs: Self) -> (Self, bool);
+}
+
 #[cfg(not(stage0))]
 macro_rules! wrapping_impl {
     ($($t:ty)*) => ($(
@@ -151,3 +171,130 @@ impl<T:WrappingOps+Shr<uint,Output=T>> Shr<uint> for Wrapping<T> {
         Wrapping(self.0 >> other)
     }
 }
+
+macro_rules! overflowing_impl {
+    ($($t:ident)*) => ($(
+        impl OverflowingOps for $t {
+            #[inline(always)]
+            fn overflowing_add(self, rhs: $t) -> ($t, bool) {
+                unsafe {
+                    concat_idents!($t, _add_with_overflow)(self, rhs)
+                }
+            }
+            #[inline(always)]
+            fn overflowing_sub(self, rhs: $t) -> ($t, bool) {
+                unsafe {
+                    concat_idents!($t, _sub_with_overflow)(self, rhs)
+                }
+            }
+            #[inline(always)]
+            fn overflowing_mul(self, rhs: $t) -> ($t, bool) {
+                unsafe {
+                    concat_idents!($t, _mul_with_overflow)(self, rhs)
+                }
+            }
+        }
+    )*)
+}
+
+overflowing_impl! { u8 u16 u32 u64 i8 i16 i32 i64 }
+
+#[cfg(target_pointer_width = "64")]
+impl OverflowingOps for usize {
+    #[inline(always)]
+    fn overflowing_add(self, rhs: usize) -> (usize, bool) {
+        unsafe {
+            let res = u64_add_with_overflow(self as u64, rhs as u64);
+            (res.0 as usize, res.1)
+        }
+    }
+    #[inline(always)]
+    fn overflowing_sub(self, rhs: usize) -> (usize, bool) {
+        unsafe {
+            let res = u64_sub_with_overflow(self as u64, rhs as u64);
+            (res.0 as usize, res.1)
+        }
+    }
+    #[inline(always)]
+    fn overflowing_mul(self, rhs: usize) -> (usize, bool) {
+        unsafe {
+            let res = u64_mul_with_overflow(self as u64, rhs as u64);
+            (res.0 as usize, res.1)
+        }
+    }
+}
+
+#[cfg(target_pointer_width = "32")]
+impl OverflowingOps for usize {
+    #[inline(always)]
+    fn overflowing_add(self, rhs: usize) -> (usize, bool) {
+        unsafe {
+            let res = u32_add_with_overflow(self as u32, rhs as u32);
+            (res.0 as usize, res.1)
+        }
+    }
+    #[inline(always)]
+    fn overflowing_sub(self, rhs: usize) -> (usize, bool) {
+        unsafe {
+            let res = u32_sub_with_overflow(self as u32, rhs as u32);
+            (res.0 as usize, res.1)
+        }
+    }
+    #[inline(always)]
+    fn overflowing_mul(self, rhs: usize) -> (usize, bool) {
+        unsafe {
+            let res = u32_mul_with_overflow(self as u32, rhs as u32);
+            (res.0 as usize, res.1)
+        }
+    }
+}
+
+#[cfg(target_pointer_width = "64")]
+impl OverflowingOps for isize {
+    #[inline(always)]
+    fn overflowing_add(self, rhs: isize) -> (isize, bool) {
+        unsafe {
+            let res = i64_add_with_overflow(self as i64, rhs as i64);
+            (res.0 as isize, res.1)
+        }
+    }
+    #[inline(always)]
+    fn overflowing_sub(self, rhs: isize) -> (isize, bool) {
+        unsafe {
+            let res = i64_sub_with_overflow(self as i64, rhs as i64);
+            (res.0 as isize, res.1)
+        }
+    }
+    #[inline(always)]
+    fn overflowing_mul(self, rhs: isize) -> (isize, bool) {
+        unsafe {
+            let res = i64_mul_with_overflow(self as i64, rhs as i64);
+            (res.0 as isize, res.1)
+        }
+    }
+}
+
+#[cfg(target_pointer_width = "32")]
+impl OverflowingOps for isize {
+    #[inline(always)]
+    fn overflowing_add(self, rhs: isize) -> (isize, bool) {
+        unsafe {
+            let res = i32_add_with_overflow(self as i32, rhs as i32);
+            (res.0 as isize, res.1)
+        }
+    }
+    #[inline(always)]
+    fn overflowing_sub(self, rhs: isize) -> (isize, bool) {
+        unsafe {
+            let res = i32_sub_with_overflow(self as i32, rhs as i32);
+            (res.0 as isize, res.1)
+        }
+    }
+    #[inline(always)]
+    fn overflowing_mul(self, rhs: isize) -> (isize, bool) {
+        unsafe {
+            let res = i32_mul_with_overflow(self as i32, rhs as i32);
+            (res.0 as isize, res.1)
+        }
+    }
+}