use std::{num, ops};
pub trait BitOps: num::Int {
#[inline(always)]
fn b_and_not(self, rhs: Self) -> Self {
!self & rhs
}
#[inline(always)]
fn b_get_block_from(self, start: usize, len: usize) -> Self {
(self >> start) & ((Self::one() << len) - Self::one())
}
#[inline(always)]
fn b_get_block(self) -> Self {
!self.b_get_singletons()
}
#[inline(always)]
fn b_gather(self, mut mask: Self) -> Self where Self: ops::Neg<Output = Self> {
let mut res = Self::zero();
let mut bin = Self::one ();
while mask != Self::zero() {
if self & mask.i_get () != Self::zero() {
res = res | bin;
}
mask = mask.i_flip();
bin = bin + bin;
}
res
}
#[inline(always)]
fn b_get_border(self) -> Self {
(self ^ (self << 1)) | (self ^ (self >> 1))
}
#[inline(always)]
fn b_get_interior(self) -> Self {
!self.b_get_border()
}
#[inline(always)]
fn b_get_singletons(self) -> Self {
(self ^ (self << 1)) & (self ^ (self >> 1))
}
#[inline(always)]
fn b_get_singletons_xi(self) -> Self {
self.i_get_singletons_xi() | self.o_get_singletons_xi()
}
#[inline(always)]
fn b_scatter(self, mut mask: Self) -> Self where Self: ops::Neg<Output = Self> {
let mut res = Self::zero();
let mut bin = Self::one ();
while mask != Self::zero() {
if self & bin != Self::zero() {
res = res | mask.i_get ();
}
mask = mask.i_flip();
bin = bin + bin;
}
res
}
#[inline(always)]
fn b_zero_high_from_pos(self, index: usize) -> Self {
self & ((Self::one() << index) - Self::one())
}
#[inline(always)]
fn i_count_total(self) -> u32 {
self.count_ones()
}
#[inline(always)]
fn i_fill_upto(self) -> Self {
self | self.wrapping_sub(Self::one())
}
#[allow(unsigned_negation)]
#[inline(always)]
fn i_get(self) -> Self where Self: ops::Neg<Output = Self> {
self & -self
}
#[inline(always)]
fn i_get_block(self) -> Self {
self & ((self << 1) | (self >> 1))
}
#[inline(always)]
fn i_get_block_border(self) -> Self {
self & ((self << 1) ^ (self >> 1))
}
#[inline(always)]
fn i_get_block_border_low(self) -> Self {
let shr = self >> 1;
(self & ((self << 1) ^ shr)) & shr
}
#[inline(always)]
fn i_get_block_border_high(self) -> Self {
let shl = self << 1;
(self & (shl ^ (self >> 1))) & shl
}
#[inline(always)]
fn i_get_border(self) -> Self {
self & !((self << 1) & (self >> 1))
}
#[inline(always)]
fn i_get_border_high(self) -> Self {
self & (self ^ (self >> 1))
}
#[inline(always)]
fn i_get_border_low(self) -> Self {
self & (self ^ (self << 1))
}
#[inline(always)]
fn i_get_interior(self) -> Self {
self & ((self << 1) & (self >> 1))
}
#[inline(always)]
fn i_get_invert(self) -> Self {
!self | self.wrapping_sub(Self::one())
}
#[inline(always)]
fn i_get_singletons(self) -> Self {
self & !((self << 1) | (self >> 1))
}
#[inline(always)]
fn i_get_singletons_xi(self) -> Self {
self.i_get_singletons()
}
#[inline(always)]
fn i_mask_upto_invert(self) -> Self {
!self | (self + Self::one())
}
#[inline(always)]
fn i_mask_upto(self) -> Self {
self ^ self.wrapping_sub(Self::one())
}
#[inline(always)]
fn i_flip(self) -> Self {
self & self.wrapping_sub(Self::one())
}
#[inline(always)]
fn o_count_leading(self) -> u32 {
self.leading_zeros()
}
#[inline(always)]
fn o_count_total(self) -> u32 {
self.count_zeros()
}
#[inline(always)]
fn o_count_trailing(self) -> u32 {
self.trailing_zeros()
}
#[inline(always)]
fn o_flip(self) -> Self {
self | (self + Self::one())
}
#[inline(always)]
fn o_fill_upto(self) -> Self {
self & (self + Self::one())
}
#[inline(always)]
fn o_get(self) -> Self {
self | !(self + Self::one())
}
#[inline(always)]
fn o_get_invert(self) -> Self {
!self & (self + Self::one())
}
#[inline(always)]
fn o_get_singletons(self) -> Self {
!self & ((self << 1) & (self >> 1))
}
#[inline(always)]
fn o_get_singletons_xi(self) -> Self {
(!self).i_get_singletons()
}
#[inline(always)]
fn o_mask_upto(self) -> Self {
self ^ (self + Self::one())
}
#[inline(always)]
fn o_mask_upto_invert(self) -> Self {
!self & self.wrapping_sub(Self::one())
}
}
impl<T: num::Int> BitOps for T {}