use crate::{BitVec, EliasFanoVec};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "mem_dbg", derive(mem_dbg::MemSize, mem_dbg::MemDbg))]
pub struct SparseRSVec {
vec: EliasFanoVec,
len: u64,
}
impl SparseRSVec {
#[must_use]
pub fn new(input: &[u64], len: u64) -> Self {
debug_assert!(input.is_sorted(), "input must be sorted");
debug_assert!(
input.windows(2).all(|w| w[0] != w[1]),
"input must be free of duplicates"
);
Self {
vec: EliasFanoVec::from_slice(input),
len,
}
}
#[must_use]
pub fn from_bitvec(input: &BitVec) -> Self {
let len = input.len() as u64;
Self::new(
input
.iter()
.enumerate()
.filter(|&(_, bit)| bit == 1)
.map(|(i, _)| i as u64)
.collect::<Vec<_>>()
.as_slice(),
len,
)
}
#[must_use]
pub fn from_bitvec_inverted(input: &BitVec) -> Self {
let len = input.len() as u64;
Self::new(
input
.iter()
.enumerate()
.filter(|&(_, bit)| bit == 0)
.map(|(i, _)| i as u64)
.collect::<Vec<_>>()
.as_slice(),
len,
)
}
#[must_use]
pub fn is_set_unchecked(&self, i: u64) -> bool {
self.vec.predecessor_unchecked(i) == i
}
#[must_use]
pub fn is_set(&self, i: u64) -> Option<bool> {
if i >= self.len {
None
} else {
Some(self.vec.predecessor(i).is_some_and(|p| p == i))
}
}
#[must_use]
pub fn get_unchecked(&self, i: u64) -> u64 {
self.is_set_unchecked(i).into()
}
#[must_use]
pub fn get(&self, i: u64) -> Option<u64> {
self.is_set(i).map(std::convert::Into::into)
}
#[must_use]
pub fn select1(&self, i: usize) -> u64 {
self.vec.get(i).unwrap_or(self.len)
}
#[must_use]
pub fn rank1(&self, i: u64) -> u64 {
self.vec.rank(i)
}
#[must_use]
pub fn rank0(&self, i: u64) -> u64 {
if i >= self.len {
self.len - self.vec.rank(self.len)
} else {
i - self.vec.rank(i)
}
}
pub fn iter1(&self) -> impl Iterator<Item = u64> + '_ {
self.vec.iter()
}
#[must_use]
pub fn len(&self) -> u64 {
self.len
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[must_use]
pub fn heap_size(&self) -> usize {
self.vec.heap_size()
}
}
impl From<BitVec> for SparseRSVec {
fn from(input: BitVec) -> Self {
Self::from_bitvec_inverted(&input)
}
}
impl<'a> From<&'a BitVec> for SparseRSVec {
fn from(input: &'a BitVec) -> Self {
Self::from_bitvec_inverted(input)
}
}
#[cfg(test)]
mod tests {
use super::SparseRSVec;
use crate::BitVec;
use rand::prelude::StdRng;
use rand::{Rng, SeedableRng};
#[test]
fn test_sparse_rank() {
let sparse = SparseRSVec::new(&[1, 3, 5, 7, 9], 12);
assert_eq!(sparse.rank1(0), 0);
assert_eq!(sparse.rank1(1), 0);
assert_eq!(sparse.rank1(2), 1);
assert_eq!(sparse.rank1(3), 1);
assert_eq!(sparse.rank1(4), 2);
assert_eq!(sparse.rank1(5), 2);
assert_eq!(sparse.rank1(6), 3);
assert_eq!(sparse.rank1(7), 3);
assert_eq!(sparse.rank1(8), 4);
assert_eq!(sparse.rank1(9), 4);
assert_eq!(sparse.rank1(10), 5);
assert_eq!(sparse.rank1(11), 5);
assert_eq!(sparse.rank1(12), 5);
assert_eq!(sparse.rank1(999), 5);
}
#[test]
fn test_sparse_select() {
let sparse = SparseRSVec::new(&[1, 3, 5, 7, 9], 12);
assert_eq!(sparse.select1(0), 1);
assert_eq!(sparse.select1(1), 3);
assert_eq!(sparse.select1(2), 5);
assert_eq!(sparse.select1(3), 7);
assert_eq!(sparse.select1(4), 9);
assert_eq!(sparse.select1(5), 12);
assert_eq!(sparse.select1(6), 12);
}
#[test]
fn test_sparse_rank0() {
let sparse = SparseRSVec::new(&[1, 3, 5, 7, 9], 12);
assert_eq!(sparse.rank0(0), 0);
assert_eq!(sparse.rank0(1), 1);
assert_eq!(sparse.rank0(2), 1);
assert_eq!(sparse.rank0(3), 2);
assert_eq!(sparse.rank0(4), 2);
assert_eq!(sparse.rank0(5), 3);
assert_eq!(sparse.rank0(6), 3);
assert_eq!(sparse.rank0(7), 4);
assert_eq!(sparse.rank0(8), 4);
assert_eq!(sparse.rank0(9), 5);
assert_eq!(sparse.rank0(10), 5);
assert_eq!(sparse.rank0(11), 6);
assert_eq!(sparse.rank0(12), 7);
assert_eq!(sparse.rank0(999), 7);
}
#[test]
fn test_empty_sparse() {
let sparse = SparseRSVec::new(&[], 0);
assert_eq!(sparse.rank1(0), 0);
assert_eq!(sparse.rank1(1), 0);
assert_eq!(sparse.rank1(999), 0);
assert_eq!(sparse.select1(0), 0);
assert_eq!(sparse.select1(1), 0);
assert_eq!(sparse.select1(999), 0);
assert_eq!(sparse.rank0(0), 0);
assert_eq!(sparse.rank0(1), 0);
assert_eq!(sparse.rank0(999), 0);
assert!(sparse.is_empty());
assert_eq!(sparse.len(), 0);
}
#[test]
fn test_sparse_get() {
let sparse = SparseRSVec::new(&[1, 3, 5, 7, 9], 12);
assert_eq!(sparse.get(0), Some(0));
assert_eq!(sparse.get(1), Some(1));
assert_eq!(sparse.get(2), Some(0));
assert_eq!(sparse.get(3), Some(1));
assert_eq!(sparse.get(4), Some(0));
assert_eq!(sparse.get(5), Some(1));
assert_eq!(sparse.get(6), Some(0));
assert_eq!(sparse.get(7), Some(1));
assert_eq!(sparse.get(8), Some(0));
assert_eq!(sparse.get(9), Some(1));
assert_eq!(sparse.get(10), Some(0));
assert_eq!(sparse.get(11), Some(0));
assert_eq!(sparse.get(12), None);
assert_eq!(sparse.get(999), None);
}
#[test]
fn test_from_bitvector() {
let mut bv = BitVec::from_ones(12);
bv.flip_bit(6);
bv.flip_bit(7);
let sparse = SparseRSVec::from_bitvec(&bv);
assert_eq!(sparse.rank1(0), 0);
assert_eq!(sparse.rank1(1), 1);
assert_eq!(sparse.rank1(2), 2);
assert_eq!(sparse.rank1(7), 6);
assert_eq!(sparse.rank1(8), 6);
assert_eq!(sparse.rank1(9), 7);
assert_eq!(sparse.rank1(12), 10);
let sparse = SparseRSVec::from_bitvec_inverted(&bv);
assert_eq!(sparse.rank1(0), 0);
assert_eq!(sparse.rank1(1), 0);
assert_eq!(sparse.rank1(2), 0);
assert_eq!(sparse.rank1(7), 1);
assert_eq!(sparse.rank1(8), 2);
assert_eq!(sparse.rank1(9), 2);
assert_eq!(sparse.rank1(12), 2);
}
#[test]
fn test_large_block() {
let sparse = SparseRSVec::new(
&[
1, 100_000, 100_001, 100_002, 100_003, 100_004, 100_005, 100_006, 100_007, 100_008,
100_009, 100_010, 1_000_000,
],
2_000_000,
);
assert_eq!(sparse.rank1(100_008), 9);
assert_eq!(sparse.rank1(100_012), 12);
}
#[test]
fn test_fuzzy() {
const L: usize = 100_000;
let mut bv = BitVec::from_zeros(L);
let mut rng = StdRng::from_seed([0; 32]);
for _ in 0..L / 4 {
bv.flip_bit(rng.gen_range(0..L));
}
let sparse = SparseRSVec::from_bitvec(&bv);
let mut ones = 0;
for i in 0..L {
assert_eq!(bv.get(i), sparse.get(i as u64));
assert_eq!(ones, sparse.rank1(i as u64));
assert_eq!(i as u64 - ones, sparse.rank0(i as u64));
if bv.get(i) == Some(1) {
assert_eq!(i, sparse.select1(ones as usize).try_into().unwrap());
ones += 1;
}
}
}
#[test]
fn test_from_padded_bitvec() {
let mut bv = BitVec::new();
bv.append_bit(1);
bv.append_bit(0);
bv.append_bits(u64::MAX, 10);
bv.drop_last(10);
bv.append_bit(0);
bv.drop_last(1);
let sparse = SparseRSVec::from_bitvec(&bv);
assert_eq!(sparse.len(), 2);
assert_eq!(sparse.get(0), Some(1));
assert_eq!(sparse.get(1), Some(0));
assert_eq!(sparse.iter1().collect::<Vec<_>>(), vec![0]);
}
}