croaring/bitset/imp.rs
1use super::Bitset;
2use core::{mem, ptr};
3
4impl Bitset {
5 #[inline]
6 #[allow(clippy::assertions_on_constants)]
7 pub(super) unsafe fn take_heap(p: *mut ffi::bitset_t) -> Self {
8 assert!(!p.is_null());
9 let result = Self { bitset: p.read() };
10 // It seems unlikely that the bitset type will meaningfully change, but check if we ever go
11 // to a version 3.
12 const _: () = assert!(ffi::ROARING_VERSION_MAJOR == 4);
13 ffi::roaring_free(p.cast());
14 result
15 }
16
17 /// Access the raw underlying slice
18 #[inline]
19 #[must_use]
20 pub const fn as_slice(&self) -> &[u64] {
21 if self.bitset.arraysize == 0 {
22 &[]
23 } else {
24 unsafe { core::slice::from_raw_parts(self.bitset.array, self.bitset.arraysize) }
25 }
26 }
27
28 /// Access the raw underlying slice
29 #[inline]
30 pub fn as_mut_slice(&mut self) -> &mut [u64] {
31 if self.bitset.arraysize == 0 {
32 &mut []
33 } else {
34 unsafe { core::slice::from_raw_parts_mut(self.bitset.array, self.bitset.arraysize) }
35 }
36 }
37
38 /// Create a new bitset
39 ///
40 /// Does not allocate
41 ///
42 /// # Examples
43 /// ```
44 /// use croaring::Bitset;
45 /// let bitset = Bitset::new();
46 /// assert_eq!(bitset.capacity(), 0);
47 /// assert_eq!(bitset.size_in_bits(), 0);
48 /// ```
49 #[inline]
50 #[doc(alias = "bitset_create")]
51 #[must_use]
52 pub const fn new() -> Self {
53 Self {
54 bitset: ffi::bitset_t {
55 array: ptr::null_mut(),
56 arraysize: 0,
57 capacity: 0,
58 },
59 }
60 }
61
62 /// Create a new bitset of the specified size
63 ///
64 /// # Examples
65 /// ```
66 /// use croaring::Bitset;
67 /// let bitset = Bitset::with_size(100);
68 /// // Actual size/capacity may be rounded up
69 /// assert!(bitset.capacity() >= 100);
70 /// assert!(bitset.size_in_bits() >= 100);
71 /// ```
72 #[inline]
73 #[doc(alias = "bitset_create_with_capacity")]
74 #[must_use]
75 pub fn with_size(size: usize) -> Self {
76 unsafe { Self::take_heap(ffi::bitset_create_with_capacity(size)) }
77 }
78
79 /// Capacity in bits
80 #[inline]
81 #[must_use]
82 pub const fn capacity(&self) -> usize {
83 self.bitset.capacity * 64
84 }
85
86 /// Set all bits to zero
87 ///
88 /// # Examples
89 /// ```
90 /// use croaring::Bitset;
91 /// let mut bitset = Bitset::with_size(64);
92 /// bitset.fill(true);
93 /// assert!(bitset.get(1));
94 /// assert!(bitset.get(63));
95 /// // Bitset size stays the same
96 /// assert!(!bitset.get(64));
97 /// bitset.fill(false);
98 /// assert!(!bitset.get(1));
99 /// assert!(!bitset.get(63));
100 /// assert!(!bitset.get(64));
101 /// ```
102 #[inline]
103 #[doc(alias = "bitset_clear")]
104 #[doc(alias = "bitset_fill")]
105 pub fn fill(&mut self, value: bool) {
106 if value {
107 unsafe { ffi::bitset_fill(&mut self.bitset) };
108 } else {
109 unsafe { ffi::bitset_clear(&mut self.bitset) };
110 }
111 }
112
113 /// How many bytes of memory the backend buffer uses
114 #[inline]
115 #[doc(alias = "bitset_size_in_bytes")]
116 #[must_use]
117 pub const fn size_in_bytes(&self) -> usize {
118 self.size_in_words() * mem::size_of::<u64>()
119 }
120
121 /// How many bits can be accessed
122 #[inline]
123 #[doc(alias = "bitset_size_in_bits")]
124 #[must_use]
125 pub const fn size_in_bits(&self) -> usize {
126 self.size_in_bytes() * 8
127 }
128
129 /// How many 64-bit words of memory the backend buffer uses
130 #[inline]
131 #[doc(alias = "bitset_size_in_words")]
132 #[must_use]
133 pub const fn size_in_words(&self) -> usize {
134 self.bitset.arraysize
135 }
136
137 /// Resize the bitset to contain `new_array_size` 64-bit words
138 ///
139 /// New bits are set to `value`
140 ///
141 /// # Examples
142 /// ```
143 /// use croaring::Bitset;
144 /// let mut bitset = Bitset::new();
145 /// bitset.resize_words(1, false);
146 /// bitset.resize_words(2, true);
147 /// assert_eq!(bitset.iter().collect::<Vec<_>>(), (64..128).collect::<Vec<_>>());
148 /// ```
149 pub fn resize_words(&mut self, new_array_size: usize, value: bool) {
150 let old_array_size = self.bitset.arraysize;
151 let res = unsafe { ffi::bitset_resize(&mut self.bitset, new_array_size, value) };
152 assert!(res);
153 if new_array_size > old_array_size {
154 let new_data_slice = &mut self.as_mut_slice()[old_array_size..];
155 new_data_slice.fill(u64::from(value) * !0);
156 }
157 }
158
159 /// For advanced users: Grow the bitset so that it can support newarraysize * 64 bits with padding.
160 /// Return true in case of success, false for failure
161 #[inline]
162 #[doc(alias = "bitset_grow")]
163 fn grow(&mut self, new_array_size: usize) {
164 assert!(unsafe { ffi::bitset_grow(&mut self.bitset, new_array_size) });
165 }
166
167 /// Attempts to recover unused memory by shrinking capacity to fit the highest set bit
168 ///
169 /// # Examples
170 /// ```
171 /// use croaring::Bitset;
172 /// let mut bitset = Bitset::new();
173 /// bitset.set(63);
174 /// bitset.set(1000);
175 /// assert!(bitset.size_in_bits() > 1000);
176 /// bitset.set_to_value(1000, false);
177 /// bitset.shrink_to_fit();
178 /// // The next highest bit is at index 63
179 /// assert_eq!(bitset.size_in_bits(), 64);
180 #[inline]
181 #[doc(alias = "bitset_trim")]
182 pub fn shrink_to_fit(&mut self) {
183 unsafe { ffi::bitset_trim(&mut self.bitset) };
184 }
185
186 /// Set the ith bit
187 ///
188 /// Will resize the bitset if needed, any other newly added bits will be initialized to zero
189 ///
190 /// # Examples
191 /// ```
192 /// use croaring::Bitset;
193 /// let mut bitset = Bitset::new();
194 /// bitset.set(1);
195 /// bitset.set(2);
196 /// bitset.set(100);
197 /// assert_eq!(bitset.iter().collect::<Vec<_>>(), vec![1, 2, 100]);
198 /// ```
199 #[inline]
200 #[doc(alias = "bitset_set")]
201 pub fn set(&mut self, i: usize) {
202 let array_idx = i / 64;
203 if array_idx >= self.bitset.arraysize {
204 self.grow(array_idx + 1);
205 }
206 self.as_mut_slice()[array_idx] |= 1 << (i % 64);
207 }
208
209 /// Set the ith bit to `value`
210 ///
211 /// Will resize the bitset if needed, any other newly added bits will be initialized to zero
212 ///
213 /// # Examples
214 /// ```
215 /// use croaring::Bitset;
216 /// let mut bitset = Bitset::new();
217 /// bitset.set_to_value(1, true);
218 /// bitset.set_to_value(2, true);
219 /// bitset.set_to_value(100, true);
220 /// bitset.set_to_value(1, false);
221 /// assert_eq!(bitset.iter().collect::<Vec<_>>(), vec![2, 100]);
222 /// ```
223 #[inline]
224 #[doc(alias = "bitset_set_to_value")]
225 pub fn set_to_value(&mut self, i: usize, value: bool) {
226 let array_idx = i / 64;
227 if array_idx >= self.bitset.arraysize {
228 self.grow(array_idx + 1);
229 }
230 let dst = &mut self.as_mut_slice()[array_idx];
231 let mask = 1 << (i % 64);
232 let value_bit = u64::from(value) << (i % 64);
233 let mut word = *dst;
234 word &= !mask;
235 word |= value_bit;
236 *dst = word;
237 }
238
239 /// Get the value of the ith bit
240 ///
241 /// If the bit is out of bounds, returns false
242 ///
243 /// # Examples
244 /// ```
245 /// use croaring::Bitset;
246 /// let mut bitset = Bitset::new();
247 /// bitset.set(1);
248 /// bitset.set(2);
249 /// assert!(bitset.get(1));
250 /// assert!(bitset.get(2));
251 /// assert!(!bitset.get(3));
252 /// ```
253 #[inline]
254 #[doc(alias = "bitset_get")]
255 #[must_use]
256 pub const fn get(&self, i: usize) -> bool {
257 let array_idx = i / 64;
258 if array_idx >= self.bitset.arraysize {
259 return false;
260 }
261 let word = self.as_slice()[array_idx];
262 let mask = 1 << (i % 64);
263 (word & mask) != 0
264 }
265
266 /// Check if the bitset is empty
267 ///
268 /// # Examples
269 /// ```
270 /// use croaring::Bitset;
271 /// let mut bitset = Bitset::new();
272 /// assert!(bitset.is_empty());
273 /// bitset.set(100);
274 /// assert!(!bitset.is_empty());
275 /// ```
276 #[inline]
277 #[doc(alias = "bitset_empty")]
278 #[must_use]
279 pub fn is_empty(&self) -> bool {
280 unsafe { ffi::bitset_empty(&self.bitset) }
281 }
282
283 /// Count of number of set bits
284 ///
285 /// # Examples
286 /// ```
287 /// use croaring::Bitset;
288 /// let mut bitset: Bitset = [1, 2, 3, 100].into_iter().collect();
289 /// assert_eq!(bitset.count(), 4);
290 /// ```
291 #[inline]
292 #[doc(alias = "bitset_count")]
293 #[must_use]
294 pub fn count(&self) -> usize {
295 unsafe { ffi::bitset_count(&self.bitset) }
296 }
297
298 /// Index of the first set bit, or usize::MAX if the bitset has no set bits
299 ///
300 /// # Examples
301 /// ```
302 /// use croaring::Bitset;
303 /// let mut bitset = Bitset::new();
304 /// // minimum returns 0 if the bitset is empty
305 /// assert_eq!(bitset.minimum(), usize::MAX);
306 /// bitset.set(100);
307 /// assert_eq!(bitset.minimum(), 100);
308 /// ```
309 #[inline]
310 #[doc(alias = "bitset_minimum")]
311 #[must_use]
312 pub fn minimum(&self) -> usize {
313 unsafe { ffi::bitset_minimum(&self.bitset) }
314 }
315
316 /// Index of the last set bit, or zero if the bitset has no set bits
317 ///
318 /// # Examples
319 /// ```
320 /// use croaring::Bitset;
321 /// let mut bitset = Bitset::new();
322 /// // maximum returns 0 if the bitset is empty
323 /// assert_eq!(bitset.maximum(), 0);
324 /// bitset.set(100);
325 /// assert_eq!(bitset.maximum(), 100);
326 /// bitset.set(1000);
327 /// assert_eq!(bitset.maximum(), 1000);
328 /// ```
329 #[inline]
330 #[doc(alias = "bitset_maximum")]
331 #[must_use]
332 pub fn maximum(&self) -> usize {
333 unsafe { ffi::bitset_maximum(&self.bitset) }
334 }
335
336 /// The size of the hypothetical union of `self` and `other`
337 ///
338 /// # Examples
339 /// ```
340 /// use croaring::Bitset;
341 /// let mut bitset1: Bitset = [1, 2, 3, 100].into_iter().collect();
342 /// let bitset2: Bitset = [2, 3, 4, 5].into_iter().collect();
343 /// assert_eq!(bitset1.union_count(&bitset2), 6);
344 /// bitset1 |= &bitset2;
345 /// assert_eq!(bitset1.count(), 6);
346 /// ```
347 #[inline]
348 #[doc(alias = "bitset_union_count")]
349 #[must_use]
350 pub fn union_count(&self, other: &Self) -> usize {
351 // CRoaring uses restrict pointers, so we can't use the same pointer for both
352 if ptr::eq(self, other) {
353 return self.count();
354 }
355 unsafe { ffi::bitset_union_count(&self.bitset, &other.bitset) }
356 }
357
358 /// The size of the hypothetical intersection of `self` and `other`
359 ///
360 /// # Examples
361 /// ```
362 /// use croaring::Bitset;
363 /// let mut bitset1: Bitset = [1, 2, 3, 100].into_iter().collect();
364 /// let bitset2: Bitset = [2, 3, 4, 5].into_iter().collect();
365 /// assert_eq!(bitset1.intersection_count(&bitset2), 2);
366 /// bitset1 &= &bitset2;
367 /// assert_eq!(bitset1.count(), 2);
368 /// ```
369 #[inline]
370 #[doc(alias = "bitset_intersection_count")]
371 #[must_use]
372 pub fn intersection_count(&self, other: &Self) -> usize {
373 // CRoaring uses restrict pointers, so we can't use the same pointer for both
374 if ptr::eq(self, other) {
375 return self.count();
376 }
377 unsafe { ffi::bitset_intersection_count(&self.bitset, &other.bitset) }
378 }
379
380 /// Return true if `self` and `other` contain no common elements
381 ///
382 /// # Examples
383 /// ```
384 /// use croaring::Bitset;
385 /// let bitset1: Bitset = [1, 2, 3, 100].into_iter().collect();
386 /// let bitset2: Bitset = [2, 3, 4, 5].into_iter().collect();
387 /// assert!(!bitset1.is_disjoint(&bitset2));
388 /// let bitset3: Bitset = [4, 5, 6, 7].into_iter().collect();
389 /// assert!(bitset1.is_disjoint(&bitset3));
390 /// ```
391 ///
392 /// Empty bitsets are always disjoint
393 ///
394 /// ```
395 /// use croaring::Bitset;
396 /// let bitset1 = Bitset::new();
397 /// let bitset2 = Bitset::new();
398 /// assert!(bitset1.is_disjoint(&bitset2));
399 /// ```
400 #[inline]
401 #[doc(alias = "bitset_disjoint")]
402 #[must_use]
403 pub fn is_disjoint(&self, other: &Self) -> bool {
404 // CRoaring uses restrict pointers, so we can't use the same pointer for both
405 if ptr::eq(self, other) {
406 return false;
407 }
408 unsafe { ffi::bitsets_disjoint(&self.bitset, &other.bitset) }
409 }
410
411 /// Return true if `self` and `other` contain at least one common element
412 ///
413 /// # Examples
414 /// ```
415 /// use croaring::Bitset;
416 /// let bitset1: Bitset = [1, 2, 3, 100].into_iter().collect();
417 /// let bitset2: Bitset = [2, 3, 4, 5].into_iter().collect();
418 /// assert!(bitset1.has_intersect(&bitset2));
419 /// let bitset3: Bitset = [4, 5, 6, 7].into_iter().collect();
420 /// assert!(!bitset1.has_intersect(&bitset3));
421 /// ```
422 #[inline]
423 #[doc(alias = "bitset_intersect")]
424 #[must_use]
425 pub fn has_intersect(&self, other: &Self) -> bool {
426 // CRoaring uses restrict pointers, so we can't use the same pointer for both
427 if ptr::eq(self, other) {
428 return true;
429 }
430 unsafe { ffi::bitsets_intersect(&self.bitset, &other.bitset) }
431 }
432
433 /// Return true if `self` is a superset of `other`
434 ///
435 /// # Examples
436 /// ```
437 /// use croaring::Bitset;
438 /// let bitset1: Bitset = [1, 2, 3, 100].into_iter().collect();
439 /// let bitset2: Bitset = [2, 3].into_iter().collect();
440 /// assert!(bitset1.is_superset(&bitset2));
441 /// let bitset3: Bitset = [4, 5, 6, 7].into_iter().collect();
442 /// assert!(!bitset1.is_superset(&bitset3));
443 /// ```
444 #[inline]
445 #[doc(alias = "bitset_contains_all")]
446 #[must_use]
447 pub fn is_superset(&self, other: &Self) -> bool {
448 // CRoaring uses restrict pointers, so we can't use the same pointer for both
449 if ptr::eq(self, other) {
450 return true;
451 }
452 unsafe { ffi::bitset_contains_all(&self.bitset, &other.bitset) }
453 }
454
455 /// The size of the hypothetical difference of `self` and `other`
456 ///
457 /// # Examples
458 /// ```
459 /// use croaring::Bitset;
460 /// let mut bitset1: Bitset = [1, 2, 3, 100].into_iter().collect();
461 /// let bitset2: Bitset = [2, 3, 4, 5].into_iter().collect();
462 /// assert_eq!(bitset1.difference_count(&bitset2), 2);
463 /// bitset1 -= &bitset2;
464 /// assert_eq!(bitset1.count(), 2);
465 /// ```
466 #[inline]
467 #[doc(alias = "bitset_difference_count")]
468 #[must_use]
469 pub fn difference_count(&self, other: &Self) -> usize {
470 // CRoaring uses restrict pointers, so we can't use the same pointer for both
471 if ptr::eq(self, other) {
472 return 0;
473 }
474 unsafe { ffi::bitset_difference_count(&self.bitset, &other.bitset) }
475 }
476
477 /// The size of the hypothetical symmetric difference (xor) of `self` and `other`
478 ///
479 /// # Examples
480 /// ```
481 /// use croaring::Bitset;
482 /// let mut bitset1: Bitset = [1, 2, 3, 100].into_iter().collect();
483 /// let bitset2: Bitset = [2, 3, 4, 5].into_iter().collect();
484 /// assert_eq!(bitset1.symmetric_difference_count(&bitset2), 4);
485 /// bitset1 ^= &bitset2;
486 /// assert_eq!(bitset1.count(), 4);
487 /// ```
488 #[inline]
489 #[doc(alias = "bitset_symmetric_difference_count")]
490 #[doc(alias = "xor_count")]
491 #[must_use]
492 pub fn symmetric_difference_count(&self, other: &Self) -> usize {
493 // CRoaring uses restrict pointers, so we can't use the same pointer for both
494 if ptr::eq(self, other) {
495 return 0;
496 }
497 unsafe { ffi::bitset_symmetric_difference_count(&self.bitset, &other.bitset) }
498 }
499
500 /// Expose the raw `CRoaring` bitset
501 ///
502 /// This allows calling raw `CRoaring` functions on the bitset.
503 #[inline]
504 #[must_use]
505 pub fn as_raw(&self) -> &ffi::bitset_t {
506 &self.bitset
507 }
508
509 /// Expose the raw `CRoaring` bitset mutably
510 ///
511 /// This allows calling raw `CRoaring` functions on the bitset.
512 #[inline]
513 #[must_use]
514 pub fn as_raw_mut(&mut self) -> &mut ffi::bitset_t {
515 &mut self.bitset
516 }
517}