Skip to content

Commit 5846310

Browse files
authored
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: rust-lang/libs-team#105
2 parents 5d5c2cc + 544b8bc commit 5846310

File tree

1 file changed

+154
-0
lines changed

1 file changed

+154
-0
lines changed

core/src/num/nonzero.rs

+154
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,160 @@ macro_rules! nonzero_signed_operations {
721721
// SAFETY: absolute value of nonzero cannot yield zero values.
722722
unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) }
723723
}
724+
725+
/// Returns `true` if `self` is negative and `false` if the
726+
/// number is positive.
727+
///
728+
/// # Example
729+
///
730+
/// ```
731+
/// #![feature(nonzero_negation_ops)]
732+
///
733+
#[doc = concat!("# use std::num::", stringify!($Ty), ";")]
734+
/// # fn main() { test().unwrap(); }
735+
/// # fn test() -> Option<()> {
736+
#[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
737+
#[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
738+
///
739+
/// assert!(neg_five.is_negative());
740+
/// assert!(!pos_five.is_negative());
741+
/// # Some(())
742+
/// # }
743+
/// ```
744+
#[must_use]
745+
#[inline]
746+
#[unstable(feature = "nonzero_negation_ops", issue = "102443")]
747+
pub const fn is_negative(self) -> bool {
748+
self.get().is_negative()
749+
}
750+
751+
/// Checked negation. Computes `-self`, returning `None` if `self == i32::MIN`.
752+
///
753+
/// # Example
754+
///
755+
/// ```
756+
/// #![feature(nonzero_negation_ops)]
757+
///
758+
#[doc = concat!("# use std::num::", stringify!($Ty), ";")]
759+
/// # fn main() { test().unwrap(); }
760+
/// # fn test() -> Option<()> {
761+
#[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
762+
#[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
763+
#[doc = concat!("let min = ", stringify!($Ty), "::new(",
764+
stringify!($Int), "::MIN)?;")]
765+
///
766+
/// assert_eq!(pos_five.checked_neg(), Some(neg_five));
767+
/// assert_eq!(min.checked_neg(), None);
768+
/// # Some(())
769+
/// # }
770+
/// ```
771+
#[inline]
772+
#[unstable(feature = "nonzero_negation_ops", issue = "102443")]
773+
pub const fn checked_neg(self) -> Option<$Ty> {
774+
if let Some(result) = self.get().checked_neg() {
775+
// SAFETY: negation of nonzero cannot yield zero values.
776+
return Some(unsafe { $Ty::new_unchecked(result) });
777+
}
778+
None
779+
}
780+
781+
/// Negates self, overflowing if this is equal to the minimum value.
782+
///
783+
#[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")]
784+
/// for documentation on overflow behaviour.
785+
///
786+
/// # Example
787+
///
788+
/// ```
789+
/// #![feature(nonzero_negation_ops)]
790+
///
791+
#[doc = concat!("# use std::num::", stringify!($Ty), ";")]
792+
/// # fn main() { test().unwrap(); }
793+
/// # fn test() -> Option<()> {
794+
#[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
795+
#[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
796+
#[doc = concat!("let min = ", stringify!($Ty), "::new(",
797+
stringify!($Int), "::MIN)?;")]
798+
///
799+
/// assert_eq!(pos_five.overflowing_neg(), (neg_five, false));
800+
/// assert_eq!(min.overflowing_neg(), (min, true));
801+
/// # Some(())
802+
/// # }
803+
/// ```
804+
#[inline]
805+
#[unstable(feature = "nonzero_negation_ops", issue = "102443")]
806+
pub const fn overflowing_neg(self) -> ($Ty, bool) {
807+
let (result, overflow) = self.get().overflowing_neg();
808+
// SAFETY: negation of nonzero cannot yield zero values.
809+
((unsafe { $Ty::new_unchecked(result) }), overflow)
810+
}
811+
812+
/// Saturating negation. Computes `-self`, returning `MAX` if
813+
/// `self == i32::MIN` instead of overflowing.
814+
///
815+
/// # Example
816+
///
817+
/// ```
818+
/// #![feature(nonzero_negation_ops)]
819+
///
820+
#[doc = concat!("# use std::num::", stringify!($Ty), ";")]
821+
/// # fn main() { test().unwrap(); }
822+
/// # fn test() -> Option<()> {
823+
#[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
824+
#[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
825+
#[doc = concat!("let min = ", stringify!($Ty), "::new(",
826+
stringify!($Int), "::MIN)?;")]
827+
#[doc = concat!("let min_plus_one = ", stringify!($Ty), "::new(",
828+
stringify!($Int), "::MIN + 1)?;")]
829+
#[doc = concat!("let max = ", stringify!($Ty), "::new(",
830+
stringify!($Int), "::MAX)?;")]
831+
///
832+
/// assert_eq!(pos_five.saturating_neg(), neg_five);
833+
/// assert_eq!(min.saturating_neg(), max);
834+
/// assert_eq!(max.saturating_neg(), min_plus_one);
835+
/// # Some(())
836+
/// # }
837+
/// ```
838+
#[inline]
839+
#[unstable(feature = "nonzero_negation_ops", issue = "102443")]
840+
pub const fn saturating_neg(self) -> $Ty {
841+
if let Some(result) = self.checked_neg() {
842+
return result;
843+
}
844+
$Ty::MAX
845+
}
846+
847+
/// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary
848+
/// of the type.
849+
///
850+
#[doc = concat!("See [`", stringify!($Int), "::wrapping_neg`]")]
851+
/// for documentation on overflow behaviour.
852+
///
853+
/// # Example
854+
///
855+
/// ```
856+
/// #![feature(nonzero_negation_ops)]
857+
///
858+
#[doc = concat!("# use std::num::", stringify!($Ty), ";")]
859+
/// # fn main() { test().unwrap(); }
860+
/// # fn test() -> Option<()> {
861+
#[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
862+
#[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
863+
#[doc = concat!("let min = ", stringify!($Ty), "::new(",
864+
stringify!($Int), "::MIN)?;")]
865+
///
866+
/// assert_eq!(pos_five.wrapping_neg(), neg_five);
867+
/// assert_eq!(min.wrapping_neg(), min);
868+
/// # Some(())
869+
/// # }
870+
/// ```
871+
#[inline]
872+
#[unstable(feature = "nonzero_negation_ops", issue = "102443")]
873+
pub const fn wrapping_neg(self) -> $Ty {
874+
let result = self.get().wrapping_neg();
875+
// SAFETY: negation of nonzero cannot yield zero values.
876+
unsafe { $Ty::new_unchecked(result) }
877+
}
724878
}
725879
)+
726880
}

0 commit comments

Comments
 (0)