Skip to content

Commit 562903a

Browse files
committed
use sign variable in abs and wrapping_abs methods
This also makes the code easier to understand by hinting at the significance of `self >> ($BITS - 1)` and by including an explanation in the comments. Also, now overflowing_abs simply uses wrapping_abs, which is clearer and avoids a potential performance regression in the LLVM IR.
1 parent fe6d05a commit 562903a

File tree

1 file changed

+26
-3
lines changed

1 file changed

+26
-3
lines changed

src/libcore/num/mod.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -1402,7 +1402,16 @@ $EndFeature, "
14021402
#[stable(feature = "no_panic_abs", since = "1.13.0")]
14031403
#[inline]
14041404
pub const fn wrapping_abs(self) -> Self {
1405-
(self ^ (self >> ($BITS - 1))).wrapping_sub(self >> ($BITS - 1))
1405+
// sign is -1 (all ones) for negative numbers, 0 otherwise.
1406+
let sign = self >> ($BITS - 1);
1407+
// For positive self, sign == 0 so the expression is simply
1408+
// (self ^ 0).wrapping_sub(0) == self == abs(self).
1409+
//
1410+
// For negative self, self ^ sign == self ^ all_ones.
1411+
// But all_ones ^ self == all_ones - self == -1 - self.
1412+
// So for negative numbers, (self ^ sign).wrapping_sub(sign) is
1413+
// (-1 - self).wrapping_sub(-1) == -self == abs(self).
1414+
(self ^ sign).wrapping_sub(sign)
14061415
}
14071416
}
14081417

@@ -1761,7 +1770,7 @@ $EndFeature, "
17611770
#[stable(feature = "no_panic_abs", since = "1.13.0")]
17621771
#[inline]
17631772
pub const fn overflowing_abs(self) -> (Self, bool) {
1764-
(self ^ (self >> ($BITS - 1))).overflowing_sub(self >> ($BITS - 1))
1773+
(self.wrapping_abs(), self == Self::min_value())
17651774
}
17661775
}
17671776

@@ -1969,7 +1978,21 @@ $EndFeature, "
19691978
// Note that the #[inline] above means that the overflow
19701979
// semantics of the subtraction depend on the crate we're being
19711980
// inlined into.
1972-
(self ^ (self >> ($BITS - 1))) - (self >> ($BITS - 1))
1981+
1982+
// sign is -1 (all ones) for negative numbers, 0 otherwise.
1983+
let sign = self >> ($BITS - 1);
1984+
// For positive self, sign == 0 so the expression is simply
1985+
// (self ^ 0) - 0 == self == abs(self).
1986+
//
1987+
// For negative self, self ^ sign == self ^ all_ones.
1988+
// But all_ones ^ self == all_ones - self == -1 - self.
1989+
// So for negative numbers, (self ^ sign) - sign is
1990+
// (-1 - self) - -1 == -self == abs(self).
1991+
//
1992+
// The subtraction overflows when self is min_value(), because
1993+
// (-1 - min_value()) - -1 is max_value() - -1 which overflows.
1994+
// This is exactly when we want self.abs() to overflow.
1995+
(self ^ sign) - sign
19731996
}
19741997
}
19751998

0 commit comments

Comments
 (0)