]> git.lizzy.rs Git - rust.git/blobdiff - src/libcore/num/mod.rs
Rollup merge of #64386 - tspiteri:const-abs2, r=oli-obk
[rust.git] / src / libcore / num / mod.rs
index df1c00ccd184f17e7c4cdf9004b8eff68ad95ef9..6658e3f779235df8036b6dfd5009264f3cbeac46 100644 (file)
@@ -1112,11 +1112,11 @@ pub fn saturating_pow(self, exp: u32) -> Self {
                           without modifying the original"]
             #[inline]
             pub const fn wrapping_add(self, rhs: Self) -> Self {
-                #[cfg(boostrap_stdarch_ignore_this)] {
+                #[cfg(bootstrap)] {
                     intrinsics::overflowing_add(self, rhs)
                 }
 
-                #[cfg(not(boostrap_stdarch_ignore_this))] {
+                #[cfg(not(bootstrap))] {
                     intrinsics::wrapping_add(self, rhs)
                 }
             }
@@ -1141,11 +1141,11 @@ pub const fn wrapping_add(self, rhs: Self) -> Self {
                           without modifying the original"]
             #[inline]
             pub const fn wrapping_sub(self, rhs: Self) -> Self {
-                #[cfg(boostrap_stdarch_ignore_this)] {
+                #[cfg(bootstrap)] {
                     intrinsics::overflowing_sub(self, rhs)
                 }
 
-                #[cfg(not(boostrap_stdarch_ignore_this))] {
+                #[cfg(not(bootstrap))] {
                     intrinsics::wrapping_sub(self, rhs)
                 }
             }
@@ -1169,11 +1169,11 @@ pub const fn wrapping_sub(self, rhs: Self) -> Self {
                           without modifying the original"]
             #[inline]
             pub const fn wrapping_mul(self, rhs: Self) -> Self {
-                #[cfg(boostrap_stdarch_ignore_this)] {
+                #[cfg(bootstrap)] {
                     intrinsics::overflowing_mul(self, rhs)
                 }
 
-                #[cfg(not(boostrap_stdarch_ignore_this))] {
+                #[cfg(not(bootstrap))] {
                     intrinsics::wrapping_mul(self, rhs)
                 }
             }
@@ -1402,7 +1402,16 @@ pub const fn wrapping_shr(self, rhs: u32) -> Self {
             #[stable(feature = "no_panic_abs", since = "1.13.0")]
             #[inline]
             pub const fn wrapping_abs(self) -> Self {
-                (self ^ (self >> ($BITS - 1))).wrapping_sub(self >> ($BITS - 1))
+                // sign is -1 (all ones) for negative numbers, 0 otherwise.
+                let sign = self >> ($BITS - 1);
+                // For positive self, sign == 0 so the expression is simply
+                // (self ^ 0).wrapping_sub(0) == self == abs(self).
+                //
+                // For negative self, self ^ sign == self ^ all_ones.
+                // But all_ones ^ self == all_ones - self == -1 - self.
+                // So for negative numbers, (self ^ sign).wrapping_sub(sign) is
+                // (-1 - self).wrapping_sub(-1) == -self == abs(self).
+                (self ^ sign).wrapping_sub(sign)
             }
         }
 
@@ -1761,7 +1770,7 @@ pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
             #[stable(feature = "no_panic_abs", since = "1.13.0")]
             #[inline]
             pub const fn overflowing_abs(self) -> (Self, bool) {
-                (self ^ (self >> ($BITS - 1))).overflowing_sub(self >> ($BITS - 1))
+                (self.wrapping_abs(), self == Self::min_value())
             }
         }
 
@@ -1969,7 +1978,21 @@ pub const fn abs(self) -> Self {
                 // Note that the #[inline] above means that the overflow
                 // semantics of the subtraction depend on the crate we're being
                 // inlined into.
-                (self ^ (self >> ($BITS - 1))) - (self >> ($BITS - 1))
+
+                // sign is -1 (all ones) for negative numbers, 0 otherwise.
+                let sign = self >> ($BITS - 1);
+                // For positive self, sign == 0 so the expression is simply
+                // (self ^ 0) - 0 == self == abs(self).
+                //
+                // For negative self, self ^ sign == self ^ all_ones.
+                // But all_ones ^ self == all_ones - self == -1 - self.
+                // So for negative numbers, (self ^ sign) - sign is
+                // (-1 - self) - -1 == -self == abs(self).
+                //
+                // The subtraction overflows when self is min_value(), because
+                // (-1 - min_value()) - -1 is max_value() - -1 which overflows.
+                // This is exactly when we want self.abs() to overflow.
+                (self ^ sign) - sign
             }
         }
 
@@ -2092,11 +2115,14 @@ pub const fn is_negative(self) -> bool { self < 0 }
 
 ```
 let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes();
-assert_eq!(bytes, if cfg!(target_endian = \"big\") {
+assert_eq!(
+    bytes,
+    if cfg!(target_endian = \"big\") {
         ", $be_bytes, "
     } else {
         ", $le_bytes, "
-    });
+    }
+);
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
             #[rustc_const_unstable(feature = "const_int_conversion")]
@@ -2188,10 +2214,10 @@ fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
 
 ```
 let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") {
-        ", $be_bytes, "
-    } else {
-        ", $le_bytes, "
-    });
+    ", $be_bytes, "
+} else {
+    ", $le_bytes, "
+});
 assert_eq!(value, ", $swap_op, ");
 ```
 
@@ -3037,11 +3063,11 @@ pub fn saturating_pow(self, exp: u32) -> Self {
                           without modifying the original"]
             #[inline]
             pub const fn wrapping_add(self, rhs: Self) -> Self {
-                #[cfg(boostrap_stdarch_ignore_this)] {
+                #[cfg(bootstrap)] {
                     intrinsics::overflowing_add(self, rhs)
                 }
 
-                #[cfg(not(boostrap_stdarch_ignore_this))] {
+                #[cfg(not(bootstrap))] {
                     intrinsics::wrapping_add(self, rhs)
                 }
             }
@@ -3065,11 +3091,11 @@ pub const fn wrapping_add(self, rhs: Self) -> Self {
                           without modifying the original"]
             #[inline]
             pub const fn wrapping_sub(self, rhs: Self) -> Self {
-                #[cfg(boostrap_stdarch_ignore_this)] {
+                #[cfg(bootstrap)] {
                     intrinsics::overflowing_sub(self, rhs)
                 }
 
-                #[cfg(not(boostrap_stdarch_ignore_this))] {
+                #[cfg(not(bootstrap))] {
                     intrinsics::wrapping_sub(self, rhs)
                 }
             }
@@ -3094,11 +3120,11 @@ pub const fn wrapping_sub(self, rhs: Self) -> Self {
                           without modifying the original"]
         #[inline]
         pub const fn wrapping_mul(self, rhs: Self) -> Self {
-            #[cfg(boostrap_stdarch_ignore_this)] {
+            #[cfg(bootstrap)] {
                 intrinsics::overflowing_mul(self, rhs)
             }
 
-            #[cfg(not(boostrap_stdarch_ignore_this))] {
+            #[cfg(not(bootstrap))] {
                 intrinsics::wrapping_mul(self, rhs)
             }
         }
@@ -3911,11 +3937,14 @@ pub fn wrapping_next_power_of_two(self) -> Self {
 
 ```
 let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes();
-assert_eq!(bytes, if cfg!(target_endian = \"big\") {
+assert_eq!(
+    bytes,
+    if cfg!(target_endian = \"big\") {
         ", $be_bytes, "
     } else {
         ", $le_bytes, "
-    });
+    }
+);
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
             #[rustc_const_unstable(feature = "const_int_conversion")]
@@ -4007,10 +4036,10 @@ fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
 
 ```
 let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") {
-        ", $be_bytes, "
-    } else {
-        ", $le_bytes, "
-    });
+    ", $be_bytes, "
+} else {
+    ", $le_bytes, "
+});
 assert_eq!(value, ", $swap_op, ");
 ```