std: Move overflowing ops to inherent methods

This commit migrates all of the methods on `num::wrapping::OverflowingOps` onto
inherent methods of the integer types. This also fills out some missing gaps in
the saturating and checked departments such as:

* `saturating_mul`
* `checked_{neg,rem,shl,shr}`

This is done in preparation for stabilization,

cc #27755
This commit is contained in:
Alex Crichton 2015-12-18 10:24:06 -08:00
parent dedaebd5a1
commit 7eb7699593

View File

@ -124,7 +124,7 @@ macro_rules! checked_op {
// `Int` + `SignedInt` implemented for signed integers
macro_rules! int_impl {
($ActualT:ty, $UnsignedT:ty, $BITS:expr,
($ActualT:ident, $UnsignedT:ty, $BITS:expr,
$add_with_overflow:path,
$sub_with_overflow:path,
$mul_with_overflow:path) => {
@ -393,7 +393,8 @@ macro_rules! int_impl {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn checked_add(self, other: Self) -> Option<Self> {
checked_op!($ActualT, $add_with_overflow, self, other)
let (a, b) = self.overflowing_add(other);
if b {None} else {Some(a)}
}
/// Checked integer subtraction. Computes `self - other`, returning
@ -410,7 +411,8 @@ macro_rules! int_impl {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn checked_sub(self, other: Self) -> Option<Self> {
checked_op!($ActualT, $sub_with_overflow, self, other)
let (a, b) = self.overflowing_sub(other);
if b {None} else {Some(a)}
}
/// Checked integer multiplication. Computes `self * other`, returning
@ -427,7 +429,8 @@ macro_rules! int_impl {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn checked_mul(self, other: Self) -> Option<Self> {
checked_op!($ActualT, $mul_with_overflow, self, other)
let (a, b) = self.overflowing_mul(other);
if b {None} else {Some(a)}
}
/// Checked integer division. Computes `self / other`, returning `None`
@ -445,14 +448,103 @@ macro_rules! int_impl {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn checked_div(self, other: Self) -> Option<Self> {
match other {
0 => None,
-1 if self == Self::min_value()
=> None,
other => Some(self / other),
if other == 0 {
None
} else {
let (a, b) = self.overflowing_div(other);
if b {None} else {Some(a)}
}
}
/// Checked integer remainder. Computes `self % other`, returning `None`
/// if `other == 0` or the operation results in underflow or overflow.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping)]
///
/// use std::i32;
///
/// assert_eq!(5i32.checked_rem(2), Some(1));
/// assert_eq!(5i32.checked_rem(0), None);
/// assert_eq!(i32::MIN.checked_rem(-1), None);
/// ```
#[unstable(feature = "wrapping", issue = "27755")]
#[inline]
pub fn checked_rem(self, other: Self) -> Option<Self> {
if other == 0 {
None
} else {
let (a, b) = self.overflowing_rem(other);
if b {None} else {Some(a)}
}
}
/// Checked negation. Computes `!self`, returning `None` if `self ==
/// MIN`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping)]
///
/// use std::i32;
///
/// assert_eq!(5i32.checked_neg(), Some(-5));
/// assert_eq!(i32::MIN.checked_neg(), None);
/// ```
#[unstable(feature = "wrapping", issue = "27755")]
#[inline]
pub fn checked_neg(self) -> Option<Self> {
let (a, b) = self.overflowing_neg();
if b {None} else {Some(a)}
}
/// Checked shift left. Computes `self << rhs`, returning `None`
/// if `rhs` is larger than or equal to the number of bits in `self`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping)]
///
/// assert_eq!(0x10i32.checked_shl(4), Some(0x100));
/// assert_eq!(0x10i32.checked_shl(33), None);
/// ```
#[unstable(feature = "wrapping", issue = "27755")]
#[inline]
pub fn checked_shl(self, rhs: u32) -> Option<Self> {
let (a, b) = self.overflowing_shl(rhs);
if b {None} else {Some(a)}
}
/// Checked shift right. Computes `self >> rhs`, returning `None`
/// if `rhs` is larger than or equal to the number of bits in `self`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping)]
///
/// assert_eq!(0x10i32.checked_shr(4), Some(0x1));
/// assert_eq!(0x10i32.checked_shr(33), None);
/// ```
#[unstable(feature = "wrapping", issue = "27755")]
#[inline]
pub fn checked_shr(self, rhs: u32) -> Option<Self> {
let (a, b) = self.overflowing_shr(rhs);
if b {None} else {Some(a)}
}
/// Saturating integer addition. Computes `self + other`, saturating at
/// the numeric bounds instead of overflowing.
///
@ -468,7 +560,7 @@ macro_rules! int_impl {
#[inline]
pub fn saturating_add(self, other: Self) -> Self {
match self.checked_add(other) {
Some(x) => x,
Some(x) => x,
None if other >= Self::zero() => Self::max_value(),
None => Self::min_value(),
}
@ -489,12 +581,40 @@ macro_rules! int_impl {
#[inline]
pub fn saturating_sub(self, other: Self) -> Self {
match self.checked_sub(other) {
Some(x) => x,
Some(x) => x,
None if other >= Self::zero() => Self::min_value(),
None => Self::max_value(),
}
}
/// Saturating integer multiplication. Computes `self * other`,
/// saturating at the numeric bounds instead of overflowing.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping)]
///
/// use std::i32;
///
/// assert_eq!(100i32.saturating_mul(127), 12700);
/// assert_eq!((1i32 << 23).saturating_mul(1 << 23), i32::MAX);
/// assert_eq!((-1i32 << 23).saturating_mul(1 << 23), i32::MIN);
/// ```
#[unstable(feature = "wrapping", issue = "27755")]
#[inline]
pub fn saturating_mul(self, other: Self) -> Self {
self.checked_mul(other).unwrap_or_else(|| {
if (self < 0 && other < 0) || (self > 0 && other > 0) {
Self::max_value()
} else {
Self::min_value()
}
})
}
/// Wrapping (modular) addition. Computes `self + other`,
/// wrapping around at the boundary of the type.
///
@ -562,6 +682,10 @@ macro_rules! int_impl {
/// in the type. In such a case, this function returns `MIN`
/// itself.
///
/// # Panics
///
/// This function will panic if `rhs` is 0.
///
/// # Examples
///
/// Basic usage:
@ -584,6 +708,10 @@ macro_rules! int_impl {
/// -1` on a signed type (where `MIN` is the negative
/// minimal value). In such a case, this function returns `0`.
///
/// # Panics
///
/// This function will panic if `rhs` is 0.
///
/// # Examples
///
/// Basic usage:
@ -657,6 +785,230 @@ macro_rules! int_impl {
self.overflowing_shr(rhs).0
}
/// Calculates `self` + `rhs`
///
/// Returns a tuple of the addition along with a boolean indicating
/// whether an arithmetic overflow would occur. If an overflow would
/// have occurred then the wrapped value is returned.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(wrapping)]
///
/// use std::i32;
///
/// assert_eq!(5i32.overflowing_add(2), (7, false));
/// assert_eq!(i32::MAX.overflowing_add(1), (i32::MIN, true));
/// ```
#[inline]
#[unstable(feature = "wrapping", issue = "27755")]
pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
unsafe {
let (a, b) = $add_with_overflow(self as $ActualT,
rhs as $ActualT);
(a as Self, b)
}
}
/// Calculates `self` - `rhs`
///
/// Returns a tuple of the subtraction along with a boolean indicating
/// whether an arithmetic overflow would occur. If an overflow would
/// have occurred then the wrapped value is returned.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(wrapping)]
///
/// use std::i32;
///
/// assert_eq!(5i32.overflowing_sub(2), (3, false));
/// assert_eq!(i32::MIN.overflowing_sub(1), (i32::MAX, true));
/// ```
#[inline]
#[unstable(feature = "wrapping", issue = "27755")]
pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
unsafe {
let (a, b) = $sub_with_overflow(self as $ActualT,
rhs as $ActualT);
(a as Self, b)
}
}
/// Calculates the multiplication of `self` and `rhs`.
///
/// Returns a tuple of the multiplication along with a boolean
/// indicating whether an arithmetic overflow would occur. If an
/// overflow would have occurred then the wrapped value is returned.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(wrapping)]
///
/// assert_eq!(5i32.overflowing_mul(2), (10, false));
/// assert_eq!(1_000_000_000i32.overflowing_mul(10), (1410065408, true));
/// ```
#[inline]
#[unstable(feature = "wrapping", issue = "27755")]
pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
unsafe {
let (a, b) = $mul_with_overflow(self as $ActualT,
rhs as $ActualT);
(a as Self, b)
}
}
/// Calculates the divisor when `self` is divided by `rhs`.
///
/// Returns a tuple of the divisor along with a boolean indicating
/// whether an arithmetic overflow would occur. If an overflow would
/// occur then self is returned.
///
/// # Panics
///
/// This function will panic if `rhs` is 0.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(wrapping)]
///
/// use std::i32;
///
/// assert_eq!(5i32.overflowing_div(2), (2, false));
/// assert_eq!(i32::MIN.overflowing_div(-1), (i32::MIN, true));
/// ```
#[inline]
#[unstable(feature = "wrapping", issue = "27755")]
pub fn overflowing_div(self, rhs: Self) -> (Self, bool) {
if self == Self::min_value() && rhs == -1 {
(self, true)
} else {
(self / rhs, false)
}
}
/// Calculates the remainder when `self` is divided by `rhs`.
///
/// Returns a tuple of the remainder after dividing along with a boolean
/// indicating whether an arithmetic overflow would occur. If an
/// overflow would occur then 0 is returned.
///
/// # Panics
///
/// This function will panic if `rhs` is 0.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(wrapping)]
///
/// use std::i32;
///
/// assert_eq!(5i32.overflowing_rem(2), (1, false));
/// assert_eq!(i32::MIN.overflowing_rem(-1), (0, true));
/// ```
#[inline]
#[unstable(feature = "wrapping", issue = "27755")]
pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
if self == Self::min_value() && rhs == -1 {
(0, true)
} else {
(self % rhs, false)
}
}
/// Negates self, overflowing if this is equal to the minimum value.
///
/// Returns a tuple of the negated version of self along with a boolean
/// indicating whether an overflow happened. If `self` is the minimum
/// value (e.g. `i32::MIN` for values of type `i32`), then the minimum
/// value will be returned again and `true` will be returned for an
/// overflow happening.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(wrapping)]
///
/// use std::i32;
///
/// assert_eq!(2i32.overflowing_neg(), (-2, false));
/// assert_eq!(i32::MIN.overflowing_neg(), (i32::MIN, true));
/// ```
#[inline]
#[unstable(feature = "wrapping", issue = "27755")]
pub fn overflowing_neg(self) -> (Self, bool) {
if self == Self::min_value() {
(Self::min_value(), true)
} else {
(-self, false)
}
}
/// Shifts self left by `rhs` bits.
///
/// Returns a tuple of the shifted version of self along with a boolean
/// indicating whether the shift value was larger than or equal to the
/// number of bits. If the shift value is too large, then value is
/// masked (N-1) where N is the number of bits, and this value is then
/// used to perform the shift.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(wrapping)]
///
/// assert_eq!(0x10i32.overflowing_shl(4), (0x100, false));
/// assert_eq!(0x10i32.overflowing_shl(36), (0x100, true));
/// ```
#[inline]
#[unstable(feature = "wrapping", issue = "27755")]
pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
(self << (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
}
/// Shifts self right by `rhs` bits.
///
/// Returns a tuple of the shifted version of self along with a boolean
/// indicating whether the shift value was larger than or equal to the
/// number of bits. If the shift value is too large, then value is
/// masked (N-1) where N is the number of bits, and this value is then
/// used to perform the shift.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(wrapping)]
///
/// assert_eq!(0x10i32.overflowing_shr(4), (0x1, false));
/// assert_eq!(0x10i32.overflowing_shr(36), (0x1, true));
/// ```
#[inline]
#[unstable(feature = "wrapping", issue = "27755")]
pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
(self >> (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
}
/// Raises self to the power of `exp`, using exponentiation by squaring.
///
/// # Examples
@ -1121,7 +1473,8 @@ macro_rules! uint_impl {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn checked_add(self, other: Self) -> Option<Self> {
checked_op!($ActualT, $add_with_overflow, self, other)
let (a, b) = self.overflowing_add(other);
if b {None} else {Some(a)}
}
/// Checked integer subtraction. Computes `self - other`, returning
@ -1138,7 +1491,8 @@ macro_rules! uint_impl {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn checked_sub(self, other: Self) -> Option<Self> {
checked_op!($ActualT, $sub_with_overflow, self, other)
let (a, b) = self.overflowing_sub(other);
if b {None} else {Some(a)}
}
/// Checked integer multiplication. Computes `self * other`, returning
@ -1155,7 +1509,8 @@ macro_rules! uint_impl {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn checked_mul(self, other: Self) -> Option<Self> {
checked_op!($ActualT, $mul_with_overflow, self, other)
let (a, b) = self.overflowing_mul(other);
if b {None} else {Some(a)}
}
/// Checked integer division. Computes `self / other`, returning `None`
@ -1179,6 +1534,69 @@ macro_rules! uint_impl {
}
}
/// Checked integer remainder. Computes `self % other`, returning `None`
/// if `other == 0` or the operation results in underflow or overflow.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping)]
///
/// assert_eq!(5u32.checked_rem(2), Some(1));
/// assert_eq!(5u32.checked_rem(0), None);
/// ```
#[unstable(feature = "wrapping", issue = "27755")]
#[inline]
pub fn checked_rem(self, other: Self) -> Option<Self> {
if other == 0 {
None
} else {
Some(self % other)
}
}
/// Checked shift left. Computes `self << rhs`, returning `None`
/// if `rhs` is larger than or equal to the number of bits in `self`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping)]
///
/// assert_eq!(0x10u32.checked_shl(4), Some(0x100));
/// assert_eq!(0x10u32.checked_shl(33), None);
/// ```
#[unstable(feature = "wrapping", issue = "27755")]
#[inline]
pub fn checked_shl(self, rhs: u32) -> Option<Self> {
let (a, b) = self.overflowing_shl(rhs);
if b {None} else {Some(a)}
}
/// Checked shift right. Computes `self >> rhs`, returning `None`
/// if `rhs` is larger than or equal to the number of bits in `self`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping)]
///
/// assert_eq!(0x10u32.checked_shr(4), Some(0x1));
/// assert_eq!(0x10u32.checked_shr(33), None);
/// ```
#[unstable(feature = "wrapping", issue = "27755")]
#[inline]
pub fn checked_shr(self, rhs: u32) -> Option<Self> {
let (a, b) = self.overflowing_shr(rhs);
if b {None} else {Some(a)}
}
/// Saturating integer addition. Computes `self + other`, saturating at
/// the numeric bounds instead of overflowing.
///
@ -1221,6 +1639,27 @@ macro_rules! uint_impl {
}
}
/// Saturating integer multiplication. Computes `self * other`,
/// saturating at the numeric bounds instead of overflowing.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(wrapping)]
///
/// use std::u32;
///
/// assert_eq!(100u32.saturating_mul(127), 12700);
/// assert_eq!((1u32 << 23).saturating_mul(1 << 23), u32::MAX);
/// ```
#[unstable(feature = "wrapping", issue = "27755")]
#[inline]
pub fn saturating_mul(self, other: Self) -> Self {
self.checked_mul(other).unwrap_or(Self::max_value())
}
/// Wrapping (modular) addition. Computes `self + other`,
/// wrapping around at the boundary of the type.
///
@ -1383,6 +1822,211 @@ macro_rules! uint_impl {
self.overflowing_shr(rhs).0
}
/// Calculates `self` + `rhs`
///
/// Returns a tuple of the addition along with a boolean indicating
/// whether an arithmetic overflow would occur. If an overflow would
/// have occurred then the wrapped value is returned.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(wrapping)]
///
/// use std::u32;
///
/// assert_eq!(5u32.overflowing_add(2), (7, false));
/// assert_eq!(u32::MAX.overflowing_add(1), (0, true));
/// ```
#[inline]
#[unstable(feature = "wrapping", issue = "27755")]
pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
unsafe {
let (a, b) = $add_with_overflow(self as $ActualT,
rhs as $ActualT);
(a as Self, b)
}
}
/// Calculates `self` - `rhs`
///
/// Returns a tuple of the subtraction along with a boolean indicating
/// whether an arithmetic overflow would occur. If an overflow would
/// have occurred then the wrapped value is returned.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(wrapping)]
///
/// use std::u32;
///
/// assert_eq!(5u32.overflowing_sub(2), (3, false));
/// assert_eq!(0u32.overflowing_sub(1), (u32::MAX, true));
/// ```
#[inline]
#[unstable(feature = "wrapping", issue = "27755")]
pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
unsafe {
let (a, b) = $sub_with_overflow(self as $ActualT,
rhs as $ActualT);
(a as Self, b)
}
}
/// Calculates the multiplication of `self` and `rhs`.
///
/// Returns a tuple of the multiplication along with a boolean
/// indicating whether an arithmetic overflow would occur. If an
/// overflow would have occurred then the wrapped value is returned.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(wrapping)]
///
/// assert_eq!(5u32.overflowing_mul(2), (10, false));
/// assert_eq!(1_000_000_000u32.overflowing_mul(10), (1410065408, true));
/// ```
#[inline]
#[unstable(feature = "wrapping", issue = "27755")]
pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
unsafe {
let (a, b) = $mul_with_overflow(self as $ActualT,
rhs as $ActualT);
(a as Self, b)
}
}
/// Calculates the divisor when `self` is divided by `rhs`.
///
/// Returns a tuple of the divisor along with a boolean indicating
/// whether an arithmetic overflow would occur. Note that for unsigned
/// integers overflow never occurs, so the second value is always
/// `false`.
///
/// # Panics
///
/// This function will panic if `rhs` is 0.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(wrapping)]
///
/// assert_eq!(5u32.overflowing_div(2), (2, false));
/// ```
#[inline]
#[unstable(feature = "wrapping", issue = "27755")]
pub fn overflowing_div(self, rhs: Self) -> (Self, bool) {
(self / rhs, false)
}
/// Calculates the remainder when `self` is divided by `rhs`.
///
/// Returns a tuple of the remainder after dividing along with a boolean
/// indicating whether an arithmetic overflow would occur. Note that for
/// unsigned integers overflow never occurs, so the second value is
/// always `false`.
///
/// # Panics
///
/// This function will panic if `rhs` is 0.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(wrapping)]
///
/// assert_eq!(5u32.overflowing_rem(2), (1, false));
/// ```
#[inline]
#[unstable(feature = "wrapping", issue = "27755")]
pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
(self % rhs, false)
}
/// Negates self in an overflowing fashion.
///
/// Returns `!self + 1` using wrapping operations to return the value
/// that represents the negation of this unsigned value. Note that for
/// positive unsigned values overflow always occurs, but negating 0 does
/// not overflow.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(wrapping)]
///
/// assert_eq!(0u32.overflowing_neg(), (0, false));
/// assert_eq!(2u32.overflowing_neg(), (-2i32 as u32, true));
/// ```
#[inline]
#[unstable(feature = "wrapping", issue = "27755")]
pub fn overflowing_neg(self) -> (Self, bool) {
((!self).wrapping_add(1), self != 0)
}
/// Shifts self left by `rhs` bits.
///
/// Returns a tuple of the shifted version of self along with a boolean
/// indicating whether the shift value was larger than or equal to the
/// number of bits. If the shift value is too large, then value is
/// masked (N-1) where N is the number of bits, and this value is then
/// used to perform the shift.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(wrapping)]
///
/// assert_eq!(0x10u32.overflowing_shl(4), (0x100, false));
/// assert_eq!(0x10u32.overflowing_shl(36), (0x100, true));
/// ```
#[inline]
#[unstable(feature = "wrapping", issue = "27755")]
pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
(self << (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
}
/// Shifts self right by `rhs` bits.
///
/// Returns a tuple of the shifted version of self along with a boolean
/// indicating whether the shift value was larger than or equal to the
/// number of bits. If the shift value is too large, then value is
/// masked (N-1) where N is the number of bits, and this value is then
/// used to perform the shift.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(wrapping)]
///
/// assert_eq!(0x10u32.overflowing_shr(4), (0x1, false));
/// assert_eq!(0x10u32.overflowing_shr(36), (0x1, true));
/// ```
#[inline]
#[unstable(feature = "wrapping", issue = "27755")]
pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
(self >> (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
}
/// Raises self to the power of `exp`, using exponentiation by squaring.
///
/// # Examples