Checked ops.

This commit is contained in:
Tomasz Drwięga 2018-01-28 17:03:47 +01:00
parent 9e23e8f4a3
commit ea29612eaa
1 changed files with 55 additions and 1 deletions

View File

@ -815,6 +815,14 @@ macro_rules! construct_uint {
} }
} }
/// Checked addition. Returns `None` if overflow occurred.
pub fn checked_add(self, other: $name) -> Option<$name> {
match self.overflowing_add(other) {
(_, true) => None,
(val, _) => Some(val),
}
}
/// Subtraction which underflows and returns a flag if it does. /// Subtraction which underflows and returns a flag if it does.
#[inline(always)] #[inline(always)]
pub fn overflowing_sub(self, other: $name) -> ($name, bool) { pub fn overflowing_sub(self, other: $name) -> ($name, bool) {
@ -829,6 +837,14 @@ macro_rules! construct_uint {
} }
} }
/// Checked subtraction. Returns `None` if overflow occurred.
pub fn checked_sub(self, other: $name) -> Option<$name> {
match self.overflowing_sub(other) {
(_, true) => None,
(val, _) => Some(val),
}
}
/// Multiply with overflow, returning a flag if it does. /// Multiply with overflow, returning a flag if it does.
#[inline(always)] #[inline(always)]
pub fn overflowing_mul(self, other: $name) -> ($name, bool) { pub fn overflowing_mul(self, other: $name) -> ($name, bool) {
@ -843,21 +859,59 @@ macro_rules! construct_uint {
} }
} }
/// Checked multiplication. Returns `None` if overflow occurred.
pub fn checked_mul(self, other: $name) -> Option<$name> {
match self.overflowing_mul(other) {
(_, true) => None,
(val, _) => Some(val),
}
}
/// Division with overflow /// Division with overflow
pub fn overflowing_div(self, other: $name) -> ($name, bool) { pub fn overflowing_div(self, other: $name) -> ($name, bool) {
(self / other, false) (self / other, false)
} }
/// Checked division. Returns `None` if `other == 0`.
pub fn checked_div(self, other: $name) -> Option<$name> {
if other.is_zero() {
None
} else {
Some(self / other)
}
}
/// Modulus with overflow. /// Modulus with overflow.
pub fn overflowing_rem(self, other: $name) -> ($name, bool) { pub fn overflowing_rem(self, other: $name) -> ($name, bool) {
(self % other, false) (self % other, false)
} }
/// Checked modulus. Returns `None` if `other == 0`.
pub fn checked_rem(self, other: $name) -> Option<$name> {
if other.is_zero() {
None
} else {
Some(self % other)
}
}
/// Negation with overflow. /// Negation with overflow.
pub fn overflowing_neg(self) -> ($name, bool) { pub fn overflowing_neg(self) -> ($name, bool) {
(!self, true) if self.is_zero() {
(self, false)
} else {
(!self, true)
}
} }
/// Checked negation. Returns `None` unless `self == 0`.
pub fn checked_neg(self) -> Option<$name> {
match self.overflowing_neg() {
(_, true) => None,
(zero, false) => Some(zero),
}
}
/// Multiplication by u32 /// Multiplication by u32
pub fn mul_u32(self, other: u32) -> Self { pub fn mul_u32(self, other: u32) -> Self {
let (ret, overflow) = self.overflowing_mul_u32(other); let (ret, overflow) = self.overflowing_mul_u32(other);