Skip to content

Commit 03d89a1

Browse files
committed
Implement feature isolate_most_least_significant_one for integer types
Implement accepted ACP for functions that isolate the most significant set bit and least significant set bit on unsigned, signed, and NonZero integers. Add function `isolate_most_significant_one` Add function `isolate_least_significant_one`
1 parent ffa9afe commit 03d89a1

File tree

3 files changed

+156
-0
lines changed

3 files changed

+156
-0
lines changed

library/core/src/num/int_macros.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,52 @@ macro_rules! int_impl {
183183
(self as $UnsignedT).trailing_ones()
184184
}
185185

186+
/// Returns `self` with only the most significant bit set, or `0` if
187+
/// the input is `0`.
188+
///
189+
/// # Examples
190+
///
191+
/// Basic usage:
192+
///
193+
/// ```
194+
/// #![feature(isolate_most_least_significant_one)]
195+
///
196+
#[doc = concat!("let n: ", stringify!($SelfT), " = 0b_01100100;")]
197+
///
198+
/// assert_eq!(n.isolate_most_significant_one(), 0b_01000000);
199+
#[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_most_significant_one(), 0);")]
200+
/// ```
201+
#[unstable(feature = "isolate_most_least_significant_one", issue = "136909")]
202+
#[must_use = "this returns the result of the operation, \
203+
without modifying the original"]
204+
#[inline(always)]
205+
pub const fn isolate_most_significant_one(self) -> Self {
206+
self & (((1 as $SelfT) << (<$SelfT>::BITS - 1)).wrapping_shr(self.leading_zeros()))
207+
}
208+
209+
/// Returns `self` with only the least significant bit set, or `0` if
210+
/// the input is `0`.
211+
///
212+
/// # Examples
213+
///
214+
/// Basic usage:
215+
///
216+
/// ```
217+
/// #![feature(isolate_most_least_significant_one)]
218+
///
219+
#[doc = concat!("let n: ", stringify!($SelfT), " = 0b_01100100;")]
220+
///
221+
/// assert_eq!(n.isolate_least_significant_one(), 0b_00000100);
222+
#[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_least_significant_one(), 0);")]
223+
/// ```
224+
#[unstable(feature = "isolate_most_least_significant_one", issue = "136909")]
225+
#[must_use = "this returns the result of the operation, \
226+
without modifying the original"]
227+
#[inline(always)]
228+
pub const fn isolate_least_significant_one(self) -> Self {
229+
self & self.wrapping_neg()
230+
}
231+
186232
/// Returns the bit pattern of `self` reinterpreted as an unsigned integer of the same size.
187233
///
188234
/// This produces the same result as an `as` cast, but ensures that the bit-width remains

library/core/src/num/nonzero.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,70 @@ macro_rules! nonzero_integer {
605605
}
606606
}
607607

608+
/// Returns `self` with only the most significant bit set.
609+
///
610+
/// # Example
611+
///
612+
/// Basic usage:
613+
///
614+
/// ```
615+
/// #![feature(isolate_most_least_significant_one)]
616+
///
617+
/// # use core::num::NonZero;
618+
/// # fn main() { test().unwrap(); }
619+
/// # fn test() -> Option<()> {
620+
#[doc = concat!("let a = NonZero::<", stringify!($Int), ">::new(0b_01100100)?;")]
621+
#[doc = concat!("let b = NonZero::<", stringify!($Int), ">::new(0b_01000000)?;")]
622+
///
623+
/// assert_eq!(a.isolate_most_significant_one(), b);
624+
/// # Some(())
625+
/// # }
626+
/// ```
627+
#[unstable(feature = "isolate_most_least_significant_one", issue = "136909")]
628+
#[must_use = "this returns the result of the operation, \
629+
without modifying the original"]
630+
#[inline(always)]
631+
pub const fn isolate_most_significant_one(self) -> Self {
632+
let n = self.get() & (((1 as $Int) << (<$Int>::BITS - 1)).wrapping_shr(self.leading_zeros()));
633+
634+
// SAFETY:
635+
// `self` is non-zero, so masking to preserve only the most
636+
// significant set bit will result in a non-zero `n`.
637+
unsafe { NonZero::new_unchecked(n) }
638+
}
639+
640+
/// Returns `self` with only the least significant bit set.
641+
///
642+
/// # Example
643+
///
644+
/// Basic usage:
645+
///
646+
/// ```
647+
/// #![feature(isolate_most_least_significant_one)]
648+
///
649+
/// # use core::num::NonZero;
650+
/// # fn main() { test().unwrap(); }
651+
/// # fn test() -> Option<()> {
652+
#[doc = concat!("let a = NonZero::<", stringify!($Int), ">::new(0b_01100100)?;")]
653+
#[doc = concat!("let b = NonZero::<", stringify!($Int), ">::new(0b_00000100)?;")]
654+
///
655+
/// assert_eq!(a.isolate_least_significant_one(), b);
656+
/// # Some(())
657+
/// # }
658+
/// ```
659+
#[unstable(feature = "isolate_most_least_significant_one", issue = "136909")]
660+
#[must_use = "this returns the result of the operation, \
661+
without modifying the original"]
662+
#[inline(always)]
663+
pub const fn isolate_least_significant_one(self) -> Self {
664+
let n = self.get();
665+
let n = n & n.wrapping_neg();
666+
667+
// SAFETY: `self` is non-zero, so `self` with only its least
668+
// significant set bit will remain non-zero.
669+
unsafe { NonZero::new_unchecked(n) }
670+
}
671+
608672
/// Returns the number of ones in the binary representation of `self`.
609673
///
610674
/// # Examples

library/core/src/num/uint_macros.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,52 @@ macro_rules! uint_impl {
213213
(!self).trailing_zeros()
214214
}
215215

216+
/// Returns `self` with only the most significant bit set, or `0` if
217+
/// the input is `0`.
218+
///
219+
/// # Examples
220+
///
221+
/// Basic usage:
222+
///
223+
/// ```
224+
/// #![feature(isolate_most_least_significant_one)]
225+
///
226+
#[doc = concat!("let n: ", stringify!($SelfT), " = 0b_01100100;")]
227+
///
228+
/// assert_eq!(n.isolate_most_significant_one(), 0b_01000000);
229+
#[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_most_significant_one(), 0);")]
230+
/// ```
231+
#[unstable(feature = "isolate_most_least_significant_one", issue = "136909")]
232+
#[must_use = "this returns the result of the operation, \
233+
without modifying the original"]
234+
#[inline(always)]
235+
pub const fn isolate_most_significant_one(self) -> Self {
236+
self & (((1 as $SelfT) << (<$SelfT>::BITS - 1)).wrapping_shr(self.leading_zeros()))
237+
}
238+
239+
/// Returns `self` with only the least significant bit set, or `0` if
240+
/// the input is `0`.
241+
///
242+
/// # Examples
243+
///
244+
/// Basic usage:
245+
///
246+
/// ```
247+
/// #![feature(isolate_most_least_significant_one)]
248+
///
249+
#[doc = concat!("let n: ", stringify!($SelfT), " = 0b_01100100;")]
250+
///
251+
/// assert_eq!(n.isolate_least_significant_one(), 0b_00000100);
252+
#[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_least_significant_one(), 0);")]
253+
/// ```
254+
#[unstable(feature = "isolate_most_least_significant_one", issue = "136909")]
255+
#[must_use = "this returns the result of the operation, \
256+
without modifying the original"]
257+
#[inline(always)]
258+
pub const fn isolate_least_significant_one(self) -> Self {
259+
self & self.wrapping_neg()
260+
}
261+
216262
/// Returns the bit pattern of `self` reinterpreted as a signed integer of the same size.
217263
///
218264
/// This produces the same result as an `as` cast, but ensures that the bit-width remains

0 commit comments

Comments
 (0)