From 6d6038a1944394fc5e64048aea6fdbad4f59ee15 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 19 Feb 2015 12:32:27 +0100 Subject: [PATCH] Added `OverflowingOps` trait to core::num::wrapping. These return the result of the operation *plus* an overflow/underflow bit. This can make it easier to write operations where you want to chain some arithmetic together, but also want to return a flag signalling if overflow every occurred. --- src/libcore/lib.rs | 1 + src/libcore/num/wrapping.rs | 147 ++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 7cc963bed358..94d37cee5b37 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 30478a8f09f3..707e41a948be 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> Shr for Wrapping { 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) + } + } +}