use std::{
fmt::Debug,
hash::Hash,
ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not},
ptr::NonNull,
};
use crate::{
BitRead, BitView, BitViewMut, Iter,
traits::{BitWord, BitWrite},
util::{
bitset_all, bitset_any, bitset_clear, bitset_count_ones, bitset_fill, bitset_flip,
bitset_free, bitset_new, bitset_new_uninit, bitset_reset, bitset_resize, bitset_set,
bitset_test_and_set, word_bit, word_bit_mask, word_len,
},
};
pub struct BitFixed<W: BitWord = usize> {
ptr: NonNull<W>,
len: usize,
}
impl<W: BitWord> BitFixed<W> {
pub fn new(bit_len: usize) -> Self {
let (ptr, _cap) = unsafe { bitset_new::<W>(bit_len) };
Self { ptr, len: bit_len }
}
pub fn new_uninit(bit_len: usize) -> Self {
let (ptr, _cap) = unsafe { bitset_new_uninit::<W>(bit_len) };
Self { ptr, len: bit_len }
}
pub fn resize(&mut self, new_bit_len: usize) {
let (ptr, _cap) = unsafe { bitset_resize(self.ptr, self.len, new_bit_len) };
self.ptr = ptr;
self.len = new_bit_len;
}
#[inline]
pub fn capacity(&self) -> usize {
word_len::<W>(self.len) * W::BITS
}
pub fn iter(&self) -> Iter<W> {
Iter::new(self.ptr, self.len)
}
pub fn as_view(&self) -> BitView<'_, W> {
BitView::new(self.ptr, self.len)
}
pub fn as_view_mut(&self) -> BitViewMut<'_, W> {
BitViewMut::new(self.ptr, self.len)
}
pub fn copy_from(&mut self, other: &Self) {
assert_eq!(self.len, other.len);
if !std::ptr::eq(self, other) {
let word_len = word_len::<W>(self.len);
unsafe {
self.ptr.copy_from_nonoverlapping(other.ptr, word_len);
}
}
}
pub fn is_disjoint(&self, other: &Self) -> bool {
assert_eq!(self.len, other.len);
let word_len = word_len::<W>(self.len);
for i in 0..word_len {
if W::from(0)
!= unsafe { *self.ptr.as_ptr().add(i) } & unsafe { *other.ptr.as_ptr().add(i) }
{
return false;
}
}
true
}
pub fn intersection_count(&self, other: &Self) -> usize {
assert_eq!(self.len, other.len);
let word_len = word_len::<W>(self.len);
let mut count = 0;
for i in 0..word_len {
let w = unsafe { *self.ptr.as_ptr().add(i) } & unsafe { *other.ptr.as_ptr().add(i) };
count += w.count_ones();
}
count
}
#[inline(always)]
fn ptr_and_mask(&self, idx: usize) -> (*mut W, W) {
let (word, bit) = word_bit::<W>(idx);
unsafe { (self.ptr.as_ptr().add(word), W::from(1) << bit) }
}
}
impl<W: BitWord> Drop for BitFixed<W> {
fn drop(&mut self) {
unsafe { bitset_free(self.ptr, self.len) };
}
}
impl<T: BitWord> Clone for BitFixed<T> {
fn clone(&self) -> Self {
if self.len != 0 {
let word_len = word_len::<T>(self.len);
let layout = std::alloc::Layout::array::<T>(word_len).unwrap();
let raw_ptr = unsafe { std::alloc::alloc(layout) } as *mut T;
if let Some(ptr) = NonNull::new(raw_ptr) {
unsafe {
self.ptr.copy_to_nonoverlapping(ptr, word_len);
}
return Self { ptr, len: self.len };
} else {
std::alloc::handle_alloc_error(layout);
}
} else {
return Self {
ptr: NonNull::dangling(),
len: 0,
};
}
}
}
impl<T: BitWord> PartialEq for BitFixed<T> {
fn eq(&self, other: &Self) -> bool {
let self_store =
unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), word_len::<T>(self.len)) };
let other_store =
unsafe { std::slice::from_raw_parts(other.ptr.as_ptr(), word_len::<T>(other.len)) };
self.len == other.len && self_store == other_store
}
}
impl<T: BitWord> Eq for BitFixed<T> {}
impl<T: BitWord> Hash for BitFixed<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
let store =
unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), word_len::<T>(self.len)) };
store.hash(state);
self.len.hash(state);
}
}
impl<T: Debug + BitWord> std::fmt::Debug for BitFixed<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let store =
unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), word_len::<T>(self.len)) };
f.debug_struct("BitFixed")
.field("len", &self.len)
.field("store", &store)
.finish()
}
}
impl<W: BitWord> BitRead for BitFixed<W> {
type Iter<'a>
= Iter<'a, W>
where
Self: 'a;
#[inline]
fn len(&self) -> usize {
self.len
}
#[inline]
fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
fn test(&self, idx: usize) -> bool {
assert!(idx < self.len);
let (ptr, mask) = self.ptr_and_mask(idx);
unsafe { (*ptr & mask) != W::from(0) }
}
fn count_ones(&self) -> usize {
unsafe { bitset_count_ones(self.ptr, self.len) }
}
fn all(&self) -> bool {
unsafe { bitset_all(self.ptr, self.len) }
}
fn any(&self) -> bool {
unsafe { bitset_any(self.ptr, self.len) }
}
#[inline]
fn iter(&self) -> Self::Iter<'_> {
Iter::new(self.ptr, self.len)
}
}
impl<W: BitWord> BitWrite for BitFixed<W> {
#[inline]
fn set(&mut self, idx: usize) {
unsafe { bitset_set(self.ptr, self.len, idx) };
}
#[inline]
fn reset(&mut self, idx: usize) {
unsafe { bitset_reset(self.ptr, self.len, idx) };
}
#[inline]
fn flip(&mut self, idx: usize) {
unsafe { bitset_flip(self.ptr, self.len, idx) };
}
#[inline]
fn test_and_set(&mut self, idx: usize) -> bool {
unsafe { bitset_test_and_set(self.ptr, self.len, idx) }
}
#[inline]
fn fill(&mut self) {
unsafe { bitset_fill(self.ptr, self.len) };
}
#[inline]
fn clear(&mut self) {
unsafe { bitset_clear(self.ptr, self.len) };
}
}
impl<T: BitWord> BitAndAssign<&Self> for BitFixed<T> {
fn bitand_assign(&mut self, rhs: &Self) {
assert_eq!(self.len, rhs.len);
for i in 0..word_len::<T>(self.len) {
unsafe {
*self.ptr.as_ptr().add(i) &= *rhs.ptr.as_ptr().add(i);
}
}
}
}
impl<T: BitWord> BitOrAssign<&Self> for BitFixed<T> {
fn bitor_assign(&mut self, rhs: &Self) {
assert_eq!(self.len, rhs.len);
for i in 0..word_len::<T>(self.len) {
unsafe {
*self.ptr.as_ptr().add(i) |= *rhs.ptr.as_ptr().add(i);
}
}
}
}
impl<T: BitWord> BitXorAssign<&Self> for BitFixed<T> {
fn bitxor_assign(&mut self, rhs: &Self) {
assert_eq!(self.len, rhs.len);
for i in 0..word_len::<T>(self.len) {
unsafe {
(*self.ptr.as_ptr().add(i)) ^= *rhs.ptr.as_ptr().add(i);
}
}
}
}
impl<T: BitWord> BitAnd<&Self> for BitFixed<T> {
type Output = BitFixed<T>;
fn bitand(self, rhs: &Self) -> Self::Output {
assert_eq!(self.len, rhs.len);
let output = Self::Output::new_uninit(self.len);
let words = word_len::<T>(self.len);
for i in 0..words {
unsafe {
output
.ptr
.as_ptr()
.add(i)
.write(self.ptr.as_ptr().add(i).read() & rhs.ptr.as_ptr().add(i).read());
}
}
output
}
}
impl<T: BitWord> BitOr<&Self> for BitFixed<T> {
type Output = BitFixed<T>;
fn bitor(self, rhs: &Self) -> Self::Output {
assert_eq!(self.len, rhs.len);
let output = Self::Output::new_uninit(self.len);
let words = word_len::<T>(self.len);
for i in 0..words {
unsafe {
output
.ptr
.as_ptr()
.add(i)
.write(self.ptr.as_ptr().add(i).read() | rhs.ptr.as_ptr().add(i).read());
}
}
output
}
}
impl<T: BitWord> BitXor<&Self> for BitFixed<T> {
type Output = BitFixed<T>;
fn bitxor(self, rhs: &Self) -> Self::Output {
assert_eq!(self.len, rhs.len);
let output = Self::Output::new_uninit(self.len);
let words = word_len::<T>(self.len);
for i in 0..words {
unsafe {
output
.ptr
.as_ptr()
.add(i)
.write(self.ptr.as_ptr().add(i).read() ^ rhs.ptr.as_ptr().add(i).read());
}
}
output
}
}
impl<T: BitWord> Not for &BitFixed<T> {
type Output = BitFixed<T>;
fn not(self) -> Self::Output {
let output = Self::Output::new(self.len);
let (word, bit, mask) = word_bit_mask::<T>(self.len);
for i in 0..word {
unsafe {
output.ptr.as_ptr().add(i).write(!*self.ptr.as_ptr().add(i));
}
}
if bit != 0 {
unsafe {
output
.ptr
.as_ptr()
.add(word)
.write((!*self.ptr.as_ptr().add(word)) & mask);
}
}
output
}
}
impl<'a, T: BitWord> From<&'a BitFixed<T>> for BitView<'a, T> {
fn from(value: &'a BitFixed<T>) -> Self {
BitView::new(value.ptr, value.len)
}
}
impl<'a, T: BitWord> From<&'a mut BitFixed<T>> for BitViewMut<'a, T> {
fn from(value: &'a mut BitFixed<T>) -> Self {
BitViewMut::new(value.ptr, value.len)
}
}
#[cfg(test)]
mod tests {
use std::collections::HashSet;
use super::*;
#[test]
fn test_new_and_len() {
let bv: BitFixed<u8> = BitFixed::new(10);
assert_eq!(bv.len(), 10);
assert!(bv.is_empty() == false);
let bv0: BitFixed<u16> = BitFixed::new(0);
assert_eq!(bv0.len(), 0);
assert!(bv0.is_empty());
let mut iter = bv.iter();
assert!(iter.next().is_none());
}
#[test]
fn test_set_and_test() {
let mut bv: BitFixed<u32> = BitFixed::new(8);
for i in 0..8 {
assert!(!bv.test(i));
bv.set(i);
assert!(bv.test(i));
}
}
#[test]
fn test_reset() {
let mut bv: BitFixed<u64> = BitFixed::new(8);
for i in 0..8 {
bv.set(i);
}
for i in 0..8 {
bv.reset(i);
assert!(!bv.test(i));
}
}
#[test]
fn test_test_and_set() {
let mut bv: BitFixed<usize> = BitFixed::new(4);
assert!(!bv.test_and_set(2));
assert!(bv.test_and_set(2));
assert!(bv.test(2));
}
#[test]
fn test_fill_and_clear() {
let mut bv: BitFixed<u8> = BitFixed::new(10);
bv.fill();
for i in 0..10 {
assert!(bv.test(i));
}
bv.clear();
for i in 0..10 {
assert!(!bv.test(i));
}
}
#[test]
fn test_count_ones() {
let mut bv: BitFixed<u16> = BitFixed::new(16);
assert_eq!(bv.count_ones(), 0);
bv.set(0);
bv.set(3);
bv.set(15);
assert_eq!(bv.count_ones(), 3);
bv.fill();
assert_eq!(bv.count_ones(), 16);
bv.clear();
assert_eq!(bv.count_ones(), 0);
}
#[test]
fn test_all_and_any() {
let mut bv: BitFixed<u32> = BitFixed::new(5);
assert!(!bv.all());
assert!(!bv.any());
bv.set(0);
assert!(!bv.all());
assert!(bv.any());
bv.fill();
assert!(bv.all());
bv.reset(2);
assert!(!bv.all());
assert!(bv.any());
bv.clear();
assert!(!bv.any());
}
#[test]
fn test_resize_grow_and_shrink() {
let mut bv: BitFixed<u64> = BitFixed::new(4);
bv.set(1);
bv.resize(8);
assert!(bv.test(1));
bv.set(7);
assert!(bv.test(7));
bv.resize(2);
assert_eq!(bv.len(), 2);
assert!(bv.test(1));
}
#[test]
fn test_zero_len() {
let mut bv: BitFixed<usize> = BitFixed::new(0);
assert_eq!(bv.len(), 0);
assert!(bv.is_empty());
bv.resize(0);
assert_eq!(bv.len(), 0);
}
#[test]
fn test_iterator_empty() {
let bv: BitFixed<u32> = BitFixed::new(0);
let mut iter = bv.iter();
assert_eq!(iter.next(), None);
}
#[test]
fn test_iterator_single_bit() {
let mut bv: BitFixed<u64> = BitFixed::new(1);
assert_eq!(bv.iter().collect::<Vec<_>>(), vec![]);
bv.set(0);
assert_eq!(bv.iter().collect::<Vec<_>>(), vec![0]);
}
#[test]
fn test_iterator_multiple_bits() {
let mut bv: BitFixed<u8> = BitFixed::new(10);
bv.set(2);
bv.set(5);
bv.set(9);
let bits: Vec<_> = bv.iter().collect();
assert_eq!(bits, vec![2, 5, 9]);
}
#[test]
fn test_iterator_all_bits_set() {
let mut bv: BitFixed<u16> = BitFixed::new(8);
bv.fill();
let bits: Vec<_> = bv.iter().collect();
assert_eq!(bits, (0..8).collect::<Vec<_>>());
}
#[test]
fn test_iterator_after_clear_and_set() {
let mut bv: BitFixed<u32> = BitFixed::new(16);
bv.fill();
bv.clear();
assert_eq!(bv.iter().collect::<Vec<_>>(), vec![]);
bv.set(7);
bv.set(15);
assert!(bv.test(7));
assert!(bv.test(15));
assert_eq!(bv.iter().collect::<Vec<_>>(), vec![7, 15]);
}
#[test]
fn test_iterator_sparse_bits() {
let mut bv: BitFixed<u64> = BitFixed::new(64);
bv.set(0);
bv.set(31);
bv.set(32);
bv.set(63);
let bits: Vec<_> = bv.iter().collect();
assert_eq!(bits, vec![0, 31, 32, 63]);
}
#[test]
fn test_iterator_large_bit_map() {
let mut bv: BitFixed<usize> = BitFixed::new(130);
for i in (0..130).step_by(13) {
bv.set(i);
}
let expected: Vec<_> = (0..130).step_by(13).collect();
let actual: Vec<_> = bv.iter().collect();
assert_eq!(actual, expected);
}
#[test]
fn test_iterator_partial_last_word() {
let mut bv: BitFixed<u8> = BitFixed::new(70); bv.set(0);
bv.set(63);
bv.set(64);
bv.set(69);
let bits: Vec<_> = bv.iter().collect();
assert_eq!(bits, vec![0, 63, 64, 69]);
}
#[test]
fn test_eq() {
let mut bs1: BitFixed<usize> = BitFixed::new(7);
let mut bs2: BitFixed<usize> = BitFixed::new(7);
assert_eq!(bs1, bs2);
bs2.set(3);
assert_ne!(bs1, bs2);
bs1.set(3);
assert_eq!(bs1, bs2);
let mut x = HashSet::new();
assert!(x.insert(bs1));
assert!(!x.insert(bs2));
}
#[test]
fn test_op() {
let len = 7;
let mut bset: BitFixed<usize> = BitFixed::new(len);
assert_eq!((!&bset).count_ones() as usize, len);
let dup = bset.clone();
bset ^= &dup;
assert_eq!(bset.count_ones(), 0);
bset ^= &!&dup;
assert_eq!(bset.count_ones() as usize, len);
}
#[test]
fn test_bitwise_operations() {
let mut bf1: BitFixed<u32> = BitFixed::new(32);
let mut bf2: BitFixed<u32> = BitFixed::new(32);
bf1.set(1);
bf1.set(3);
bf1.set(5);
bf1.set(7);
bf2.set(3);
bf2.set(5);
bf2.set(9);
let bf_and = bf1.clone() & &bf2;
assert!(!bf_and.test(1));
assert!(bf_and.test(3));
assert!(bf_and.test(5));
assert!(!bf_and.test(7));
assert!(!bf_and.test(9));
assert_eq!(bf_and.count_ones(), 2);
let bf_or = bf1.clone() | &bf2;
assert!(bf_or.test(1));
assert!(bf_or.test(3));
assert!(bf_or.test(5));
assert!(bf_or.test(7));
assert!(bf_or.test(9));
assert_eq!(bf_or.count_ones(), 5);
let bf_xor = bf1.clone() ^ &bf2;
assert!(bf_xor.test(1));
assert!(!bf_xor.test(3)); assert!(!bf_xor.test(5)); assert!(bf_xor.test(7));
assert!(bf_xor.test(9));
assert_eq!(bf_xor.count_ones(), 3);
let bf_not = !&bf1;
assert!(!bf_not.test(1));
assert!(!bf_not.test(3));
assert!(!bf_not.test(5));
assert!(!bf_not.test(7));
assert!(bf_not.test(0));
assert!(bf_not.test(2));
assert!(bf_not.test(4));
assert!(bf_not.test(6));
assert_eq!(bf_not.count_ones(), 32 - 4);
}
#[test]
fn test_bitwise_operations_edge_cases() {
let empty1: BitFixed<u16> = BitFixed::new(0);
let empty2: BitFixed<u16> = BitFixed::new(0);
let empty_and = empty1.clone() & &empty2;
let empty_or = empty1.clone() | &empty2;
let empty_xor = empty1.clone() ^ &empty2;
let empty_not = !&empty1;
assert_eq!(empty_and.len(), 0);
assert_eq!(empty_or.len(), 0);
assert_eq!(empty_xor.len(), 0);
assert_eq!(empty_not.len(), 0);
let mut single1: BitFixed<u8> = BitFixed::new(1);
let single2: BitFixed<u8> = BitFixed::new(1);
single1.set(0);
let single_and = single1.clone() & &single2;
assert!(!single_and.test(0));
let single_or = single1.clone() | &single2;
assert!(single_or.test(0));
let single_xor = single1.clone() ^ &single2;
assert!(single_xor.test(0));
let single_not = !&single1;
assert!(!single_not.test(0));
let mut odd1: BitFixed<u64> = BitFixed::new(65); let mut odd2: BitFixed<u64> = BitFixed::new(65);
odd1.set(0);
odd1.set(63); odd1.set(64);
odd2.set(63);
odd2.set(64);
let odd_and = odd1.clone() & &odd2;
assert!(!odd_and.test(0));
assert!(odd_and.test(63));
assert!(odd_and.test(64));
let odd_or = odd1.clone() | &odd2;
assert!(odd_or.test(0));
assert!(odd_or.test(63));
assert!(odd_or.test(64));
let odd_xor = odd1.clone() ^ &odd2;
assert!(odd_xor.test(0));
assert!(!odd_xor.test(63));
assert!(!odd_xor.test(64));
}
#[test]
fn test_copy_from() {
let len = 10;
let mut bv1: BitFixed<u16> = BitFixed::new(len);
let mut bv2: BitFixed<u16> = BitFixed::new(len);
bv1.set(2);
bv1.set(5);
bv2.set(7);
bv2.set(9);
bv2.copy_from(&bv1);
for i in 0..len {
assert_eq!(bv2.test(i), bv1.test(i));
}
}
#[test]
fn test_is_disjoint() {
let len = 8;
let mut bv1: BitFixed<u32> = BitFixed::new(len);
let mut bv2: BitFixed<u32> = BitFixed::new(len);
assert!(bv1.is_disjoint(&bv2));
bv1.set(2);
bv2.set(3);
assert!(bv1.is_disjoint(&bv2));
bv2.set(2);
assert!(!bv1.is_disjoint(&bv2));
bv1.clear();
bv2.clear();
assert!(bv1.is_disjoint(&bv2));
}
#[test]
fn test_intersection_count() {
let len = 10;
let mut bv1: BitFixed<u8> = BitFixed::new(len);
let mut bv2: BitFixed<u8> = BitFixed::new(len);
assert_eq!(bv1.intersection_count(&bv2), 0);
bv1.set(1);
bv1.set(3);
bv1.set(5);
bv2.set(3);
bv2.set(5);
bv2.set(7);
assert_eq!(bv1.intersection_count(&bv2), 2);
bv2.set(1);
assert_eq!(bv1.intersection_count(&bv2), 3);
bv1.clear();
assert_eq!(bv1.intersection_count(&bv2), 0);
}
#[test]
fn test_debug() {
let mut bset: BitFixed<u8> = BitFixed::new(10);
bset.set(1);
bset.set(7);
bset.set(9);
assert_eq!(format!("{bset:?}"), "BitFixed { len: 10, store: [130, 2] }");
}
}