use rand::Rng;
use ref_cast::RefCast;
use std::fmt;
pub use std::ops::{BitAndAssign, BitXorAssign, Deref, DerefMut, Index, IndexMut, Range};
pub type BitBlock = u64;
pub const BLOCKSIZE: usize = 64;
pub const MSB_OFF: BitBlock = 0x7fffffffffffffff;
pub const MSB_ON: BitBlock = 0x8000000000000000;
#[inline]
pub fn min_blocks(bits: usize) -> usize {
bits / BLOCKSIZE + if bits % BLOCKSIZE == 0 { 0 } else { 1 }
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct BitVec(Vec<BitBlock>);
#[derive(RefCast, PartialEq, Eq, PartialOrd, Ord, Debug)]
#[repr(transparent)]
pub struct BitSlice([BitBlock]);
pub struct BitIter<'a> {
inner: std::slice::Iter<'a, BitBlock>,
c: usize,
block: BitBlock,
}
impl<'a> Iterator for BitIter<'a> {
type Item = bool;
fn next(&mut self) -> Option<Self::Item> {
if self.c == BLOCKSIZE {
self.block = self.inner.next().copied()?;
self.c = 0;
}
let bit = self.block & MSB_ON == MSB_ON;
self.block = self.block.wrapping_shl(1);
self.c += 1;
Some(bit)
}
}
pub type BitBlockIter<'a> = std::iter::Copied<std::slice::Iter<'a, BitBlock>>;
impl BitSlice {
#[inline]
pub fn to_vec(&self) -> BitVec {
self.0.to_vec().into()
}
#[inline]
pub fn block_iter(&self) -> BitBlockIter<'_> {
self.0.iter().copied()
}
#[inline]
pub fn block_iter_mut(&mut self) -> impl Iterator<Item = &mut BitBlock> {
self.0.iter_mut()
}
#[inline]
pub fn iter(&self) -> BitIter {
BitIter {
inner: self.0.iter(),
c: BLOCKSIZE,
block: 0,
}
}
#[inline]
pub fn count_ones(&self) -> usize {
self.block_iter().fold(0, |c, bits| c + bits.count_ones()) as usize
}
#[inline]
pub fn count_zeros(&self) -> usize {
self.block_iter().fold(0, |c, bits| c + bits.count_zeros()) as usize
}
#[inline]
pub fn dot(&self, rhs: &BitSlice) -> bool {
let mut c = 0;
for (bits0, bits1) in self.0.iter().zip(rhs.0.iter()) {
c ^= (*bits0 & *bits1).count_ones() & 1;
}
c == 1
}
#[inline]
pub fn bit(&self, index: usize) -> bool {
let block_index = index / BLOCKSIZE;
let bit_index = (index % BLOCKSIZE) as u32;
let block = self.0[block_index].rotate_left(bit_index);
block & MSB_ON == MSB_ON
}
#[inline]
pub fn set_bit(&mut self, index: usize, value: bool) {
let block_index = index / BLOCKSIZE;
let bit_index = (index % BLOCKSIZE) as u32;
let mut block = self.0[block_index].rotate_left(bit_index);
if value {
block |= MSB_ON;
} else {
block &= MSB_OFF;
}
self.0[block_index] = block.rotate_right(bit_index);
}
pub fn first_one_in_range(&self, from: usize, to: usize) -> Option<usize> {
for i in from..to {
if self.0[i] != 0 {
return Some((i - from) * BLOCKSIZE + (self.0[i].leading_zeros() as usize));
}
}
None
}
pub fn xor_range(&mut self, source: usize, target: usize, len: usize) {
for i in 0..len {
self.0[target + i] ^= self.0[source + i];
}
}
pub fn extract(&self, start: usize, len: usize) -> BitVec {
BitVec(self.0[start..(start + len)].into())
}
pub fn xor_in(&mut self, source: &BitSlice, target_pos: usize) {
for i in 0..source.len() {
self.0[target_pos + i] ^= source.0[i];
}
}
#[inline]
pub fn swap(&mut self, source: usize, target: usize) {
self.0.swap(source, target);
}
#[inline]
pub fn swap_range(&mut self, source: usize, target: usize, len: usize) {
for i in 0..len {
self.0.swap(source + i, target + i);
}
}
#[inline]
pub fn len(&self) -> usize {
self.0.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline]
pub fn num_bits(&self) -> usize {
self.0.len() * BLOCKSIZE
}
}
impl Index<Range<usize>> for BitSlice {
type Output = BitSlice;
fn index(&self, index: Range<usize>) -> &Self::Output {
BitSlice::ref_cast(&self.0[index])
}
}
impl Index<usize> for BitSlice {
type Output = BitBlock;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
self.0.index(index)
}
}
impl IndexMut<usize> for BitSlice {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.0.index_mut(index)
}
}
impl IndexMut<Range<usize>> for BitSlice {
fn index_mut(&mut self, index: Range<usize>) -> &mut Self::Output {
BitSlice::ref_cast_mut(self.0.index_mut(index))
}
}
impl BitVec {
#[inline]
pub fn len(&self) -> usize {
self.0.len()
}
#[inline]
pub fn num_bits(&self) -> usize {
self.0.len() * BLOCKSIZE
}
#[inline]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline]
pub fn bit(&self, index: usize) -> bool {
self.deref().bit(index)
}
#[inline]
pub fn set_bit(&mut self, index: usize, value: bool) {
self.deref_mut().set_bit(index, value)
}
#[inline]
pub fn iter(&self) -> BitIter {
self.deref().iter()
}
#[inline]
pub fn count_ones(&self) -> usize {
self.deref().count_ones()
}
#[inline]
pub fn count_zeros(&self) -> usize {
self.deref().count_zeros()
}
#[inline]
pub fn bit_range(&self, from_block: usize, to_block: usize) -> &BitSlice {
BitSlice::ref_cast(&self.0[from_block..to_block])
}
#[inline]
pub fn bit_range_mut(&mut self, from_block: usize, to_block: usize) -> &mut BitSlice {
BitSlice::ref_cast_mut(&mut self.0[from_block..to_block])
}
#[inline]
pub fn random(rng: &mut impl Rng, num_blocks: usize) -> Self {
(0..num_blocks).map(|_| rng.random::<BitBlock>()).collect()
}
#[inline]
pub fn zeros(num_blocks: usize) -> Self {
BitVec(vec![0; num_blocks])
}
#[inline]
pub fn ones(num_blocks: usize) -> Self {
BitVec(vec![BitBlock::MAX; num_blocks])
}
pub fn new() -> Self {
BitVec(Vec::new())
}
pub fn with_capacity(num_blocks: usize) -> Self {
BitVec(Vec::with_capacity(num_blocks))
}
pub fn reserve(&mut self, additional: usize) {
self.0.reserve(additional);
}
pub fn push_block(&mut self, block: BitBlock) {
self.0.push(block);
}
pub fn extend_from_slice(&mut self, other: &BitSlice) {
self.0.extend_from_slice(&other.0);
}
pub fn extend_from_slice_left_shifted(&mut self, other: &BitSlice, shift: usize) {
if shift >= BLOCKSIZE {
panic!("Shift must be less than BLOCKSIZE");
} else if shift == 0 {
self.extend_from_slice(other);
return;
} else if self.0.is_empty() {
panic!("Cannot append to an empty BitVec with left shift");
}
self.0.reserve(other.0.len());
for bits in other.0.iter() {
let left_part = bits.wrapping_shr((BLOCKSIZE - shift) as u32);
let right_part = bits.wrapping_shl(shift as u32);
if let Some(last) = self.0.last_mut() {
*last |= left_part;
}
self.0.push(right_part);
}
}
pub fn pop(&mut self) -> Option<BitBlock> {
self.0.pop()
}
}
impl fmt::Display for BitVec {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for &bits in self.0.iter() {
write!(f, "{:064b}", bits)?;
}
Ok(())
}
}
impl BitAndAssign<&Self> for BitSlice {
#[inline]
fn bitand_assign(&mut self, rhs: &Self) {
for (bits0, bits1) in self.0.iter_mut().zip(rhs.0.iter()) {
*bits0 &= bits1;
}
}
}
impl BitXorAssign<&Self> for BitSlice {
#[inline]
fn bitxor_assign(&mut self, rhs: &BitSlice) {
for (bits0, bits1) in self.0.iter_mut().zip(rhs.0.iter()) {
*bits0 ^= bits1;
}
}
}
impl From<Vec<BitBlock>> for BitVec {
fn from(value: Vec<BitBlock>) -> Self {
BitVec(value)
}
}
impl From<BitVec> for Vec<BitBlock> {
fn from(value: BitVec) -> Self {
value.0
}
}
impl FromIterator<BitBlock> for BitVec {
fn from_iter<T: IntoIterator<Item = BitBlock>>(iter: T) -> Self {
Vec::from_iter(iter).into()
}
}
impl FromIterator<bool> for BitVec {
fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
let mut v = vec![];
let mut c = 0;
let mut block: BitBlock = 0;
for bit in iter {
if bit {
block |= 1;
}
c += 1;
if c == BLOCKSIZE {
c = 0;
v.push(block);
block = 0;
} else {
block <<= 1;
}
}
if c != 0 {
block <<= BLOCKSIZE - c - 1;
v.push(block);
}
BitVec(v)
}
}
impl Deref for BitVec {
type Target = BitSlice;
fn deref(&self) -> &Self::Target {
BitSlice::ref_cast(&self.0)
}
}
impl DerefMut for BitVec {
fn deref_mut(&mut self) -> &mut Self::Target {
BitSlice::ref_cast_mut(&mut self.0)
}
}
impl From<Vec<bool>> for BitVec {
fn from(value: Vec<bool>) -> Self {
BitVec::from_iter(value.iter().copied())
}
}
impl From<BitVec> for Vec<bool> {
fn from(value: BitVec) -> Self {
value.iter().collect()
}
}
#[cfg(test)]
mod test {
use super::*;
use rand::{rngs::SmallRng, SeedableRng};
#[test]
fn bit_xor_and() {
let sz = 8;
let mut rng = SmallRng::seed_from_u64(1);
let vec = BitVec::random(&mut rng, sz);
let mut vec1 = vec.clone();
*vec1 ^= &vec;
assert_eq!(vec1, BitVec::zeros(sz));
vec1 = vec.clone();
*vec1 &= &BitVec::zeros(sz);
assert_eq!(vec1, BitVec::zeros(sz));
vec1 = vec.clone();
*vec1 &= &vec;
assert_eq!(vec1, vec);
}
#[test]
fn bit_get_set() {
let sz = 4;
let bits = vec![0, 3, 100, 201, 255];
let mut vec0 = BitVec::zeros(sz);
for &b in &bits {
vec0.set_bit(b, true);
}
for i in 0..(sz * BLOCKSIZE) {
assert_eq!(vec0.bit(i), bits.contains(&i));
}
let mut vec1 = BitVec::ones(sz);
for &b in &bits {
vec1.set_bit(b, false);
}
for i in 0..(sz * BLOCKSIZE) {
assert_eq!(vec1.bit(i), !bits.contains(&i));
}
}
#[test]
fn bool_vec() {
let mut rng = SmallRng::seed_from_u64(1);
let bool_vec: Vec<bool> = (0..300).map(|_| rng.random()).collect();
let vec: BitVec = bool_vec.clone().into();
let bool_vec1: Vec<bool> = vec.clone().into();
for (i, &b) in bool_vec.iter().enumerate() {
assert_eq!((i, vec.bit(i)), (i, b));
assert_eq!((i, bool_vec1[i]), (i, b));
}
assert_eq!(vec.num_bits(), bool_vec1.len());
for i in bool_vec.len()..vec.len() {
assert_eq!((i, vec.bit(i)), (i, false));
assert_eq!((i, bool_vec1[i]), (i, false));
}
}
#[test]
fn xor_range() {
let i = BitBlock::MAX;
let vec0: BitVec = vec![0, i, 0, i, 0, 0, i, i, 0, 0].into();
let mut vec1 = vec0.clone();
vec1.xor_range(1, 5, 3);
let vec2: BitVec = vec![0, i, 0, i, 0, i, i, 0, 0, 0].into();
assert_eq!(vec1, vec2);
vec1.xor_range(1, 5, 3);
assert_eq!(vec0, vec1);
}
#[test]
fn block_index() {
let mut rng = SmallRng::seed_from_u64(1);
let vec: BitVec = BitVec::random(&mut rng, 10);
let r1: &BitSlice = &vec[4..9];
for i in 0..r1.len() {
assert_eq!(vec[4 + i], r1[i]);
}
}
#[test]
fn extend_from_slice_left_shifted() {
let mut rng = SmallRng::seed_from_u64(1);
let shift = 17;
let mask = BitBlock::MAX.wrapping_shl(17);
let mut v1 = BitVec::random(&mut rng, 10);
v1[9] &= mask;
let v2 = BitVec::random(&mut rng, 10);
let mut v3 = v1.clone();
v3.extend_from_slice_left_shifted(&v2, shift);
for i in 0..v3.num_bits() {
if i < 10 * BLOCKSIZE - shift {
assert_eq!(v3.bit(i), v1.bit(i));
} else if i < 20 * BLOCKSIZE - shift {
assert_eq!(v3.bit(i), v2.bit(i - (10 * BLOCKSIZE - shift)));
} else {
assert_eq!(v3.bit(i), false);
}
}
}
}