mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-04 11:04:03 +00:00
Rollup merge of #88780 - orlp:int-abs-diff, r=m-ou-se
Added abs_diff for integer types. Closes https://github.com/rust-lang/rust/issues/62111.
This commit is contained in:
commit
234fa90878
@ -2235,6 +2235,46 @@ macro_rules! int_impl {
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the absolute difference between `self` and `other`.
|
||||
///
|
||||
/// This function always returns the correct answer without overflow or
|
||||
/// panics by returning an unsigned integer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(int_abs_diff)]
|
||||
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(80), 20", stringify!($UnsignedT), ");")]
|
||||
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(110), 10", stringify!($UnsignedT), ");")]
|
||||
#[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").abs_diff(80), 180", stringify!($UnsignedT), ");")]
|
||||
#[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").abs_diff(-120), 20", stringify!($UnsignedT), ");")]
|
||||
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.abs_diff(", stringify!($SelfT), "::MAX), ", stringify!($UnsignedT), "::MAX);")]
|
||||
/// ```
|
||||
#[unstable(feature = "int_abs_diff", issue = "89492")]
|
||||
#[inline]
|
||||
pub const fn abs_diff(self, other: Self) -> $UnsignedT {
|
||||
if self < other {
|
||||
// Converting a non-negative x from signed to unsigned by using
|
||||
// `x as U` is left unchanged, but a negative x is converted
|
||||
// to value x + 2^N. Thus if `s` and `o` are binary variables
|
||||
// respectively indicating whether `self` and `other` are
|
||||
// negative, we are computing the mathematical value:
|
||||
//
|
||||
// (other + o*2^N) - (self + s*2^N) mod 2^N
|
||||
// other - self + (o-s)*2^N mod 2^N
|
||||
// other - self mod 2^N
|
||||
//
|
||||
// Finally, taking the mod 2^N of the mathematical value of
|
||||
// `other - self` does not change it as it already is
|
||||
// in the range [0, 2^N).
|
||||
(other as $UnsignedT).wrapping_sub(self as $UnsignedT)
|
||||
} else {
|
||||
(self as $UnsignedT).wrapping_sub(other as $UnsignedT)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a number representing sign of `self`.
|
||||
///
|
||||
/// - `0` if the number is zero
|
||||
|
@ -1490,6 +1490,33 @@ macro_rules! uint_impl {
|
||||
(c, b | d)
|
||||
}
|
||||
|
||||
/// Computes the absolute difference between `self` and `other`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(int_abs_diff)]
|
||||
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(80), 20", stringify!($SelfT), ");")]
|
||||
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(110), 10", stringify!($SelfT), ");")]
|
||||
/// ```
|
||||
#[unstable(feature = "int_abs_diff", issue = "89492")]
|
||||
#[inline]
|
||||
pub const fn abs_diff(self, other: Self) -> Self {
|
||||
if mem::size_of::<Self>() == 1 {
|
||||
// Trick LLVM into generating the psadbw instruction when SSE2
|
||||
// is available and this function is autovectorized for u8's.
|
||||
(self as i32).wrapping_sub(other as i32).abs() as Self
|
||||
} else {
|
||||
if self < other {
|
||||
other - self
|
||||
} else {
|
||||
self - other
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates the multiplication of `self` and `rhs`.
|
||||
///
|
||||
/// Returns a tuple of the multiplication along with a boolean
|
||||
|
Loading…
Reference in New Issue
Block a user