pub trait Bzhi {
fn bzhi(self, bit_position: u32) -> Self;
}
macro_rules! empty {
($_x:ident, $_y:ident, $_i:ident) => {};
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
macro_rules! bzhi_spec {
($x:ident, $y:ident, $intr:ident) => {
#[cfg(feature = "unstable")]
#[cfg(
all(
any(target_arch = "x86", target_arch = "x86_64"),
target_feature = "bmi2"
)
)]
{
return unsafe {
::mem::transmute(::arch::$intr(
::mem::transmute($x),
$y as u32,
))
};
}
};
}
macro_rules! impl_bzhi {
($id:ident, $arch_bzhi:ident, $intr:ident) => {
impl Bzhi for $id {
#[inline]
#[allow(unreachable_code)]
fn bzhi(self, bit_position: u32) -> Self {
debug_assert!(
bit_position < (::mem::size_of::<Self>() * 8) as u32
);
$arch_bzhi!(self, bit_position, $intr);
self & ((1 << bit_position) - 1)
}
}
};
($id:ident) => {
impl_bzhi!($id, empty, empty);
};
}
impl_all!(impl_bzhi: u8, u16, i8, i16);
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
impl_bzhi!(u32, bzhi_spec, _bzhi_u32);
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
impl_bzhi!(i32, bzhi_spec, _bzhi_u32);
#[cfg(target_arch = "x86_64")]
impl_bzhi!(u64, bzhi_spec, _bzhi_u64);
#[cfg(target_arch = "x86_64")]
impl_bzhi!(i64, bzhi_spec, _bzhi_u64);
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
impl_all!(impl_bzhi: u32, i32);
#[cfg(not(target_arch = "x86_64"))]
impl_all!(impl_bzhi: i64, u64);