1use alloc::vec::Vec;
9use core::cell::Cell;
10
11use crate::FxHashMap;
12
13const SMALL_ELEMS: usize = 12;
14
15#[derive(Clone, Debug)]
21enum AdaptiveMap {
22 Small {
23 len: u32,
24 keys: [u32; SMALL_ELEMS],
25 values: [u64; SMALL_ELEMS],
26 },
27 Large(FxHashMap<u32, u64>),
28}
29
30const INVALID: u32 = 0xffff_ffff;
31
32impl AdaptiveMap {
33 fn new() -> Self {
34 Self::Small {
35 len: 0,
36 keys: [INVALID; SMALL_ELEMS],
37 values: [0; SMALL_ELEMS],
38 }
39 }
40
41 #[inline(always)]
42 fn get_or_insert<'a>(&'a mut self, key: u32) -> &'a mut u64 {
43 let small_mode_idx = match self {
46 &mut Self::Small {
47 len,
48 ref mut keys,
49 ref values,
50 } => {
51 if let Some(i) = keys[..len as usize].iter().position(|&k| k == key) {
58 Some(i)
59 } else if len != SMALL_ELEMS as u32 {
60 debug_assert!(len < SMALL_ELEMS as u32);
61 None
62 } else if let Some(i) = values.iter().position(|&v| v == 0) {
63 keys[i] = key;
65 Some(i)
66 } else {
67 *self = Self::Large(keys.iter().copied().zip(values.iter().copied()).collect());
68 None
69 }
70 }
71 _ => None,
72 };
73
74 match self {
75 Self::Small { len, keys, values } => {
76 if let Some(i) = small_mode_idx {
80 return &mut values[i];
81 }
82 debug_assert!(*len < SMALL_ELEMS as u32);
85 let idx = *len as usize;
86 *len += 1;
87 keys[idx] = key;
88 values[idx] = 0;
89 &mut values[idx]
90 }
91 Self::Large(map) => map.entry(key).or_insert(0),
92 }
93 }
94
95 #[inline(always)]
96 fn get_mut(&mut self, key: u32) -> Option<&mut u64> {
97 match self {
98 &mut Self::Small {
99 len,
100 ref keys,
101 ref mut values,
102 } => {
103 for i in 0..len {
104 if keys[i as usize] == key {
105 return Some(&mut values[i as usize]);
106 }
107 }
108 None
109 }
110 &mut Self::Large(ref mut map) => map.get_mut(&key),
111 }
112 }
113 #[inline(always)]
114 fn get(&self, key: u32) -> Option<u64> {
115 match self {
116 &Self::Small {
117 len,
118 ref keys,
119 ref values,
120 } => {
121 for i in 0..len {
122 if keys[i as usize] == key {
123 let value = values[i as usize];
124 return Some(value);
125 }
126 }
127 None
128 }
129 &Self::Large(ref map) => {
130 let value = map.get(&key).cloned();
131 value
132 }
133 }
134 }
135 fn iter<'a>(&'a self) -> AdaptiveMapIter<'a> {
136 match self {
137 &Self::Small {
138 len,
139 ref keys,
140 ref values,
141 } => AdaptiveMapIter::Small(&keys[0..len as usize], &values[0..len as usize]),
142 &Self::Large(ref map) => AdaptiveMapIter::Large(map.iter()),
143 }
144 }
145
146 fn is_empty(&self) -> bool {
147 match self {
148 AdaptiveMap::Small { values, .. } => values.iter().all(|&value| value == 0),
149 AdaptiveMap::Large(m) => m.values().all(|&value| value == 0),
150 }
151 }
152}
153
154enum AdaptiveMapIter<'a> {
155 Small(&'a [u32], &'a [u64]),
156 Large(hashbrown::hash_map::Iter<'a, u32, u64>),
157}
158
159impl<'a> core::iter::Iterator for AdaptiveMapIter<'a> {
160 type Item = (u32, u64);
161
162 #[inline]
163 fn next(&mut self) -> Option<Self::Item> {
164 match self {
165 &mut Self::Small(ref mut keys, ref mut values) => {
166 if keys.is_empty() {
167 None
168 } else {
169 let (k, v) = ((*keys)[0], (*values)[0]);
170 *keys = &(*keys)[1..];
171 *values = &(*values)[1..];
172 Some((k, v))
173 }
174 }
175 &mut Self::Large(ref mut it) => it.next().map(|(&k, &v)| (k, v)),
176 }
177 }
178}
179
180#[derive(Clone)]
183pub struct IndexSet {
184 elems: AdaptiveMap,
185 cache: Cell<(u32, u64)>,
186}
187
188const BITS_PER_WORD: usize = 64;
189
190impl IndexSet {
191 pub fn new() -> Self {
192 Self {
193 elems: AdaptiveMap::new(),
194 cache: Cell::new((INVALID, 0)),
195 }
196 }
197
198 #[inline(always)]
199 fn elem(&mut self, bit_index: usize) -> &mut u64 {
200 let word_index = (bit_index / BITS_PER_WORD) as u32;
201 if self.cache.get().0 == word_index {
202 self.cache.set((INVALID, 0));
203 }
204 self.elems.get_or_insert(word_index)
205 }
206
207 #[inline(always)]
208 fn maybe_elem_mut(&mut self, bit_index: usize) -> Option<&mut u64> {
209 let word_index = (bit_index / BITS_PER_WORD) as u32;
210 if self.cache.get().0 == word_index {
211 self.cache.set((INVALID, 0));
212 }
213 self.elems.get_mut(word_index)
214 }
215
216 #[inline(always)]
217 fn maybe_elem(&self, bit_index: usize) -> Option<u64> {
218 let word_index = (bit_index / BITS_PER_WORD) as u32;
219 if self.cache.get().0 == word_index {
220 Some(self.cache.get().1)
221 } else {
222 self.elems.get(word_index)
223 }
224 }
225
226 #[inline(always)]
227 pub fn set(&mut self, idx: usize, val: bool) {
228 let bit = idx % BITS_PER_WORD;
229 if val {
230 *self.elem(idx) |= 1 << bit;
231 } else if let Some(word) = self.maybe_elem_mut(idx) {
232 *word &= !(1 << bit);
233 }
234 }
235
236 pub fn assign(&mut self, other: &Self) {
237 self.elems = other.elems.clone();
238 self.cache = other.cache.clone();
239 }
240
241 #[inline(always)]
242 pub fn get(&self, idx: usize) -> bool {
243 let bit = idx % BITS_PER_WORD;
244 if let Some(word) = self.maybe_elem(idx) {
245 (word & (1 << bit)) != 0
246 } else {
247 false
248 }
249 }
250
251 pub fn union_with(&mut self, other: &Self) -> bool {
252 let mut changed = 0;
253 for (word_idx, bits) in other.elems.iter() {
254 if bits == 0 {
255 continue;
256 }
257 let word_idx = word_idx as usize;
258 let self_word = self.elem(word_idx * BITS_PER_WORD);
259 changed |= bits & !*self_word;
260 *self_word |= bits;
261 }
262 changed != 0
263 }
264
265 pub fn iter<'a>(&'a self) -> impl Iterator<Item = usize> + 'a {
266 self.elems.iter().flat_map(|(word_idx, bits)| {
267 let word_idx = word_idx as usize;
268 SetBitsIter(bits).map(move |i| BITS_PER_WORD * word_idx + i)
269 })
270 }
271
272 pub(crate) fn is_small(&self) -> bool {
275 match &self.elems {
276 &AdaptiveMap::Small { .. } => true,
277 _ => false,
278 }
279 }
280
281 pub(crate) fn is_empty(&self) -> bool {
283 self.elems.is_empty()
284 }
285}
286
287pub struct SetBitsIter(u64);
288
289impl Iterator for SetBitsIter {
290 type Item = usize;
291
292 #[inline]
293 fn next(&mut self) -> Option<usize> {
294 core::num::NonZeroU64::new(self.0).map(|nz| {
298 let bitidx = nz.trailing_zeros();
299 self.0 &= self.0 - 1; bitidx as usize
301 })
302 }
303}
304
305impl core::fmt::Debug for IndexSet {
306 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
307 let vals = self.iter().collect::<Vec<_>>();
308 write!(f, "{:?}", vals)
309 }
310}
311
312#[cfg(test)]
313mod test {
314 use super::IndexSet;
315
316 #[test]
317 fn test_set_bits_iter() {
318 let mut vec = IndexSet::new();
319 let mut sum = 0;
320 for i in 0..1024 {
321 if i % 17 == 0 {
322 vec.set(i, true);
323 sum += i;
324 }
325 }
326
327 let mut checksum = 0;
328 for bit in vec.iter() {
329 debug_assert!(bit % 17 == 0);
330 checksum += bit;
331 }
332
333 debug_assert_eq!(sum, checksum);
334 }
335
336 #[test]
337 fn test_expand_remove_zero_elems() {
338 let mut vec = IndexSet::new();
339 for i in 0..12 {
341 vec.set(64 * i, true);
342 }
343 vec.set(64 * 5, false);
346 vec.set(64 * 100, true);
347 debug_assert!(vec.is_small());
348 }
349}