#[cfg(feature = "rayon")]
use crate::RAYON_MIN_LEN;
use crate::prelude::{bit_field_slice::*, *};
use crate::utils::{
CannotCastToAtomicError, transmute_boxed_slice_from_atomic, transmute_boxed_slice_into_atomic,
transmute_vec_from_atomic, transmute_vec_into_atomic,
};
use crate::{panic_if_out_of_bounds, panic_if_value};
use anyhow::{Result, bail};
use common_traits::{
AsBytes, Atomic, AtomicInteger, AtomicUnsignedInt, CastableInto, IntoAtomic, invariant_eq,
};
use mem_dbg::*;
#[cfg(feature = "rayon")]
use rayon::prelude::*;
use std::iter::FusedIterator;
use std::sync::atomic::{Ordering, compiler_fence, fence};
use value_traits::slices::{SliceByValue, SliceByValueMut};
#[macro_export]
macro_rules! bit_field_vec {
($w:expr) => {
$crate::bits::BitFieldVec::<usize, _>::new($w, 0)
};
($w:expr; $n:expr; $v:expr) => {
compile_error!(
"the syntax bit_field_vec![width; length; value] has been removed: use bit_field_vec![width => value; length] instead"
)
};
($w:expr => $v:expr; $n:expr) => {
{
let mut bit_field_vec = $crate::bits::BitFieldVec::<usize, _>::with_capacity($w, $n);
let v: usize = $v;
bit_field_vec.resize($n, v);
bit_field_vec
}
};
($w:expr; $($x:expr),+ $(,)?) => {
{
let mut b = $crate::bits::BitFieldVec::<usize, _>::with_capacity($w, [$($x),+].len());
$(
let x: usize = $x;
b.push(x);
)*
b
}
};
}
#[derive(Debug, Clone, Copy, Hash, MemDbg, MemSize, value_traits::Subslices)]
#[value_traits_subslices(bound = "B: AsRef<[W]>")]
#[derive(value_traits::SubslicesMut)]
#[value_traits_subslices_mut(bound = "B: AsRef<[W]> + AsMut<[W]>")]
#[cfg_attr(feature = "epserde", derive(epserde::Epserde))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BitFieldVec<W: Word = usize, B = Vec<W>> {
bits: B,
bit_width: usize,
mask: W,
len: usize,
}
fn mask<W: Word>(bit_width: usize) -> W {
if bit_width == 0 {
W::ZERO
} else {
W::MAX >> W::BITS.checked_sub(bit_width).expect("bit_width > W::BITS")
}
}
impl<W: Word, B> BitFieldVec<W, B> {
#[inline(always)]
pub unsafe fn from_raw_parts(bits: B, bit_width: usize, len: usize) -> Self {
Self {
bits,
bit_width,
mask: mask(bit_width),
len,
}
}
#[inline(always)]
pub fn into_raw_parts(self) -> (B, usize, usize) {
(self.bits, self.bit_width, self.len)
}
#[inline(always)]
pub unsafe fn map<W2: Word, B2>(self, f: impl FnOnce(B) -> B2) -> BitFieldVec<W2, B2> {
BitFieldVec {
bits: f(self.bits),
bit_width: self.bit_width,
mask: mask(self.bit_width),
len: self.len,
}
}
}
impl<W: Word, B: AsRef<[W]>> BitFieldVec<W, B> {
pub fn addr_of(&self, index: usize) -> *const W {
let start_bit = index * self.bit_width;
let word_index = start_bit / W::BITS;
(&self.bits.as_ref()[word_index]) as *const _
}
pub fn get_unaligned(&self, index: usize) -> W {
assert!(
self.bit_width <= W::BITS - 8 + 2
|| self.bit_width == W::BITS - 8 + 4
|| self.bit_width == W::BITS
);
panic_if_out_of_bounds!(index, self.len);
assert!(
(index * self.bit_width) / W::BYTES + W::BYTES <= self.bits.as_ref().len() * W::BYTES
);
unsafe { self.get_unaligned_unchecked(index) }
}
pub unsafe fn get_unaligned_unchecked(&self, index: usize) -> W {
debug_assert!(
self.bit_width <= W::BITS - 8 + 2
|| self.bit_width == W::BITS - 8 + 4
|| self.bit_width == W::BITS
);
let base_ptr = self.bits.as_ref().as_ptr() as *const u8;
let start_bit = index * self.bit_width;
debug_assert!(start_bit / W::BYTES + W::BYTES <= self.bits.as_ref().len() * W::BYTES);
let ptr = unsafe { base_ptr.add(start_bit / 8) } as *const W;
let word = unsafe { core::ptr::read_unaligned(ptr) };
(word >> (start_bit % 8)) & self.mask
}
pub fn as_slice(&self) -> &[W] {
self.bits.as_ref()
}
}
pub struct ChunksMut<'a, W: Word> {
remaining: usize,
bit_width: usize,
chunk_size: usize,
iter: std::slice::ChunksMut<'a, W>,
}
impl<'a, W: Word> Iterator for ChunksMut<'a, W> {
type Item = BitFieldVec<W, &'a mut [W]>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|chunk| {
let size = Ord::min(self.chunk_size, self.remaining);
let next = unsafe { BitFieldVec::from_raw_parts(chunk, self.bit_width, size) };
self.remaining -= size;
next
})
}
}
impl<'a, W: Word> ExactSizeIterator for ChunksMut<'a, W> where
std::slice::ChunksMut<'a, W>: ExactSizeIterator
{
}
impl<'a, W: Word> FusedIterator for ChunksMut<'a, W> where
std::slice::ChunksMut<'a, W>: FusedIterator
{
}
impl<W: Word, B: AsRef<[W]>> BitFieldVec<W, B> {}
impl<W: Word> BitFieldVec<W, Vec<W>> {
pub fn new(bit_width: usize, len: usize) -> Self {
let n_of_words = Ord::max(1, (len * bit_width).div_ceil(W::BITS));
Self {
bits: vec![W::ZERO; n_of_words],
bit_width,
mask: mask(bit_width),
len,
}
}
pub fn new_unaligned(bit_width: usize, len: usize) -> Self {
let n_of_words = (len * bit_width).div_ceil(W::BITS);
Self {
bits: vec![W::ZERO; n_of_words + 1],
bit_width,
mask: mask(bit_width),
len,
}
}
pub fn with_capacity(bit_width: usize, capacity: usize) -> Self {
let n_of_words = Ord::max(1, (capacity * bit_width).div_ceil(W::BITS));
Self {
bits: Vec::with_capacity(n_of_words),
bit_width,
mask: mask(bit_width),
len: 0,
}
}
pub unsafe fn set_len(&mut self, len: usize) {
debug_assert!(len * self.bit_width <= self.bits.len() * W::BITS);
self.len = len;
}
pub fn clear(&mut self) {
self.len = 0;
}
pub fn bit_width(&self) -> usize {
debug_assert!(self.bit_width <= W::BITS);
self.bit_width
}
pub fn mask(&self) -> W {
self.mask
}
pub fn from_slice<SW>(slice: &impl BitFieldSlice<SW>) -> Result<Self>
where
SW: Word + CastableInto<W>,
{
let mut max_len: usize = 0;
for i in 0..slice.len() {
max_len = Ord::max(max_len, unsafe {
slice.get_value_unchecked(i).len() as usize
});
}
if max_len > W::BITS {
bail!(
"Cannot convert a slice of bit width {} into a slice with W = {}",
max_len,
std::any::type_name::<W>()
);
}
let mut result = Self::new(max_len, slice.len());
for i in 0..slice.len() {
unsafe { result.set_value_unchecked(i, slice.get_value_unchecked(i).cast()) };
}
Ok(result)
}
pub fn push(&mut self, value: W) {
panic_if_value!(value, self.mask, self.bit_width);
if (self.len + 1) * self.bit_width > self.bits.len() * W::BITS {
self.bits.push(W::ZERO);
}
unsafe {
self.set_value_unchecked(self.len, value);
}
self.len += 1;
}
pub fn resize(&mut self, new_len: usize, value: W) {
panic_if_value!(value, self.mask, self.bit_width);
if new_len > self.len {
if new_len * self.bit_width > self.bits.len() * W::BITS {
self.bits
.resize((new_len * self.bit_width).div_ceil(W::BITS), W::ZERO);
}
for i in self.len..new_len {
unsafe {
self.set_value_unchecked(i, value);
}
}
}
self.len = new_len;
}
pub fn pop(&mut self) -> Option<W> {
if self.len == 0 {
return None;
}
let value = self.index_value(self.len - 1);
self.len -= 1;
Some(value)
}
}
impl<W: Word, B: AsRef<[W]> + AsMut<[W]>> BitFieldVec<W, B> {}
impl<W: Word, T> BitWidth<W> for BitFieldVec<W, T> {
#[inline(always)]
fn bit_width(&self) -> usize {
debug_assert!(self.bit_width <= W::BITS);
self.bit_width
}
}
impl<W: Word, B: AsRef<[W]>> SliceByValue for BitFieldVec<W, B> {
type Value = W;
#[inline(always)]
fn len(&self) -> usize {
self.len
}
unsafe fn get_value_unchecked(&self, index: usize) -> W {
let pos = index * self.bit_width;
let word_index = pos / W::BITS;
let bit_index = pos % W::BITS;
let bits = self.bits.as_ref();
unsafe {
if bit_index + self.bit_width <= W::BITS {
(*bits.get_unchecked(word_index) >> bit_index) & self.mask
} else {
((*bits.get_unchecked(word_index) >> bit_index)
| (*bits.get_unchecked(word_index + 1) << (W::BITS - bit_index)))
& self.mask
}
}
}
}
impl<W: Word, B: AsRef<[W]>> BitFieldSlice<W> for BitFieldVec<W, B> {
fn as_slice(&self) -> &[W] {
self.bits.as_ref()
}
}
impl<W: Word, B: AsRef<[W]> + AsMut<[W]>> BitFieldSliceMut<W> for BitFieldVec<W, B> {
#[inline(always)]
fn mask(&self) -> W {
self.mask
}
fn reset(&mut self) {
let bit_len = self.len * self.bit_width;
let full_words = bit_len / W::BITS;
let residual = bit_len % W::BITS;
let bits = self.bits.as_mut();
bits[..full_words].iter_mut().for_each(|x| *x = W::ZERO);
if residual != 0 {
bits[full_words] &= W::MAX << residual;
}
}
#[cfg(feature = "rayon")]
fn par_reset(&mut self) {
let bit_len = self.len * self.bit_width;
let full_words = bit_len / W::BITS;
let residual = bit_len % W::BITS;
let bits = self.bits.as_mut();
bits[..full_words]
.par_iter_mut()
.with_min_len(RAYON_MIN_LEN)
.for_each(|x| *x = W::ZERO);
if residual != 0 {
bits[full_words] &= W::MAX << residual;
}
}
fn as_mut_slice(&mut self) -> &mut [W] {
self.bits.as_mut()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ChunksMutError<W: Word> {
bit_width: usize,
chunk_size: usize,
_marker: core::marker::PhantomData<W>,
}
impl<W: Word> core::fmt::Display for ChunksMutError<W> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"try_chunks_mut needs that the bit width ({}) times the chunk size ({}) is a multiple of W::BITS ({}) to return more than one chunk",
self.bit_width,
self.chunk_size,
W::BITS
)
}
}
impl<W: Word> std::error::Error for ChunksMutError<W> {}
impl<W: Word, B: AsRef<[W]> + AsMut<[W]>> SliceByValueMut for BitFieldVec<W, B> {
#[inline(always)]
fn set_value(&mut self, index: usize, value: W) {
panic_if_out_of_bounds!(index, self.len);
panic_if_value!(value, self.mask, self.bit_width);
unsafe {
self.set_value_unchecked(index, value);
}
}
unsafe fn set_value_unchecked(&mut self, index: usize, value: W) {
let pos = index * self.bit_width;
let word_index = pos / W::BITS;
let bit_index = pos % W::BITS;
let bits = self.bits.as_mut();
unsafe {
if bit_index + self.bit_width <= W::BITS {
let mut word = *bits.get_unchecked_mut(word_index);
word &= !(self.mask << bit_index);
word |= value << bit_index;
*bits.get_unchecked_mut(word_index) = word;
} else {
let mut word = *bits.get_unchecked_mut(word_index);
word &= (W::ONE << bit_index) - W::ONE;
word |= value << bit_index;
*bits.get_unchecked_mut(word_index) = word;
let mut word = *bits.get_unchecked_mut(word_index + 1);
word &= !(self.mask >> (W::BITS - bit_index));
word |= value >> (W::BITS - bit_index);
*bits.get_unchecked_mut(word_index + 1) = word;
}
}
}
fn replace_value(&mut self, index: usize, value: W) -> W {
panic_if_out_of_bounds!(index, self.len);
panic_if_value!(value, self.mask, self.bit_width);
unsafe { self.replace_value_unchecked(index, value) }
}
unsafe fn replace_value_unchecked(&mut self, index: usize, value: W) -> W {
let pos = index * self.bit_width;
let word_index = pos / W::BITS;
let bit_index = pos % W::BITS;
let bits = self.bits.as_mut();
unsafe {
if bit_index + self.bit_width <= W::BITS {
let mut word = *bits.get_unchecked_mut(word_index);
let old_value = (word >> bit_index) & self.mask;
word &= !(self.mask << bit_index);
word |= value << bit_index;
*bits.get_unchecked_mut(word_index) = word;
old_value
} else {
let mut word = *bits.get_unchecked_mut(word_index);
let mut old_value = word >> bit_index;
word &= (W::ONE << bit_index) - W::ONE;
word |= value << bit_index;
*bits.get_unchecked_mut(word_index) = word;
let mut word = *bits.get_unchecked_mut(word_index + 1);
old_value |= word << (W::BITS - bit_index);
word &= !(self.mask >> (W::BITS - bit_index));
word |= value >> (W::BITS - bit_index);
*bits.get_unchecked_mut(word_index + 1) = word;
old_value & self.mask
}
}
}
fn copy(&self, from: usize, dst: &mut Self, to: usize, len: usize) {
assert_eq!(
self.bit_width, dst.bit_width,
"Bit widths must be equal (self: {}, dest: {})",
self.bit_width, dst.bit_width
);
let len = Ord::min(Ord::min(len, dst.len - to), self.len - from);
if len == 0 {
return;
}
let bit_width = Ord::min(self.bit_width, dst.bit_width);
let bit_len = len * bit_width;
let src_pos = from * self.bit_width;
let dst_pos = to * dst.bit_width;
let src_bit = src_pos % W::BITS;
let dst_bit = dst_pos % W::BITS;
let src_first_word = src_pos / W::BITS;
let dst_first_word = dst_pos / W::BITS;
let src_last_word = (src_pos + bit_len - 1) / W::BITS;
let dst_last_word = (dst_pos + bit_len - 1) / W::BITS;
let source = self.bits.as_ref();
let dest = dst.bits.as_mut();
if src_first_word == src_last_word && dst_first_word == dst_last_word {
let mask = W::MAX >> (W::BITS - bit_len);
let word = (source[src_first_word] >> src_bit) & mask;
dest[dst_first_word] &= !(mask << dst_bit);
dest[dst_first_word] |= word << dst_bit;
} else if src_first_word == src_last_word {
let mask = W::MAX >> (W::BITS - bit_len);
let word = (source[src_first_word] >> src_bit) & mask;
dest[dst_first_word] &= !(mask << dst_bit);
dest[dst_first_word] |= (word & mask) << dst_bit;
dest[dst_last_word] &= !(mask >> (W::BITS - dst_bit));
dest[dst_last_word] |= (word & mask) >> (W::BITS - dst_bit);
} else if dst_first_word == dst_last_word {
let mask = W::MAX >> (W::BITS - bit_len);
let word = ((source[src_first_word] >> src_bit)
| (source[src_last_word] << (W::BITS - src_bit)))
& mask;
dest[dst_first_word] &= !(mask << dst_bit);
dest[dst_first_word] |= word << dst_bit;
} else if src_bit == dst_bit {
let mask = W::MAX << dst_bit;
dest[dst_first_word] &= !mask;
dest[dst_first_word] |= source[src_first_word] & mask;
dest[(1 + dst_first_word)..dst_last_word]
.copy_from_slice(&source[(1 + src_first_word)..src_last_word]);
let residual =
bit_len - (W::BITS - src_bit) - (dst_last_word - dst_first_word - 1) * W::BITS;
let mask = W::MAX >> (W::BITS - residual);
dest[dst_last_word] &= !mask;
dest[dst_last_word] |= source[src_last_word] & mask;
} else if src_bit < dst_bit {
let dst_mask = W::MAX << dst_bit;
let src_mask = W::MAX << src_bit;
let shift = dst_bit - src_bit;
dest[dst_first_word] &= !dst_mask;
dest[dst_first_word] |= (source[src_first_word] & src_mask) << shift;
let mut word = source[src_first_word] >> (W::BITS - shift);
for i in 1..dst_last_word - dst_first_word {
dest[dst_first_word + i] = word | (source[src_first_word + i] << shift);
word = source[src_first_word + i] >> (W::BITS - shift);
}
let residual =
bit_len - (W::BITS - dst_bit) - (dst_last_word - dst_first_word - 1) * W::BITS;
let mask = W::MAX >> (W::BITS - residual);
dest[dst_last_word] &= !mask;
dest[dst_last_word] |= source[src_last_word] & mask;
} else {
let dst_mask = W::MAX << dst_bit;
let src_mask = W::MAX << src_bit;
let shift = src_bit - dst_bit;
dest[dst_first_word] &= !dst_mask;
dest[dst_first_word] |= (source[src_first_word] & src_mask) >> shift;
dest[dst_first_word] |= source[src_first_word + 1] << (W::BITS - shift);
let mut word = source[src_first_word + 1] >> shift;
for i in 1..dst_last_word - dst_first_word {
word |= source[src_first_word + i + 1] << (W::BITS - shift);
dest[dst_first_word + i] = word;
word = source[src_first_word + i + 1] >> shift;
}
word |= source[src_last_word] << (W::BITS - shift);
let residual =
bit_len - (W::BITS - dst_bit) - (dst_last_word - dst_first_word - 1) * W::BITS;
let mask = W::MAX >> (W::BITS - residual);
dest[dst_last_word] &= !mask;
dest[dst_last_word] |= word & mask;
}
}
#[inline]
unsafe fn apply_in_place_unchecked<F>(&mut self, mut f: F)
where
F: FnMut(Self::Value) -> Self::Value,
{
if self.is_empty() {
return;
}
let bit_width = self.bit_width();
if bit_width == 0 {
return;
}
let mask = self.mask();
let number_of_words: usize = self.bits.as_ref().len();
let last_word_idx = number_of_words.saturating_sub(1);
let mut write_buffer: W = W::ZERO;
let mut read_buffer: W = *unsafe { self.bits.as_ref().get_unchecked(0) };
if bit_width.is_power_of_two() {
let mut bits_in_buffer = 0;
let mut buffer_limit = (self.len() * bit_width) % W::BITS;
if buffer_limit == 0 {
buffer_limit = W::BITS;
}
for read_idx in 1..number_of_words {
let next_word: W = *unsafe { self.bits.as_ref().get_unchecked(read_idx) };
loop {
let next_bits_in_buffer = bits_in_buffer + bit_width;
if next_bits_in_buffer > W::BITS {
break;
}
let value = read_buffer & mask;
read_buffer >>= bit_width;
let new_value = f(value);
write_buffer |= new_value << bits_in_buffer;
bits_in_buffer = next_bits_in_buffer;
}
invariant_eq!(read_buffer, W::ZERO);
*unsafe { self.bits.as_mut().get_unchecked_mut(read_idx - 1) } = write_buffer;
read_buffer = next_word;
write_buffer = W::ZERO;
bits_in_buffer = 0;
}
while bits_in_buffer < buffer_limit {
let value = read_buffer & mask;
read_buffer >>= bit_width;
let new_value = f(value);
write_buffer |= new_value << bits_in_buffer;
bits_in_buffer += bit_width;
}
*unsafe { self.bits.as_mut().get_unchecked_mut(last_word_idx) } = write_buffer;
return;
}
let mut global_bit_index: usize = 0;
let mut lower_word_limit = 0;
let mut upper_word_limit = W::BITS;
for word_number in 0..last_word_idx {
while global_bit_index + bit_width <= upper_word_limit {
let offset = global_bit_index - lower_word_limit;
global_bit_index += bit_width;
let element = self.mask() & (read_buffer >> offset);
let new_element = f(element);
write_buffer |= new_element << offset;
}
let next_word = *unsafe { self.bits.as_ref().get_unchecked(word_number + 1) };
let mut new_write_buffer = W::ZERO;
if upper_word_limit != global_bit_index {
let remainder = upper_word_limit - global_bit_index;
let offset = global_bit_index - lower_word_limit;
let element = ((read_buffer >> offset) | (next_word << remainder)) & self.mask();
global_bit_index += bit_width;
let new_element = f(element);
write_buffer |= new_element << offset;
new_write_buffer = new_element >> remainder;
};
read_buffer = next_word;
*unsafe { self.bits.as_mut().get_unchecked_mut(word_number) } = write_buffer;
write_buffer = new_write_buffer;
lower_word_limit = upper_word_limit;
upper_word_limit += W::BITS;
}
let mut offset = global_bit_index - lower_word_limit;
while offset < self.len() * bit_width - global_bit_index {
let element = self.mask() & (read_buffer >> offset);
let new_element = f(element);
write_buffer |= new_element << offset;
offset += bit_width;
}
*unsafe { self.bits.as_mut().get_unchecked_mut(last_word_idx) } = write_buffer;
}
type ChunksMut<'a>
= ChunksMut<'a, W>
where
Self: 'a;
type ChunksMutError = ChunksMutError<W>;
fn try_chunks_mut(
&mut self,
chunk_size: usize,
) -> Result<Self::ChunksMut<'_>, ChunksMutError<W>> {
let len = self.len();
let bit_width = self.bit_width();
if len <= chunk_size || (chunk_size * bit_width) % W::BITS == 0 {
Ok(ChunksMut {
remaining: len,
bit_width: self.bit_width,
chunk_size,
iter: self.bits.as_mut()[..(len * bit_width).div_ceil(W::BITS)]
.chunks_mut((chunk_size * bit_width).div_ceil(W::BITS)),
})
} else {
Err(ChunksMutError {
bit_width,
chunk_size,
_marker: core::marker::PhantomData,
})
}
}
}
#[derive(Debug, Clone, MemDbg, MemSize)]
pub struct BitFieldVecUncheckedIter<'a, W, B>
where
W: Word,
{
vec: &'a BitFieldVec<W, B>,
word_index: usize,
window: W,
fill: usize,
}
impl<'a, W: Word, B: AsRef<[W]>> BitFieldVecUncheckedIter<'a, W, B> {
fn new(vec: &'a BitFieldVec<W, B>, index: usize) -> Self {
if index > vec.len() {
panic!("Start index out of bounds: {} > {}", index, vec.len());
}
let (fill, word_index);
let window = if index == vec.len() {
word_index = 0;
fill = 0;
W::ZERO
} else {
let bit_offset = index * vec.bit_width;
let bit_index = bit_offset % W::BITS;
word_index = bit_offset / W::BITS;
fill = W::BITS - bit_index;
unsafe {
*vec.bits.as_ref().get_unchecked(word_index) >> bit_index
}
};
Self {
vec,
word_index,
window,
fill,
}
}
}
impl<W: Word, B: AsRef<[W]>> crate::traits::UncheckedIterator
for BitFieldVecUncheckedIter<'_, W, B>
{
type Item = W;
unsafe fn next_unchecked(&mut self) -> W {
let bit_width = self.vec.bit_width;
if self.fill >= bit_width {
self.fill -= bit_width;
let res = self.window & self.vec.mask;
self.window >>= bit_width;
return res;
}
let res = self.window;
self.word_index += 1;
self.window = *unsafe { self.vec.bits.as_ref().get_unchecked(self.word_index) };
let res = (res | (self.window << self.fill)) & self.vec.mask;
let used = bit_width - self.fill;
self.window >>= used;
self.fill = W::BITS - used;
res
}
}
impl<'a, W: Word, B: AsRef<[W]>> IntoUncheckedIterator for &'a BitFieldVec<W, B> {
type Item = W;
type IntoUncheckedIter = BitFieldVecUncheckedIter<'a, W, B>;
fn into_unchecked_iter_from(self, from: usize) -> Self::IntoUncheckedIter {
BitFieldVecUncheckedIter::new(self, from)
}
}
#[derive(Debug, Clone, MemDbg, MemSize)]
pub struct BitFieldVecUncheckedBackIter<'a, W: Word, B> {
vec: &'a BitFieldVec<W, B>,
word_index: usize,
window: W,
fill: usize,
}
impl<'a, W: Word, B: AsRef<[W]>> BitFieldVecUncheckedBackIter<'a, W, B> {
fn new(vec: &'a BitFieldVec<W, B>, index: usize) -> Self {
if index > vec.len() {
panic!("Start index out of bounds: {} > {}", index, vec.len());
}
let (word_index, fill);
let window = if index == 0 {
word_index = 0;
fill = 0;
W::ZERO
} else {
let bit_offset = (index * vec.bit_width).saturating_sub(1);
let bit_index = bit_offset % W::BITS;
word_index = bit_offset / W::BITS;
fill = bit_index + 1;
unsafe {
*vec.bits.as_ref().get_unchecked(word_index) << (W::BITS - fill)
}
};
Self {
vec,
word_index,
window,
fill,
}
}
}
impl<W: Word, B: AsRef<[W]>> crate::traits::UncheckedIterator
for BitFieldVecUncheckedBackIter<'_, W, B>
{
type Item = W;
unsafe fn next_unchecked(&mut self) -> W {
let bit_width = self.vec.bit_width;
if self.fill >= bit_width {
self.fill -= bit_width;
self.window = self.window.rotate_left(bit_width as u32);
return self.window & self.vec.mask;
}
let mut res = self.window.rotate_left(self.fill as u32);
self.word_index -= 1;
self.window = *unsafe { self.vec.bits.as_ref().get_unchecked(self.word_index) };
let used = bit_width - self.fill;
res = ((res << used) | (self.window >> (W::BITS - used))) & self.vec.mask;
self.window <<= used;
self.fill = W::BITS - used;
res
}
}
impl<'a, W: Word, B: AsRef<[W]>> IntoUncheckedBackIterator for &'a BitFieldVec<W, B> {
type Item = W;
type IntoUncheckedIterBack = BitFieldVecUncheckedBackIter<'a, W, B>;
fn into_unchecked_iter_back(self) -> Self::IntoUncheckedIterBack {
BitFieldVecUncheckedBackIter::new(self, self.len())
}
fn into_unchecked_iter_back_from(self, from: usize) -> Self::IntoUncheckedIterBack {
BitFieldVecUncheckedBackIter::new(self, from)
}
}
#[derive(Debug, Clone, MemDbg, MemSize)]
pub struct BitFieldVecIter<'a, W, B>
where
W: Word,
{
unchecked: BitFieldVecUncheckedIter<'a, W, B>,
range: core::ops::Range<usize>,
}
impl<'a, W: Word, B: AsRef<[W]>> BitFieldVecIter<'a, W, B> {
fn new(vec: &'a BitFieldVec<W, B>, from: usize) -> Self {
let len = vec.len();
if from > len {
panic!("Start index out of bounds: {} > {}", from, len);
}
Self {
unchecked: BitFieldVecUncheckedIter::new(vec, from),
range: from..len,
}
}
}
impl<W: Word, B: AsRef<[W]>> Iterator for BitFieldVecIter<'_, W, B> {
type Item = W;
fn next(&mut self) -> Option<Self::Item> {
if self.range.is_empty() {
return None;
}
let res = unsafe { self.unchecked.next_unchecked() };
self.range.start += 1;
Some(res)
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.range.len(), Some(self.range.len()))
}
}
impl<W: Word, B: AsRef<[W]>> ExactSizeIterator for BitFieldVecIter<'_, W, B> {
#[inline(always)]
fn len(&self) -> usize {
self.range.len()
}
}
impl<W: Word, B: AsRef<[W]>> FusedIterator for BitFieldVecIter<'_, W, B> {}
impl<W: Word, B: AsRef<[W]>> DoubleEndedIterator for BitFieldVecIter<'_, W, B> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.range.is_empty() {
return None;
}
self.range.end -= 1;
let res = unsafe { self.unchecked.vec.get_value_unchecked(self.range.end) };
Some(res)
}
}
impl<W: Word, B: AsRef<[W]>, C: AsRef<[W]>> PartialEq<BitFieldVec<W, C>> for BitFieldVec<W, B> {
fn eq(&self, other: &BitFieldVec<W, C>) -> bool {
if self.bit_width() != other.bit_width() {
return false;
}
if self.len() != other.len() {
return false;
}
let bit_len = self.len() * self.bit_width();
if self.bits.as_ref()[..bit_len / W::BITS] != other.bits.as_ref()[..bit_len / W::BITS] {
return false;
}
let residual = bit_len % W::BITS;
residual == 0
|| (self.bits.as_ref()[bit_len / W::BITS] ^ other.bits.as_ref()[bit_len / W::BITS])
<< (W::BITS - residual)
== W::ZERO
}
}
impl<'a, W: Word, B: AsRef<[W]>> IntoIterator for &'a BitFieldVec<W, B> {
type Item = W;
type IntoIter = BitFieldVecIter<'a, W, B>;
fn into_iter(self) -> Self::IntoIter {
BitFieldVecIter::new(self, 0)
}
}
impl<'a, W: Word, B: AsRef<[W]>> IntoIteratorFrom for &'a BitFieldVec<W, B> {
type IntoIterFrom = BitFieldVecIter<'a, W, B>;
fn into_iter_from(self, from: usize) -> Self::IntoIterFrom {
BitFieldVecIter::new(self, from)
}
}
impl<W: Word> core::iter::Extend<W> for BitFieldVec<W, Vec<W>> {
fn extend<T: IntoIterator<Item = W>>(&mut self, iter: T) {
for value in iter {
self.push(value);
}
}
}
impl<W: Word, B: AsRef<[W]>> BitFieldVec<W, B> {
pub fn iter_from(&self, from: usize) -> BitFieldVecIter<'_, W, B> {
BitFieldVecIter::new(self, from)
}
pub fn iter(&self) -> BitFieldVecIter<'_, W, B> {
self.iter_from(0)
}
}
#[derive(Debug, Clone, Hash, MemDbg, MemSize)]
#[cfg_attr(feature = "epserde", derive(epserde::Epserde))]
pub struct AtomicBitFieldVec<W: Word + IntoAtomic = usize, B = Vec<<W as IntoAtomic>::AtomicType>> {
bits: B,
bit_width: usize,
mask: W,
len: usize,
}
impl<W: Word + IntoAtomic, B> AtomicBitFieldVec<W, B> {
#[inline(always)]
pub unsafe fn from_raw_parts(bits: B, bit_width: usize, len: usize) -> Self {
Self {
bits,
bit_width,
mask: mask(bit_width),
len,
}
}
#[inline(always)]
pub fn into_raw_parts(self) -> (B, usize, usize) {
(self.bits, self.bit_width, self.len)
}
pub fn mask(&self) -> W {
self.mask
}
}
impl<W: Word + IntoAtomic, B: AsRef<[W::AtomicType]>> AtomicBitFieldVec<W, B> {
pub fn as_slice(&self) -> &[W::AtomicType] {
self.bits.as_ref()
}
}
impl<W: Word + IntoAtomic> AtomicBitFieldVec<W>
where
W::AtomicType: AtomicUnsignedInt,
{
pub fn new(bit_width: usize, len: usize) -> AtomicBitFieldVec<W> {
let n_of_words = Ord::max(1, (len * bit_width).div_ceil(W::BITS));
AtomicBitFieldVec::<W> {
bits: (0..n_of_words)
.map(|_| W::AtomicType::new(W::ZERO))
.collect(),
bit_width,
mask: mask(bit_width),
len,
}
}
}
impl<W: Word + IntoAtomic, B> BitWidth<W::AtomicType> for AtomicBitFieldVec<W, B> {
#[inline(always)]
fn bit_width(&self) -> usize {
debug_assert!(self.bit_width <= W::BITS);
self.bit_width
}
}
impl<W: Word + IntoAtomic, T: AsRef<[W::AtomicType]>> SliceByValue for AtomicBitFieldVec<W, T>
where
W::AtomicType: AtomicUnsignedInt + AsBytes,
Self: AtomicBitFieldSlice<W>,
{
type Value = W;
#[inline(always)]
fn len(&self) -> usize {
self.len
}
unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
unsafe { self.get_atomic_unchecked(index, Ordering::Relaxed) }
}
}
impl<W: Word + IntoAtomic, T: AsRef<[W::AtomicType]>> AtomicBitFieldSlice<W>
for AtomicBitFieldVec<W, T>
where
W::AtomicType: AtomicUnsignedInt + AsBytes,
{
#[inline]
fn len(&self) -> usize {
self.len
}
#[inline]
unsafe fn get_atomic_unchecked(&self, index: usize, order: Ordering) -> W {
let pos = index * self.bit_width;
let word_index = pos / W::BITS;
let bit_index = pos % W::BITS;
let bits = self.bits.as_ref();
unsafe {
if bit_index + self.bit_width <= W::BITS {
(bits.get_unchecked(word_index).load(order) >> bit_index) & self.mask
} else {
((bits.get_unchecked(word_index).load(order) >> bit_index)
| (bits.get_unchecked(word_index + 1).load(order) << (W::BITS - bit_index)))
& self.mask
}
}
}
#[inline(always)]
fn set_atomic(&self, index: usize, value: W, order: Ordering) {
panic_if_out_of_bounds!(index, self.len);
panic_if_value!(value, self.mask, self.bit_width);
unsafe {
self.set_atomic_unchecked(index, value, order);
}
}
#[inline]
unsafe fn set_atomic_unchecked(&self, index: usize, value: W, order: Ordering) {
unsafe {
debug_assert!(self.bit_width <= W::BITS);
let pos = index * self.bit_width;
let word_index = pos / W::BITS;
let bit_index = pos % W::BITS;
let bits = self.bits.as_ref();
if bit_index + self.bit_width <= W::BITS {
let mut current = bits.get_unchecked(word_index).load(order);
loop {
let mut new = current;
new &= !(self.mask << bit_index);
new |= value << bit_index;
match bits
.get_unchecked(word_index)
.compare_exchange(current, new, order, order)
{
Ok(_) => break,
Err(e) => current = e,
}
}
} else {
let mut word = bits.get_unchecked(word_index).load(order);
fence(Ordering::Acquire);
loop {
let mut new = word;
new &= (W::ONE << bit_index) - W::ONE;
new |= value << bit_index;
match bits
.get_unchecked(word_index)
.compare_exchange(word, new, order, order)
{
Ok(_) => break,
Err(e) => word = e,
}
}
fence(Ordering::Release);
compiler_fence(Ordering::SeqCst);
let mut word = bits.get_unchecked(word_index + 1).load(order);
fence(Ordering::Acquire);
loop {
let mut new = word;
new &= !(self.mask >> (W::BITS - bit_index));
new |= value >> (W::BITS - bit_index);
match bits
.get_unchecked(word_index + 1)
.compare_exchange(word, new, order, order)
{
Ok(_) => break,
Err(e) => word = e,
}
}
fence(Ordering::Release);
}
}
}
fn reset_atomic(&mut self, ordering: Ordering) {
let bit_len = self.len * self.bit_width;
let full_words = bit_len / W::BITS;
let residual = bit_len % W::BITS;
let bits = self.bits.as_ref();
bits[..full_words]
.iter()
.for_each(|x| x.store(W::ZERO, ordering));
if residual != 0 {
bits[full_words].fetch_and(W::MAX << residual, ordering);
}
}
#[cfg(feature = "rayon")]
fn par_reset_atomic(&mut self, ordering: Ordering) {
let bit_len = self.len * self.bit_width;
let full_words = bit_len / W::BITS;
let residual = bit_len % W::BITS;
let bits = self.bits.as_ref();
bits[..full_words]
.par_iter()
.with_min_len(RAYON_MIN_LEN)
.for_each(|x| x.store(W::ZERO, ordering));
if residual != 0 {
bits[full_words].fetch_and(W::MAX << residual, ordering);
}
}
}
impl<W: Word + IntoAtomic> From<AtomicBitFieldVec<W, Vec<W::AtomicType>>>
for BitFieldVec<W, Vec<W>>
{
#[inline]
fn from(value: AtomicBitFieldVec<W, Vec<W::AtomicType>>) -> Self {
BitFieldVec {
bits: transmute_vec_from_atomic(value.bits),
len: value.len,
bit_width: value.bit_width,
mask: value.mask,
}
}
}
impl<W: Word + IntoAtomic> From<AtomicBitFieldVec<W, Box<[W::AtomicType]>>>
for BitFieldVec<W, Box<[W]>>
{
#[inline]
fn from(value: AtomicBitFieldVec<W, Box<[W::AtomicType]>>) -> Self {
BitFieldVec {
bits: transmute_boxed_slice_from_atomic(value.bits),
len: value.len,
bit_width: value.bit_width,
mask: value.mask,
}
}
}
impl<'a, W: Word + IntoAtomic> From<AtomicBitFieldVec<W, &'a [W::AtomicType]>>
for BitFieldVec<W, &'a [W]>
{
#[inline]
fn from(value: AtomicBitFieldVec<W, &'a [W::AtomicType]>) -> Self {
BitFieldVec {
bits: unsafe { core::mem::transmute::<&'a [W::AtomicType], &'a [W]>(value.bits) },
len: value.len,
bit_width: value.bit_width,
mask: value.mask,
}
}
}
impl<'a, W: Word + IntoAtomic> From<AtomicBitFieldVec<W, &'a mut [W::AtomicType]>>
for BitFieldVec<W, &'a mut [W]>
{
#[inline]
fn from(value: AtomicBitFieldVec<W, &'a mut [W::AtomicType]>) -> Self {
BitFieldVec {
bits: unsafe {
core::mem::transmute::<&'a mut [W::AtomicType], &'a mut [W]>(value.bits)
},
len: value.len,
bit_width: value.bit_width,
mask: value.mask,
}
}
}
impl<W: Word + IntoAtomic> From<BitFieldVec<W, Vec<W>>>
for AtomicBitFieldVec<W, Vec<W::AtomicType>>
{
#[inline]
fn from(value: BitFieldVec<W, Vec<W>>) -> Self {
AtomicBitFieldVec {
bits: transmute_vec_into_atomic(value.bits),
len: value.len,
bit_width: value.bit_width,
mask: value.mask,
}
}
}
impl<W: Word + IntoAtomic> From<BitFieldVec<W, Box<[W]>>>
for AtomicBitFieldVec<W, Box<[W::AtomicType]>>
{
#[inline]
fn from(value: BitFieldVec<W, Box<[W]>>) -> Self {
AtomicBitFieldVec {
bits: transmute_boxed_slice_into_atomic(value.bits),
len: value.len,
bit_width: value.bit_width,
mask: value.mask,
}
}
}
impl<'a, W: Word + IntoAtomic> TryFrom<BitFieldVec<W, &'a [W]>>
for AtomicBitFieldVec<W, &'a [W::AtomicType]>
{
type Error = CannotCastToAtomicError<W>;
#[inline]
fn try_from(value: BitFieldVec<W, &'a [W]>) -> Result<Self, Self::Error> {
if core::mem::align_of::<W::AtomicType>() != core::mem::align_of::<W>() {
return Err(CannotCastToAtomicError::default());
}
Ok(AtomicBitFieldVec {
bits: unsafe { core::mem::transmute::<&'a [W], &'a [W::AtomicType]>(value.bits) },
len: value.len,
bit_width: value.bit_width,
mask: value.mask,
})
}
}
impl<'a, W: Word + IntoAtomic> TryFrom<BitFieldVec<W, &'a mut [W]>>
for AtomicBitFieldVec<W, &'a mut [W::AtomicType]>
{
type Error = CannotCastToAtomicError<W>;
#[inline]
fn try_from(value: BitFieldVec<W, &'a mut [W]>) -> Result<Self, Self::Error> {
if core::mem::align_of::<W::AtomicType>() != core::mem::align_of::<W>() {
return Err(CannotCastToAtomicError::default());
}
Ok(AtomicBitFieldVec {
bits: unsafe {
core::mem::transmute::<&'a mut [W], &'a mut [W::AtomicType]>(value.bits)
},
len: value.len,
bit_width: value.bit_width,
mask: value.mask,
})
}
}
impl<W: Word> From<BitFieldVec<W, Vec<W>>> for BitFieldVec<W, Box<[W]>> {
fn from(value: BitFieldVec<W, Vec<W>>) -> Self {
BitFieldVec {
bits: value.bits.into_boxed_slice(),
len: value.len,
bit_width: value.bit_width,
mask: value.mask,
}
}
}
impl<W: Word> From<BitFieldVec<W, Box<[W]>>> for BitFieldVec<W, Vec<W>> {
fn from(value: BitFieldVec<W, Box<[W]>>) -> Self {
BitFieldVec {
bits: value.bits.into_vec(),
len: value.len,
bit_width: value.bit_width,
mask: value.mask,
}
}
}
impl<'a, W: Word, B: AsRef<[W]>> value_traits::iter::IterateByValueGat<'a> for BitFieldVec<W, B> {
type Item = W;
type Iter = BitFieldVecIter<'a, W, B>;
}
impl<W: Word, B: AsRef<[W]>> value_traits::iter::IterateByValue for BitFieldVec<W, B> {
fn iter_value(&self) -> <Self as value_traits::iter::IterateByValueGat<'_>>::Iter {
self.iter_from(0)
}
}
impl<'a, W: Word, B: AsRef<[W]>> value_traits::iter::IterateByValueFromGat<'a>
for BitFieldVec<W, B>
{
type Item = W;
type IterFrom = BitFieldVecIter<'a, W, B>;
}
impl<W: Word, B: AsRef<[W]>> value_traits::iter::IterateByValueFrom for BitFieldVec<W, B> {
fn iter_value_from(
&self,
from: usize,
) -> <Self as value_traits::iter::IterateByValueGat<'_>>::Iter {
self.iter_from(from)
}
}
impl<'a, 'b, W: Word, B: AsRef<[W]>> value_traits::iter::IterateByValueGat<'a>
for BitFieldVecSubsliceImpl<'b, W, B>
{
type Item = W;
type Iter = BitFieldVecIter<'a, W, B>;
}
impl<'a, W: Word, B: AsRef<[W]>> value_traits::iter::IterateByValue
for BitFieldVecSubsliceImpl<'a, W, B>
{
fn iter_value(&self) -> <Self as value_traits::iter::IterateByValueGat<'_>>::Iter {
self.slice.iter_from(0)
}
}
impl<'a, 'b, W: Word, B: AsRef<[W]>> value_traits::iter::IterateByValueFromGat<'a>
for BitFieldVecSubsliceImpl<'b, W, B>
{
type Item = W;
type IterFrom = BitFieldVecIter<'a, W, B>;
}
impl<'a, W: Word, B: AsRef<[W]>> value_traits::iter::IterateByValueFrom
for BitFieldVecSubsliceImpl<'a, W, B>
{
fn iter_value_from(
&self,
from: usize,
) -> <Self as value_traits::iter::IterateByValueGat<'_>>::Iter {
self.slice.iter_from(from)
}
}
impl<'a, 'b, W: Word, B: AsRef<[W]>> value_traits::iter::IterateByValueGat<'a>
for BitFieldVecSubsliceImplMut<'b, W, B>
{
type Item = W;
type Iter = BitFieldVecIter<'a, W, B>;
}
impl<'a, W: Word, B: AsRef<[W]>> value_traits::iter::IterateByValue
for BitFieldVecSubsliceImplMut<'a, W, B>
{
fn iter_value(&self) -> <Self as value_traits::iter::IterateByValueGat<'_>>::Iter {
self.slice.iter_from(0)
}
}
impl<'a, 'b, W: Word, B: AsRef<[W]>> value_traits::iter::IterateByValueFromGat<'a>
for BitFieldVecSubsliceImplMut<'b, W, B>
{
type Item = W;
type IterFrom = BitFieldVecIter<'a, W, B>;
}
impl<'a, W: Word, B: AsRef<[W]>> value_traits::iter::IterateByValueFrom
for BitFieldVecSubsliceImplMut<'a, W, B>
{
fn iter_value_from(
&self,
from: usize,
) -> <Self as value_traits::iter::IterateByValueGat<'_>>::Iter {
self.slice.iter_from(from)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_with_capacity() {
let mut b = BitFieldVec::<usize, _>::with_capacity(10, 100);
let capacity = b.bits.capacity();
for _ in 0..100 {
b.push(0);
}
assert_eq!(b.bits.capacity(), capacity);
}
fn copy<W: Word, B: AsRef<[W]>, C: AsRef<[W]> + AsMut<[W]>>(
source: &BitFieldVec<W, B>,
from: usize,
dest: &mut BitFieldVec<W, C>,
to: usize,
len: usize,
) {
let len = Ord::min(Ord::min(len, dest.len - to), source.len - from);
for i in 0..len {
dest.set_value(to + i, source.index_value(from + i));
}
}
#[test]
fn test_copy() {
for src_pattern in 0..8 {
for dst_pattern in 0..8 {
let source = bit_field_vec![3 => src_pattern; 100];
let mut dest_actual = bit_field_vec![3 => dst_pattern; 100];
let mut dest_expected = dest_actual.clone();
source.copy(1, &mut dest_actual, 2, 10);
copy(&source, 1, &mut dest_expected, 2, 10);
assert_eq!(dest_actual, dest_expected);
let source = bit_field_vec![3 => src_pattern; 100];
let mut dest_actual = bit_field_vec![3 => dst_pattern; 100];
let mut dest_expected = dest_actual.clone();
source.copy(1, &mut dest_actual, 20, 10);
copy(&source, 1, &mut dest_expected, 20, 10);
assert_eq!(dest_actual, dest_expected);
let source = bit_field_vec![3 => src_pattern; 100];
let mut dest_actual = bit_field_vec![3 => dst_pattern; 100];
let mut dest_expected = dest_actual.clone();
source.copy(20, &mut dest_actual, 1, 10);
copy(&source, 20, &mut dest_expected, 1, 10);
assert_eq!(dest_actual, dest_expected);
let source = bit_field_vec![3 => src_pattern; 1000];
let mut dest_actual = bit_field_vec![3 => dst_pattern; 1000];
let mut dest_expected = dest_actual.clone();
source.copy(3, &mut dest_actual, 3 + 3 * 128, 40);
copy(&source, 3, &mut dest_expected, 3 + 3 * 128, 40);
assert_eq!(dest_actual, dest_expected);
let source = bit_field_vec![3 => src_pattern; 1000];
let mut dest_actual = bit_field_vec![3 => dst_pattern; 1000];
let mut dest_expected = dest_actual.clone();
source.copy(3, &mut dest_actual, 3 + 3 * 128, 61);
copy(&source, 3, &mut dest_expected, 3 + 3 * 128, 61);
assert_eq!(dest_actual, dest_expected);
let source = bit_field_vec![3 => src_pattern; 1000];
let mut dest_actual = bit_field_vec![3 => dst_pattern; 1000];
let mut dest_expected = dest_actual.clone();
source.copy(3, &mut dest_actual, 7 + 64 * 3, 40);
copy(&source, 3, &mut dest_expected, 7 + 64 * 3, 40);
assert_eq!(dest_actual, dest_expected);
let source = bit_field_vec![3 => src_pattern; 1000];
let mut dest_actual = bit_field_vec![3 => dst_pattern; 1000];
let mut dest_expected = dest_actual.clone();
source.copy(3, &mut dest_actual, 7 + 64 * 3, 40 + 17);
copy(&source, 3, &mut dest_expected, 7 + 64 * 3, 40 + 17);
assert_eq!(dest_actual, dest_expected);
let source = bit_field_vec![3 => src_pattern; 1000];
let mut dest_actual = bit_field_vec![3 => dst_pattern; 1000];
let mut dest_expected = dest_actual.clone();
source.copy(7, &mut dest_actual, 3 + 64 * 3, 40 + 64);
copy(&source, 7, &mut dest_expected, 3 + 64 * 3, 40 + 64);
assert_eq!(dest_actual, dest_expected);
let source = bit_field_vec![3 => src_pattern; 1000];
let mut dest_actual = bit_field_vec![3 => dst_pattern; 1000];
let mut dest_expected = dest_actual.clone();
source.copy(7, &mut dest_actual, 3 + 64 * 3, 40 + 21 + 64);
copy(&source, 7, &mut dest_expected, 3 + 64 * 3, 40 + 21 + 64);
assert_eq!(dest_actual, dest_expected);
}
}
}
}