2025-04-20 23:54:16 +02:00
|
|
|
use core::{num::NonZeroUsize, usize};
|
|
|
|
|
|
|
|
use allocator_api2::{
|
|
|
|
alloc::{Allocator, Global},
|
|
|
|
boxed::Box,
|
|
|
|
vec::Vec,
|
|
|
|
};
|
|
|
|
use bytemuck::Contiguous;
|
|
|
|
|
|
|
|
const SPARSE_PAGESIZE: usize = (1 << 10) * 4;
|
|
|
|
type SparsePage<A> = Option<(Box<[Option<NonZeroUsize>; SPARSE_PAGESIZE], A>, usize)>;
|
|
|
|
|
2025-05-05 00:32:45 +02:00
|
|
|
/// A sparse set for fast lookup of large indices
|
|
|
|
///
|
|
|
|
/// The sparse allocator is mainly used for bulk allocations in the system's page size
|
|
|
|
/// for the lookup array. It will also be used for the array of pointers into those
|
|
|
|
/// bulk allocations. Additionally it will be used for the reverse map that generates keys
|
|
|
|
/// from the value in the internal packed array
|
|
|
|
///
|
|
|
|
/// The packed allocator will exclusively be used to store the values of type `T`.
|
|
|
|
///
|
|
|
|
/// All operations on this datastructure, meaning insertion, lookup, and deletion, are `O(1)`.
|
|
|
|
///
|
|
|
|
/// This datastructure does not in any way guarantee ordering of the values on
|
|
|
|
/// its own.
|
|
|
|
#[derive(Hash)]
|
2025-04-20 23:54:16 +02:00
|
|
|
pub struct SparseSet<T, PackedAlloc = Global, SparseAlloc = Global>
|
|
|
|
where
|
|
|
|
PackedAlloc: Allocator,
|
|
|
|
SparseAlloc: Allocator,
|
|
|
|
{
|
2025-05-05 00:32:45 +02:00
|
|
|
/// The paginated array of keys. The value at the key is an index into the dense array minus
|
|
|
|
/// one where the value corresponding to that key is stored.
|
2025-04-20 23:54:16 +02:00
|
|
|
sparse: Vec<SparsePage<SparseAlloc>, SparseAlloc>,
|
2025-05-05 00:32:45 +02:00
|
|
|
/// The dense array where the values corresponding to the keys are stored
|
2025-04-20 23:54:16 +02:00
|
|
|
dense: Vec<T, PackedAlloc>,
|
2025-05-05 00:32:45 +02:00
|
|
|
/// The reverse map to get the index in the sparse array from the index in the dense array
|
2025-04-20 23:54:16 +02:00
|
|
|
dense_to_id: Vec<usize, SparseAlloc>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> SparseSet<T> {
|
2025-05-05 00:32:45 +02:00
|
|
|
/// Creates a new [`SparseSet`] with the global allocator.
|
2025-04-20 23:54:16 +02:00
|
|
|
pub const fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
sparse: Vec::new(),
|
|
|
|
dense: Vec::new(),
|
|
|
|
dense_to_id: Vec::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-05 00:32:45 +02:00
|
|
|
impl<T> Default for SparseSet<T> {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-04 23:27:24 +02:00
|
|
|
impl<T, PackedAlloc, SparseAlloc> core::fmt::Debug for SparseSet<T, PackedAlloc, SparseAlloc>
|
|
|
|
where
|
|
|
|
T: core::fmt::Debug,
|
|
|
|
PackedAlloc: Allocator,
|
|
|
|
SparseAlloc: Allocator,
|
|
|
|
{
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
f.debug_map()
|
|
|
|
.entries(self.dense_to_id.iter().zip(self.dense.iter()))
|
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-20 23:54:16 +02:00
|
|
|
impl<T, PackedAlloc, SparseAlloc> SparseSet<T, PackedAlloc, SparseAlloc>
|
|
|
|
where
|
|
|
|
PackedAlloc: Allocator,
|
|
|
|
SparseAlloc: Allocator + Clone,
|
|
|
|
{
|
2025-05-05 00:32:45 +02:00
|
|
|
/// Inserts an element into the sparse set with the key `id`. This will
|
|
|
|
/// return the previous value if it already exists.
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use zenyx::collections::SparseSet;
|
|
|
|
///
|
|
|
|
/// let mut sparse_set: SparseSet<u32> = SparseSet::new();
|
|
|
|
///
|
|
|
|
/// sparse_set.insert(10, 123);
|
|
|
|
/// assert_eq!(sparse_set.get(10), Some(&123));
|
|
|
|
///
|
|
|
|
/// let prev = sparse_set.insert(10, 9);
|
|
|
|
/// assert_eq!(prev, Some(123));
|
|
|
|
/// assert_eq!(sparse_set.get(10), Some(&9));
|
|
|
|
/// ```
|
2025-04-20 23:54:16 +02:00
|
|
|
pub fn insert(&mut self, id: usize, value: T) -> Option<T> {
|
|
|
|
match self.get_dense_idx(id) {
|
|
|
|
Some(idx) => {
|
|
|
|
let previous = core::mem::replace(&mut self.dense[idx], value);
|
|
|
|
self.dense_to_id[idx] = id;
|
|
|
|
Some(previous)
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
self.increase_page_usage_count(id);
|
|
|
|
self.set_dense_idx(id, Some(self.dense.len()));
|
|
|
|
self.dense.push(value);
|
|
|
|
self.dense_to_id.push(id);
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-05 00:32:45 +02:00
|
|
|
/// Gets the value with the key `id`
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use zenyx::collections::SparseSet;
|
|
|
|
///
|
|
|
|
/// let mut sparse_set: SparseSet<u32> = SparseSet::new();
|
|
|
|
///
|
|
|
|
/// sparse_set.insert(10, 123);
|
|
|
|
/// assert_eq!(sparse_set.get(10), Some(&123));
|
|
|
|
/// ```
|
2025-04-20 23:54:16 +02:00
|
|
|
pub fn get(&self, id: usize) -> Option<&T> {
|
|
|
|
self.dense.get(self.get_dense_idx(id)?)
|
|
|
|
}
|
|
|
|
|
2025-05-05 00:32:45 +02:00
|
|
|
/// Gets the value with the key `id` mutably.
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use zenyx::collections::SparseSet;
|
|
|
|
///
|
|
|
|
/// let mut sparse_set: SparseSet<u32> = SparseSet::new();
|
|
|
|
///
|
|
|
|
/// sparse_set.insert(10, 123);
|
|
|
|
/// let value = sparse_set.get_mut(10).unwrap();
|
|
|
|
/// *value = 0;
|
|
|
|
/// assert_eq!(sparse_set.get(10), Some(&0));
|
|
|
|
/// ```
|
2025-04-20 23:54:16 +02:00
|
|
|
pub fn get_mut(&mut self, id: usize) -> Option<&mut T> {
|
|
|
|
let idx = self.get_dense_idx(id)?;
|
|
|
|
self.dense.get_mut(idx)
|
|
|
|
}
|
|
|
|
|
2025-05-05 00:32:45 +02:00
|
|
|
/// Sets the dense index of an `key` to `idx`. This will remove said index
|
|
|
|
/// if it is [`None`].
|
2025-04-20 23:54:16 +02:00
|
|
|
fn set_dense_idx(&mut self, id: usize, idx: Option<usize>) {
|
|
|
|
let page = id / SPARSE_PAGESIZE;
|
|
|
|
let sparse_index = id % SPARSE_PAGESIZE;
|
|
|
|
|
|
|
|
if page >= self.sparse.len() {
|
|
|
|
self.sparse.resize(page + 1, None);
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.sparse[page].is_none() {
|
|
|
|
self.sparse[page] = Some((
|
|
|
|
Box::new_in([None; 4096], self.sparse.allocator().clone()),
|
|
|
|
1,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
|
|
|
match &mut self.sparse[page] {
|
|
|
|
Some(page) => {
|
|
|
|
page.0[sparse_index] = idx.map(|i| NonZeroUsize::new(i + 1).unwrap());
|
|
|
|
}
|
|
|
|
None => unreachable!("wtf, failed to init sparse page 5 lines above??"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-05 00:32:45 +02:00
|
|
|
/// Gets the index in the dense array for a key `id`
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use zenyx::collections::SparseSet;
|
|
|
|
///
|
|
|
|
/// let mut sparse_set: SparseSet<u32> = SparseSet::new();
|
|
|
|
/// sparse_set.insert(10, 123);
|
|
|
|
/// assert_eq!(sparse_set.values()[sparse_set.get_dense_idx(10).unwrap()], 123);
|
|
|
|
/// ```
|
2025-04-20 23:54:16 +02:00
|
|
|
pub fn get_dense_idx(&self, id: usize) -> Option<usize> {
|
|
|
|
let page = id / SPARSE_PAGESIZE;
|
|
|
|
let sparse_index = id % SPARSE_PAGESIZE;
|
|
|
|
let page = self.sparse.get(page)?.as_ref()?;
|
|
|
|
page.0[sparse_index].map(|idx| idx.into_integer() - 1)
|
|
|
|
}
|
|
|
|
|
2025-05-05 00:32:45 +02:00
|
|
|
/// This reduces the usage count for a page in the sparse array, deallocating
|
|
|
|
/// it if it is not used anymore
|
2025-04-20 23:54:16 +02:00
|
|
|
fn reduce_page_usage_count(&mut self, id: usize) {
|
|
|
|
let page = id / SPARSE_PAGESIZE;
|
|
|
|
let Some(usage) = &mut self.sparse[page] else {
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
usage.1 -= 1;
|
|
|
|
let usage = usage.1;
|
|
|
|
if usage == 0 {
|
|
|
|
self.sparse[page] = None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-05 00:32:45 +02:00
|
|
|
/// Increase the page usage count for a page in the sparse array
|
2025-04-20 23:54:16 +02:00
|
|
|
fn increase_page_usage_count(&mut self, id: usize) {
|
|
|
|
let page = id / SPARSE_PAGESIZE;
|
|
|
|
if page >= self.sparse.len() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let Some(usage) = &mut self.sparse[page] else {
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
usage.1 += 1;
|
|
|
|
}
|
|
|
|
|
2025-05-05 00:32:45 +02:00
|
|
|
/// Removes the value with the key `id` from the sparse set, returning the
|
|
|
|
/// value if it existed.
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use zenyx::collections::SparseSet;
|
|
|
|
///
|
|
|
|
/// let mut sparse_set: SparseSet<u32> = SparseSet::new();
|
|
|
|
///
|
|
|
|
/// sparse_set.insert(10, 123);
|
|
|
|
/// assert_eq!(sparse_set.remove(10), Some(123));
|
|
|
|
/// assert_eq!(sparse_set.remove(10), None);
|
|
|
|
/// ```
|
2025-04-20 23:54:16 +02:00
|
|
|
pub fn remove(&mut self, id: usize) -> Option<T> {
|
|
|
|
let index = self.get_dense_idx(id)?;
|
|
|
|
if self.dense.is_empty() {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.set_dense_idx(*self.dense_to_id.last().unwrap(), Some(index));
|
|
|
|
self.set_dense_idx(id, None);
|
|
|
|
self.reduce_page_usage_count(id);
|
|
|
|
|
|
|
|
let previous = self.dense.swap_remove(index);
|
|
|
|
self.dense_to_id.swap_remove(index);
|
|
|
|
Some(previous)
|
|
|
|
}
|
|
|
|
|
2025-05-05 00:32:45 +02:00
|
|
|
/// Returns if there are values in this sparse set.
|
|
|
|
/// ```
|
|
|
|
/// use zenyx::collections::SparseSet;
|
|
|
|
///
|
|
|
|
/// let mut sparse_set: SparseSet<u32> = SparseSet::new();
|
|
|
|
/// assert!(sparse_set.is_empty());
|
|
|
|
/// sparse_set.insert(10, 123);
|
|
|
|
/// assert!(!sparse_set.is_empty());
|
|
|
|
/// ```
|
2025-04-21 00:05:33 +02:00
|
|
|
pub fn is_empty(&self) -> bool {
|
2025-04-20 23:54:16 +02:00
|
|
|
self.len() == 0
|
|
|
|
}
|
|
|
|
|
2025-05-05 00:32:45 +02:00
|
|
|
/// Returns the number of values in this sparse set
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use zenyx::collections::SparseSet;
|
|
|
|
///
|
|
|
|
/// let mut sparse_set: SparseSet<u32> = SparseSet::new();
|
|
|
|
/// sparse_set.insert(10, 123);
|
|
|
|
/// sparse_set.insert(10, 9);
|
|
|
|
/// sparse_set.insert(11, 10);
|
|
|
|
/// assert_eq!(sparse_set.len(), 2);
|
|
|
|
/// ```
|
2025-04-20 23:54:16 +02:00
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
self.dense.len()
|
|
|
|
}
|
|
|
|
|
2025-05-05 00:32:45 +02:00
|
|
|
/// Checks if the sparse set contains a value with key `id`
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use zenyx::collections::SparseSet;
|
|
|
|
///
|
|
|
|
/// let mut sparse_set: SparseSet<u32> = SparseSet::new();
|
|
|
|
/// assert!(!sparse_set.contains(10));
|
|
|
|
/// sparse_set.insert(10, 123);
|
|
|
|
/// assert!(sparse_set.contains(10));
|
|
|
|
/// ```
|
2025-04-20 23:54:16 +02:00
|
|
|
pub fn contains(&self, id: usize) -> bool {
|
|
|
|
self.get_dense_idx(id).is_some()
|
|
|
|
}
|
|
|
|
|
2025-05-05 00:32:45 +02:00
|
|
|
/// Gets the keys of all values in the sparse set. This method does not provide
|
|
|
|
/// any ordering guarantees other than the keys contained corresponding to
|
|
|
|
/// the values with the same index returned by [`Self::values`].
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use zenyx::collections::SparseSet;
|
|
|
|
///
|
|
|
|
/// let mut sparse_set: SparseSet<u32> = SparseSet::new();
|
|
|
|
/// assert!(sparse_set.keys().is_empty());
|
|
|
|
/// sparse_set.insert(10, 10);
|
|
|
|
/// sparse_set.insert(9, 10);
|
|
|
|
/// sparse_set.insert(11, 10);
|
|
|
|
///
|
|
|
|
/// assert_eq!(sparse_set.keys(), &[10, 9, 11]);
|
|
|
|
/// sparse_set.remove(10);
|
|
|
|
/// assert_eq!(sparse_set.keys(), &[11, 9]);
|
|
|
|
/// ```
|
2025-04-20 23:54:16 +02:00
|
|
|
pub fn keys(&self) -> &[usize] {
|
|
|
|
&self.dense_to_id
|
|
|
|
}
|
|
|
|
|
2025-05-05 00:32:45 +02:00
|
|
|
/// Gets all values in the sparse set, the corresponding `key` is at the same
|
|
|
|
/// position in the slice returned by [`Self::keys`].
|
|
|
|
///
|
|
|
|
/// Otherwise there are no ordering guarantees.
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use zenyx::collections::SparseSet;
|
|
|
|
///
|
|
|
|
/// let mut sparse_set: SparseSet<u32> = SparseSet::new();
|
|
|
|
/// assert!(sparse_set.values().is_empty());
|
|
|
|
/// sparse_set.insert(10, 10);
|
|
|
|
/// sparse_set.insert(9, 9);
|
|
|
|
/// sparse_set.insert(11, 11);
|
|
|
|
///
|
|
|
|
/// assert_eq!(sparse_set.values(), &[10, 9, 11]);
|
|
|
|
/// sparse_set.remove(10);
|
|
|
|
/// assert_eq!(sparse_set.values(), &[11, 9]);
|
|
|
|
/// ```
|
2025-04-20 23:54:16 +02:00
|
|
|
pub fn values(&self) -> &[T] {
|
|
|
|
&self.dense
|
|
|
|
}
|
|
|
|
|
2025-05-05 00:32:45 +02:00
|
|
|
/// Mutable version of [`Self::keys`]
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use zenyx::collections::SparseSet;
|
|
|
|
///
|
|
|
|
/// let mut sparse_set: SparseSet<u32> = SparseSet::new();
|
|
|
|
/// assert!(sparse_set.values().is_empty());
|
|
|
|
/// sparse_set.insert(10, 10);
|
|
|
|
/// sparse_set.insert(9, 9);
|
|
|
|
/// sparse_set.insert(11, 11);
|
|
|
|
///
|
|
|
|
/// let dense_of_9 = sparse_set.get_dense_idx(9).unwrap();
|
|
|
|
/// let dense_of_10 = sparse_set.get_dense_idx(10).unwrap();
|
|
|
|
///
|
|
|
|
/// let values = sparse_set.values_mut();
|
|
|
|
/// values[dense_of_10] = 9;
|
|
|
|
/// values[dense_of_9] = 10;
|
|
|
|
///
|
|
|
|
/// assert_eq!(sparse_set.get(10), Some(&9));
|
|
|
|
/// assert_eq!(sparse_set.get(9), Some(&10));
|
|
|
|
/// ```
|
|
|
|
pub fn values_mut(&mut self) -> &mut [T] {
|
|
|
|
&mut self.dense
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Creates a new [`SparseSet`] with the values allocated by the `packed_alloc`
|
|
|
|
/// and everything else, as described in the top level documentation for [`SparseSet`]
|
|
|
|
/// in the `sparse_alloc`.
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use zenyx::collections::SparseSet;
|
|
|
|
/// use allocator_api2::alloc::Global;
|
|
|
|
///
|
|
|
|
/// let sparse_set = SparseSet::<u32>::new_in(Global, Global);
|
|
|
|
/// ```
|
2025-04-20 23:54:16 +02:00
|
|
|
pub fn new_in(packed_alloc: PackedAlloc, sparse_alloc: SparseAlloc) -> Self {
|
|
|
|
Self {
|
|
|
|
dense: Vec::new_in(packed_alloc),
|
|
|
|
sparse: Vec::new_in(sparse_alloc.clone()),
|
|
|
|
dense_to_id: Vec::new_in(sparse_alloc),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T, PackedAlloc> SparseSet<T, PackedAlloc>
|
|
|
|
where
|
|
|
|
PackedAlloc: Allocator,
|
|
|
|
{
|
2025-05-05 00:32:45 +02:00
|
|
|
/// Creates a new [`SparseSet`] with the values allocated by the `packed_alloc`
|
|
|
|
/// Everything else, as described in the top level documentation for [`SparseSet`]
|
|
|
|
/// is allocated using the global allocator.
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use zenyx::collections::SparseSet;
|
|
|
|
/// use allocator_api2::alloc::Global;
|
|
|
|
///
|
|
|
|
/// let sparse_set = SparseSet::<u32>::new_in_packed(Global);
|
|
|
|
/// ```
|
2025-04-20 23:54:16 +02:00
|
|
|
pub const fn new_in_packed(packed_alloc: PackedAlloc) -> Self {
|
|
|
|
Self {
|
|
|
|
sparse: Vec::new(),
|
|
|
|
dense: Vec::new_in(packed_alloc),
|
|
|
|
dense_to_id: Vec::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn insert() {
|
|
|
|
let mut sparse_set = SparseSet::<u32>::new();
|
|
|
|
sparse_set.insert(10, 1);
|
|
|
|
assert_eq!(sparse_set.keys(), &[10]);
|
|
|
|
assert_eq!(sparse_set.values(), &[1]);
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
sparse_set.sparse[0].as_ref().unwrap().0[10].unwrap(),
|
|
|
|
NonZeroUsize::new(1).unwrap()
|
|
|
|
);
|
|
|
|
assert_eq!(sparse_set.sparse[0].as_ref().unwrap().1, 1);
|
|
|
|
assert_eq!(sparse_set.insert(10, 2).unwrap(), 1);
|
|
|
|
assert_eq!(sparse_set.values(), &[2]);
|
|
|
|
assert_eq!(sparse_set.sparse[0].as_ref().unwrap().1, 1);
|
|
|
|
|
|
|
|
sparse_set.insert(11, 4);
|
|
|
|
assert_eq!(sparse_set.keys(), &[10, 11]);
|
|
|
|
assert_eq!(sparse_set.values(), &[2, 4]);
|
|
|
|
assert_eq!(
|
|
|
|
sparse_set.sparse[0].as_ref().unwrap().0[11].unwrap(),
|
|
|
|
NonZeroUsize::new(2).unwrap()
|
|
|
|
);
|
|
|
|
assert_eq!(sparse_set.sparse[0].as_ref().unwrap().1, 2);
|
|
|
|
|
|
|
|
sparse_set.insert(5000, 3);
|
|
|
|
assert_eq!(sparse_set.keys(), &[10, 11, 5000]);
|
|
|
|
assert_eq!(sparse_set.values(), &[2, 4, 3]);
|
|
|
|
assert_eq!(
|
|
|
|
sparse_set.sparse[5000 / SPARSE_PAGESIZE]
|
|
|
|
.as_ref()
|
|
|
|
.unwrap()
|
|
|
|
.0[5000 % SPARSE_PAGESIZE]
|
|
|
|
.unwrap(),
|
|
|
|
NonZeroUsize::new(3).unwrap()
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
sparse_set.sparse[5000 / SPARSE_PAGESIZE]
|
|
|
|
.as_ref()
|
|
|
|
.unwrap()
|
|
|
|
.1,
|
|
|
|
1
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_eq!(*sparse_set.get(10).unwrap(), 2);
|
|
|
|
assert_eq!(*sparse_set.get(11).unwrap(), 4);
|
|
|
|
assert_eq!(*sparse_set.get(5000).unwrap(), 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn remove() {
|
|
|
|
let mut sparse_set = SparseSet::<u32>::new();
|
|
|
|
sparse_set.insert(10, 1);
|
|
|
|
sparse_set.insert(11, 2);
|
|
|
|
sparse_set.insert(12, 2);
|
|
|
|
sparse_set.insert(SPARSE_PAGESIZE, 1);
|
|
|
|
sparse_set.insert(SPARSE_PAGESIZE + 1, 2);
|
|
|
|
sparse_set.insert(SPARSE_PAGESIZE + 2, 3);
|
|
|
|
|
|
|
|
assert_eq!(sparse_set.remove(SPARSE_PAGESIZE + 2).unwrap(), 3);
|
|
|
|
assert_eq!(sparse_set.sparse[1].as_ref().unwrap().1, 2);
|
2025-05-04 23:27:24 +02:00
|
|
|
assert_eq!(
|
|
|
|
sparse_set.keys(),
|
|
|
|
[10, 11, 12, SPARSE_PAGESIZE, SPARSE_PAGESIZE + 1]
|
|
|
|
);
|
2025-04-20 23:54:16 +02:00
|
|
|
assert_eq!(sparse_set.values(), [1, 2, 2, 1, 2]);
|
|
|
|
|
|
|
|
assert_eq!(sparse_set.remove(SPARSE_PAGESIZE + 1).unwrap(), 2);
|
|
|
|
assert_eq!(sparse_set.sparse[1].as_ref().unwrap().1, 1);
|
|
|
|
assert_eq!(sparse_set.keys(), [10, 11, 12, SPARSE_PAGESIZE]);
|
|
|
|
assert_eq!(sparse_set.values(), [1, 2, 2, 1]);
|
|
|
|
|
|
|
|
assert_eq!(sparse_set.remove(SPARSE_PAGESIZE).unwrap(), 1);
|
|
|
|
assert!(sparse_set.sparse[1].is_none());
|
|
|
|
assert_eq!(sparse_set.keys(), [10, 11, 12]);
|
|
|
|
assert_eq!(sparse_set.values(), [1, 2, 2]);
|
|
|
|
|
|
|
|
sparse_set.insert(SPARSE_PAGESIZE, 1);
|
|
|
|
sparse_set.insert(SPARSE_PAGESIZE + 1, 2);
|
|
|
|
sparse_set.insert(SPARSE_PAGESIZE + 2, 3);
|
|
|
|
|
|
|
|
assert_eq!(sparse_set.remove(10).unwrap(), 1);
|
|
|
|
assert_eq!(sparse_set.sparse[0].as_ref().unwrap().1, 2);
|
2025-05-04 23:27:24 +02:00
|
|
|
// swap-remove
|
|
|
|
assert_eq!(
|
|
|
|
sparse_set.keys(),
|
|
|
|
[
|
|
|
|
SPARSE_PAGESIZE + 2,
|
|
|
|
11,
|
|
|
|
12,
|
|
|
|
SPARSE_PAGESIZE,
|
|
|
|
SPARSE_PAGESIZE + 1
|
|
|
|
]
|
|
|
|
);
|
2025-04-20 23:54:16 +02:00
|
|
|
assert_eq!(sparse_set.values(), [3, 2, 2, 1, 2]);
|
|
|
|
|
|
|
|
assert_eq!(sparse_set.remove(11).unwrap(), 2);
|
|
|
|
assert_eq!(sparse_set.sparse[0].as_ref().unwrap().1, 1);
|
2025-05-04 23:27:24 +02:00
|
|
|
assert_eq!(
|
|
|
|
sparse_set.keys(),
|
|
|
|
[
|
|
|
|
SPARSE_PAGESIZE + 2,
|
|
|
|
SPARSE_PAGESIZE + 1,
|
|
|
|
12,
|
|
|
|
SPARSE_PAGESIZE
|
|
|
|
]
|
|
|
|
);
|
2025-04-20 23:54:16 +02:00
|
|
|
assert_eq!(sparse_set.values(), [3, 2, 2, 1]);
|
|
|
|
|
|
|
|
assert_eq!(sparse_set.remove(12).unwrap(), 2);
|
|
|
|
assert!(sparse_set.sparse[0].is_none());
|
2025-05-04 23:27:24 +02:00
|
|
|
assert_eq!(
|
|
|
|
sparse_set.keys(),
|
|
|
|
[SPARSE_PAGESIZE + 2, SPARSE_PAGESIZE + 1, SPARSE_PAGESIZE]
|
|
|
|
);
|
2025-04-20 23:54:16 +02:00
|
|
|
assert_eq!(sparse_set.values(), [3, 2, 1]);
|
|
|
|
}
|
|
|
|
}
|