Skip to content

Commit c146ff5

Browse files
authored
Rollup merge of rust-lang#88780 - orlp:int-abs-diff, r=m-ou-se
Added abs_diff for integer types. Closes rust-lang#62111.
2 parents d87f3f3 + 6dd6e7c commit c146ff5

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

library/core/src/num/int_macros.rs

+40
Original file line numberDiff line numberDiff line change
@@ -2235,6 +2235,46 @@ macro_rules! int_impl {
22352235
}
22362236
}
22372237

2238+
/// Computes the absolute difference between `self` and `other`.
2239+
///
2240+
/// This function always returns the correct answer without overflow or
2241+
/// panics by returning an unsigned integer.
2242+
///
2243+
/// # Examples
2244+
///
2245+
/// Basic usage:
2246+
///
2247+
/// ```
2248+
/// #![feature(int_abs_diff)]
2249+
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(80), 20", stringify!($UnsignedT), ");")]
2250+
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(110), 10", stringify!($UnsignedT), ");")]
2251+
#[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").abs_diff(80), 180", stringify!($UnsignedT), ");")]
2252+
#[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").abs_diff(-120), 20", stringify!($UnsignedT), ");")]
2253+
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.abs_diff(", stringify!($SelfT), "::MAX), ", stringify!($UnsignedT), "::MAX);")]
2254+
/// ```
2255+
#[unstable(feature = "int_abs_diff", issue = "89492")]
2256+
#[inline]
2257+
pub const fn abs_diff(self, other: Self) -> $UnsignedT {
2258+
if self < other {
2259+
// Converting a non-negative x from signed to unsigned by using
2260+
// `x as U` is left unchanged, but a negative x is converted
2261+
// to value x + 2^N. Thus if `s` and `o` are binary variables
2262+
// respectively indicating whether `self` and `other` are
2263+
// negative, we are computing the mathematical value:
2264+
//
2265+
// (other + o*2^N) - (self + s*2^N) mod 2^N
2266+
// other - self + (o-s)*2^N mod 2^N
2267+
// other - self mod 2^N
2268+
//
2269+
// Finally, taking the mod 2^N of the mathematical value of
2270+
// `other - self` does not change it as it already is
2271+
// in the range [0, 2^N).
2272+
(other as $UnsignedT).wrapping_sub(self as $UnsignedT)
2273+
} else {
2274+
(self as $UnsignedT).wrapping_sub(other as $UnsignedT)
2275+
}
2276+
}
2277+
22382278
/// Returns a number representing sign of `self`.
22392279
///
22402280
/// - `0` if the number is zero

library/core/src/num/uint_macros.rs

+27
Original file line numberDiff line numberDiff line change
@@ -1490,6 +1490,33 @@ macro_rules! uint_impl {
14901490
(c, b | d)
14911491
}
14921492

1493+
/// Computes the absolute difference between `self` and `other`.
1494+
///
1495+
/// # Examples
1496+
///
1497+
/// Basic usage:
1498+
///
1499+
/// ```
1500+
/// #![feature(int_abs_diff)]
1501+
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(80), 20", stringify!($SelfT), ");")]
1502+
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(110), 10", stringify!($SelfT), ");")]
1503+
/// ```
1504+
#[unstable(feature = "int_abs_diff", issue = "89492")]
1505+
#[inline]
1506+
pub const fn abs_diff(self, other: Self) -> Self {
1507+
if mem::size_of::<Self>() == 1 {
1508+
// Trick LLVM into generating the psadbw instruction when SSE2
1509+
// is available and this function is autovectorized for u8's.
1510+
(self as i32).wrapping_sub(other as i32).abs() as Self
1511+
} else {
1512+
if self < other {
1513+
other - self
1514+
} else {
1515+
self - other
1516+
}
1517+
}
1518+
}
1519+
14931520
/// Calculates the multiplication of `self` and `rhs`.
14941521
///
14951522
/// Returns a tuple of the multiplication along with a boolean

0 commit comments

Comments
 (0)