From f846ed53e41a18fbb900e794467351fda5ffbb80 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 21:37:28 -0800 Subject: [PATCH] Move leading_zeros and trailing_zeros methods into nonzero_integer macro --- library/core/src/num/nonzero.rs | 146 ++++++++++++++++---------------- 1 file changed, 75 insertions(+), 71 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 75429d9059a..9c396710fd4 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -26,8 +26,12 @@ macro_rules! nonzero_integer { ( Self = $Ty:ident, Primitive = $signedness:ident $Int:ident, + UnsignedPrimitive = $UnsignedPrimitive:ty, feature = $feature:literal, original_stabilization = $since:literal, + + // Used in doc comments. + leading_zeros_test = $leading_zeros_test:expr, ) => { /// An integer that is known not to equal zero. /// @@ -122,6 +126,53 @@ pub const fn get(self) -> $Int { } self.0 } + + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", stringify!($leading_zeros_test), ").unwrap();")] + /// + /// assert_eq!(n.leading_zeros(), 0); + /// ``` + #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn leading_zeros(self) -> u32 { + // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`. + unsafe { intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive) as u32 } + } + + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();")] + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn trailing_zeros(self) -> u32 { + // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`. + unsafe { intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive) as u32 } + } } #[stable(feature = "from_nonzero", since = "1.31.0")] @@ -206,77 +257,6 @@ fn from_str(src: &str) -> Result { }; } -macro_rules! nonzero_leading_trailing_zeros { - ( $( $Ty: ident($Uint: ty) , $LeadingTestExpr:expr ;)+ ) => { - $( - impl $Ty { - /// Returns the number of leading zeros in the binary representation of `self`. - /// - /// On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", stringify!($LeadingTestExpr), ").unwrap();")] - /// - /// assert_eq!(n.leading_zeros(), 0); - /// ``` - #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] - #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn leading_zeros(self) -> u32 { - // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`. - unsafe { intrinsics::ctlz_nonzero(self.get() as $Uint) as u32 } - } - - /// Returns the number of trailing zeros in the binary representation - /// of `self`. - /// - /// On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();")] - /// - /// assert_eq!(n.trailing_zeros(), 3); - /// ``` - #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] - #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn trailing_zeros(self) -> u32 { - // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`. - unsafe { intrinsics::cttz_nonzero(self.get() as $Uint) as u32 } - } - - } - )+ - } -} - -nonzero_leading_trailing_zeros! { - NonZeroU8(u8), u8::MAX; - NonZeroU16(u16), u16::MAX; - NonZeroU32(u32), u32::MAX; - NonZeroU64(u64), u64::MAX; - NonZeroU128(u128), u128::MAX; - NonZeroUsize(usize), usize::MAX; - NonZeroI8(u8), -1i8; - NonZeroI16(u16), -1i16; - NonZeroI32(u32), -1i32; - NonZeroI64(u64), -1i64; - NonZeroI128(u128), -1i128; - NonZeroIsize(usize), -1isize; -} - macro_rules! nonzero_integer_impl_div_rem { ($Ty:ident signed $Int:ty) => { // nothing for signed ints @@ -1376,83 +1356,107 @@ impl $Ty { nonzero_integer! { Self = NonZeroU8, Primitive = unsigned u8, + UnsignedPrimitive = u8, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = u8::MAX, } nonzero_integer! { Self = NonZeroU16, Primitive = unsigned u16, + UnsignedPrimitive = u16, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = u16::MAX, } nonzero_integer! { Self = NonZeroU32, Primitive = unsigned u32, + UnsignedPrimitive = u32, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = u32::MAX, } nonzero_integer! { Self = NonZeroU64, Primitive = unsigned u64, + UnsignedPrimitive = u64, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = u64::MAX, } nonzero_integer! { Self = NonZeroU128, Primitive = unsigned u128, + UnsignedPrimitive = u128, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = u128::MAX, } nonzero_integer! { Self = NonZeroUsize, Primitive = unsigned usize, + UnsignedPrimitive = usize, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = usize::MAX, } nonzero_integer! { Self = NonZeroI8, Primitive = signed i8, + UnsignedPrimitive = u8, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1i8, } nonzero_integer! { Self = NonZeroI16, Primitive = signed i16, + UnsignedPrimitive = u16, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1i16, } nonzero_integer! { Self = NonZeroI32, Primitive = signed i32, + UnsignedPrimitive = u32, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1i32, } nonzero_integer! { Self = NonZeroI64, Primitive = signed i64, + UnsignedPrimitive = u64, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1i64, } nonzero_integer! { Self = NonZeroI128, Primitive = signed i128, + UnsignedPrimitive = u128, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1i128, } nonzero_integer! { Self = NonZeroIsize, Primitive = signed isize, + UnsignedPrimitive = usize, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1isize, }