Skip to content

Commit ae63b9e

Browse files
author
Kamil Niski
committed
Add Overflowing trait
Closes issue #168
1 parent 3973bab commit ae63b9e

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

src/ops/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub mod checked;
22
pub mod inv;
33
pub mod mul_add;
4+
pub mod overflowing;
45
pub mod saturating;
56
pub mod wrapping;

src/ops/overflowing.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use core::ops::{Add, Mul, Sub};
2+
3+
macro_rules! overflowing_impl {
4+
($trait_name:ident, $method:ident, $t:ty) => {
5+
impl $trait_name for $t {
6+
#[inline]
7+
fn $method(&self, v: &Self) -> (Self, bool) {
8+
<$t>::$method(*self, *v)
9+
}
10+
}
11+
};
12+
}
13+
14+
/// If an overflow would have occurred then the wrapped value is returned.
15+
pub trait OverflowingAdd: Sized + Add<Self, Output = Self> {
16+
/// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would occur.
17+
fn overflowing_add(&self, v: &Self) -> (Self, bool);
18+
}
19+
20+
overflowing_impl!(OverflowingAdd, overflowing_add, u8);
21+
overflowing_impl!(OverflowingAdd, overflowing_add, u16);
22+
overflowing_impl!(OverflowingAdd, overflowing_add, u32);
23+
overflowing_impl!(OverflowingAdd, overflowing_add, u64);
24+
overflowing_impl!(OverflowingAdd, overflowing_add, usize);
25+
#[cfg(has_i128)]
26+
overflowing_impl!(OverflowingAdd, overflowing_add, u128);
27+
28+
overflowing_impl!(OverflowingAdd, overflowing_add, i8);
29+
overflowing_impl!(OverflowingAdd, overflowing_add, i16);
30+
overflowing_impl!(OverflowingAdd, overflowing_add, i32);
31+
overflowing_impl!(OverflowingAdd, overflowing_add, i64);
32+
overflowing_impl!(OverflowingAdd, overflowing_add, isize);
33+
#[cfg(has_i128)]
34+
overflowing_impl!(OverflowingAdd, overflowing_add, i128);
35+
36+
/// If an overflow would have occurred then the wrapped value is returned.
37+
pub trait OverflowingSub: Sized + Sub<Self, Output = Self> {
38+
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
39+
fn overflowing_sub(&self, v: &Self) -> (Self, bool);
40+
}
41+
42+
overflowing_impl!(OverflowingSub, overflowing_sub, u8);
43+
overflowing_impl!(OverflowingSub, overflowing_sub, u16);
44+
overflowing_impl!(OverflowingSub, overflowing_sub, u32);
45+
overflowing_impl!(OverflowingSub, overflowing_sub, u64);
46+
overflowing_impl!(OverflowingSub, overflowing_sub, usize);
47+
#[cfg(has_i128)]
48+
overflowing_impl!(OverflowingSub, overflowing_sub, u128);
49+
50+
overflowing_impl!(OverflowingSub, overflowing_sub, i8);
51+
overflowing_impl!(OverflowingSub, overflowing_sub, i16);
52+
overflowing_impl!(OverflowingSub, overflowing_sub, i32);
53+
overflowing_impl!(OverflowingSub, overflowing_sub, i64);
54+
overflowing_impl!(OverflowingSub, overflowing_sub, isize);
55+
#[cfg(has_i128)]
56+
overflowing_impl!(OverflowingSub, overflowing_sub, i128);
57+
58+
/// If an overflow would have occurred then the wrapped value is returned.
59+
pub trait OverflowingMul: Sized + Mul<Self, Output = Self> {
60+
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
61+
fn overflowing_mul(&self, v: &Self) -> (Self, bool);
62+
}
63+
64+
overflowing_impl!(OverflowingMul, overflowing_mul, u8);
65+
overflowing_impl!(OverflowingMul, overflowing_mul, u16);
66+
overflowing_impl!(OverflowingMul, overflowing_mul, u32);
67+
overflowing_impl!(OverflowingMul, overflowing_mul, u64);
68+
overflowing_impl!(OverflowingMul, overflowing_mul, usize);
69+
#[cfg(has_i128)]
70+
overflowing_impl!(OverflowingMul, overflowing_mul, u128);
71+
72+
overflowing_impl!(OverflowingMul, overflowing_mul, i8);
73+
overflowing_impl!(OverflowingMul, overflowing_mul, i16);
74+
overflowing_impl!(OverflowingMul, overflowing_mul, i32);
75+
overflowing_impl!(OverflowingMul, overflowing_mul, i64);
76+
overflowing_impl!(OverflowingMul, overflowing_mul, isize);
77+
#[cfg(has_i128)]
78+
overflowing_impl!(OverflowingMul, overflowing_mul, i128);
79+
80+
#[test]
81+
fn test_overflowing_traits() {
82+
fn overflowing_add<T: OverflowingAdd>(a: T, b: T) -> (T, bool) {
83+
a.overflowing_add(&b)
84+
}
85+
fn overflowing_sub<T: OverflowingSub>(a: T, b: T) -> (T, bool) {
86+
a.overflowing_sub(&b)
87+
}
88+
fn overflowing_mul<T: OverflowingMul>(a: T, b: T) -> (T, bool) {
89+
a.overflowing_mul(&b)
90+
}
91+
assert_eq!(overflowing_add(5i16, 2), (7, false));
92+
assert_eq!(overflowing_add(std::i16::MAX, 1), (std::i16::MIN, true));
93+
assert_eq!(overflowing_sub(5i16, 2), (3, false));
94+
assert_eq!(overflowing_sub(std::i16::MIN, 1), (std::i16::MAX, true));
95+
assert_eq!(overflowing_mul(5i16, 2), (10, false));
96+
assert_eq!(overflowing_mul(1_000_000_000i32, 10), (1410065408, true));
97+
}

0 commit comments

Comments
 (0)