#[cfg(not(target_pointer_width = "64"))]
use crate::popcount::popcount;
#[cfg(target_pointer_width = "64")]
use crate::popcount::popcountll;
#[cfg(target_pointer_width = "64")]
pub const BITMAP_NB_BITS: usize = 64;
#[cfg(not(target_pointer_width = "64"))]
pub const BITMAP_NB_BITS: usize = 32;
#[cfg(target_pointer_width = "64")]
const BUCKET_SHIFT: usize = 6;
#[cfg(not(target_pointer_width = "64"))]
const BUCKET_SHIFT: usize = 5;
const BUCKET_MASK: usize = BITMAP_NB_BITS - 1;
#[cfg(target_pointer_width = "64")]
pub type Bitmap = u64;
#[cfg(not(target_pointer_width = "64"))]
pub type Bitmap = u32;
#[inline]
pub fn sparse_ibucket(ibucket: usize) -> usize {
ibucket >> BUCKET_SHIFT
}
#[inline]
pub fn index_in_sparse_bucket(ibucket: usize) -> u8 {
(ibucket & BUCKET_MASK) as u8
}
#[inline]
pub fn nb_sparse_buckets(bucket_count: usize) -> usize {
if bucket_count == 0 {
return 0;
}
let rounded = crate::util::round_up_to_power_of_two(bucket_count);
core::cmp::max(1, sparse_ibucket(rounded))
}
#[inline]
pub(crate) fn popcount_bitmap(val: Bitmap) -> u8 {
#[cfg(target_pointer_width = "64")]
{
popcountll(val) as u8
}
#[cfg(not(target_pointer_width = "64"))]
{
popcount(val) as u8
}
}
pub struct SparseArray<T> {
values: Vec<T>,
bitmap_vals: Bitmap,
bitmap_deleted_vals: Bitmap,
last_array: bool,
}
impl<T> SparseArray<T> {
pub fn new() -> Self {
Self {
values: Vec::new(),
bitmap_vals: 0,
bitmap_deleted_vals: 0,
last_array: false,
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.values.is_empty()
}
#[inline]
pub fn len(&self) -> usize {
self.values.len()
}
#[cfg(test)]
#[inline]
pub fn capacity(&self) -> usize {
self.values.capacity()
}
#[inline]
pub fn last(&self) -> bool {
self.last_array
}
#[inline]
pub fn set_as_last(&mut self) {
self.last_array = true;
}
#[inline]
pub fn bitmap_vals(&self) -> Bitmap {
self.bitmap_vals
}
#[inline]
pub fn bitmap_deleted_vals(&self) -> Bitmap {
self.bitmap_deleted_vals
}
#[inline]
pub fn values(&self) -> &[T] {
&self.values
}
#[inline]
pub fn values_mut(&mut self) -> &mut [T] {
&mut self.values
}
#[inline]
pub fn has_value(&self, index: u8) -> bool {
(self.bitmap_vals & (1 as Bitmap) << index) != 0
}
#[inline]
pub fn has_deleted_value(&self, index: u8) -> bool {
(self.bitmap_deleted_vals & (1 as Bitmap) << index) != 0
}
#[inline]
pub fn index_to_offset(&self, index: u8) -> usize {
let mask = ((1 as Bitmap) << index).wrapping_sub(1);
popcount_bitmap(self.bitmap_vals & mask) as usize
}
pub fn offset_to_index(&self, offset: usize) -> u8 {
let mut bitmap = self.bitmap_vals;
let mut index: u8 = 0;
let mut nb_ones = 0;
while bitmap != 0 {
if bitmap & 0x1 == 1 {
if nb_ones == offset {
break;
}
nb_ones += 1;
}
index += 1;
bitmap >>= 1;
}
index
}
#[inline]
pub fn value(&self, index: u8) -> &T {
&self.values[self.index_to_offset(index)]
}
#[inline]
pub fn value_mut(&mut self, index: u8) -> &mut T {
let offset = self.index_to_offset(index);
&mut self.values[offset]
}
pub fn set(&mut self, index: u8, value: T, growth_step: usize) -> usize {
debug_assert!(!self.has_value(index));
let offset = self.index_to_offset(index);
if self.values.len() == self.values.capacity() {
self.values.reserve_exact(growth_step.max(1));
}
self.values.insert(offset, value);
self.bitmap_vals |= (1 as Bitmap) << index;
self.bitmap_deleted_vals &= !((1 as Bitmap) << index);
offset
}
pub fn remove_value(&mut self, offset: usize, index: u8) -> T {
debug_assert!(self.has_value(index));
let value = self.values.remove(offset);
self.bitmap_vals &= !((1 as Bitmap) << index);
self.bitmap_deleted_vals |= (1 as Bitmap) << index;
value
}
pub fn erase_all(&mut self) -> usize {
let removed = self.values.len();
self.values.clear();
self.bitmap_deleted_vals |= self.bitmap_vals;
self.bitmap_vals = 0;
removed
}
#[inline]
pub fn into_values(self) -> Vec<T> {
self.values
}
pub fn from_parts(bitmap_vals: Bitmap, bitmap_deleted_vals: Bitmap, values: Vec<T>) -> Self {
debug_assert_eq!(popcount_bitmap(bitmap_vals) as usize, values.len());
Self {
values,
bitmap_vals,
bitmap_deleted_vals,
last_array: false,
}
}
}
impl<T: Clone> Clone for SparseArray<T> {
fn clone(&self) -> Self {
Self {
values: self.values.clone(),
bitmap_vals: self.bitmap_vals,
bitmap_deleted_vals: self.bitmap_deleted_vals,
last_array: self.last_array,
}
}
}
impl<T> Default for SparseArray<T> {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn capacity_grows_by_fixed_step() {
const STEP: usize = 4;
let mut array: SparseArray<i32> = SparseArray::new();
for index in 0..8u8 {
array.set(index, index as i32, STEP);
let expected = array.len().div_ceil(STEP) * STEP;
assert_eq!(array.capacity(), expected, "at len {}", array.len());
}
}
#[test]
fn a_larger_step_reserves_more_slack() {
let mut high: SparseArray<i32> = SparseArray::new();
let mut low: SparseArray<i32> = SparseArray::new();
high.set(0, 0, 2);
low.set(0, 0, 8);
assert_eq!(high.capacity(), 2);
assert_eq!(low.capacity(), 8);
}
}