pumpkin_core/containers/
sparse_set.rs1use crate::containers::HashSet;
32use crate::containers::StorageKey;
33use crate::pumpkin_assert_moderate;
34use crate::pumpkin_assert_simple;
35
36#[derive(Debug, Clone)]
50pub struct SparseSet<T> {
51 size: usize,
53 domain: Vec<T>,
56 indices: Vec<usize>,
59 mapping: fn(&T) -> i32,
63 index_offset: i32,
64}
65
66impl<T: StorageKey> SparseSet<T> {
67 pub fn new(input: Vec<T>) -> Self {
72 Self::new_with_mapping(input, |element: &T| element.index() as i32)
73 }
74}
75
76impl<T> SparseSet<T> {
77 pub fn new_with_mapping(input: Vec<T>, mapping: fn(&T) -> i32) -> Self {
85 let input_len = input.len();
86
87 let mut min_index = 0;
88 let mut max_index = 0;
89
90 let mut used_indices = HashSet::new();
91
92 for element in input.iter() {
93 let index = (mapping)(element);
94 let not_previously_inserted = used_indices.insert(index);
95
96 pumpkin_assert_simple!(
97 not_previously_inserted,
98 "Two elements in the provided `input` map to the same index."
99 );
100
101 min_index = min_index.min(index);
102 max_index = max_index.max(index);
103 }
104
105 pumpkin_assert_simple!(min_index <= max_index);
106
107 let mut indices =
109 std::iter::repeat_n(usize::MAX, (max_index.abs() + min_index.abs()) as usize + 1)
110 .collect::<Vec<_>>();
111 for (i, element) in input.iter().enumerate().collect::<Vec<_>>() {
114 indices[((mapping)(element) - min_index) as usize] = i;
115 }
116
117 SparseSet {
118 size: input_len,
119 domain: input,
120 indices,
121 mapping,
122 index_offset: -min_index,
123 }
124 }
125
126 fn get_mapping(&self, element: &T) -> usize {
127 let output_index = (self.mapping)(element) + self.index_offset;
128 output_index.try_into().unwrap()
129 }
130
131 pub fn set_to_empty(&mut self) {
132 self.indices = vec![usize::MAX; self.indices.len()];
133 self.domain.clear();
134 self.size = 0;
135 }
136
137 pub fn restore_temporarily_removed(&mut self) {
138 self.size = self.domain.len();
139 }
140
141 pub fn is_empty(&self) -> bool {
143 self.size == 0
144 }
145
146 pub fn len(&self) -> usize {
148 self.size
149 }
150
151 pub fn get(&self, index: usize) -> &T {
154 pumpkin_assert_simple!(index < self.size);
155 &self.domain[index]
156 }
157
158 fn swap(&mut self, i: usize, j: usize) {
161 self.domain.swap(i, j);
162
163 let index_i = self.get_mapping(&self.domain[i]);
164 self.indices[index_i] = i;
165
166 let index_j = self.get_mapping(&self.domain[j]);
167 self.indices[index_j] = j;
168 }
169
170 pub fn remove(&mut self, to_remove: &T) {
173 if self.indices[self.get_mapping(to_remove)] < self.size {
174 self.size -= 1;
176 if self.size > 0 {
177 self.swap(self.indices[self.get_mapping(to_remove)], self.size);
178 }
179
180 self.swap(
181 self.indices[self.get_mapping(to_remove)],
182 self.domain.len() - 1,
183 );
184 let element = self.domain.pop().expect("Has to have something to pop.");
185 pumpkin_assert_moderate!((self.mapping)(&element) == (self.mapping)(to_remove));
186
187 let to_remove_index = self.get_mapping(to_remove);
188 self.indices[to_remove_index] = usize::MAX;
189 } else if self.indices[self.get_mapping(to_remove)] < self.domain.len() {
190 self.swap(
191 self.indices[self.get_mapping(to_remove)],
192 self.domain.len() - 1,
193 );
194 let element = self.domain.pop().expect("Has to have something to pop.");
195 pumpkin_assert_moderate!((self.mapping)(&element) == (self.mapping)(to_remove));
196
197 let to_remove_index = self.get_mapping(to_remove);
198 self.indices[to_remove_index] = usize::MAX;
199 }
200 }
201
202 pub fn remove_temporarily(&mut self, to_remove: &T) {
203 if self.indices[self.get_mapping(to_remove)] < self.size {
204 self.size -= 1;
206 self.swap(self.indices[self.get_mapping(to_remove)], self.size);
207 }
208 }
209
210 pub fn contains(&self, element: &T) -> bool {
212 self.get_mapping(element) < self.indices.len()
213 && self.indices[self.get_mapping(element)] < self.size
214 }
215
216 pub fn accommodate(&mut self, element: &T) {
218 let index = self.get_mapping(element);
219 if self.indices.len() <= index {
220 self.indices.resize(index + 1, usize::MAX);
221 }
222 }
223
224 pub fn insert(&mut self, element: T) {
230 if !self.contains(&element) {
231 self.accommodate(&element);
232
233 let mut index = self.indices[self.get_mapping(&element)];
234
235 if index >= self.domain.len() {
241 index = self.domain.len();
242
243 let element_index = self.get_mapping(&element);
244 self.indices[element_index] = index;
245
246 self.domain.push(element);
247 }
248
249 self.swap(self.size, index);
250 self.size += 1;
251 }
252 }
253
254 pub fn iter(&self) -> impl Iterator<Item = &T> {
256 self.domain[..self.size].iter()
257 }
258
259 pub fn out_of_domain(&self) -> impl Iterator<Item = &T> {
260 self.domain[self.size..].iter()
261 }
262}
263
264impl<T> IntoIterator for SparseSet<T> {
265 type Item = T;
266
267 type IntoIter = std::iter::Take<std::vec::IntoIter<T>>;
268
269 fn into_iter(self) -> Self::IntoIter {
270 self.domain.into_iter().take(self.size)
271 }
272}
273
274#[cfg(test)]
275mod tests {
276 use super::SparseSet;
277
278 fn mapping_function(input: &i32) -> i32 {
279 *input
280 }
281
282 #[test]
283 fn test_len() {
284 let sparse_set = SparseSet::new_with_mapping(vec![0, 1, 2], mapping_function);
285 assert_eq!(sparse_set.len(), 3);
286 }
287
288 #[test]
289 fn removal() {
290 let mut sparse_set = SparseSet::new_with_mapping(vec![0, 1, 2], mapping_function);
291 sparse_set.remove(&1);
292 assert_eq!(sparse_set.domain, vec![0, 2]);
293 assert_eq!(sparse_set.size, 2);
294 assert_eq!(sparse_set.indices, vec![0, usize::MAX, 1]);
295 }
296
297 #[test]
298 fn removal_adjusts_size() {
299 let mut sparse_set = SparseSet::new_with_mapping(vec![0, 1, 2], mapping_function);
300 assert_eq!(sparse_set.size, 3);
301 sparse_set.remove(&0);
302 assert_eq!(sparse_set.size, 2);
303 }
304
305 #[test]
306 fn remove_all_elements_leads_to_empty_set() {
307 let mut sparse_set = SparseSet::new_with_mapping(vec![0, 1, 2], mapping_function);
308 sparse_set.remove(&0);
309 sparse_set.remove(&1);
310 sparse_set.remove(&2);
311 assert!(sparse_set.is_empty());
312 }
313
314 #[test]
315 fn iter1() {
316 let sparse_set = SparseSet::new_with_mapping(vec![5, 10, 2], mapping_function);
317 let v: Vec<i32> = sparse_set.iter().copied().collect();
318 assert_eq!(v.len(), 3);
319 assert!(v.contains(&10));
320 assert!(v.contains(&5));
321 assert!(v.contains(&2));
322 }
323
324 #[test]
325 fn iter2() {
326 let mut sparse_set = SparseSet::new_with_mapping(vec![5, 10, 2], mapping_function); sparse_set.insert(100); sparse_set.insert(2); sparse_set.insert(20); sparse_set.remove(&10); sparse_set.insert(10); sparse_set.remove(&10); let v: Vec<i32> = sparse_set.iter().copied().collect();
335 assert_eq!(v.len(), 4);
336 assert!(v.contains(&5));
337 assert!(v.contains(&2));
338 assert!(v.contains(&100));
339 assert!(v.contains(&20));
340 assert!(!v.contains(&10));
341 }
342
343 #[test]
344 fn remove_temporarily_simple() {
345 let mut sparse_set = SparseSet::new_with_mapping(vec![0], mapping_function);
346
347 sparse_set.remove_temporarily(&0);
348 sparse_set.insert(0);
349 sparse_set.remove_temporarily(&0);
350
351 assert!(sparse_set.is_empty())
352 }
353
354 #[test]
355 fn remove_temporarily() {
356 let mut sparse_set = SparseSet::new_with_mapping(vec![2, 0, 1], mapping_function);
357
358 assert!(!sparse_set.is_empty());
359
360 sparse_set.remove_temporarily(&0);
361 sparse_set.insert(0);
362 sparse_set.remove_temporarily(&0);
363 assert!(!sparse_set.contains(&0));
364
365 assert!(!sparse_set.is_empty());
366
367 sparse_set.remove_temporarily(&0);
368 assert!(!sparse_set.contains(&0));
369
370 sparse_set.remove_temporarily(&0);
371 sparse_set.remove_temporarily(&2);
372 assert!(!sparse_set.contains(&2));
373 sparse_set.remove_temporarily(&1);
374 assert!(!sparse_set.contains(&1));
375
376 assert!(sparse_set.is_empty());
377
378 sparse_set.insert(1);
379
380 assert!(sparse_set.contains(&1));
381
382 assert!(!sparse_set.contains(&0));
383 assert!(sparse_set.contains(&1));
384 assert!(!sparse_set.contains(&2));
385
386 sparse_set.restore_temporarily_removed();
387
388 assert!(sparse_set.contains(&0));
389 assert!(sparse_set.contains(&1));
390 assert!(sparse_set.contains(&2));
391 }
392
393 #[test]
394 fn remove_temporarily_non_continuous() {
395 let mut sparse_set = SparseSet::new_with_mapping(vec![5, 10, 2], mapping_function);
396 sparse_set.remove_temporarily(&10);
397 assert!(!sparse_set.contains(&10));
398
399 sparse_set.remove_temporarily(&5);
400 sparse_set.remove_temporarily(&2);
401 assert!(sparse_set.is_empty());
402 }
403
404 #[test]
405 fn remove_temporarily_non_continuous_spanning() {
406 let mut sparse_set = SparseSet::new_with_mapping(vec![5, 10, -2], mapping_function);
407 sparse_set.remove_temporarily(&10);
408 assert!(!sparse_set.contains(&10));
409
410 sparse_set.remove_temporarily(&-2);
411 assert!(!sparse_set.contains(&-2));
412
413 sparse_set.remove_temporarily(&5);
414
415 assert!(sparse_set.is_empty());
416 }
417
418 #[test]
419 fn remove_temporarily_non_continuous_negative() {
420 let mut sparse_set = SparseSet::new_with_mapping(vec![-5, -10, -2], mapping_function);
421 sparse_set.remove_temporarily(&-10);
422 assert!(!sparse_set.contains(&-10));
423
424 sparse_set.remove_temporarily(&-2);
425 assert!(!sparse_set.contains(&-2));
426
427 sparse_set.remove_temporarily(&-5);
428
429 assert!(sparse_set.is_empty());
430 }
431}