Skip to content

Commit

Permalink
Merge pull request #289 from RoaringBitmap/clone-iter-slice
Browse files Browse the repository at this point in the history
Implement Clone on the bitmap::Iter type
  • Loading branch information
Kerollmops authored Nov 25, 2024
2 parents dd8bc5a + 06f3578 commit b16c016
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- stable
- beta
- nightly
- 1.67.0
- 1.71.1
env:
RUSTFLAGS: "-C target-cpu=native -C opt-level=3"
ROARINGRS_BENCH_OFFLINE: "true"
Expand Down
3 changes: 3 additions & 0 deletions roaring/src/bitmap/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub struct Container {
pub store: Store,
}

#[derive(Clone)]
pub struct Iter<'a> {
pub key: u16,
inner: store::Iter<'a>,
Expand All @@ -41,6 +42,7 @@ impl Container {
self.store.is_empty()
}

#[inline]
pub fn insert(&mut self, index: u16) -> bool {
if self.store.insert(index) {
self.ensure_correct_store();
Expand Down Expand Up @@ -159,6 +161,7 @@ impl Container {
self.store.min()
}

#[inline]
pub fn max(&self) -> Option<u16> {
self.store.max()
}
Expand Down
2 changes: 2 additions & 0 deletions roaring/src/bitmap/inherent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ impl RoaringBitmap {
/// assert_eq!(rb.insert(3), false);
/// assert_eq!(rb.contains(3), true);
/// ```
#[inline]
pub fn insert(&mut self, value: u32) -> bool {
let (key, index) = util::split(value);
let container = match self.containers.binary_search_by_key(&key, |c| c.key) {
Expand Down Expand Up @@ -512,6 +513,7 @@ impl RoaringBitmap {
/// rb.insert(4);
/// assert_eq!(rb.max(), Some(4));
/// ```
#[inline]
pub fn max(&self) -> Option<u32> {
self.containers.last().and_then(|tail| tail.max().map(|max| util::join(tail.key, max)))
}
Expand Down
2 changes: 2 additions & 0 deletions roaring/src/bitmap/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ use crate::{NonSortedIntegers, RoaringBitmap};
use alloc::vec::Vec;

/// An iterator for `RoaringBitmap`.
#[derive(Clone)]
pub struct Iter<'a> {
front: Option<container::Iter<'a>>,
containers: slice::Iter<'a, Container>,
back: Option<container::Iter<'a>>,
}

/// An iterator for `RoaringBitmap`.
#[derive(Clone)]
pub struct IntoIter {
front: Option<container::Iter<'static>>,
containers: vec::IntoIter<Container>,
Expand Down
2 changes: 2 additions & 0 deletions roaring/src/bitmap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod container;
mod fmt;
mod multiops;
mod proptests;
mod statistics;
mod store;
mod util;

Expand All @@ -22,6 +23,7 @@ pub(crate) mod serialization;
use self::cmp::Pairs;
pub use self::iter::IntoIter;
pub use self::iter::Iter;
pub use self::statistics::Statistics;

#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
Expand Down
107 changes: 107 additions & 0 deletions roaring/src/bitmap/statistics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use core::mem;

use crate::bitmap::container::Container;
use crate::RoaringBitmap;

use super::store::Store;

/// Detailed statistics on the composition of a bitmap.
#[derive(Clone, Copy, PartialEq, Debug)]
#[non_exhaustive]
pub struct Statistics {
/// Number of containers in the bitmap
pub n_containers: u32,
/// Number of array containers in the bitmap
pub n_array_containers: u32,
/// Number of run containers in the bitmap
pub n_run_containers: u32,
/// Number of bitset containers in the bitmap
pub n_bitset_containers: u32,
/// Number of values stored in array containers
pub n_values_array_containers: u32,
/// Number of values stored in run containers
pub n_values_run_containers: u32,
/// Number of values stored in bitset containers
pub n_values_bitset_containers: u64,
/// Number of bytes used by array containers
pub n_bytes_array_containers: u64,
/// Number of bytes used by run containers
pub n_bytes_run_containers: u64,
/// Number of bytes used by bitset containers
pub n_bytes_bitset_containers: u64,
/// Maximum value stored in the bitmap
pub max_value: Option<u32>,
/// Minimum value stored in the bitmap
pub min_value: Option<u32>,
/// Number of values stored in the bitmap
pub cardinality: u64,
}

impl RoaringBitmap {
/// Returns statistics about the composition of a roaring bitmap.
///
/// ```
/// use roaring::RoaringBitmap;
///
/// let mut bitmap: RoaringBitmap = (1..100).collect();
/// let statistics = bitmap.statistics();
///
/// assert_eq!(statistics.n_containers, 1);
/// assert_eq!(statistics.n_array_containers, 1);
/// assert_eq!(statistics.n_run_containers, 0);
/// assert_eq!(statistics.n_bitset_containers, 0);
/// assert_eq!(statistics.n_values_array_containers, 99);
/// assert_eq!(statistics.n_values_run_containers, 0);
/// assert_eq!(statistics.n_values_bitset_containers, 0);
/// assert_eq!(statistics.n_bytes_array_containers, 512);
/// assert_eq!(statistics.n_bytes_run_containers, 0);
/// assert_eq!(statistics.n_bytes_bitset_containers, 0);
/// assert_eq!(statistics.max_value, Some(99));
/// assert_eq!(statistics.min_value, Some(1));
/// assert_eq!(statistics.cardinality, 99);
/// ```
pub fn statistics(&self) -> Statistics {
let mut n_containers = 0;
let mut n_array_containers = 0;
let mut n_bitset_containers = 0;
let mut n_values_array_containers = 0;
let mut n_values_bitset_containers = 0;
let mut n_bytes_array_containers = 0;
let mut n_bytes_bitset_containers = 0;
let mut cardinality = 0;

for Container { key: _, store } in &self.containers {
match store {
Store::Array(array) => {
cardinality += array.len();
n_values_array_containers += array.len() as u32;
n_bytes_array_containers += (array.capacity() * mem::size_of::<u32>()) as u64;
n_array_containers += 1;
}
Store::Bitmap(bitmap) => {
cardinality += bitmap.len();
n_values_bitset_containers += bitmap.len();
n_bytes_bitset_containers += bitmap.capacity() as u64;
n_bitset_containers += 1;
}
}
n_containers += 1;
}

Statistics {
n_containers,
n_array_containers,
n_run_containers: 0,
n_bitset_containers,
n_values_array_containers,
n_values_run_containers: 0,
n_values_bitset_containers,
n_bytes_array_containers,
n_bytes_run_containers: 0,
n_bytes_bitset_containers,
max_value: self.max(),
min_value: self.min(),
cardinality,
}
}
}
7 changes: 7 additions & 0 deletions roaring/src/bitmap/store/array_store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ impl ArrayStore {
ArrayStore { vec: Vec::with_capacity(capacity) }
}

/// The number of total values that can be inserted without needing to reallocate.
pub fn capacity(&self) -> usize {
self.vec.capacity()
}

///
/// Create a new SortedU16Vec from a given vec
/// It is up to the caller to ensure the vec is sorted and deduplicated
Expand All @@ -47,6 +52,7 @@ impl ArrayStore {
}
}

#[inline]
pub fn insert(&mut self, index: u16) -> bool {
self.vec.binary_search(&index).map_err(|loc| self.vec.insert(loc, index)).is_err()
}
Expand Down Expand Up @@ -208,6 +214,7 @@ impl ArrayStore {
self.vec.first().copied()
}

#[inline]
pub fn max(&self) -> Option<u16> {
self.vec.last().copied()
}
Expand Down
7 changes: 7 additions & 0 deletions roaring/src/bitmap/store/bitmap_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ impl BitmapStore {
BitmapStore { len: (BITMAP_LENGTH as u64) * 64, bits: Box::new([u64::MAX; BITMAP_LENGTH]) }
}

pub fn capacity(&self) -> usize {
BITMAP_LENGTH * u64::BITS as usize
}

pub fn try_from(len: u64, bits: Box<[u64; BITMAP_LENGTH]>) -> Result<BitmapStore, Error> {
let actual_len = bits.iter().map(|v| v.count_ones() as u64).sum();
if len != actual_len {
Expand All @@ -52,6 +56,7 @@ impl BitmapStore {
}
}

#[inline]
pub fn insert(&mut self, index: u16) -> bool {
let (key, bit) = (key(index), bit(index));
let old_w = self.bits[key];
Expand Down Expand Up @@ -253,6 +258,7 @@ impl BitmapStore {
.map(|(index, bit)| (index * 64 + (bit.trailing_zeros() as usize)) as u16)
}

#[inline]
pub fn max(&self) -> Option<u16> {
self.bits
.iter()
Expand Down Expand Up @@ -403,6 +409,7 @@ impl Display for Error {
#[cfg(feature = "std")]
impl std::error::Error for Error {}

#[derive(Clone)]
pub struct BitmapIter<B: Borrow<[u64; BITMAP_LENGTH]>> {
key: u16,
value: u64,
Expand Down
3 changes: 3 additions & 0 deletions roaring/src/bitmap/store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub enum Store {
Bitmap(BitmapStore),
}

#[derive(Clone)]
pub enum Iter<'a> {
Array(slice::Iter<'a, u16>),
Vec(vec::IntoIter<u16>),
Expand All @@ -49,6 +50,7 @@ impl Store {
Store::Bitmap(BitmapStore::full())
}

#[inline]
pub fn insert(&mut self, index: u16) -> bool {
match self {
Array(vec) => vec.insert(index),
Expand Down Expand Up @@ -191,6 +193,7 @@ impl Store {
}
}

#[inline]
pub fn max(&self) -> Option<u16> {
match self {
Array(vec) => vec.max(),
Expand Down

0 comments on commit b16c016

Please sign in to comment.