use std::{iter::FusedIterator, ops::Range};
use super::{ceiling_div, n_lowest_bits, n_lowest_bits_1_64};
pub struct BitBIterator<'a, const B: bool> {
segment_iter: std::slice::Iter<'a, u64>,
first_segment_bit: usize,
current_segment: u64
}
impl<'a, const B: bool> BitBIterator<'a, B> {
pub fn new(slice: &'a [u64]) -> Self {
let mut segment_iter = slice.into_iter();
let current_segment = if B {
segment_iter.next().copied().unwrap_or(0)
} else {
!segment_iter.next().copied().unwrap_or(0)
};
Self {
segment_iter,
first_segment_bit: 0,
current_segment
}
}
}
impl<'a, const B: bool> Iterator for BitBIterator<'a, B> {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
while self.current_segment == 0 {
self.current_segment = if B { *self.segment_iter.next()? } else { !*self.segment_iter.next()? };
self.first_segment_bit += 64;
}
let result = self.current_segment.trailing_zeros();
self.current_segment ^= 1<<result;
Some(self.first_segment_bit + (result as usize))
}
#[inline] fn size_hint(&self) -> (usize, Option<usize>) {
let result = self.len();
(result, Some(result))
}
}
impl<'a, const B: bool> ExactSizeIterator for BitBIterator<'a, B> {
#[inline] fn len(&self) -> usize {
if B {
self.current_segment.count_ones() as usize + self.segment_iter.as_slice().count_bit_ones()
} else {
self.current_segment.count_zeros() as usize + self.segment_iter.as_slice().count_bit_zeros()
}
}
}
impl<'a, const B: bool> FusedIterator for BitBIterator<'a, B> where std::slice::Iter<'a, u64>: FusedIterator {}
pub type BitOnesIterator<'a> = BitBIterator<'a, true>;
pub type BitZerosIterator<'a> = BitBIterator<'a, false>;
pub struct BitIterator<'bv> {
bit_vec: &'bv [u64],
bit_range: Range<usize>,
}
impl<'bv> BitIterator<'bv> {
#[inline] pub fn new(bit_vec: &'bv [u64]) -> Self {
Self { bit_vec, bit_range: 0..bit_vec.len()*64 }
}
#[inline] pub unsafe fn with_range_unchecked(bit_vec: &'bv [u64], bit_range: Range<usize>) -> Self {
Self { bit_vec, bit_range }
}
#[inline] pub fn with_range(bit_vec: &'bv [u64], bit_range: Range<usize>) -> Self {
assert!(bit_range.end <= bit_vec.len()*64, "BitIterator bit range out of bounds.");
Self { bit_vec, bit_range }
}
#[inline] pub fn bit_range(&self) -> &Range<usize> { &self.bit_range }
#[inline] pub fn bit_vec(&self) -> &'bv [u64] { &self.bit_vec }
}
impl<'bv> Iterator for BitIterator<'bv> {
type Item = bool;
#[inline] fn next(&mut self) -> Option<Self::Item> {
self.bit_range.next().map(|bit_nr| unsafe { self.bit_vec.get_bit_unchecked(bit_nr) })
}
#[inline] fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.bit_range.nth(n).map(|bit_nr| unsafe { self.bit_vec.get_bit_unchecked(bit_nr) })
}
#[inline] fn size_hint(&self) -> (usize, Option<usize>) {
self.bit_range.size_hint()
}
}
impl<'bv> DoubleEndedIterator for BitIterator<'bv> {
#[inline] fn next_back(&mut self) -> Option<Self::Item> {
self.bit_range.next_back().map(|bit_nr| unsafe { self.bit_vec.get_bit_unchecked(bit_nr) })
}
#[inline] fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
self.bit_range.nth_back(n).map(|bit_nr| unsafe { self.bit_vec.get_bit_unchecked(bit_nr) })
}
}
impl<'a> ExactSizeIterator for BitIterator<'a> where Range<usize>: ExactSizeIterator {
#[inline] fn len(&self) -> usize { self.bit_range.len() }
}
impl<'a> FusedIterator for BitIterator<'a> where Range<usize>: FusedIterator {}
pub trait BitAccess {
fn get_bit(&self, bit_nr: usize) -> bool;
unsafe fn get_bit_unchecked(&self, bit_nr: usize) -> bool;
fn try_get_bit(&self, bit_nr: usize) -> Option<bool>;
#[inline] fn get_successive_bit(&self, bit_nr: &mut usize) -> bool {
let result = self.get_bit(*bit_nr);
*bit_nr += 1;
result
}
fn set_bit_to(&mut self, bit_nr: usize, value: bool);
unsafe fn set_bit_to_unchecked(&mut self, bit_nr: usize, value: bool);
#[inline] fn set_successive_bit_to(&mut self, bit_nr: &mut usize, value: bool) {
self.set_bit_to(*bit_nr, value); *bit_nr += 1;
}
#[inline] unsafe fn set_successive_bit_to_unchecked(&mut self, bit_nr: &mut usize, value: bool) {
self.set_bit_to_unchecked(*bit_nr, value); *bit_nr += 1;
}
fn init_bit(&mut self, bit_nr: usize, value: bool);
unsafe fn init_bit_unchecked(&mut self, bit_nr: usize, value: bool);
#[inline] fn init_successive_bit(&mut self, bit_nr: &mut usize, value: bool) {
self.init_bit(*bit_nr, value); *bit_nr += 1;
}
#[inline] unsafe fn init_successive_bit_unchecked(&mut self, bit_nr: &mut usize, value: bool) {
self.init_bit_unchecked(*bit_nr, value); *bit_nr += 1;
}
fn set_bit(&mut self, bit_nr: usize);
unsafe fn set_bit_unchecked(&mut self, bit_nr: usize);
fn clear_bit(&mut self, bit_nr: usize);
unsafe fn clear_bit_unchecked(&mut self, bit_nr: usize);
#[inline] fn get_bits_unmasked(&self, begin: usize, len: u8) -> u64 {
self.try_get_bits_unmasked(begin, len).expect("bit range out of bounds")
}
#[inline] fn get_bits(&self, begin: usize, len: u8) -> u64 {
self.get_bits_unmasked(begin, len) & n_lowest_bits(len)
}
fn try_get_bits_unmasked(&self, begin: usize, len: u8) -> Option<u64>;
#[inline(always)] fn try_get_bits(&self, begin: usize, len: u8) -> Option<u64> {
self.try_get_bits_unmasked(begin, len).map(|result| result & n_lowest_bits(len))
}
unsafe fn get_bits_unmasked_unchecked(&self, begin: usize, len: u8) -> u64;
#[inline(always)] unsafe fn get_bits_unchecked(&self, begin: usize, len: u8) -> u64 {
self.get_bits_unmasked_unchecked(begin, len) & n_lowest_bits(len)
}
#[inline] fn get_successive_bits(&self, begin: &mut usize, len: u8) -> u64 {
let result = self.get_bits(*begin, len);
*begin += len as usize;
result
}
fn init_bits(&mut self, begin: usize, v: u64, len: u8);
#[inline] fn init_successive_bits(&mut self, begin: &mut usize, v: u64, len: u8) {
self.init_bits(*begin, v, len); *begin += len as usize;
}
unsafe fn init_bits_unchecked(&mut self, begin: usize, v: u64, len: u8);
fn set_bits(&mut self, begin: usize, v: u64, len: u8);
#[inline] fn set_successive_bits(&mut self, begin: &mut usize, v: u64, len: u8) {
self.set_bits(*begin, v, len); *begin += len as usize;
}
unsafe fn set_bits_unchecked(&mut self, begin: usize, v: u64, len: u8);
fn xor_bits(&mut self, begin: usize, v: u64, len: u8);
fn xor_successive_bits(&mut self, begin: &mut usize, v: u64, len: u8) {
self.xor_bits(*begin, v, len); *begin += len as usize;
}
fn count_bit_zeros(&self) -> usize;
fn count_bit_ones(&self) -> usize;
fn bit_ones(&'_ self) -> BitOnesIterator<'_>;
fn bit_zeros(&'_ self) -> BitZerosIterator<'_>;
fn bit_iter(&'_ self) -> BitIterator<'_>;
fn bit_in_range_iter(&'_ self, bit_range: Range<usize>) -> BitIterator<'_>;
unsafe fn bit_in_unchecked_range_iter(&'_ self, bit_range: Range<usize>) -> BitIterator<'_>;
#[inline(always)] fn get_fragment_unmasked(&self, index: usize, v_size: u8) -> u64 {
self.get_bits_unmasked(index * v_size as usize, v_size)
}
#[inline(always)] fn get_fragment(&self, index: usize, v_size: u8) -> u64 {
self.get_bits(index * v_size as usize, v_size)
}
#[inline(always)] fn try_get_fragment_unmasked(&self, index: usize, v_size: u8) -> Option<u64> {
self.try_get_bits_unmasked(index * v_size as usize, v_size)
}
#[inline(always)] fn try_get_fragment(&self, index: usize, v_size: u8) -> Option<u64> {
self.try_get_bits(index * v_size as usize, v_size)
}
#[inline(always)] unsafe fn get_fragment_unmasked_unchecked(&self, index: usize, v_size: u8) -> u64 {
self.get_bits_unmasked_unchecked(index * v_size as usize, v_size)
}
#[inline(always)] unsafe fn get_fragment_unchecked(&self, index: usize, v_size: u8) -> u64 {
self.get_bits_unchecked(index * v_size as usize, v_size)
}
#[inline(always)] fn get_successive_fragment(&self, index: &mut usize, v_size: u8) -> u64 {
let result = self.get_fragment(*index, v_size);
*index += 1;
result
}
#[inline(always)] fn init_fragment(&mut self, index: usize, v: u64, v_size: u8) {
self.init_bits(index * v_size as usize, v, v_size)
}
#[inline(always)] fn init_successive_fragment(&mut self, index: &mut usize, v: u64, v_size: u8) {
self.init_fragment(*index, v, v_size); *index += 1;
}
#[inline(always)] unsafe fn init_fragment_unchecked(&mut self, index: usize, v: u64, v_size: u8) {
self.init_bits_unchecked(index * v_size as usize, v, v_size)
}
#[inline(always)] fn set_fragment(&mut self, index: usize, v: u64, v_size: u8) {
self.set_bits(index * v_size as usize, v, v_size)
}
#[inline(always)] unsafe fn set_fragment_unchecked(&mut self, index: usize, v: u64, v_size: u8) {
self.set_bits_unchecked(index * v_size as usize, v, v_size)
}
#[inline(always)] fn set_successive_fragment(&mut self, index: &mut usize, v: u64, v_size: u8) {
self.set_fragment(*index, v, v_size); *index += 1;
}
#[inline(always)] fn xor_fragment(&mut self, index: usize, v: u64, v_size: u8) {
self.xor_bits(index * v_size as usize, v, v_size)
}
#[inline(always)] fn xor_successive_fragment(&mut self, index: &mut usize, v: u64, v_size: u8) {
self.xor_fragment(*index, v, v_size); *index += 1;
}
fn swap_fragments(&mut self, index1: usize, index2: usize, v_size: u8) {
let v1 = self.get_fragment(index1, v_size);
unsafe{self.set_fragment_unchecked(index1, self.get_fragment(index2, v_size), v_size)};
unsafe{self.set_fragment_unchecked(index2, v1, v_size);}
}
fn conditionally_change_bits<NewValue>(&mut self, new_value: NewValue, begin: usize, v_size: u8) -> u64
where NewValue: FnOnce(u64) -> Option<u64>
{
let old = self.get_bits(begin, v_size);
if let Some(new) = new_value(old) { unsafe{self.set_bits_unchecked(begin, new, v_size)}; }
old
}
#[inline(always)] fn conditionally_change_fragment<NewValue>(&mut self, new_value: NewValue, index: usize, v_size: u8) -> u64
where NewValue: FnOnce(u64) -> Option<u64>
{
self.conditionally_change_bits(new_value, index * v_size as usize, v_size)
}
#[inline(always)] fn conditionally_copy_bits<Pred>(&mut self, src: &Self, predicate: Pred, begin: usize, v_size: u8)
where Pred: FnOnce(u64, u64) -> bool
{
let src_bits = src.get_bits(begin, v_size);
self.conditionally_change_bits(|self_bits| predicate(self_bits, src_bits).then(|| src_bits), begin, v_size);
}
#[inline(always)] fn conditionally_copy_fragment<Pred>(&mut self, src: &Self, predicate: Pred, index: usize, v_size: u8)
where Pred: FnOnce(u64, u64) -> bool
{
self.conditionally_copy_bits(src, predicate, index * v_size as usize, v_size)
}
fn trailing_zero_bits(&self) -> usize;
unsafe fn find_bit_one_unchecked(&self, start_index: usize) -> usize;
fn find_bit_one(&self, start_index: usize) -> Option<usize>;
unsafe fn rfind_bit_one_unchecked(&self, start_index: usize) -> usize;
}
pub trait BitVec where Self: Sized {
fn with_64bit_segments(segments_value: u64, segments_len: usize) -> Self;
fn with_bitwords(word: u64, word_len_bits: u8, words_count: usize) -> Self;
#[inline(always)] fn with_zeroed_64bit_segments(segments_len: usize) -> Self {
Self::with_64bit_segments(0, segments_len)
}
#[inline(always)] fn with_filled_64bit_segments(segments_len: usize) -> Self {
Self::with_64bit_segments(u64::MAX, segments_len)
}
#[inline(always)] fn with_zeroed_bits(bit_len: usize) -> Self {
Self::with_zeroed_64bit_segments(ceiling_div(bit_len, 64))
}
#[inline(always)] fn with_filled_bits(bit_len: usize) -> Self {
Self::with_filled_64bit_segments(ceiling_div(bit_len, 64))
}
}
impl BitVec for Box<[u64]> {
#[inline(always)] fn with_64bit_segments(segments_value: u64, segments_len: usize) -> Self {
vec![segments_value; segments_len].into_boxed_slice()
}
fn with_bitwords(word: u64, word_len_bits: u8, words_count: usize) -> Self {
let mut result = Self::with_zeroed_bits(words_count * word_len_bits as usize);
for index in 0..words_count { result.init_fragment(index, word, word_len_bits); }
result
}
}
#[cfg(feature = "aligned-vec")]
impl<const ALIGN: usize> BitVec for aligned_vec::ABox<[u64], aligned_vec::ConstAlign<ALIGN>> {
#[inline(always)] fn with_64bit_segments(segments_value: u64, segments_len: usize) -> Self {
aligned_vec::avec![[ALIGN] | segments_value; segments_len].into_boxed_slice()
}
fn with_bitwords(word: u64, word_len_bits: u8, words_count: usize) -> Self {
let mut result = Self::with_zeroed_bits(words_count * word_len_bits as usize);
for index in 0..words_count { result.init_fragment(index, word, word_len_bits); }
result
}
}
#[inline(always)] fn set_bit_to(to_change: &mut u64, bit_nr: usize, value: bool) {
*to_change &= !(1u64 << bit_nr);
*to_change |= (value as u64) << bit_nr;
}
#[inline(always)] fn set_bits_to(to_change: &mut u64, shifted_v: u64, shifted_v_mask: u64) {
*to_change &= !shifted_v_mask;
*to_change |= shifted_v;
}
impl BitAccess for [u64] {
#[inline(always)] fn get_bit(&self, bit_nr: usize) -> bool {
self[bit_nr / 64] & (1u64 << (bit_nr % 64)) != 0
}
#[inline(always)] fn set_bit_to(&mut self, bit_nr: usize, value: bool) {
set_bit_to(&mut self[bit_nr / 64], bit_nr % 64, value)
}
#[inline(always)] unsafe fn set_bit_to_unchecked(&mut self, bit_nr: usize, value: bool) {
debug_assert!(bit_nr / 64 < self.len());
set_bit_to(self.get_unchecked_mut(bit_nr / 64), bit_nr % 64, value)
}
#[inline(always)] unsafe fn get_bit_unchecked(&self, bit_nr: usize) -> bool {
debug_assert!(bit_nr / 64 < self.len());
self.get_unchecked(bit_nr / 64) & (1u64 << (bit_nr % 64) as u64) != 0
}
#[inline(always)] fn try_get_bit(&self, bit_nr: usize) -> Option<bool> {
Some(self.get(bit_nr / 64)? & (1u64 << (bit_nr % 64) as u64) != 0)
}
#[inline(always)] fn init_bit(&mut self, bit_nr: usize, value: bool) {
self[bit_nr / 64] |= (value as u64) << (bit_nr % 64);
}
#[inline] unsafe fn init_bit_unchecked(&mut self, bit_nr: usize, value: bool) {
debug_assert!(bit_nr / 64 < self.len());
*self.get_unchecked_mut(bit_nr / 64) |= (value as u64) << (bit_nr % 64);
}
#[inline(always)] fn set_bit(&mut self, bit_nr: usize) {
self[bit_nr / 64] |= 1u64 << (bit_nr % 64)
}
#[inline(always)] unsafe fn set_bit_unchecked(&mut self, bit_nr: usize) {
debug_assert!(bit_nr / 64 < self.len());
*self.get_unchecked_mut(bit_nr / 64) |= 1u64 << (bit_nr % 64)
}
#[inline(always)] fn clear_bit(&mut self, bit_nr: usize) {
self[bit_nr / 64] &= !((1u64) << (bit_nr % 64))
}
#[inline(always)] unsafe fn clear_bit_unchecked(&mut self, bit_nr: usize) {
debug_assert!(bit_nr / 64 < self.len());
*self.get_unchecked_mut(bit_nr / 64) &= !((1u64) << (bit_nr % 64))
}
fn count_bit_zeros(&self) -> usize {
self.into_iter().map(|s| s.count_zeros() as usize).sum()
}
fn count_bit_ones(&self) -> usize {
self.into_iter().map(|s| s.count_ones() as usize).sum()
}
#[inline(always)] fn bit_ones(&'_ self) -> BitOnesIterator<'_> {
BitOnesIterator::new(self)
}
#[inline(always)] fn bit_zeros(&'_ self) -> BitZerosIterator<'_> {
BitZerosIterator::new(self)
}
#[inline(always)] fn bit_iter(&'_ self) -> BitIterator<'_> {
BitIterator::new(self)
}
#[inline(always)] fn bit_in_range_iter(&'_ self, bit_range: Range<usize>) -> BitIterator<'_> {
BitIterator::with_range(self, bit_range)
}
#[inline(always)] unsafe fn bit_in_unchecked_range_iter(&'_ self, bit_range: Range<usize>) -> BitIterator<'_> {
BitIterator::with_range_unchecked(self, bit_range)
}
#[inline] fn try_get_bits_unmasked(&self, begin: usize, len: u8) -> Option<u64> {
let (segment, offset) = (begin / 64, (begin % 64) as u8);
let w1 = self.get(segment)? >> offset;
Some(if offset+len > 64 { let bits_in_w1 = 64-offset; w1 | (self.get(segment+1)? << bits_in_w1)
} else {
w1
})
}
#[inline] unsafe fn get_bits_unmasked_unchecked(&self, begin: usize, len: u8) -> u64 {
let (segment, offset) = (begin / 64, (begin % 64) as u8);
debug_assert!(segment < self.len());
let w1 = self.get_unchecked(segment) >> offset;
if offset+len > 64 { let bits_in_w1 = 64-offset; debug_assert!(segment+1 < self.len());
w1 | (self.get_unchecked(segment+1) << bits_in_w1)
} else {
w1
}
}
fn init_bits(&mut self, begin: usize, v: u64, len: u8) {
debug_assert!({let f = self.get_bits(begin, len); f == 0 || f == v});
let (segment, offset) = (begin / 64, (begin % 64) as u8);
if offset + len > 64 {
self[segment+1] |= v >> (64-offset);
}
self[segment] |= v << offset;
}
unsafe fn init_bits_unchecked(&mut self, begin: usize, v: u64, len: u8) {
debug_assert!({let f = self.get_bits(begin, len); f == 0 || f == v});
let (segment, offset) = (begin / 64, (begin % 64) as u8);
if offset + len > 64 {
*self.get_unchecked_mut(segment+1) |= v >> (64-offset);
}
*self.get_unchecked_mut(segment) |= v << offset;
}
fn set_bits(&mut self, begin: usize, v: u64, len: u8) {
let (segment, offset) = (begin / 64, (begin % 64) as u8);
let v_mask = n_lowest_bits(len);
if offset + len > 64 {
let shift = 64-offset; set_bits_to(&mut self[segment+1], v>>shift, v_mask>>shift);
}
set_bits_to(&mut self[segment], v<<offset, v_mask<<offset);
}
unsafe fn set_bits_unchecked(&mut self, begin: usize, v: u64, len: u8) {
let (segment, offset) = (begin / 64, (begin % 64) as u8);
let v_mask = n_lowest_bits(len);
if offset + len > 64 {
let shift = 64-offset; debug_assert!(segment+1 < self.len());
set_bits_to(self.get_unchecked_mut(segment+1), v>>shift, v_mask>>shift);
}
debug_assert!(segment < self.len());
set_bits_to(self.get_unchecked_mut(segment), v<<offset, v_mask<<offset);
}
fn xor_bits(&mut self, begin: usize, v: u64, len: u8) {
let (segment, offset) = (begin / 64, (begin % 64) as u8);
if offset + len > 64 {
let shift = 64-offset;
self[segment+1] ^= v >> shift;
}
self[segment] ^= v << offset;
}
fn conditionally_change_bits<NewValue>(&mut self, new_value: NewValue, begin: usize, v_size: u8) -> u64
where NewValue: FnOnce(u64) -> Option<u64>
{
let (segment, offset) = (begin / 64, (begin % 64) as u64);
let w1 = self[segment]>>offset;
let bits_in_w1 = 64-offset;
let v_mask = n_lowest_bits(v_size);
let r = if v_size as u64 > bits_in_w1 {
w1 | (self[segment+1] << bits_in_w1)
} else {
w1
} & v_mask;
if let Some(v) = new_value(r) {
if v_size as u64 > bits_in_w1 {
set_bits_to(&mut self[segment + 1], v >> bits_in_w1, v_mask >> bits_in_w1);
}
set_bits_to(&mut self[segment], v << offset, v_mask << offset);
}
r
}
fn conditionally_copy_bits<Pred>(&mut self, src: &Self, predicate: Pred, begin: usize, v_size: u8)
where Pred: FnOnce(u64, u64) -> bool
{
let (segment, offset) = (begin / 64, (begin % 64) as u8);
let self_w1 = self[segment]>>offset;
let mut src_w1 = src[segment]>>offset;
let bits_in_w1 = 64-offset;
let v_mask = n_lowest_bits(v_size);
if v_size > bits_in_w1 {
let w2_mask = v_mask >> bits_in_w1;
let self_bits = self_w1 | ((self[segment+1] & w2_mask) << bits_in_w1);
let src_w2 = src[segment+1] & w2_mask;
if predicate(self_bits, src_w1 | (src_w2 << bits_in_w1)) {
set_bits_to(&mut self[segment+1], src_w2, w2_mask);
set_bits_to(&mut self[segment], src_w1 << offset, v_mask << offset);
}
} else {
src_w1 &= v_mask;
if predicate(self_w1 & v_mask, src_w1) {
set_bits_to(&mut self[segment], src_w1 << offset, v_mask << offset);
}
};
}
fn trailing_zero_bits(&self) -> usize {
for (i, v) in self.iter().copied().enumerate() {
if v != 0 { return i * 64 + v.trailing_zeros() as usize; }
}
self.len() * 64 }
fn find_bit_one(&self, start_index: usize) -> Option<usize> {
let mut word_index = start_index / 64;
let mut bits = self.get(word_index)? & !n_lowest_bits((start_index % 64) as u8);
while bits == 0 {
word_index += 1;
bits = *self.get(word_index)?;
}
Some(word_index * 64 + (bits.trailing_zeros() as usize))
}
unsafe fn find_bit_one_unchecked(&self, start_index: usize) -> usize {
let mut word_index = start_index / 64;
debug_assert!(word_index < self.len());
let mut bits = self.get_unchecked(word_index) & !n_lowest_bits((start_index % 64) as u8);
while bits == 0 {
word_index += 1;
debug_assert!(word_index < self.len());
bits = *self.get_unchecked(word_index);
}
word_index * 64 + bits.trailing_zeros() as usize
}
unsafe fn rfind_bit_one_unchecked(&self, start_index: usize) -> usize {
let mut word_index = start_index / 64;
debug_assert!(word_index < self.len());
let mut bits = self.get_unchecked(word_index) & n_lowest_bits_1_64((start_index % 64) as u8 + 1);
while bits == 0 {
word_index -= 1;
debug_assert!(word_index < self.len());
bits = *self.get_unchecked(word_index);
}
word_index * 64 + bits.ilog2() as usize
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fragments_init_set_swap() {
let mut b = Box::<[u64]>::with_zeroed_64bit_segments(2);
assert_eq!(b.as_ref(), [0u64, 0u64]);
b.init_fragment(1, 0b101, 3);
assert_eq!(b.get_fragment(1, 3), 0b101);
assert_eq!(unsafe{b.find_bit_one_unchecked(0)}, 3);
assert_eq!(unsafe{b.find_bit_one_unchecked(3)}, 3);
assert_eq!(unsafe{b.find_bit_one_unchecked(4)}, 5);
assert_eq!(b.get_fragment(0, 3), 0);
assert_eq!(b.get_fragment(2, 3), 0);
b.init_fragment(2, 0b10110_10110_10110_10110_10110_10110, 30);
assert_eq!(b.get_fragment(2, 30), 0b10110_10110_10110_10110_10110_10110);
assert_eq!(b.get_fragment(1, 30), 0);
assert_eq!(b.get_fragment(3, 30), 0);
b.set_fragment(2, 0b11010_11010_11111_00000_11111_10110, 30);
assert_eq!(b.get_fragment(2, 30), 0b11010_11010_11111_00000_11111_10110);
assert_eq!(b.get_fragment(1, 30), 0);
assert_eq!(b.get_fragment(3, 30), 0);
b.swap_fragments(2, 3, 30);
assert_eq!(b.get_fragment(3, 30), 0b11010_11010_11111_00000_11111_10110);
assert_eq!(b.get_fragment(2, 30), 0);
assert_eq!(b.get_fragment(1, 30), 0);
}
#[test]
fn fragments_conditionally_change() {
let mut b = Box::<[u64]>::with_zeroed_64bit_segments(2);
let old = b.conditionally_change_fragment(|old| if 0b101>old {Some(0b101)} else {None}, 1, 3);
assert_eq!(old, 0);
assert_eq!(b.get_fragment(1, 3), 0b101);
assert_eq!(b.get_fragment(0, 3), 0);
assert_eq!(b.get_fragment(2, 3), 0);
let bits = 0b10110_10110_10110_10110_10110_10110;
let old = b.conditionally_change_fragment(|old| if old==bits {Some(bits)} else {None}, 2, 30);
assert_eq!(old, 0);
assert_eq!(b.get_fragment(2, 30), 0);
assert_eq!(b.get_fragment(1, 30), 0);
assert_eq!(b.get_fragment(3, 30), 0);
let old = b.conditionally_change_fragment(|old| if old!=bits {Some(bits)} else {None}, 2, 30);
assert_eq!(old, 0);
assert_eq!(b.get_fragment(2, 30), bits);
assert_eq!(b.get_fragment(1, 30), 0);
assert_eq!(b.get_fragment(3, 30), 0);
let bits2 = 0b1100_11111_00000_10110_00111_11100;
let old = b.conditionally_change_fragment(|old| if old!=bits2 {Some(bits2)} else {None}, 2, 30);
assert_eq!(old, bits);
assert_eq!(b.get_fragment(2, 30), bits2);
assert_eq!(b.get_fragment(1, 30), 0);
assert_eq!(b.get_fragment(3, 30), 0);
}
#[test]
fn fragments_conditionally_copy() {
let src = Box::<[u64]>::with_filled_64bit_segments(2);
let mut dst = Box::<[u64]>::with_zeroed_64bit_segments(2);
dst.conditionally_copy_fragment(&src,
|old, new| { assert_eq!(old, 0); assert_eq!(new, 0b111); old > new},
11, 3);
assert_eq!(dst.get_fragment(11, 3), 0);
assert_eq!(dst.get_fragment(12, 3), 0);
dst.conditionally_copy_fragment(&src,
|old, new| { assert_eq!(old, 0); assert_eq!(new, 0b111); old < new},
11, 3);
assert_eq!(dst.get_fragment(11, 3), 0b111);
assert_eq!(dst.get_fragment(12, 3), 0);
dst.conditionally_copy_fragment(&src,
|old, new| { assert_eq!(old, 0); assert_eq!(new, 0b111); old > new},
21, 3);
assert_eq!(dst.get_fragment(21, 3), 0);
assert_eq!(dst.get_fragment(22, 3), 0);
dst.conditionally_copy_fragment(&src,
|old, new| { assert_eq!(old, 0); assert_eq!(new, 0b111); old < new},
21, 3);
assert_eq!(dst.get_fragment(21, 3), 0b111);
assert_eq!(dst.get_fragment(22, 3), 0);
}
#[test]
fn bits() {
let mut b = Box::<[u64]>::with_filled_64bit_segments(2);
assert_eq!(b.as_ref(), [u64::MAX, u64::MAX]);
assert_eq!(b.count_bit_ones(), 128);
assert_eq!(b.count_bit_zeros(), 0);
assert!(b.get_bit(3));
assert_eq!(b.try_get_bit(3), Some(true));
assert!(b.get_bit(73));
assert_eq!(b.try_get_bit(73), Some(true));
assert_eq!(b.try_get_bit(127), Some(true));
assert_eq!(b.try_get_bit(128), None);
b.clear_bit(73);
assert_eq!(b.count_bit_ones(), 127);
assert_eq!(b.count_bit_zeros(), 1);
assert!(!b.get_bit(73));
assert_eq!(b.try_get_bit(73), Some(false));
assert!(b.get_bit(72));
assert!(b.get_bit(74));
b.set_bit(73);
assert!(b.get_bit(73));
b.xor_bits(72, 0b011, 3);
assert!(!b.get_bit(72));
assert!(!b.get_bit(73));
assert!(b.get_bit(74));
}
#[test]
fn iterators() {
let b = [0b101u64, 0b10u64];
let mut ones = b.bit_ones();
assert_eq!(ones.len(), 3);
assert_eq!(ones.next(), Some(0));
assert_eq!(ones.len(), 2);
assert_eq!(ones.next(), Some(2));
assert_eq!(ones.len(), 1);
assert_eq!(ones.next(), Some(64+1));
assert_eq!(ones.len(), 0);
assert_eq!(ones.next(), None);
assert_eq!(ones.len(), 0);
assert_eq!(ones.next(), None);
assert_eq!(ones.len(), 0);
let mut all = b.bit_iter();
assert_eq!(all.len(), 2*64);
assert_eq!(all.next(), Some(true));
assert_eq!(all.len(), 2*64-1);
assert_eq!(all.next(), Some(false));
assert_eq!(all.len(), 2*64-2);
assert_eq!(all.next(), Some(true));
assert_eq!(all.len(), 2*64-3);
assert_eq!(all.nth(64-4), Some(false)); assert_eq!(all.len(), 64);
assert_eq!(all.next(), Some(false));
assert_eq!(all.len(), 63);
assert_eq!(all.next(), Some(true));
assert_eq!(all.len(), 62);
assert_eq!(all.nth(61), Some(false));
assert_eq!(all.len(), 0);
assert_eq!(all.len(), 0);
assert_eq!(all.next(), None);
assert_eq!(all.len(), 0);
}
}