diff options
| author | Scott McMurray <scottmcm@users.noreply.github.com> | 2021-01-16 19:27:51 -0800 |
|---|---|---|
| committer | Scott McMurray <scottmcm@users.noreply.github.com> | 2021-01-16 19:27:51 -0800 |
| commit | 3e16e9211ef7eff4d421f384140e729df1120372 (patch) | |
| tree | a74213915efb1c110b7fde4f96b70c13978e49d3 | |
| parent | 6c869d34ae2d87d21db9892d4dc088639bcbe041 (diff) | |
| download | rust-3e16e9211ef7eff4d421f384140e729df1120372.tar.gz rust-3e16e9211ef7eff4d421f384140e729df1120372.zip | |
Add NonZeroUn::is_power_of_two
This saves instructions on both new and old machines.
| -rw-r--r-- | library/core/src/num/nonzero.rs | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index ba8918b192f..111feb7dbec 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -286,3 +286,43 @@ nonzero_integers_div! { NonZeroU128(u128); NonZeroUsize(usize); } + +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: + /// + /// ``` + /// #![feature(nonzero_is_power_of_two)] + /// + #[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()); + /// ``` + #[unstable(feature = "nonzero_is_power_of_two", issue = "81106")] + #[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 } |
