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.
This commit is contained in:
Felix S. Klock II 2015-02-19 12:32:27 +01:00
parent 280dea743b
commit 6d6038a194
2 changed files with 148 additions and 0 deletions

View File

@ -69,6 +69,7 @@
#![feature(unboxed_closures)]
#![feature(rustc_attrs)]
#![feature(optin_builtin_traits)]
#![feature(concat_idents)]
#[macro_use]
mod macros;

View File

@ -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)
}
}
}