use crate::set::Positions;
use crate::word::Word;
pub trait Bits: Word {
#[must_use]
fn run_starts(self, k: u32) -> Self {
if k == 0 {
return Self::ONES;
}
if k > Self::BITS {
return Self::ZERO;
}
let mut x = self;
let mut n = k;
while n > 1 {
let s = n >> 1;
x = x.and(x.shr(s));
n -= s;
}
x
}
#[inline]
#[must_use]
fn has_run(self, k: u32) -> bool {
!self.run_starts(k).is_zero()
}
#[must_use]
fn longest_run(self) -> u32 {
let (mut lo, mut hi) = (0, Self::BITS);
while lo < hi {
let mid = lo + (hi - lo).div_ceil(2);
if self.has_run(mid) {
lo = mid;
} else {
hi = mid - 1;
}
}
lo
}
#[inline]
#[must_use]
fn rank(self, i: u32) -> u32 {
self.and(Self::low_ones(i)).count_ones()
}
#[inline]
#[must_use]
fn select(self, k: u32) -> Option<u32> {
if k >= self.count_ones() {
None
} else {
Some(self.select_lowest(k))
}
}
#[inline]
#[must_use]
fn first_set(self) -> Option<u32> {
if self.is_zero() {
None
} else {
Some(self.trailing_zeros())
}
}
#[inline]
#[must_use]
fn last_set(self) -> Option<u32> {
if self.is_zero() {
None
} else {
Some(Self::BITS - 1 - self.leading_zeros())
}
}
#[inline]
fn positions(self) -> Positions<Self> {
Positions(self)
}
#[inline]
#[must_use]
fn prefix_or(self) -> Self {
self.or(Self::ZERO.wrapping_sub(self))
}
#[inline]
#[must_use]
fn prefix_xor(self) -> Self {
self.xor_scan()
}
#[inline]
#[must_use]
fn delta_xor(self) -> Self {
self.xor(self.shl(1))
}
#[inline]
#[must_use]
fn gray_encode(self) -> Self {
self.xor(self.shr(1))
}
#[inline]
#[must_use]
fn gray_decode(self) -> Self {
let mut x = self;
let mut s = 1;
while s < Self::BITS {
x = x.xor(x.shr(s));
s <<= 1;
}
x
}
#[must_use]
fn find_escaped(self, prev_ends_odd: bool) -> (Self, bool) {
let even = Self::splat_byte(0x55);
let odd = even.not();
let flip = if prev_ends_odd { Self::ONE } else { Self::ZERO };
let start_edges = self.and(self.shl(1).not());
let even_start_mask = even.xor(flip);
let even_starts = start_edges.and(even_start_mask);
let odd_starts = start_edges.and(even_start_mask.not());
let even_carries = self.wrapping_add(even_starts);
let odd_carries = self.wrapping_add(odd_starts).or(flip);
let overflow = self
.and(odd_starts)
.or(self.or(odd_starts).and(odd_carries.not()));
let carry = overflow.bit(Self::BITS - 1);
let even_carry_ends = even_carries.and(self.not());
let odd_carry_ends = odd_carries.and(self.not());
let even_start_odd_end = even_carry_ends.and(odd);
let odd_start_even_end = odd_carry_ends.and(even);
(even_start_odd_end.or(odd_start_even_end), carry)
}
#[inline]
#[must_use]
fn fill_up(self, propagate: Self, stride: u32) -> Self {
if stride == 0 || stride >= Self::BITS {
return self;
}
let mut reach = self;
let mut prop = propagate;
let mut s = stride;
while s < Self::BITS {
reach = reach.or(prop.and(reach.shl(s)));
prop = prop.and(prop.shl(s));
s <<= 1;
}
reach
}
#[inline]
#[must_use]
fn fill_down(self, propagate: Self, stride: u32) -> Self {
if stride == 0 || stride >= Self::BITS {
return self;
}
let mut reach = self;
let mut prop = propagate;
let mut s = stride;
while s < Self::BITS {
reach = reach.or(prop.and(reach.shr(s)));
prop = prop.and(prop.shr(s));
s <<= 1;
}
reach
}
#[inline]
#[must_use]
fn compact(self, mask: Self) -> Self {
self.pext(mask)
}
#[inline]
#[must_use]
fn expand(self, mask: Self) -> Self {
self.pdep(mask)
}
#[inline]
#[must_use]
fn lowest_set_mask(self) -> Self {
self.and(Self::ZERO.wrapping_sub(self))
}
#[inline]
#[must_use]
fn below_lowest_set(self) -> Self {
self.not().and(self.wrapping_sub(Self::ONE))
}
#[inline]
#[must_use]
fn up_to_lowest_set(self) -> Self {
self.xor(self.wrapping_sub(Self::ONE))
}
#[inline]
#[must_use]
fn set_lowest_zero(self) -> Self {
self.or(self.wrapping_add(Self::ONE))
}
#[inline]
#[must_use]
fn clear_lowest_run(self) -> Self {
self.or(self.wrapping_sub(Self::ONE))
.wrapping_add(Self::ONE)
.and(self)
}
#[inline]
#[must_use]
fn blend(self, other: Self, mask: Self) -> Self {
self.xor(self.xor(other).and(mask))
}
#[inline]
#[must_use]
fn next_same_popcount(self) -> Option<Self> {
let s = self.lowest_set_mask();
let r = self.wrapping_add(s);
if r.is_zero() {
return None;
}
let ones = self.xor(r).shr(self.trailing_zeros()).shr(2);
Some(r.or(ones))
}
#[inline]
#[must_use]
fn is_pow2(self) -> bool {
!self.is_zero() && self.clear_lowest_set().is_zero()
}
#[inline]
#[must_use]
fn round_down_pow2(self) -> Option<Self> {
self.last_set().map(|p| Self::ONE.shl(p))
}
#[inline]
#[must_use]
fn round_up_pow2(self) -> Option<Self> {
if self.shr(1).is_zero() {
return Some(Self::ONE);
}
let lz = self.wrapping_sub(Self::ONE).leading_zeros();
if lz == 0 {
None
} else {
Some(Self::ONE.shl(Self::BITS - lz))
}
}
#[inline]
#[must_use]
fn log2_floor(self) -> Option<u32> {
self.last_set()
}
#[inline]
#[must_use]
fn log2_ceil(self) -> Option<u32> {
if self.is_zero() {
None
} else {
Some(Self::BITS - self.wrapping_sub(Self::ONE).leading_zeros())
}
}
#[inline]
#[must_use]
fn lanes_lo() -> Self {
Self::splat_byte(0x01)
}
#[inline]
#[must_use]
fn lanes_hi() -> Self {
Self::splat_byte(0x80)
}
#[inline]
#[must_use]
fn zero_bytes(self) -> Self {
let low7 = Self::splat_byte(0x7F);
let y = self.and(low7).wrapping_add(low7).or(self).or(low7);
y.not()
}
#[inline]
#[must_use]
fn has_zero_byte(self) -> bool {
!self.zero_bytes().is_zero()
}
#[inline]
#[must_use]
fn first_zero_byte(self) -> Option<u32> {
let z = self.zero_bytes();
if z.is_zero() {
None
} else {
Some(z.trailing_zeros() / 8)
}
}
#[inline]
#[must_use]
fn bytes_eq(self, b: u8) -> Self {
self.xor(Self::splat_byte(b)).zero_bytes()
}
#[inline]
#[must_use]
fn bytes_ge(self, n: u8) -> Self {
debug_assert!((1..=128).contains(&n), "bytes_ge: n={n} outside 1..=128");
let low7 = Self::splat_byte(0x7F);
self.and(low7)
.wrapping_add(Self::splat_byte(0x80 - n))
.or(self)
.and(Self::lanes_hi())
}
#[inline]
#[must_use]
fn bytes_lt(self, n: u8) -> Self {
self.bytes_ge(n).xor(Self::lanes_hi())
}
#[inline]
#[must_use]
fn count_bytes_eq(self, b: u8) -> u32 {
self.bytes_eq(b).count_ones()
}
#[inline]
#[must_use]
fn sum_bytes(self) -> u32 {
u32::from(
self.wrapping_mul(Self::lanes_lo())
.shr(Self::BITS - 8)
.low_byte(),
)
}
#[inline]
#[must_use]
fn delta_swap(self, mask: Self, shift: u32) -> Self {
debug_assert!(
mask.and(mask.shl(shift)).is_zero() && mask.shl(shift).shr(shift) == mask,
"delta_swap: mask and mask << shift must be disjoint and in range"
);
let t = self.xor(self.shr(shift)).and(mask);
self.xor(t).xor(t.shl(shift))
}
}
impl<W: Word> Bits for W {}