Rollup merge of #102342 - jmillikin:nonzero-negation, r=scottmcm
Add negation methods for signed non-zero integers. Performing negation with defined wrapping semantics (such as `wrapping_neg()`) on a non-zero integer currently requires unpacking to a primitive and re-wrapping. Since negation of non-zero signed integers always produces a non-zero result, it is safe to implement the various `*_neg()` methods for `NonZeroI{N}`. I'm not sure what to do about the `#[unstable(..., issue = "none")]` here -- should I file a tracking issue, or is that handled by the Rust dev team? ACP: https://github.com/rust-lang/libs-team/issues/105
This commit is contained in:
commit
609152aa8a
@ -721,6 +721,160 @@ macro_rules! nonzero_signed_operations {
|
|||||||
// SAFETY: absolute value of nonzero cannot yield zero values.
|
// SAFETY: absolute value of nonzero cannot yield zero values.
|
||||||
unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) }
|
unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if `self` is negative and `false` if the
|
||||||
|
/// number is positive.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(nonzero_negation_ops)]
|
||||||
|
///
|
||||||
|
#[doc = concat!("# use std::num::", stringify!($Ty), ";")]
|
||||||
|
/// # fn main() { test().unwrap(); }
|
||||||
|
/// # fn test() -> Option<()> {
|
||||||
|
#[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
|
||||||
|
#[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
|
||||||
|
///
|
||||||
|
/// assert!(neg_five.is_negative());
|
||||||
|
/// assert!(!pos_five.is_negative());
|
||||||
|
/// # Some(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "nonzero_negation_ops", issue = "102443")]
|
||||||
|
pub const fn is_negative(self) -> bool {
|
||||||
|
self.get().is_negative()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checked negation. Computes `-self`, returning `None` if `self == i32::MIN`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(nonzero_negation_ops)]
|
||||||
|
///
|
||||||
|
#[doc = concat!("# use std::num::", stringify!($Ty), ";")]
|
||||||
|
/// # fn main() { test().unwrap(); }
|
||||||
|
/// # fn test() -> Option<()> {
|
||||||
|
#[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
|
||||||
|
#[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
|
||||||
|
#[doc = concat!("let min = ", stringify!($Ty), "::new(",
|
||||||
|
stringify!($Int), "::MIN)?;")]
|
||||||
|
///
|
||||||
|
/// assert_eq!(pos_five.checked_neg(), Some(neg_five));
|
||||||
|
/// assert_eq!(min.checked_neg(), None);
|
||||||
|
/// # Some(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "nonzero_negation_ops", issue = "102443")]
|
||||||
|
pub const fn checked_neg(self) -> Option<$Ty> {
|
||||||
|
if let Some(result) = self.get().checked_neg() {
|
||||||
|
// SAFETY: negation of nonzero cannot yield zero values.
|
||||||
|
return Some(unsafe { $Ty::new_unchecked(result) });
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Negates self, overflowing if this is equal to the minimum value.
|
||||||
|
///
|
||||||
|
#[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")]
|
||||||
|
/// for documentation on overflow behaviour.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(nonzero_negation_ops)]
|
||||||
|
///
|
||||||
|
#[doc = concat!("# use std::num::", stringify!($Ty), ";")]
|
||||||
|
/// # fn main() { test().unwrap(); }
|
||||||
|
/// # fn test() -> Option<()> {
|
||||||
|
#[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
|
||||||
|
#[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
|
||||||
|
#[doc = concat!("let min = ", stringify!($Ty), "::new(",
|
||||||
|
stringify!($Int), "::MIN)?;")]
|
||||||
|
///
|
||||||
|
/// assert_eq!(pos_five.overflowing_neg(), (neg_five, false));
|
||||||
|
/// assert_eq!(min.overflowing_neg(), (min, true));
|
||||||
|
/// # Some(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "nonzero_negation_ops", issue = "102443")]
|
||||||
|
pub const fn overflowing_neg(self) -> ($Ty, bool) {
|
||||||
|
let (result, overflow) = self.get().overflowing_neg();
|
||||||
|
// SAFETY: negation of nonzero cannot yield zero values.
|
||||||
|
((unsafe { $Ty::new_unchecked(result) }), overflow)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Saturating negation. Computes `-self`, returning `MAX` if
|
||||||
|
/// `self == i32::MIN` instead of overflowing.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(nonzero_negation_ops)]
|
||||||
|
///
|
||||||
|
#[doc = concat!("# use std::num::", stringify!($Ty), ";")]
|
||||||
|
/// # fn main() { test().unwrap(); }
|
||||||
|
/// # fn test() -> Option<()> {
|
||||||
|
#[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
|
||||||
|
#[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
|
||||||
|
#[doc = concat!("let min = ", stringify!($Ty), "::new(",
|
||||||
|
stringify!($Int), "::MIN)?;")]
|
||||||
|
#[doc = concat!("let min_plus_one = ", stringify!($Ty), "::new(",
|
||||||
|
stringify!($Int), "::MIN + 1)?;")]
|
||||||
|
#[doc = concat!("let max = ", stringify!($Ty), "::new(",
|
||||||
|
stringify!($Int), "::MAX)?;")]
|
||||||
|
///
|
||||||
|
/// assert_eq!(pos_five.saturating_neg(), neg_five);
|
||||||
|
/// assert_eq!(min.saturating_neg(), max);
|
||||||
|
/// assert_eq!(max.saturating_neg(), min_plus_one);
|
||||||
|
/// # Some(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "nonzero_negation_ops", issue = "102443")]
|
||||||
|
pub const fn saturating_neg(self) -> $Ty {
|
||||||
|
if let Some(result) = self.checked_neg() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
$Ty::MAX
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary
|
||||||
|
/// of the type.
|
||||||
|
///
|
||||||
|
#[doc = concat!("See [`", stringify!($Int), "::wrapping_neg`]")]
|
||||||
|
/// for documentation on overflow behaviour.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(nonzero_negation_ops)]
|
||||||
|
///
|
||||||
|
#[doc = concat!("# use std::num::", stringify!($Ty), ";")]
|
||||||
|
/// # fn main() { test().unwrap(); }
|
||||||
|
/// # fn test() -> Option<()> {
|
||||||
|
#[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
|
||||||
|
#[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
|
||||||
|
#[doc = concat!("let min = ", stringify!($Ty), "::new(",
|
||||||
|
stringify!($Int), "::MIN)?;")]
|
||||||
|
///
|
||||||
|
/// assert_eq!(pos_five.wrapping_neg(), neg_five);
|
||||||
|
/// assert_eq!(min.wrapping_neg(), min);
|
||||||
|
/// # Some(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "nonzero_negation_ops", issue = "102443")]
|
||||||
|
pub const fn wrapping_neg(self) -> $Ty {
|
||||||
|
let result = self.get().wrapping_neg();
|
||||||
|
// SAFETY: negation of nonzero cannot yield zero values.
|
||||||
|
unsafe { $Ty::new_unchecked(result) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user