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` Add tests
This commit is contained in:
parent
ffa9afef18
commit
97bc99a18f
@ -183,6 +183,52 @@ macro_rules! int_impl {
|
||||
(self as $UnsignedT).trailing_ones()
|
||||
}
|
||||
|
||||
/// Returns `self` with only the most significant bit set, or `0` if
|
||||
/// the input is `0`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(isolate_most_least_significant_one)]
|
||||
///
|
||||
#[doc = concat!("let n: ", stringify!($SelfT), " = 0b_01100100;")]
|
||||
///
|
||||
/// assert_eq!(n.isolate_most_significant_one(), 0b_01000000);
|
||||
#[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_most_significant_one(), 0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "isolate_most_least_significant_one", issue = "136909")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
pub const fn isolate_most_significant_one(self) -> Self {
|
||||
self & (((1 as $SelfT) << (<$SelfT>::BITS - 1)).wrapping_shr(self.leading_zeros()))
|
||||
}
|
||||
|
||||
/// Returns `self` with only the least significant bit set, or `0` if
|
||||
/// the input is `0`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(isolate_most_least_significant_one)]
|
||||
///
|
||||
#[doc = concat!("let n: ", stringify!($SelfT), " = 0b_01100100;")]
|
||||
///
|
||||
/// assert_eq!(n.isolate_least_significant_one(), 0b_00000100);
|
||||
#[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_least_significant_one(), 0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "isolate_most_least_significant_one", issue = "136909")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
pub const fn isolate_least_significant_one(self) -> Self {
|
||||
self & self.wrapping_neg()
|
||||
}
|
||||
|
||||
/// Returns the bit pattern of `self` reinterpreted as an unsigned integer of the same size.
|
||||
///
|
||||
/// This produces the same result as an `as` cast, but ensures that the bit-width remains
|
||||
|
@ -605,6 +605,70 @@ macro_rules! nonzero_integer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `self` with only the most significant bit set.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(isolate_most_least_significant_one)]
|
||||
///
|
||||
/// # use core::num::NonZero;
|
||||
/// # fn main() { test().unwrap(); }
|
||||
/// # fn test() -> Option<()> {
|
||||
#[doc = concat!("let a = NonZero::<", stringify!($Int), ">::new(0b_01100100)?;")]
|
||||
#[doc = concat!("let b = NonZero::<", stringify!($Int), ">::new(0b_01000000)?;")]
|
||||
///
|
||||
/// assert_eq!(a.isolate_most_significant_one(), b);
|
||||
/// # Some(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "isolate_most_least_significant_one", issue = "136909")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
pub const fn isolate_most_significant_one(self) -> Self {
|
||||
let n = self.get() & (((1 as $Int) << (<$Int>::BITS - 1)).wrapping_shr(self.leading_zeros()));
|
||||
|
||||
// SAFETY:
|
||||
// `self` is non-zero, so masking to preserve only the most
|
||||
// significant set bit will result in a non-zero `n`.
|
||||
unsafe { NonZero::new_unchecked(n) }
|
||||
}
|
||||
|
||||
/// Returns `self` with only the least significant bit set.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(isolate_most_least_significant_one)]
|
||||
///
|
||||
/// # use core::num::NonZero;
|
||||
/// # fn main() { test().unwrap(); }
|
||||
/// # fn test() -> Option<()> {
|
||||
#[doc = concat!("let a = NonZero::<", stringify!($Int), ">::new(0b_01100100)?;")]
|
||||
#[doc = concat!("let b = NonZero::<", stringify!($Int), ">::new(0b_00000100)?;")]
|
||||
///
|
||||
/// assert_eq!(a.isolate_least_significant_one(), b);
|
||||
/// # Some(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "isolate_most_least_significant_one", issue = "136909")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
pub const fn isolate_least_significant_one(self) -> Self {
|
||||
let n = self.get();
|
||||
let n = n & n.wrapping_neg();
|
||||
|
||||
// SAFETY: `self` is non-zero, so `self` with only its least
|
||||
// significant set bit will remain non-zero.
|
||||
unsafe { NonZero::new_unchecked(n) }
|
||||
}
|
||||
|
||||
/// Returns the number of ones in the binary representation of `self`.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -213,6 +213,52 @@ macro_rules! uint_impl {
|
||||
(!self).trailing_zeros()
|
||||
}
|
||||
|
||||
/// Returns `self` with only the most significant bit set, or `0` if
|
||||
/// the input is `0`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(isolate_most_least_significant_one)]
|
||||
///
|
||||
#[doc = concat!("let n: ", stringify!($SelfT), " = 0b_01100100;")]
|
||||
///
|
||||
/// assert_eq!(n.isolate_most_significant_one(), 0b_01000000);
|
||||
#[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_most_significant_one(), 0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "isolate_most_least_significant_one", issue = "136909")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
pub const fn isolate_most_significant_one(self) -> Self {
|
||||
self & (((1 as $SelfT) << (<$SelfT>::BITS - 1)).wrapping_shr(self.leading_zeros()))
|
||||
}
|
||||
|
||||
/// Returns `self` with only the least significant bit set, or `0` if
|
||||
/// the input is `0`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(isolate_most_least_significant_one)]
|
||||
///
|
||||
#[doc = concat!("let n: ", stringify!($SelfT), " = 0b_01100100;")]
|
||||
///
|
||||
/// assert_eq!(n.isolate_least_significant_one(), 0b_00000100);
|
||||
#[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_least_significant_one(), 0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "isolate_most_least_significant_one", issue = "136909")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
pub const fn isolate_least_significant_one(self) -> Self {
|
||||
self & self.wrapping_neg()
|
||||
}
|
||||
|
||||
/// Returns the bit pattern of `self` reinterpreted as a signed integer of the same size.
|
||||
///
|
||||
/// This produces the same result as an `as` cast, but ensures that the bit-width remains
|
||||
|
@ -43,6 +43,7 @@
|
||||
#![feature(ip)]
|
||||
#![feature(ip_from)]
|
||||
#![feature(is_ascii_octdigit)]
|
||||
#![feature(isolate_most_least_significant_one)]
|
||||
#![feature(iter_advance_by)]
|
||||
#![feature(iter_array_chunks)]
|
||||
#![feature(iter_chain)]
|
||||
|
@ -321,6 +321,106 @@ fn nonzero_trailing_zeros() {
|
||||
assert_eq!(TRAILING_ZEROS, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nonzero_isolate_most_significant_one() {
|
||||
// Signed most significant one
|
||||
macro_rules! nonzero_int_impl {
|
||||
($($T:ty),+) => {
|
||||
$(
|
||||
{
|
||||
const BITS: $T = -1;
|
||||
const MOST_SIG_ONE: $T = 1 << (<$T>::BITS - 1);
|
||||
|
||||
// Right shift the most significant one through each
|
||||
// bit position, starting with all bits set
|
||||
let mut i = 0;
|
||||
while i < <$T>::BITS {
|
||||
assert_eq!(
|
||||
NonZero::<$T>::new(BITS >> i).unwrap().isolate_most_significant_one(),
|
||||
NonZero::<$T>::new(MOST_SIG_ONE >> i).unwrap().isolate_most_significant_one()
|
||||
);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
// Unsigned most significant one
|
||||
macro_rules! nonzero_uint_impl {
|
||||
($($T:ty),+) => {
|
||||
$(
|
||||
{
|
||||
const BITS: $T = <$T>::MAX;
|
||||
const MOST_SIG_ONE: $T = 1 << (<$T>::BITS - 1);
|
||||
|
||||
let mut i = 0;
|
||||
while i < <$T>::BITS {
|
||||
assert_eq!(
|
||||
NonZero::<$T>::new(BITS >> i).unwrap().isolate_most_significant_one(),
|
||||
NonZero::<$T>::new(MOST_SIG_ONE >> i).unwrap().isolate_most_significant_one(),
|
||||
);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
nonzero_int_impl!(i8, i16, i32, i64, i128, isize);
|
||||
nonzero_uint_impl!(u8, u16, u32, u64, u128, usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nonzero_isolate_least_significant_one() {
|
||||
// Signed least significant one
|
||||
macro_rules! nonzero_int_impl {
|
||||
($($T:ty),+) => {
|
||||
$(
|
||||
{
|
||||
const BITS: $T = -1;
|
||||
const LEAST_SIG_ONE: $T = 1;
|
||||
|
||||
// Left shift the least significant one through each
|
||||
// bit position, starting with all bits set
|
||||
let mut i = 0;
|
||||
while i < <$T>::BITS {
|
||||
assert_eq!(
|
||||
NonZero::<$T>::new(BITS << i).unwrap().isolate_least_significant_one(),
|
||||
NonZero::<$T>::new(LEAST_SIG_ONE << i).unwrap().isolate_least_significant_one()
|
||||
);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
// Unsigned least significant one
|
||||
macro_rules! nonzero_uint_impl {
|
||||
($($T:ty),+) => {
|
||||
$(
|
||||
{
|
||||
const BITS: $T = <$T>::MAX;
|
||||
const LEAST_SIG_ONE: $T = 1;
|
||||
|
||||
let mut i = 0;
|
||||
while i < <$T>::BITS {
|
||||
assert_eq!(
|
||||
NonZero::<$T>::new(BITS << i).unwrap().isolate_least_significant_one(),
|
||||
NonZero::<$T>::new(LEAST_SIG_ONE << i).unwrap().isolate_least_significant_one(),
|
||||
);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
nonzero_int_impl!(i8, i16, i32, i64, i128, isize);
|
||||
nonzero_uint_impl!(u8, u16, u32, u64, u128, usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nonzero_uint_div() {
|
||||
let nz = NonZero::new(1).unwrap();
|
||||
|
@ -192,6 +192,40 @@ macro_rules! int_module {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_isolate_most_significant_one() {
|
||||
const BITS: $T = -1;
|
||||
const MOST_SIG_ONE: $T = 1 << (<$T>::BITS - 1);
|
||||
|
||||
// Right shift the most significant one through each
|
||||
// bit position, starting with all bits set
|
||||
let mut i = 0;
|
||||
while i < <$T>::BITS {
|
||||
assert_eq!(
|
||||
(BITS >> i).isolate_most_significant_one(),
|
||||
(MOST_SIG_ONE >> i).isolate_most_significant_one()
|
||||
);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_isolate_least_significant_one() {
|
||||
const BITS: $T = -1;
|
||||
const LEAST_SIG_ONE: $T = 1;
|
||||
|
||||
// Left shift the least significant one through each
|
||||
// bit position, starting with all bits set
|
||||
let mut i = 0;
|
||||
while i < <$T>::BITS {
|
||||
assert_eq!(
|
||||
(BITS << i).isolate_least_significant_one(),
|
||||
(LEAST_SIG_ONE << i).isolate_least_significant_one()
|
||||
);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str() {
|
||||
fn from_str<T: std::str::FromStr>(t: &str) -> Option<T> {
|
||||
|
@ -141,6 +141,40 @@ macro_rules! uint_module {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_isolate_most_significant_one() {
|
||||
const BITS: $T = <$T>::MAX;
|
||||
const MOST_SIG_ONE: $T = 1 << (<$T>::BITS - 1);
|
||||
|
||||
// Right shift the most significant one through each
|
||||
// bit position, starting with all bits set
|
||||
let mut i = 0;
|
||||
while i < <$T>::BITS {
|
||||
assert_eq!(
|
||||
(BITS >> i).isolate_most_significant_one(),
|
||||
(MOST_SIG_ONE >> i).isolate_most_significant_one(),
|
||||
);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_isolate_least_significant_one() {
|
||||
const BITS: $T = <$T>::MAX;
|
||||
const LEAST_SIG_ONE: $T = 1;
|
||||
|
||||
// Left shift the least significant one through each
|
||||
// bit position, starting with all bits set
|
||||
let mut i = 0;
|
||||
while i < <$T>::BITS {
|
||||
assert_eq!(
|
||||
(BITS << i).isolate_least_significant_one(),
|
||||
(LEAST_SIG_ONE << i).isolate_least_significant_one(),
|
||||
);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn from_str<T: core::str::FromStr>(t: &str) -> Option<T> {
|
||||
core::str::FromStr::from_str(t).ok()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user