diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index c9693a22e87..0c34012ab5c 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -750,6 +750,34 @@ pub const fn midpoint(self, rhs: Self) -> Self { // never being 0. unsafe { $Ty::new_unchecked(self.get().midpoint(rhs.get())) } } + + /// Returns `true` if and only if `self == (1 << k)` for some `k`. + /// + /// On many architectures, this function can perform better than `is_power_of_two()` + /// on the underlying integer type, as special handling of zero can be avoided. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")] + /// assert!(eight.is_power_of_two()); + #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")] + /// assert!(!ten.is_power_of_two()); + /// ``` + #[must_use] + #[stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] + #[rustc_const_stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] + #[inline] + pub const fn is_power_of_two(self) -> bool { + // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here. + // On the basic x86-64 target, this saves 3 instructions for the zero check. + // On x86_64 with BMI1, being nonzero lets it codegen to `BLSR`, which saves an instruction + // compared to the `POPCNT` implementation on the underlying integer type. + + intrinsics::ctpop(self.get()) < 2 + } }; // Methods for signed nonzero types only. @@ -1149,46 +1177,6 @@ macro_rules! sign_dependent_expr { }; } -macro_rules! nonzero_unsigned_is_power_of_two { - ( $( $Ty: ident )+ ) => { - $( - impl $Ty { - - /// Returns `true` if and only if `self == (1 << k)` for some `k`. - /// - /// On many architectures, this function can perform better than `is_power_of_two()` - /// on the underlying integer type, as special handling of zero can be avoided. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - #[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")] - /// assert!(eight.is_power_of_two()); - #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")] - /// assert!(!ten.is_power_of_two()); - /// ``` - #[must_use] - #[stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] - #[rustc_const_stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] - #[inline] - pub const fn is_power_of_two(self) -> bool { - // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here. - // On the basic x86-64 target, this saves 3 instructions for the zero check. - // On x86_64 with BMI1, being nonzero lets it codegen to `BLSR`, which saves an instruction - // compared to the `POPCNT` implementation on the underlying integer type. - - intrinsics::ctpop(self.get()) < 2 - } - - } - )+ - } -} - -nonzero_unsigned_is_power_of_two! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize } - macro_rules! nonzero_min_max_unsigned { ( $( $Ty: ident($Int: ident); )+ ) => { $(