numerical_multiset/lib.rs
1//! This crate implements an ordered multiset of machine
2//! numbers.
3//!
4//! Well, that sentence is quite a mouthful. Let's break it down into
5//! more digestible chunks:
6//!
7//! - **Multiset:** The [`NumericalMultiset`] container provided by this crate
8//! implements a generalization of the mathematical set, the multiset.
9//! Unlike a set, a multiset can conceptually hold multiple copies of a value.
10//! This is done by tracking how many occurences of each value are present.
11//! - **Ordered:** Multiset implementations are usually based on associative
12//! containers, using distinct multiset elements as keys and integer occurence
13//! counts as values. A popular choice is hash maps, which do not provide any
14//! meaningful key ordering:
15//!
16//! - Any key insertion may change the order of keys that is exposed by
17//! iterators.
18//! - There is no way to find e.g. the smallest key without iterating over
19//! all key.
20//!
21//! In contrast, [`NumericalMultiset`] is based on an ordered associative
22//! container. This allows it to efficiently answer order-related queries,
23//! like in-order iteration over elements or extraction of the minimum/maximum
24//! element. The price to pay is that order-insenstive multiset operations,
25//! like item insertions and removals, will scale a little less well to
26//! larger sets of distinct values than in a hash-based implementation.
27//! - **Numbers:** The multiset provided by this crate is not general-purpose,
28//! but specialized for machine number types (`u32`, `f32`...) and newtypes
29//! thereof. These types are all `Copy`, which lets us provide a simplified
30//! value-based API, that may also result in slightly improved runtime
31//! performance in some scenarios.
32
33use std::{
34 cmp::Ordering,
35 collections::btree_map::{self, BTreeMap, Entry},
36 hash::Hash,
37 iter::FusedIterator,
38 num::NonZeroUsize,
39 ops::{BitAnd, BitOr, BitXor, RangeBounds, Sub},
40};
41
42/// An ordered multiset of machine numbers.
43///
44/// You can learn more about the design rationale and overall capabilities of
45/// this data structure in the [crate-level documentation](index.html).
46///
47/// At the time of writing, this data structure is based on the standard
48/// library's [`BTreeMap`], and many points of the [`BTreeMap`] documentation
49/// also apply to it. In particular, it is a logic error to modify the order of
50/// values stored inside of the multiset using internal mutability tricks.
51///
52/// # Floating-point data
53///
54/// To build multisets of floating-point numbers, you will need to handle the
55/// fact that NaN is unordered. This can be done using one of the [`Ord`] float
56/// wrappers available on crates.io, which work by either [asserting absence of
57/// NaNs](https://docs.rs/ordered-float/latest/ordered_float/struct.NotNan.html)
58/// or [making NaNs
59/// ordered](https://docs.rs/ordered-float/latest/ordered_float/struct.OrderedFloat.html).
60///
61/// For optimal `NumericalMultiset` performance, we advise...
62///
63/// - Preferring
64/// [`NotNan`](https://docs.rs/ordered-float/latest/ordered_float/struct.NotNan.html)-like
65/// wrappers, whose `Ord` implementation can leverage fast hardware
66/// comparisons instead of implementing other ordering semantics in software.
67/// - Using them right from the point where your application receives inputs, to
68/// avoid repeatedly checking your inputs for NaNs by having to rebuild such
69/// wrappers every time a number is inserted into a `NumericalMultiset`.
70///
71/// # Terminology
72///
73/// Because multisets can hold multiple occurences of a value, it is useful to
74/// have concise wording to distinguish between unique values and (possibly
75/// duplicate) occurences of these values.
76///
77/// Throughout this documentation, we will use the following terminology:
78///
79/// - "values" refers to distinct values of type `T` as defined by the [`Eq`]
80/// implementation of `T`.
81/// - "items" refers to possibly duplicate occurences of a value within the
82/// multiset.
83/// - "multiplicity" refers to the number of occurences of a value within the
84/// multiset, i.e. the number of items that are equal to this value.
85///
86/// # Examples
87///
88/// ```
89/// use numerical_multiset::NumericalMultiset;
90/// use std::num::NonZeroUsize;
91///
92/// // Create a multiset
93/// let mut mset = NumericalMultiset::new();
94///
95/// // Inserting items is handled much like a standard library set type,
96/// // except we return an Option<NonZeroUsize> instead of a boolean.
97/// assert!(mset.insert(123).is_none());
98/// assert!(mset.insert(456).is_none());
99///
100/// // This allows us to report the number of pre-existing items
101/// // that have the same value, if any.
102/// assert_eq!(mset.insert(123), NonZeroUsize::new(1));
103///
104/// // It is possible to query the minimal and maximal values cheaply, along
105/// // with their multiplicity within the multiset.
106/// let nonzero = |x| NonZeroUsize::new(x).unwrap();
107/// assert_eq!(mset.first(), Some((123, nonzero(2))));
108/// assert_eq!(mset.last(), Some((456, nonzero(1))));
109///
110/// // ...and it is more generally possible to iterate over values and
111/// // multiplicities in order, from the smallest value to the largest one:
112/// for (elem, multiplicity) in &mset {
113/// println!("{elem} with multiplicity {multiplicity}");
114/// }
115/// ```
116#[derive(Clone, Debug, Default, Eq)]
117pub struct NumericalMultiset<T> {
118 /// Mapping from distinct values to their multiplicities
119 value_to_multiplicity: BTreeMap<T, NonZeroUsize>,
120
121 /// Number of items = sum of all multiplicities
122 len: usize,
123}
124//
125impl<T> NumericalMultiset<T> {
126 /// Makes a new, empty `NumericalMultiset`.
127 ///
128 /// Does not allocate anything on its own.
129 ///
130 /// # Examples
131 ///
132 /// ```
133 /// use numerical_multiset::NumericalMultiset;
134 ///
135 /// let mset = NumericalMultiset::<i32>::new();
136 /// assert!(mset.is_empty());
137 /// ```
138 #[must_use = "Only effect is to produce a result"]
139 pub fn new() -> Self {
140 Self {
141 value_to_multiplicity: BTreeMap::new(),
142 len: 0,
143 }
144 }
145
146 /// Clears the multiset, removing all items.
147 ///
148 /// # Examples
149 ///
150 /// ```
151 /// use numerical_multiset::NumericalMultiset;
152 ///
153 /// let mut v = NumericalMultiset::from_iter([1, 2, 3]);
154 /// v.clear();
155 /// assert!(v.is_empty());
156 /// ```
157 pub fn clear(&mut self) {
158 self.value_to_multiplicity.clear();
159 self.len = 0;
160 }
161
162 /// Number of items currently present in the multiset, including
163 /// duplicate occurences of the same value.
164 ///
165 /// See also [`num_values()`](Self::num_values) for a count of distinct
166 /// values, ignoring duplicates.
167 ///
168 /// # Examples
169 ///
170 /// ```
171 /// use numerical_multiset::NumericalMultiset;
172 ///
173 /// let mut v = NumericalMultiset::new();
174 /// assert_eq!(v.len(), 0);
175 /// v.insert(1);
176 /// assert_eq!(v.len(), 1);
177 /// v.insert(1);
178 /// assert_eq!(v.len(), 2);
179 /// v.insert(2);
180 /// assert_eq!(v.len(), 3);
181 /// ```
182 #[must_use = "Only effect is to produce a result"]
183 pub fn len(&self) -> usize {
184 self.len
185 }
186
187 /// Number of distinct values currently present in the multiset
188 ///
189 /// See also [`len()`](Self::len) for a count of multiset items,
190 /// including duplicate occurences of the same value.
191 ///
192 /// # Examples
193 ///
194 /// ```
195 /// use numerical_multiset::NumericalMultiset;
196 ///
197 /// let mut v = NumericalMultiset::new();
198 /// assert_eq!(v.num_values(), 0);
199 /// v.insert(1);
200 /// assert_eq!(v.num_values(), 1);
201 /// v.insert(1);
202 /// assert_eq!(v.num_values(), 1);
203 /// v.insert(2);
204 /// assert_eq!(v.num_values(), 2);
205 /// ```
206 #[must_use = "Only effect is to produce a result"]
207 pub fn num_values(&self) -> usize {
208 self.value_to_multiplicity.len()
209 }
210
211 /// Truth that the multiset contains no items
212 ///
213 /// # Examples
214 ///
215 /// ```
216 /// use numerical_multiset::NumericalMultiset;
217 ///
218 /// let mut v = NumericalMultiset::new();
219 /// assert!(v.is_empty());
220 /// v.insert(1);
221 /// assert!(!v.is_empty());
222 /// ```
223 #[must_use = "Only effect is to produce a result"]
224 pub fn is_empty(&self) -> bool {
225 self.len == 0
226 }
227
228 /// Creates a consuming iterator visiting all distinct values in the
229 /// multiset, i.e. the mathematical support of the multiset.
230 ///
231 /// Values are emitted in ascending order, and the multiset cannot be used
232 /// after calling this method.
233 ///
234 /// Call `into_iter()` (from the [`IntoIterator`] trait) to get a variation
235 /// of this iterator that additionally tells you how many occurences of each
236 /// value were present in the multiset, in the usual `(value, multiplicity)`
237 /// format.
238 ///
239 /// # Examples
240 ///
241 /// ```
242 /// use numerical_multiset::NumericalMultiset;
243 ///
244 /// let mset = NumericalMultiset::from_iter([3, 1, 2, 2]);
245 /// assert!(mset.into_values().eq([1, 2, 3]));
246 /// ```
247 #[must_use = "Only effect is to produce a result"]
248 pub fn into_values(
249 self,
250 ) -> impl DoubleEndedIterator<Item = T> + ExactSizeIterator + FusedIterator {
251 self.value_to_multiplicity.into_keys()
252 }
253
254 /// Update `self.len` to match `self.value_to_multiplicity`'s contents
255 ///
256 /// This expensive `O(N)` operation should only be performed after calling
257 /// into `BTreeMap` operations that do not provide the right hooks to update
258 /// the length field more efficiently.
259 fn reset_len(&mut self) {
260 self.len = self.value_to_multiplicity.values().map(|x| x.get()).sum();
261 }
262}
263
264impl<T: Copy> NumericalMultiset<T> {
265 /// Iterator over all distinct values in the multiset, along with their
266 /// multiplicities.
267 ///
268 /// Values are emitted in ascending order.
269 ///
270 /// See also [`values()`](Self::values) for a more efficient alternative if
271 /// you do not need to know how many occurences of each value are present.
272 ///
273 /// # Examples
274 ///
275 /// ```
276 /// use numerical_multiset::NumericalMultiset;
277 /// use std::num::NonZeroUsize;
278 ///
279 /// let mset = NumericalMultiset::from_iter([3, 1, 2, 2]);
280 ///
281 /// let mut iter = mset.iter();
282 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
283 /// assert_eq!(iter.next(), Some((1, nonzero(1))));
284 /// assert_eq!(iter.next(), Some((2, nonzero(2))));
285 /// assert_eq!(iter.next(), Some((3, nonzero(1))));
286 /// assert_eq!(iter.next(), None);
287 /// ```
288 #[must_use = "Only effect is to produce a result"]
289 pub fn iter(&self) -> Iter<'_, T> {
290 self.into_iter()
291 }
292
293 /// Iterator over all distinct values in the multiset, i.e. the mathematical
294 /// support of the multiset.
295 ///
296 /// Values are emitted in ascending order.
297 ///
298 /// See also [`iter()`](Self::iter) if you need to know how many occurences
299 /// of each value are present in the multiset.
300 ///
301 /// # Examples
302 ///
303 /// ```
304 /// use numerical_multiset::NumericalMultiset;
305 ///
306 /// let mset = NumericalMultiset::from_iter([3, 1, 2, 2]);
307 ///
308 /// let mut iter = mset.values();
309 /// assert_eq!(iter.next(), Some(1));
310 /// assert_eq!(iter.next(), Some(2));
311 /// assert_eq!(iter.next(), Some(3));
312 /// assert_eq!(iter.next(), None);
313 /// ```
314 #[must_use = "Only effect is to produce a result"]
315 pub fn values(
316 &self,
317 ) -> impl DoubleEndedIterator<Item = T> + ExactSizeIterator + FusedIterator + Clone {
318 self.value_to_multiplicity.keys().copied()
319 }
320}
321
322impl<T: Ord> NumericalMultiset<T> {
323 /// Returns `true` if the multiset contains at least one occurence of a
324 /// value.
325 ///
326 /// See also [`multiplicity()`](Self::multiplicity) if you need to know how
327 /// many occurences of a value are present inside of the multiset.
328 ///
329 /// # Examples
330 ///
331 /// ```
332 /// use numerical_multiset::NumericalMultiset;
333 ///
334 /// let mset = NumericalMultiset::from_iter([1, 2, 2]);
335 ///
336 /// assert_eq!(mset.contains(1), true);
337 /// assert_eq!(mset.contains(2), true);
338 /// assert_eq!(mset.contains(3), false);
339 /// ```
340 #[inline]
341 #[must_use = "Only effect is to produce a result"]
342 pub fn contains(&self, value: T) -> bool {
343 self.value_to_multiplicity.contains_key(&value)
344 }
345
346 /// Returns the number of occurences of a value inside of the multiset, or
347 /// `None` if this value is not present.
348 ///
349 /// See also [`contains()`](Self::contains) for a more efficient alternative
350 /// if you only need to know whether at least one occurence of `value` is
351 /// present inside of the multiset.
352 ///
353 /// # Examples
354 ///
355 /// ```
356 /// use numerical_multiset::NumericalMultiset;
357 /// use std::num::NonZeroUsize;
358 ///
359 /// let mset = NumericalMultiset::from_iter([1, 2, 2]);
360 ///
361 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
362 /// assert_eq!(mset.multiplicity(1), Some(nonzero(1)));
363 /// assert_eq!(mset.multiplicity(2), Some(nonzero(2)));
364 /// assert_eq!(mset.multiplicity(3), None);
365 /// ```
366 #[inline]
367 #[must_use = "Only effect is to produce a result"]
368 pub fn multiplicity(&self, value: T) -> Option<NonZeroUsize> {
369 self.value_to_multiplicity.get(&value).copied()
370 }
371
372 /// Returns `true` if `self` has no items in common with `other`. This is
373 /// logically equivalent to checking for an empty intersection, but may be
374 /// more efficient.
375 ///
376 /// # Examples
377 ///
378 /// ```
379 /// use numerical_multiset::NumericalMultiset;
380 ///
381 /// let a = NumericalMultiset::from_iter([1, 2, 2]);
382 /// let mut b = NumericalMultiset::new();
383 ///
384 /// assert!(a.is_disjoint(&b));
385 /// b.insert(3);
386 /// assert!(a.is_disjoint(&b));
387 /// b.insert(2);
388 /// assert!(!a.is_disjoint(&b));
389 /// ```
390 #[must_use = "Only effect is to produce a result"]
391 pub fn is_disjoint(&self, other: &Self) -> bool {
392 let mut iter1 = self.value_to_multiplicity.keys().peekable();
393 let mut iter2 = other.value_to_multiplicity.keys().peekable();
394 'joint_iter: loop {
395 match (iter1.peek(), iter2.peek()) {
396 // As long as both iterators yield values, must watch out for
397 // common values through well-ordered joint iteration.
398 (Some(value1), Some(value2)) => {
399 match value1.cmp(value2) {
400 // Advance the iterator which is behind, trying to make
401 // it reach the same value as the other iterator.
402 Ordering::Less => {
403 let _ = iter1.next();
404 continue 'joint_iter;
405 }
406 Ordering::Greater => {
407 let _ = iter2.next();
408 continue 'joint_iter;
409 }
410
411 // The same value was yielded by both iterators, which
412 // means that the multisets are not disjoint.
413 Ordering::Equal => return false,
414 }
415 }
416
417 // Once one iterator ends, we know there is no common value
418 // left, so we can conclude that the multisets are disjoint.
419 (Some(_), None) | (None, Some(_)) | (None, None) => return true,
420 }
421 }
422 }
423
424 /// Returns `true` if this multiset is a subset of another, i.e., `other`
425 /// contains at least all the items in `self`.
426 ///
427 /// In a multiset context, this means that if `self` contains N occurences
428 /// of a certain value, then `other` must contain at least N occurences of
429 /// that value.
430 ///
431 /// # Examples
432 ///
433 /// ```
434 /// use numerical_multiset::NumericalMultiset;
435 ///
436 /// let sup = NumericalMultiset::from_iter([1, 2, 2]);
437 /// let mut mset = NumericalMultiset::new();
438 ///
439 /// assert!(mset.is_subset(&sup));
440 /// mset.insert(2);
441 /// assert!(mset.is_subset(&sup));
442 /// mset.insert(2);
443 /// assert!(mset.is_subset(&sup));
444 /// mset.insert(2);
445 /// assert!(!mset.is_subset(&sup));
446 /// ```
447 #[must_use = "Only effect is to produce a result"]
448 pub fn is_subset(&self, other: &Self) -> bool {
449 let mut other_iter = other.value_to_multiplicity.iter().peekable();
450 for (value, &multiplicity) in self.value_to_multiplicity.iter() {
451 // Check if this value also exists in the other iterator
452 'other_iter: loop {
453 match other_iter.peek() {
454 Some((other_value, other_multiplicity)) => match value.cmp(other_value) {
455 // Other iterator is ahead, and because it emits values
456 // in sorted order, we know it's never going to get back
457 // to the current value.
458 //
459 // We can thus conclude that `other` does not contain
460 // `value` and thus `self` is not a subset of it.
461 Ordering::Less => return false,
462
463 // Other iterator is behind and may get to the current
464 // value later in its sorted sequence, so we must
465 // advance it and check again.
466 Ordering::Greater => {
467 let _ = other_iter.next();
468 continue 'other_iter;
469 }
470
471 // Current value exists in both iterators
472 Ordering::Equal => {
473 // For `self` to be a subset, `other` must also
474 // contain at least the same number of occurences of
475 // this common value. Check this.
476 if **other_multiplicity < multiplicity {
477 return false;
478 }
479
480 // We're done checking this common value, now we can
481 // advance the other iterator beyond it and move to
482 // the next value from `self`.
483 let _ = other_iter.next();
484 break 'other_iter;
485 }
486 },
487
488 // Other iterator has ended, it won't yield `value`. Thus
489 // `other` doesn't contain `value` and therefore `self` is
490 // not a subset of `other`.
491 None => return false,
492 }
493 }
494 }
495 true
496 }
497
498 /// Returns `true` if this multiset is a superset of another, i.e., `self`
499 /// contains at least all the items in `other`.
500 ///
501 /// In a multiset context, this means that if `other` contains N occurences
502 /// of a certain value, then `self` must contain at least N occurences of
503 /// that value.
504 ///
505 /// # Examples
506 ///
507 /// ```
508 /// use numerical_multiset::NumericalMultiset;
509 ///
510 /// let sub = NumericalMultiset::from_iter([1, 2, 2]);
511 /// let mut mset = NumericalMultiset::new();
512 ///
513 /// assert!(!mset.is_superset(&sub));
514 ///
515 /// mset.insert(3);
516 /// mset.insert(1);
517 /// assert!(!mset.is_superset(&sub));
518 ///
519 /// mset.insert(2);
520 /// assert!(!mset.is_superset(&sub));
521 ///
522 /// mset.insert(2);
523 /// assert!(mset.is_superset(&sub));
524 /// ```
525 #[must_use = "Only effect is to produce a result"]
526 pub fn is_superset(&self, other: &Self) -> bool {
527 other.is_subset(self)
528 }
529
530 /// Remove all occurences of the smallest value from the multiset, if any.
531 ///
532 /// Returns the former smallest value along with the number of occurences of
533 /// this value that were previously present in the multiset.
534 ///
535 /// See also [`pop_first()`](Self::pop_first) if you only want to remove one
536 /// occurence of the smallest value.
537 ///
538 /// # Examples
539 ///
540 /// ```
541 /// use numerical_multiset::NumericalMultiset;
542 /// use std::num::NonZeroUsize;
543 ///
544 /// let mut mset = NumericalMultiset::from_iter([1, 1, 2]);
545 ///
546 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
547 /// assert_eq!(mset.pop_all_first(), Some((1, nonzero(2))));
548 /// assert_eq!(mset.pop_all_first(), Some((2, nonzero(1))));
549 /// assert_eq!(mset.pop_all_first(), None);
550 /// ```
551 #[inline]
552 #[must_use = "Invalid removal should be handled"]
553 pub fn pop_all_first(&mut self) -> Option<(T, NonZeroUsize)> {
554 self.value_to_multiplicity
555 .pop_first()
556 .inspect(|(_value, count)| self.len -= count.get())
557 }
558
559 /// Remove all occurences of the largest value from the multiset, if any
560 ///
561 /// Returns the former largest value along with the number of occurences of
562 /// this value that were previously present in the multiset.
563 ///
564 /// See also [`pop_last()`](Self::pop_last) if you only want to remove one
565 /// occurence of the largest value.
566 ///
567 /// # Examples
568 ///
569 /// ```
570 /// use numerical_multiset::NumericalMultiset;
571 /// use std::num::NonZeroUsize;
572 ///
573 /// let mut mset = NumericalMultiset::from_iter([1, 1, 2]);
574 ///
575 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
576 /// assert_eq!(mset.pop_all_last(), Some((2, nonzero(1))));
577 /// assert_eq!(mset.pop_all_last(), Some((1, nonzero(2))));
578 /// assert_eq!(mset.pop_all_last(), None);
579 /// ```
580 #[inline]
581 #[must_use = "Invalid removal should be handled"]
582 pub fn pop_all_last(&mut self) -> Option<(T, NonZeroUsize)> {
583 self.value_to_multiplicity
584 .pop_last()
585 .inspect(|(_value, count)| self.len -= count.get())
586 }
587
588 /// Insert an item into the multiset, tell how many identical items were
589 /// already present in the multiset before insertion.
590 ///
591 /// See also [`insert_multiple()`](Self::insert_multiple) for a more
592 /// efficient alternative if you need to insert multiple copies of a value.
593 ///
594 /// # Examples
595 ///
596 /// ```
597 /// use numerical_multiset::NumericalMultiset;
598 /// use std::num::NonZeroUsize;
599 ///
600 /// let mut mset = NumericalMultiset::new();
601 ///
602 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
603 /// assert_eq!(mset.insert(1), None);
604 /// assert_eq!(mset.insert(1), Some(nonzero(1)));
605 /// assert_eq!(mset.insert(1), Some(nonzero(2)));
606 /// assert_eq!(mset.insert(2), None);
607 ///
608 /// assert_eq!(mset.len(), 4);
609 /// assert_eq!(mset.num_values(), 2);
610 /// ```
611 #[inline]
612 pub fn insert(&mut self, value: T) -> Option<NonZeroUsize> {
613 self.insert_multiple(value, NonZeroUsize::new(1).unwrap())
614 }
615
616 /// Insert multiple copies of an item, tell how many identical items were
617 /// already present in the multiset.
618 ///
619 /// This method is typically used for the purpose of efficiently
620 /// transferring all copies of a value from one multiset to another.
621 ///
622 /// See also [`insert()`](Self::insert) for a convenience shortcut in cases
623 /// where you only need to insert one copy of a value.
624 ///
625 /// # Examples
626 ///
627 /// ```
628 /// use numerical_multiset::NumericalMultiset;
629 /// use std::num::NonZeroUsize;
630 ///
631 /// let mut mset = NumericalMultiset::new();
632 ///
633 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
634 /// assert_eq!(mset.insert_multiple(1, nonzero(2)), None);
635 /// assert_eq!(mset.insert_multiple(1, nonzero(3)), Some(nonzero(2)));
636 /// assert_eq!(mset.insert_multiple(2, nonzero(2)), None);
637 ///
638 /// assert_eq!(mset.len(), 7);
639 /// assert_eq!(mset.num_values(), 2);
640 /// ```
641 #[inline]
642 pub fn insert_multiple(&mut self, value: T, count: NonZeroUsize) -> Option<NonZeroUsize> {
643 let result = match self.value_to_multiplicity.entry(value) {
644 Entry::Vacant(v) => {
645 v.insert(count);
646 None
647 }
648 Entry::Occupied(mut o) => {
649 let old_count = *o.get();
650 *o.get_mut() = old_count
651 .checked_add(count.get())
652 .expect("Multiplicity counter has overflown");
653 Some(old_count)
654 }
655 };
656 self.len += count.get();
657 result
658 }
659
660 /// Insert multiple copies of a value, replacing all occurences of this
661 /// value that were previously present in the multiset. Tell how many
662 /// occurences of the value were previously present in the multiset.
663 ///
664 /// # Examples
665 ///
666 /// ```
667 /// use numerical_multiset::NumericalMultiset;
668 /// use std::num::NonZeroUsize;
669 ///
670 /// let mut mset = NumericalMultiset::new();
671 ///
672 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
673 /// assert_eq!(mset.replace_all(1, nonzero(2)), None);
674 /// assert_eq!(mset.replace_all(1, nonzero(3)), Some(nonzero(2)));
675 /// assert_eq!(mset.replace_all(2, nonzero(2)), None);
676 ///
677 /// assert_eq!(mset.len(), 5);
678 /// assert_eq!(mset.num_values(), 2);
679 /// ```
680 #[inline]
681 pub fn replace_all(&mut self, value: T, count: NonZeroUsize) -> Option<NonZeroUsize> {
682 let result = match self.value_to_multiplicity.entry(value) {
683 Entry::Vacant(v) => {
684 v.insert(count);
685 None
686 }
687 Entry::Occupied(mut o) => {
688 let old_count = *o.get();
689 *o.get_mut() = count;
690 self.len -= old_count.get();
691 Some(old_count)
692 }
693 };
694 self.len += count.get();
695 result
696 }
697
698 /// Attempt to remove one item from the multiset, on success tell how many
699 /// identical items were previously present in the multiset (including the
700 /// one that was just removed).
701 ///
702 /// See also [`remove_all()`](Self::remove_all) if you want to remove all
703 /// occurences of a value from the multiset.
704 ///
705 /// # Examples
706 ///
707 /// ```
708 /// use numerical_multiset::NumericalMultiset;
709 /// use std::num::NonZeroUsize;
710 ///
711 /// let mut mset = NumericalMultiset::from_iter([1, 1, 2]);
712 ///
713 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
714 /// assert_eq!(mset.remove(1), Some(nonzero(2)));
715 /// assert_eq!(mset.remove(1), Some(nonzero(1)));
716 /// assert_eq!(mset.remove(1), None);
717 /// assert_eq!(mset.remove(2), Some(nonzero(1)));
718 /// assert_eq!(mset.remove(2), None);
719 /// ```
720 #[inline]
721 #[must_use = "Invalid removal should be handled"]
722 pub fn remove(&mut self, value: T) -> Option<NonZeroUsize> {
723 match self.value_to_multiplicity.entry(value) {
724 Entry::Vacant(_) => None,
725 Entry::Occupied(mut o) => {
726 let old_multiplicity = *o.get();
727 self.len -= 1;
728 match NonZeroUsize::new(old_multiplicity.get() - 1) {
729 Some(new_multiplicity) => {
730 *o.get_mut() = new_multiplicity;
731 }
732 None => {
733 o.remove_entry();
734 }
735 }
736 Some(old_multiplicity)
737 }
738 }
739 }
740
741 /// Attempt to remove all occurences of a value from the multiset, on
742 /// success tell how many items were removed from the multiset.
743 ///
744 /// See also [`remove()`](Self::remove) if you only want to remove one
745 /// occurence of a value from the multiset.
746 ///
747 /// # Examples
748 ///
749 /// ```
750 /// use numerical_multiset::NumericalMultiset;
751 /// use std::num::NonZeroUsize;
752 ///
753 /// let mut mset = NumericalMultiset::from_iter([1, 1, 2]);
754 ///
755 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
756 /// assert_eq!(mset.remove_all(1), Some(nonzero(2)));
757 /// assert_eq!(mset.remove_all(1), None);
758 /// assert_eq!(mset.remove_all(2), Some(nonzero(1)));
759 /// assert_eq!(mset.remove_all(2), None);
760 /// ```
761 #[inline]
762 #[must_use = "Invalid removal should be handled"]
763 pub fn remove_all(&mut self, value: T) -> Option<NonZeroUsize> {
764 let result = self.value_to_multiplicity.remove(&value);
765 self.len -= result.map_or(0, |nz| nz.get());
766 result
767 }
768
769 /// Splits the collection into two at the specified `value`.
770 ///
771 /// This returns a new multiset containing all items greater than or equal
772 /// to `value`. The multiset on which this method was called will retain all
773 /// items strictly smaller than `value`.
774 ///
775 /// # Examples
776 ///
777 /// ```
778 /// use numerical_multiset::NumericalMultiset;
779 /// use std::num::NonZeroUsize;
780 ///
781 /// let mut a = NumericalMultiset::from_iter([1, 2, 2, 3, 3, 3, 4]);
782 /// let b = a.split_off(3);
783 ///
784 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
785 /// assert!(a.iter().eq([
786 /// (1, nonzero(1)),
787 /// (2, nonzero(2)),
788 /// ]));
789 /// assert!(b.iter().eq([
790 /// (3, nonzero(3)),
791 /// (4, nonzero(1)),
792 /// ]));
793 /// ```
794 pub fn split_off(&mut self, value: T) -> Self {
795 let mut result = Self {
796 value_to_multiplicity: self.value_to_multiplicity.split_off(&value),
797 len: 0,
798 };
799 self.reset_len();
800 result.reset_len();
801 result
802 }
803}
804
805impl<T: Copy + Ord> NumericalMultiset<T> {
806 /// Double-ended iterator over a sub-range of values and their
807 /// multiplicities
808 ///
809 /// The simplest way is to use the range syntax `min..max`, thus
810 /// `range(min..max)` will yield values from `min` (inclusive) to `max`
811 /// (exclusive).
812 ///
813 /// The range may also be entered as `(Bound<T>, Bound<T>)`, so
814 /// for example `range((Excluded(4), Included(10)))` will yield a
815 /// left-exclusive, right-inclusive value range from 4 to 10.
816 ///
817 /// # Panics
818 ///
819 /// May panic if range `start > end`, or if range `start == end` and both
820 /// bounds are `Excluded`.
821 ///
822 /// # Examples
823 ///
824 /// ```
825 /// use numerical_multiset::NumericalMultiset;
826 /// use std::num::NonZeroUsize;
827 ///
828 /// let mset = NumericalMultiset::from_iter([3, 3, 5, 8, 8]);
829 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
830 /// assert!(mset.range(4..).eq([
831 /// (5, nonzero(1)),
832 /// (8, nonzero(2)),
833 /// ]));
834 /// ```
835 #[must_use = "Only effect is to produce a result"]
836 pub fn range<R>(
837 &self,
838 range: R,
839 ) -> impl DoubleEndedIterator<Item = (T, NonZeroUsize)> + FusedIterator
840 where
841 R: RangeBounds<T>,
842 {
843 self.value_to_multiplicity
844 .range(range)
845 .map(|(&k, &v)| (k, v))
846 }
847
848 /// Visits the items representing the difference, i.e., those that are in
849 /// `self` but not in `other`. They are sorted in ascending value order and
850 /// emitted in the usual deduplicated `(value, multiplicity)` format.
851 ///
852 /// The difference is computed item-wise, not value-wise, so if both
853 /// `self` and `other` contain occurences of a certain value `v` with
854 /// respective multiplicities `s` and `o`, then...
855 ///
856 /// - If `self` contains more occurences of `v` than `other` (i.e. `s > o`),
857 /// then the difference will contain `s - o` occurences of `v`.
858 /// - Otherwise (if `s <= o`) the difference will not contain any occurence
859 /// of `v`.
860 ///
861 /// # Examples
862 ///
863 /// ```
864 /// use numerical_multiset::NumericalMultiset;
865 /// use std::num::NonZeroUsize;
866 ///
867 /// let a = NumericalMultiset::from_iter([1, 1, 2, 2, 3]);
868 /// let b = NumericalMultiset::from_iter([2, 3, 4]);
869 ///
870 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
871 /// assert!(a.difference(&b).eq([
872 /// (1, nonzero(2)),
873 /// (2, nonzero(1)),
874 /// ]));
875 /// ```
876 #[must_use = "Only effect is to produce a result"]
877 pub fn difference<'a>(
878 &'a self,
879 other: &'a Self,
880 ) -> impl Iterator<Item = (T, NonZeroUsize)> + Clone + 'a {
881 let mut iter = self.iter();
882 let mut other_iter = other.iter().peekable();
883 std::iter::from_fn(move || {
884 // Advance self iterator normally
885 let (mut value, mut multiplicity) = iter.next()?;
886
887 // Check if this value also exists in the other iterator
888 'other_iter: loop {
889 match other_iter.peek() {
890 Some((other_value, other_multiplicity)) => match value.cmp(other_value) {
891 // Other iterator is ahead, and because it emits values
892 // in sorted order, we know it's never going to get back
893 // to the current value. So we can yield it.
894 Ordering::Less => return Some((value, multiplicity)),
895
896 // Other iterator is behind and may get to the current
897 // value later in its sorted sequence, so we must
898 // advance it and check again.
899 Ordering::Greater => {
900 let _ = other_iter.next();
901 continue 'other_iter;
902 }
903
904 // Current value exists in both iterators
905 Ordering::Equal => {
906 // If `self` contains more occurences of the common
907 // value than `other`, then we must still yield
908 // those occurences.
909 if multiplicity > *other_multiplicity {
910 let difference_multiplicity = NonZeroUsize::new(
911 multiplicity.get() - other_multiplicity.get(),
912 )
913 .expect("Checked above that this is fine");
914 let _ = other_iter.next();
915 return Some((value, difference_multiplicity));
916 } else {
917 // Otherwise, discard this entry on both sides
918 // and move on to the next iterator items.
919 let _ = other_iter.next();
920 (value, multiplicity) = iter.next()?;
921 continue 'other_iter;
922 }
923 }
924 },
925
926 // Other iterator has ended, can yield all remaining items
927 None => return Some((value, multiplicity)),
928 }
929 }
930 })
931 }
932
933 /// Visits the items representing the symmetric difference, i.e., those
934 /// that are in `self` or in `other` but not in both. They are sorted in
935 /// ascending value order and emitted in the usual deduplicated `(value,
936 /// multiplicity)` format.
937 ///
938 /// The symmetric difference is computed item-wise, not value-wise, so if
939 /// both `self` and `other` contain occurences of a certain value `v` with
940 /// respective multiplicities `s` and `o`, then...
941 ///
942 /// - If `self` contains as many occurences of `v` as `other` (i.e. `s ==
943 /// o`), then the symmetric difference will not contain any occurence of
944 /// `v`.
945 /// - Otherwise (if `s != o`) the symmetric difference will contain
946 /// `s.abs_diff(o)` occurences of `v`.
947 ///
948 /// # Examples
949 ///
950 /// ```
951 /// use numerical_multiset::NumericalMultiset;
952 /// use std::num::NonZeroUsize;
953 ///
954 /// let a = NumericalMultiset::from_iter([1, 1, 2, 2, 3]);
955 /// let b = NumericalMultiset::from_iter([2, 3, 4]);
956 ///
957 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
958 /// assert!(a.symmetric_difference(&b).eq([
959 /// (1, nonzero(2)),
960 /// (2, nonzero(1)),
961 /// (4, nonzero(1)),
962 /// ]));
963 /// ```
964 #[must_use = "Only effect is to produce a result"]
965 pub fn symmetric_difference<'a>(
966 &'a self,
967 other: &'a Self,
968 ) -> impl Iterator<Item = (T, NonZeroUsize)> + Clone + 'a {
969 let mut iter1 = self.iter().peekable();
970 let mut iter2 = other.iter().peekable();
971 std::iter::from_fn(move || {
972 'joint_iter: loop {
973 match (iter1.peek(), iter2.peek()) {
974 // As long as both iterators yield values, must be careful to
975 // yield values from both iterators, in the right order, and to
976 // skip common values.
977 (Some((value1, multiplicity1)), Some((value2, multiplicity2))) => {
978 match value1.cmp(value2) {
979 // Yield the smallest value, if any, advancing the
980 // corresponding iterator along the way
981 Ordering::Less => return iter1.next(),
982 Ordering::Greater => return iter2.next(),
983
984 // Same value was yielded by both iterators
985 Ordering::Equal => {
986 // If the value was yielded with different
987 // multiplicities, then we must still yield an
988 // entry with a multiplicity that is the
989 // absolute difference of these multiplicities.
990 if multiplicity1 != multiplicity2 {
991 let value12 = *value1;
992 let difference_multiplicity = NonZeroUsize::new(
993 multiplicity1.get().abs_diff(multiplicity2.get()),
994 )
995 .expect("Checked above that this is fine");
996 let _ = (iter1.next(), iter2.next());
997 return Some((value12, difference_multiplicity));
998 } else {
999 // Otherwise ignore the common value,
1000 // advance both iterators and try again
1001 let _ = (iter1.next(), iter2.next());
1002 continue 'joint_iter;
1003 }
1004 }
1005 }
1006 }
1007
1008 // One one iterator ends, we know there's no common value
1009 // left and there is no sorted sequence merging business to
1010 // care about, so we can just yield the remainder as-is.
1011 (Some(_), None) => return iter1.next(),
1012 (None, Some(_)) => return iter2.next(),
1013 (None, None) => return None,
1014 }
1015 }
1016 })
1017 }
1018
1019 /// Visits the items representing the intersection, i.e., those that are
1020 /// both in `self` and `other`. They are sorted in ascending value order and
1021 /// emitted in the usual deduplicated `(value, multiplicity)` format.
1022 ///
1023 /// The intersection is computed item-wise, not value-wise, so if both
1024 /// `self` and `other` contain occurences of a certain value `v` with
1025 /// respective multiplicities `s` and `o`, then the intersection will
1026 /// contain `s.min(o)` occurences of `v`.
1027 ///
1028 /// # Examples
1029 ///
1030 /// ```
1031 /// use numerical_multiset::NumericalMultiset;
1032 /// use std::num::NonZeroUsize;
1033 ///
1034 /// let a = NumericalMultiset::from_iter([1, 1, 2, 2, 3]);
1035 /// let b = NumericalMultiset::from_iter([2, 3, 4]);
1036 ///
1037 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
1038 /// assert!(a.intersection(&b).eq([
1039 /// (2, nonzero(1)),
1040 /// (3, nonzero(1)),
1041 /// ]));
1042 /// ```
1043 #[must_use = "Only effect is to produce a result"]
1044 pub fn intersection<'a>(
1045 &'a self,
1046 other: &'a Self,
1047 ) -> impl Iterator<Item = (T, NonZeroUsize)> + Clone + 'a {
1048 let mut iter1 = self.iter().peekable();
1049 let mut iter2 = other.iter().peekable();
1050 std::iter::from_fn(move || {
1051 'joint_iter: loop {
1052 match (iter1.peek(), iter2.peek()) {
1053 // As long as both iterators yield values, must be careful
1054 // to yield common values with merged multiplicities
1055 (Some((value1, multiplicity1)), Some((value2, multiplicity2))) => {
1056 match value1.cmp(value2) {
1057 // Advance the iterator which is behind, trying to make
1058 // it reach the same value as the other iterator.
1059 Ordering::Less => {
1060 let _ = iter1.next();
1061 continue 'joint_iter;
1062 }
1063 Ordering::Greater => {
1064 let _ = iter2.next();
1065 continue 'joint_iter;
1066 }
1067
1068 // Merge items associated with a common value
1069 Ordering::Equal => {
1070 let value12 = *value1;
1071 let multiplicity12 = *multiplicity1.min(multiplicity2);
1072 let _ = (iter1.next(), iter2.next());
1073 return Some((value12, multiplicity12));
1074 }
1075 }
1076 }
1077
1078 // One one iterator ends, we know there's no common value
1079 // left, so we can just yield nothing.
1080 (Some(_), None) | (None, Some(_)) | (None, None) => return None,
1081 }
1082 }
1083 })
1084 }
1085
1086 /// Visits the items representing the union, i.e., those that are in
1087 /// either `self` or `other`, without counting values that are present in
1088 /// both multisets twice. They are sorted in ascending value order and
1089 /// emitted in the usual deduplicated `(value, multiplicity)` format.
1090 ///
1091 /// The union is computed item-wise, not value-wise, so if both
1092 /// `self` and `other` contain occurences of a certain value `v` with
1093 /// respective multiplicities `s` and `o`, then the union will contain
1094 /// `s.max(o)` occurences of `v`.
1095 ///
1096 /// # Examples
1097 ///
1098 /// ```
1099 /// use numerical_multiset::NumericalMultiset;
1100 /// use std::num::NonZeroUsize;
1101 ///
1102 /// let a = NumericalMultiset::from_iter([1, 1, 2, 2, 3]);
1103 /// let b = NumericalMultiset::from_iter([2, 3, 4]);
1104 ///
1105 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
1106 /// assert!(a.union(&b).eq([
1107 /// (1, nonzero(2)),
1108 /// (2, nonzero(2)),
1109 /// (3, nonzero(1)),
1110 /// (4, nonzero(1)),
1111 /// ]));
1112 /// ```
1113 #[must_use = "Only effect is to produce a result"]
1114 pub fn union<'a>(
1115 &'a self,
1116 other: &'a Self,
1117 ) -> impl Iterator<Item = (T, NonZeroUsize)> + Clone + 'a {
1118 let mut iter1 = self.iter().peekable();
1119 let mut iter2 = other.iter().peekable();
1120 std::iter::from_fn(move || match (iter1.peek(), iter2.peek()) {
1121 // As long as both iterators yield values, must be careful to
1122 // yield values in the right order and merge common multiplicities
1123 (Some((value1, multiplicity1)), Some((value2, multiplicity2))) => {
1124 match value1.cmp(value2) {
1125 // Yield non-common values in the right order
1126 Ordering::Less => iter1.next(),
1127 Ordering::Greater => iter2.next(),
1128
1129 // Merge items associated with a common value
1130 Ordering::Equal => {
1131 let value12 = *value1;
1132 let multiplicity12 = *multiplicity1.max(multiplicity2);
1133 let _ = (iter1.next(), iter2.next());
1134 Some((value12, multiplicity12))
1135 }
1136 }
1137 }
1138
1139 // Once one iterator ends, we can just yield the rest as-is
1140 (Some(_), None) => iter1.next(),
1141 (None, Some(_)) => iter2.next(),
1142 (None, None) => None,
1143 })
1144 }
1145
1146 /// Minimal value present in the multiset, if any, along with its
1147 /// multiplicity.
1148 ///
1149 /// # Examples
1150 ///
1151 /// ```
1152 /// use numerical_multiset::NumericalMultiset;
1153 /// use std::num::NonZeroUsize;
1154 ///
1155 /// let mut mset = NumericalMultiset::new();
1156 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
1157 /// assert_eq!(mset.first(), None);
1158 /// mset.insert(2);
1159 /// assert_eq!(mset.first(), Some((2, nonzero(1))));
1160 /// mset.insert(2);
1161 /// assert_eq!(mset.first(), Some((2, nonzero(2))));
1162 /// mset.insert(1);
1163 /// assert_eq!(mset.first(), Some((1, nonzero(1))));
1164 /// ```
1165 #[inline]
1166 #[must_use = "Only effect is to produce a result"]
1167 pub fn first(&self) -> Option<(T, NonZeroUsize)> {
1168 self.value_to_multiplicity
1169 .first_key_value()
1170 .map(|(&k, &v)| (k, v))
1171 }
1172
1173 /// Maximal value present in the multiset, if any, along with its
1174 /// multiplicity.
1175 ///
1176 /// # Examples
1177 ///
1178 /// ```
1179 /// use numerical_multiset::NumericalMultiset;
1180 /// use std::num::NonZeroUsize;
1181 ///
1182 /// let mut mset = NumericalMultiset::new();
1183 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
1184 /// assert_eq!(mset.last(), None);
1185 /// mset.insert(1);
1186 /// assert_eq!(mset.last(), Some((1, nonzero(1))));
1187 /// mset.insert(1);
1188 /// assert_eq!(mset.last(), Some((1, nonzero(2))));
1189 /// mset.insert(2);
1190 /// assert_eq!(mset.last(), Some((2, nonzero(1))));
1191 /// ```
1192 #[inline]
1193 #[must_use = "Only effect is to produce a result"]
1194 pub fn last(&self) -> Option<(T, NonZeroUsize)> {
1195 self.value_to_multiplicity
1196 .last_key_value()
1197 .map(|(&k, &v)| (k, v))
1198 }
1199
1200 /// Remove the smallest item from the multiset.
1201 ///
1202 /// See also [`pop_all_first()`](Self::pop_all_first) if you want to remove
1203 /// all occurences of the smallest value from the multiset.
1204 ///
1205 /// # Examples
1206 ///
1207 /// ```
1208 /// use numerical_multiset::NumericalMultiset;
1209 ///
1210 /// let mut mset = NumericalMultiset::new();
1211 /// mset.insert(1);
1212 /// mset.insert(1);
1213 /// mset.insert(2);
1214 ///
1215 /// assert_eq!(mset.pop_first(), Some(1));
1216 /// assert_eq!(mset.pop_first(), Some(1));
1217 /// assert_eq!(mset.pop_first(), Some(2));
1218 /// assert_eq!(mset.pop_first(), None);
1219 /// ```
1220 #[inline]
1221 #[must_use = "Invalid removal should be handled"]
1222 pub fn pop_first(&mut self) -> Option<T> {
1223 let mut occupied = self.value_to_multiplicity.first_entry()?;
1224 let old_multiplicity = *occupied.get();
1225 let value = *occupied.key();
1226 match NonZeroUsize::new(old_multiplicity.get() - 1) {
1227 Some(new_multiplicity) => {
1228 *occupied.get_mut() = new_multiplicity;
1229 }
1230 None => {
1231 occupied.remove_entry();
1232 }
1233 }
1234 self.len -= 1;
1235 Some(value)
1236 }
1237
1238 /// Remove the largest item from the multiset.
1239 ///
1240 /// See also [`pop_all_last()`](Self::pop_all_last) if you want to remove
1241 /// all occurences of the smallest value from the multiset.
1242 ///
1243 /// # Examples
1244 ///
1245 /// ```
1246 /// use numerical_multiset::NumericalMultiset;
1247 ///
1248 /// let mut mset = NumericalMultiset::new();
1249 /// mset.insert(1);
1250 /// mset.insert(1);
1251 /// mset.insert(2);
1252 ///
1253 /// assert_eq!(mset.pop_last(), Some(2));
1254 /// assert_eq!(mset.pop_last(), Some(1));
1255 /// assert_eq!(mset.pop_last(), Some(1));
1256 /// assert_eq!(mset.pop_last(), None);
1257 /// ```
1258 #[inline]
1259 #[must_use = "Invalid removal should be handled"]
1260 pub fn pop_last(&mut self) -> Option<T> {
1261 let mut occupied = self.value_to_multiplicity.last_entry()?;
1262 let old_multiplicity = *occupied.get();
1263 let value = *occupied.key();
1264 match NonZeroUsize::new(old_multiplicity.get() - 1) {
1265 Some(new_multiplicity) => {
1266 *occupied.get_mut() = new_multiplicity;
1267 }
1268 None => {
1269 occupied.remove_entry();
1270 }
1271 }
1272 self.len -= 1;
1273 Some(value)
1274 }
1275
1276 /// Retains only the items specified by the predicate.
1277 ///
1278 /// For efficiency reasons, the filtering callback `f` is not run once per
1279 /// item, but once per distinct value present inside of the multiset.
1280 /// However, it is also provided with the multiplicity of that value within
1281 /// the multiset, which can be used as a filtering criterion.
1282 ///
1283 /// Furthermore, you get read/write access to the multiplicity, which allows
1284 /// you to change it if you desire to do so.
1285 ///
1286 /// In other words, this method removes all values `v` with multiplicity `m`
1287 /// for which `f(v, m)` returns `false`, and allows changing the
1288 /// multiplicity for all values where `f` returns `true`.
1289 ///
1290 /// Values are visited in ascending order.
1291 ///
1292 /// # Examples
1293 ///
1294 /// ```
1295 /// use numerical_multiset::NumericalMultiset;
1296 /// use std::num::NonZeroUsize;
1297 ///
1298 /// let mut mset = NumericalMultiset::from_iter([1, 1, 2, 3, 4, 4, 5, 5, 5]);
1299 /// // Keep even values with an even multiplicity
1300 /// // and odd values with an odd multiplicity.
1301 /// mset.retain(|value, multiplicity| value % 2 == multiplicity.get() % 2);
1302 ///
1303 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
1304 /// assert!(mset.iter().eq([
1305 /// (3, nonzero(1)),
1306 /// (4, nonzero(2)),
1307 /// (5, nonzero(3)),
1308 /// ]));
1309 /// ```
1310 pub fn retain(&mut self, mut f: impl FnMut(T, &mut NonZeroUsize) -> bool) {
1311 self.value_to_multiplicity.retain(|&k, v| f(k, v));
1312 self.reset_len();
1313 }
1314
1315 /// Moves all items from `other` into `self`, leaving `other` empty.
1316 ///
1317 /// # Examples
1318 ///
1319 /// ```
1320 /// use numerical_multiset::NumericalMultiset;
1321 /// use std::num::NonZeroUsize;
1322 ///
1323 /// let mut a = NumericalMultiset::from_iter([1, 1, 2, 3]);
1324 /// let mut b = NumericalMultiset::from_iter([3, 3, 4, 5]);
1325 ///
1326 /// a.append(&mut b);
1327 ///
1328 /// assert_eq!(a.len(), 8);
1329 /// assert!(b.is_empty());
1330 ///
1331 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
1332 /// assert!(a.iter().eq([
1333 /// (1, nonzero(2)),
1334 /// (2, nonzero(1)),
1335 /// (3, nonzero(3)),
1336 /// (4, nonzero(1)),
1337 /// (5, nonzero(1)),
1338 /// ]));
1339 /// ```
1340 pub fn append(&mut self, other: &mut Self) {
1341 // Fast path when self is empty
1342 if self.is_empty() {
1343 std::mem::swap(self, other);
1344 return;
1345 }
1346
1347 // Otherwise just insert everything into self. This is the fastest
1348 // available approach because...
1349 //
1350 // - BTreeMap::append() does not have the right semantics, if both self
1351 // and other contain entries associated with a certain value it will
1352 // discard the entries from self instead of adding those from others.
1353 // - BTreeMap does not externally expose a mutable iterator that allows
1354 // for both modification of existing entries and insertions of new
1355 // entries, which is what we would need in order to implement this
1356 // loop more efficiently.
1357 for (value, multiplicity) in other.iter() {
1358 self.insert_multiple(value, multiplicity);
1359 }
1360 other.clear();
1361 }
1362}
1363
1364impl<T: Copy + Ord> BitAnd<&NumericalMultiset<T>> for &NumericalMultiset<T> {
1365 type Output = NumericalMultiset<T>;
1366
1367 /// Returns the intersection of `self` and `rhs` as a new `NumericalMultiset<T>`.
1368 ///
1369 /// # Examples
1370 ///
1371 /// ```
1372 /// use numerical_multiset::NumericalMultiset;
1373 ///
1374 /// let a = NumericalMultiset::from_iter([1, 1, 2, 2, 3]);
1375 /// let b = NumericalMultiset::from_iter([2, 3, 4]);
1376 /// assert_eq!(
1377 /// &a & &b,
1378 /// NumericalMultiset::from_iter([2, 3])
1379 /// );
1380 /// ```
1381 #[must_use = "Only effect is to produce a result"]
1382 fn bitand(self, rhs: &NumericalMultiset<T>) -> Self::Output {
1383 self.intersection(rhs).collect()
1384 }
1385}
1386
1387impl<T: Copy + Ord> BitOr<&NumericalMultiset<T>> for &NumericalMultiset<T> {
1388 type Output = NumericalMultiset<T>;
1389
1390 /// Returns the union of `self` and `rhs` as a new `NumericalMultiset<T>`.
1391 ///
1392 /// # Examples
1393 ///
1394 /// ```
1395 /// use numerical_multiset::NumericalMultiset;
1396 ///
1397 /// let a = NumericalMultiset::from_iter([1, 1, 2, 2, 3]);
1398 /// let b = NumericalMultiset::from_iter([2, 3, 4]);
1399 /// assert_eq!(
1400 /// &a | &b,
1401 /// NumericalMultiset::from_iter([1, 1, 2, 2, 3, 4])
1402 /// );
1403 /// ```
1404 #[must_use = "Only effect is to produce a result"]
1405 fn bitor(self, rhs: &NumericalMultiset<T>) -> Self::Output {
1406 self.union(rhs).collect()
1407 }
1408}
1409
1410impl<T: Copy + Ord> BitXor<&NumericalMultiset<T>> for &NumericalMultiset<T> {
1411 type Output = NumericalMultiset<T>;
1412
1413 /// Returns the symmetric difference of `self` and `rhs` as a new `NumericalMultiset<T>`.
1414 ///
1415 /// # Examples
1416 ///
1417 /// ```
1418 /// use numerical_multiset::NumericalMultiset;
1419 ///
1420 /// let a = NumericalMultiset::from_iter([1, 1, 2, 2, 3]);
1421 /// let b = NumericalMultiset::from_iter([2, 3, 4]);
1422 /// assert_eq!(
1423 /// &a ^ &b,
1424 /// NumericalMultiset::from_iter([1, 1, 2, 4])
1425 /// );
1426 /// ```
1427 #[must_use = "Only effect is to produce a result"]
1428 fn bitxor(self, rhs: &NumericalMultiset<T>) -> Self::Output {
1429 self.symmetric_difference(rhs).collect()
1430 }
1431}
1432
1433impl<T: Ord> Extend<T> for NumericalMultiset<T> {
1434 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1435 for element in iter {
1436 self.insert(element);
1437 }
1438 }
1439}
1440
1441impl<T: Ord> Extend<(T, NonZeroUsize)> for NumericalMultiset<T> {
1442 /// More efficient alternative to [`Extend<T>`] for cases where you know in
1443 /// advance that you are going to insert several copies of a value
1444 ///
1445 /// # Examples
1446 ///
1447 /// ```
1448 /// use numerical_multiset::NumericalMultiset;
1449 /// use std::num::NonZeroUsize;
1450 ///
1451 /// let mut mset = NumericalMultiset::from_iter([1, 2, 3]);
1452 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
1453 /// mset.extend([(3, nonzero(3)), (4, nonzero(2))]);
1454 /// assert_eq!(mset, NumericalMultiset::from_iter([1, 2, 3, 3, 3, 3, 4, 4]));
1455 /// ```
1456 fn extend<I: IntoIterator<Item = (T, NonZeroUsize)>>(&mut self, iter: I) {
1457 for (value, count) in iter {
1458 self.insert_multiple(value, count);
1459 }
1460 }
1461}
1462
1463impl<T: Ord> FromIterator<T> for NumericalMultiset<T> {
1464 #[must_use = "Only effect is to produce a result"]
1465 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1466 let mut result = Self::new();
1467 result.extend(iter);
1468 result
1469 }
1470}
1471
1472impl<T: Ord> FromIterator<(T, NonZeroUsize)> for NumericalMultiset<T> {
1473 /// More efficient alternative to [`FromIterator<T>`] for cases where you
1474 /// know in advance that you are going to insert several copies of a value
1475 ///
1476 /// # Examples
1477 ///
1478 /// ```
1479 /// use numerical_multiset::NumericalMultiset;
1480 /// use std::num::NonZeroUsize;
1481 ///
1482 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
1483 /// assert_eq!(
1484 /// NumericalMultiset::from_iter([1, 2, 2, 2, 3, 3]),
1485 /// NumericalMultiset::from_iter([
1486 /// (1, nonzero(1)),
1487 /// (2, nonzero(3)),
1488 /// (3, nonzero(2)),
1489 /// ])
1490 /// );
1491 /// ```
1492 #[must_use = "Only effect is to produce a result"]
1493 fn from_iter<I: IntoIterator<Item = (T, NonZeroUsize)>>(iter: I) -> Self {
1494 let mut result = Self::new();
1495 result.extend(iter);
1496 result
1497 }
1498}
1499
1500impl<T: Hash> Hash for NumericalMultiset<T> {
1501 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1502 self.value_to_multiplicity.hash(state)
1503 }
1504}
1505
1506impl<'a, T: Copy> IntoIterator for &'a NumericalMultiset<T> {
1507 type Item = (T, NonZeroUsize);
1508 type IntoIter = Iter<'a, T>;
1509
1510 #[must_use = "Only effect is to produce a result"]
1511 fn into_iter(self) -> Self::IntoIter {
1512 Iter(self.value_to_multiplicity.iter())
1513 }
1514}
1515//
1516/// An iterator over the contents of an [`NumericalMultiset`], sorted by value.
1517///
1518/// This `struct` is created by the [`iter()`](NumericalMultiset::iter) method on
1519/// [`NumericalMultiset`]. See its documentation for more.
1520#[derive(Clone, Debug, Default)]
1521pub struct Iter<'a, T: Copy>(btree_map::Iter<'a, T, NonZeroUsize>);
1522//
1523impl<T: Copy> DoubleEndedIterator for Iter<'_, T> {
1524 #[inline]
1525 fn next_back(&mut self) -> Option<Self::Item> {
1526 self.0.next_back().map(|(&k, &v)| (k, v))
1527 }
1528
1529 #[inline]
1530 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1531 self.0.nth_back(n).map(|(&k, &v)| (k, v))
1532 }
1533}
1534//
1535impl<T: Copy> ExactSizeIterator for Iter<'_, T> {
1536 #[must_use = "Only effect is to produce a result"]
1537 fn len(&self) -> usize {
1538 self.0.len()
1539 }
1540}
1541//
1542impl<T: Copy> FusedIterator for Iter<'_, T> {}
1543//
1544impl<T: Copy> Iterator for Iter<'_, T> {
1545 type Item = (T, NonZeroUsize);
1546
1547 #[inline]
1548 fn next(&mut self) -> Option<Self::Item> {
1549 self.0.next().map(|(&k, &v)| (k, v))
1550 }
1551
1552 #[must_use = "Only effect is to produce a result"]
1553 fn size_hint(&self) -> (usize, Option<usize>) {
1554 self.0.size_hint()
1555 }
1556
1557 fn count(self) -> usize
1558 where
1559 Self: Sized,
1560 {
1561 self.0.count()
1562 }
1563
1564 fn last(self) -> Option<Self::Item>
1565 where
1566 Self: Sized,
1567 {
1568 self.0.last().map(|(&k, &v)| (k, v))
1569 }
1570
1571 #[inline]
1572 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1573 self.0.nth(n).map(|(&k, &v)| (k, v))
1574 }
1575
1576 fn is_sorted(self) -> bool
1577 where
1578 Self: Sized,
1579 Self::Item: PartialOrd,
1580 {
1581 true
1582 }
1583}
1584
1585impl<T> IntoIterator for NumericalMultiset<T> {
1586 type Item = (T, NonZeroUsize);
1587 type IntoIter = IntoIter<T>;
1588
1589 /// Gets an iterator for moving out the `NumericalMultiset`’s contents.
1590 ///
1591 /// Items are grouped by value and emitted in `(value, multiplicity)`
1592 /// format, in ascending value order.
1593 ///
1594 /// # Examples
1595 ///
1596 /// ```
1597 /// use numerical_multiset::NumericalMultiset;
1598 /// use std::num::NonZeroUsize;
1599 ///
1600 /// let mset = NumericalMultiset::from_iter([3, 1, 2, 2]);
1601 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
1602 /// assert!(mset.into_iter().eq([
1603 /// (1, nonzero(1)),
1604 /// (2, nonzero(2)),
1605 /// (3, nonzero(1))
1606 /// ]));
1607 /// ```
1608 fn into_iter(self) -> Self::IntoIter {
1609 IntoIter(self.value_to_multiplicity.into_iter())
1610 }
1611}
1612//
1613/// An owning iterator over the contents of an [`NumericalMultiset`], sorted by
1614/// value.
1615///
1616/// This struct is created by the `into_iter()` method on [`NumericalMultiset`]
1617/// (provided by the [`IntoIterator`] trait). See its documentation for more.
1618#[derive(Debug, Default)]
1619pub struct IntoIter<T>(btree_map::IntoIter<T, NonZeroUsize>);
1620//
1621impl<T> DoubleEndedIterator for IntoIter<T> {
1622 #[inline]
1623 fn next_back(&mut self) -> Option<Self::Item> {
1624 self.0.next_back()
1625 }
1626
1627 #[inline]
1628 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1629 self.0.nth_back(n)
1630 }
1631}
1632//
1633impl<T> ExactSizeIterator for IntoIter<T> {
1634 #[must_use = "Only effect is to produce a result"]
1635 fn len(&self) -> usize {
1636 self.0.len()
1637 }
1638}
1639//
1640impl<T> FusedIterator for IntoIter<T> {}
1641//
1642impl<T> Iterator for IntoIter<T> {
1643 type Item = (T, NonZeroUsize);
1644
1645 #[inline]
1646 fn next(&mut self) -> Option<Self::Item> {
1647 self.0.next()
1648 }
1649
1650 #[must_use = "Only effect is to produce a result"]
1651 fn size_hint(&self) -> (usize, Option<usize>) {
1652 self.0.size_hint()
1653 }
1654
1655 fn count(self) -> usize
1656 where
1657 Self: Sized,
1658 {
1659 self.0.count()
1660 }
1661
1662 fn last(self) -> Option<Self::Item>
1663 where
1664 Self: Sized,
1665 {
1666 self.0.last()
1667 }
1668
1669 #[inline]
1670 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1671 self.0.nth(n)
1672 }
1673
1674 fn is_sorted(self) -> bool
1675 where
1676 Self: Sized,
1677 Self::Item: PartialOrd,
1678 {
1679 true
1680 }
1681}
1682
1683impl<T: Ord> Ord for NumericalMultiset<T> {
1684 #[must_use = "Only effect is to produce a result"]
1685 fn cmp(&self, other: &Self) -> Ordering {
1686 self.value_to_multiplicity.cmp(&other.value_to_multiplicity)
1687 }
1688}
1689
1690impl<T: PartialEq> PartialEq for NumericalMultiset<T> {
1691 #[must_use = "Only effect is to produce a result"]
1692 fn eq(&self, other: &Self) -> bool {
1693 self.len == other.len && self.value_to_multiplicity == other.value_to_multiplicity
1694 }
1695}
1696
1697impl<T: PartialOrd> PartialOrd for NumericalMultiset<T> {
1698 #[must_use = "Only effect is to produce a result"]
1699 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1700 self.value_to_multiplicity
1701 .partial_cmp(&other.value_to_multiplicity)
1702 }
1703}
1704
1705impl<T: Copy + Ord> Sub<&NumericalMultiset<T>> for &NumericalMultiset<T> {
1706 type Output = NumericalMultiset<T>;
1707
1708 /// Returns the difference of `self` and `rhs` as a new `NumericalMultiset<T>`.
1709 ///
1710 /// # Examples
1711 ///
1712 /// ```
1713 /// use numerical_multiset::NumericalMultiset;
1714 ///
1715 /// let a = NumericalMultiset::from_iter([1, 1, 2, 2, 3]);
1716 /// let b = NumericalMultiset::from_iter([2, 3, 4]);
1717 /// assert_eq!(
1718 /// &a - &b,
1719 /// NumericalMultiset::from_iter([1, 1, 2])
1720 /// );
1721 /// ```
1722 #[must_use = "Only effect is to produce a result"]
1723 fn sub(self, rhs: &NumericalMultiset<T>) -> Self::Output {
1724 self.difference(rhs).collect()
1725 }
1726}
1727
1728#[cfg(test)]
1729mod test {
1730 use super::*;
1731 use proptest::{prelude::*, sample::SizeRange};
1732 use std::{
1733 cmp::Ordering,
1734 collections::HashSet,
1735 fmt::Debug,
1736 hash::{BuildHasher, RandomState},
1737 ops::Range,
1738 };
1739
1740 /// Clearer name for the constant 1 in NonZeroUsize format
1741 const ONE: NonZeroUsize = NonZeroUsize::MIN;
1742
1743 /// Alternative to Iterator::eq that prints a clearer message on failure
1744 fn check_equal_iterable<V, It1, It2>(it1: It1, it2: It2)
1745 where
1746 It1: IntoIterator<Item = V>,
1747 It2: IntoIterator<Item = V>,
1748 V: Debug + PartialEq,
1749 {
1750 assert_eq!(
1751 it1.into_iter().collect::<Vec<_>>(),
1752 it2.into_iter().collect::<Vec<_>>(),
1753 );
1754 }
1755
1756 /// Alternative to it.count() == 0 that prints a clearer message on failure
1757 fn check_empty_iterable<It>(it: It)
1758 where
1759 It: IntoIterator,
1760 It::Item: Debug + PartialEq,
1761 {
1762 check_equal_iterable(it, std::iter::empty());
1763 }
1764
1765 /// Check properties that should be true of any pair of multisets
1766 fn check_any_mset_pair(mset1: &NumericalMultiset<i32>, mset2: &NumericalMultiset<i32>) {
1767 let intersection = mset1 & mset2;
1768 for (val, mul) in &intersection {
1769 assert_eq!(
1770 mul,
1771 mset1
1772 .multiplicity(val)
1773 .unwrap()
1774 .min(mset2.multiplicity(val).unwrap()),
1775 );
1776 }
1777 for val1 in mset1.values() {
1778 assert!(intersection.contains(val1) || !mset2.contains(val1));
1779 }
1780 for val2 in mset2.values() {
1781 assert!(intersection.contains(val2) || !mset1.contains(val2));
1782 }
1783 check_equal_iterable(mset1.intersection(mset2), &intersection);
1784
1785 let union = mset1 | mset2;
1786 for (val, mul) in &union {
1787 assert_eq!(
1788 mul.get(),
1789 mset1
1790 .multiplicity(val)
1791 .map_or(0, |nz| nz.get())
1792 .max(mset2.multiplicity(val).map_or(0, |nz| nz.get()))
1793 );
1794 }
1795 for val in mset1.values().chain(mset2.values()) {
1796 assert!(union.contains(val));
1797 }
1798 check_equal_iterable(mset1.union(mset2), &union);
1799
1800 let difference = mset1 - mset2;
1801 for (val, mul) in &difference {
1802 assert_eq!(
1803 mul.get(),
1804 mset1
1805 .multiplicity(val)
1806 .unwrap()
1807 .get()
1808 .checked_sub(mset2.multiplicity(val).map_or(0, |nz| nz.get()))
1809 .unwrap()
1810 );
1811 }
1812 for (val, mul1) in mset1 {
1813 assert!(difference.contains(val) || mset2.multiplicity(val).unwrap() >= mul1);
1814 }
1815 check_equal_iterable(mset1.difference(mset2), difference);
1816
1817 let symmetric_difference = mset1 ^ mset2;
1818 for (val, mul) in &symmetric_difference {
1819 assert_eq!(
1820 mul.get(),
1821 mset1
1822 .multiplicity(val)
1823 .map_or(0, |nz| nz.get())
1824 .abs_diff(mset2.multiplicity(val).map_or(0, |nz| nz.get()))
1825 );
1826 }
1827 for (val1, mul1) in mset1 {
1828 assert!(
1829 symmetric_difference.contains(val1) || mset2.multiplicity(val1).unwrap() >= mul1
1830 );
1831 }
1832 for (val2, mul2) in mset2 {
1833 assert!(
1834 symmetric_difference.contains(val2) || mset1.multiplicity(val2).unwrap() >= mul2
1835 );
1836 }
1837 check_equal_iterable(mset1.symmetric_difference(mset2), symmetric_difference);
1838
1839 assert_eq!(mset1.is_disjoint(mset2), intersection.is_empty(),);
1840
1841 if mset1.is_subset(mset2) {
1842 for (val, mul1) in mset1 {
1843 assert!(mset2.multiplicity(val).unwrap() >= mul1);
1844 }
1845 } else {
1846 assert!(
1847 mset1.iter().any(|(val1, mul1)| {
1848 mset2.multiplicity(val1).is_none_or(|mul2| mul2 < mul1)
1849 })
1850 )
1851 }
1852 assert_eq!(mset2.is_superset(mset1), mset1.is_subset(mset2));
1853
1854 let mut combined = mset1.clone();
1855 let mut appended = mset2.clone();
1856 combined.append(&mut appended);
1857 assert_eq!(
1858 combined,
1859 mset1
1860 .iter()
1861 .chain(mset2.iter())
1862 .collect::<NumericalMultiset<_>>()
1863 );
1864 assert!(appended.is_empty());
1865
1866 let mut extended_by_tuples = mset1.clone();
1867 extended_by_tuples.extend(mset2.iter());
1868 assert_eq!(extended_by_tuples, combined);
1869
1870 let mut extended_by_values = mset1.clone();
1871 extended_by_values.extend(
1872 mset2
1873 .iter()
1874 .flat_map(|(val, mul)| std::iter::repeat_n(val, mul.get())),
1875 );
1876 assert_eq!(
1877 extended_by_values, combined,
1878 "{mset1:?} + {mset2:?} != {extended_by_values:?}"
1879 );
1880
1881 assert_eq!(
1882 mset1.cmp(mset2),
1883 mset1
1884 .value_to_multiplicity
1885 .cmp(&mset2.value_to_multiplicity)
1886 );
1887 assert_eq!(mset1.partial_cmp(mset2), Some(mset1.cmp(mset2)));
1888 }
1889
1890 /// Check properties that should be true of any multiset, knowing its contents
1891 fn check_any_mset(mset: &NumericalMultiset<i32>, contents: &[(i32, NonZeroUsize)]) {
1892 let sorted_contents = contents
1893 .iter()
1894 .map(|(v, m)| (*v, m.get()))
1895 .collect::<BTreeMap<i32, usize>>();
1896
1897 check_equal_iterable(
1898 mset.iter().map(|(val, mul)| (val, mul.get())),
1899 sorted_contents.iter().map(|(&k, &v)| (k, v)),
1900 );
1901 check_equal_iterable(mset, mset.iter());
1902 check_equal_iterable(mset.clone(), mset.iter());
1903 check_equal_iterable(mset.range(..), mset.iter());
1904 check_equal_iterable(mset.values(), sorted_contents.keys().copied());
1905 check_equal_iterable(mset.clone().into_values(), mset.values());
1906
1907 assert_eq!(mset.len(), sorted_contents.values().sum());
1908 assert_eq!(mset.num_values(), contents.len());
1909 assert_eq!(mset.is_empty(), contents.is_empty());
1910
1911 for (&val, &mul) in &sorted_contents {
1912 assert!(mset.contains(val));
1913 assert_eq!(mset.multiplicity(val).unwrap().get(), mul);
1914 }
1915
1916 assert_eq!(
1917 mset.first().map(|(val, mul)| (val, mul.get())),
1918 sorted_contents.first_key_value().map(|(&k, &v)| (k, v)),
1919 );
1920 assert_eq!(
1921 mset.last().map(|(val, mul)| (val, mul.get())),
1922 sorted_contents.last_key_value().map(|(&k, &v)| (k, v)),
1923 );
1924
1925 #[allow(clippy::eq_op)]
1926 {
1927 assert_eq!(mset, mset);
1928 }
1929 assert_eq!(*mset, mset.clone());
1930 assert_eq!(mset.cmp(mset), Ordering::Equal);
1931 assert_eq!(mset.partial_cmp(mset), Some(mset.cmp(mset)));
1932
1933 let state = RandomState::new();
1934 assert_eq!(
1935 state.hash_one(mset),
1936 state.hash_one(&mset.value_to_multiplicity),
1937 );
1938
1939 let mut mutable = mset.clone();
1940 if let Some((first, first_mul)) = mset.first() {
1941 // Pop the smallest items...
1942 assert_eq!(mutable.pop_all_first(), Some((first, first_mul)));
1943 assert_eq!(mutable.len(), mset.len() - first_mul.get());
1944 assert_eq!(mutable.num_values(), mset.num_values() - 1);
1945 assert!(!mutable.contains(first));
1946 assert_eq!(mutable.multiplicity(first), None);
1947 assert_ne!(mutable, *mset);
1948
1949 // ...then insert them back
1950 assert_eq!(mutable.insert_multiple(first, first_mul), None);
1951 assert_eq!(mutable, *mset);
1952
1953 // Same with a single item
1954 assert_eq!(mutable.pop_first(), Some(first));
1955 assert_eq!(mutable.len(), mset.len() - 1);
1956 let new_first_mul = NonZeroUsize::new(first_mul.get() - 1);
1957 let first_is_single = new_first_mul.is_none();
1958 assert_eq!(
1959 mutable.num_values(),
1960 mset.num_values() - first_is_single as usize
1961 );
1962 assert_eq!(mutable.contains(first), !first_is_single);
1963 assert_eq!(mutable.multiplicity(first), new_first_mul);
1964 assert_ne!(mutable, *mset);
1965 assert_eq!(mutable.insert(first), new_first_mul);
1966 assert_eq!(mutable, *mset);
1967
1968 // If there is a first item, there is a last item
1969 let (last, last_mul) = mset.last().unwrap();
1970
1971 // And everything we checked for the smallest items should also
1972 // applies to the largest ones
1973 assert_eq!(mutable.pop_all_last(), Some((last, last_mul)));
1974 assert_eq!(mutable.len(), mset.len() - last_mul.get());
1975 assert_eq!(mutable.num_values(), mset.num_values() - 1);
1976 assert!(!mutable.contains(last));
1977 assert_eq!(mutable.multiplicity(last), None);
1978 assert_ne!(mutable, *mset);
1979 //
1980 assert_eq!(mutable.insert_multiple(last, last_mul), None);
1981 assert_eq!(mutable, *mset);
1982 //
1983 assert_eq!(mutable.pop_last(), Some(last));
1984 assert_eq!(mutable.len(), mset.len() - 1);
1985 let new_last_mul = NonZeroUsize::new(last_mul.get() - 1);
1986 let last_is_single = new_last_mul.is_none();
1987 assert_eq!(
1988 mutable.num_values(),
1989 mset.num_values() - last_is_single as usize
1990 );
1991 assert_eq!(mutable.contains(last), !last_is_single);
1992 assert_eq!(mutable.multiplicity(last), new_last_mul);
1993 assert_ne!(mutable, *mset);
1994 assert_eq!(mutable.insert(last), new_last_mul);
1995 assert_eq!(mutable, *mset);
1996 } else {
1997 assert!(mset.is_empty());
1998 assert_eq!(mutable.pop_first(), None);
1999 assert!(mutable.is_empty());
2000 assert_eq!(mutable.pop_all_first(), None);
2001 assert!(mutable.is_empty());
2002 assert_eq!(mutable.pop_last(), None);
2003 assert!(mutable.is_empty());
2004 assert_eq!(mutable.pop_all_last(), None);
2005 assert!(mutable.is_empty());
2006 }
2007
2008 let mut retain_all = mset.clone();
2009 retain_all.retain(|_, _| true);
2010 assert_eq!(retain_all, *mset);
2011
2012 let mut retain_nothing = mset.clone();
2013 retain_nothing.retain(|_, _| false);
2014 assert!(retain_nothing.is_empty());
2015 }
2016
2017 /// Check properties that should be true of an empty multiset
2018 fn check_empty_mset(empty: &NumericalMultiset<i32>) {
2019 check_any_mset(empty, &[]);
2020
2021 assert_eq!(empty.len(), 0);
2022 assert_eq!(empty.num_values(), 0);
2023 assert!(empty.is_empty());
2024 assert_eq!(empty.first(), None);
2025 assert_eq!(empty.last(), None);
2026
2027 check_empty_iterable(empty.iter());
2028 check_empty_iterable(empty.values());
2029 check_empty_iterable(empty.clone());
2030 check_empty_iterable(empty.clone().into_values());
2031
2032 let mut mutable = empty.clone();
2033 assert_eq!(mutable.pop_first(), None);
2034 assert_eq!(mutable.pop_last(), None);
2035 assert_eq!(mutable.pop_all_first(), None);
2036 assert_eq!(mutable.pop_all_last(), None);
2037 }
2038
2039 /// Check that clear() makes a multiset empty
2040 fn check_clear_outcome(mut mset: NumericalMultiset<i32>) {
2041 mset.clear();
2042 check_empty_mset(&mset);
2043 }
2044
2045 /// Check the various ways to build an empty multiset
2046 #[test]
2047 fn empty() {
2048 check_empty_mset(&NumericalMultiset::default());
2049 let mset = NumericalMultiset::<i32>::new();
2050 check_empty_mset(&mset);
2051 check_clear_outcome(mset);
2052 }
2053
2054 /// Maximal acceptable multiplicity value
2055 fn max_multiplicity() -> usize {
2056 SizeRange::default().end_excl()
2057 }
2058
2059 /// Generate a reasonably low multiplicity value
2060 fn multiplicity() -> impl Strategy<Value = NonZeroUsize> {
2061 prop_oneof![Just(1), Just(2), 3..max_multiplicity()]
2062 .prop_map(|m| NonZeroUsize::new(m).unwrap())
2063 }
2064
2065 /// Build an arbitrary multiset
2066 fn mset_contents() -> impl Strategy<Value = Vec<(i32, NonZeroUsize)>> {
2067 any::<HashSet<i32>>().prop_flat_map(|values| {
2068 prop::collection::vec(multiplicity(), values.len()).prop_map(move |multiplicities| {
2069 values.iter().copied().zip(multiplicities).collect()
2070 })
2071 })
2072 }
2073
2074 proptest! {
2075 /// Check properties of arbitrary multisets
2076 #[test]
2077 fn single(contents in mset_contents()) {
2078 for mset in [
2079 contents.iter().copied().collect(),
2080 contents.iter().flat_map(|(v, m)| {
2081 std::iter::repeat_n(*v, m.get())
2082 }).collect(),
2083 ] {
2084 check_any_mset(&mset, &contents);
2085 check_any_mset_pair(&mset, &mset);
2086 let empty = NumericalMultiset::default();
2087 check_any_mset_pair(&mset, &empty);
2088 check_any_mset_pair(&empty, &mset);
2089 check_clear_outcome(mset);
2090 }
2091 }
2092 }
2093
2094 /// Build an arbitrary multiset
2095 fn mset() -> impl Strategy<Value = NumericalMultiset<i32>> {
2096 mset_contents().prop_map(NumericalMultiset::from_iter)
2097 }
2098
2099 /// Build a multiset and pick a value that has a high chance of being from
2100 /// the multiset if it is not empty.
2101 fn mset_and_value() -> impl Strategy<Value = (NumericalMultiset<i32>, i32)> {
2102 mset().prop_flat_map(|mset| {
2103 if mset.is_empty() {
2104 (Just(mset), any::<i32>()).boxed()
2105 } else {
2106 let inner_value = prop::sample::select(mset.values().collect::<Vec<_>>());
2107 let value = prop_oneof![inner_value, any::<i32>()];
2108 (Just(mset), value).boxed()
2109 }
2110 })
2111 }
2112
2113 proptest! {
2114 /// Test operations that combine a multiset with a value
2115 #[test]
2116 fn with_value((initial, value) in mset_and_value()) {
2117 // Most operations depend on whether the value was present...
2118 if let Some(&mul) = initial.value_to_multiplicity.get(&value) {
2119 assert!(initial.contains(value));
2120 assert_eq!(initial.multiplicity(value), Some(mul));
2121 {
2122 let mut mset = initial.clone();
2123 assert_eq!(mset.insert(value), Some(mul));
2124 let mut expected = initial.clone();
2125 let Entry::Occupied(mut entry) = expected.value_to_multiplicity.entry(value) else {
2126 unreachable!();
2127 };
2128 *entry.get_mut() = mul.checked_add(1).unwrap();
2129 expected.len += 1;
2130 assert_eq!(mset, expected);
2131 }
2132 {
2133 let mut mset = initial.clone();
2134 assert_eq!(mset.remove(value), Some(mul));
2135 let mut expected = initial.clone();
2136 if mul == ONE {
2137 expected.value_to_multiplicity.remove(&value);
2138 } else {
2139 let Entry::Occupied(mut entry) = expected.value_to_multiplicity.entry(value) else {
2140 unreachable!();
2141 };
2142 *entry.get_mut() = NonZeroUsize::new(mul.get() - 1).unwrap();
2143 }
2144 expected.len -= 1;
2145 assert_eq!(mset, expected);
2146 }
2147 {
2148 let mut mset = initial.clone();
2149 assert_eq!(mset.remove_all(value), Some(mul));
2150 let mut expected = initial.clone();
2151 expected.value_to_multiplicity.remove(&value);
2152 expected.len -= mul.get();
2153 assert_eq!(mset, expected);
2154 }
2155 } else {
2156 assert!(!initial.contains(value));
2157 assert_eq!(initial.multiplicity(value), None);
2158 {
2159 let mut mset = initial.clone();
2160 assert_eq!(mset.insert(value), None);
2161 let mut expected = initial.clone();
2162 expected.value_to_multiplicity.insert(value, ONE);
2163 expected.len += 1;
2164 assert_eq!(mset, expected);
2165 }
2166 {
2167 let mut mset = initial.clone();
2168 assert_eq!(mset.remove(value), None);
2169 assert_eq!(mset, initial);
2170 assert_eq!(mset.remove_all(value), None);
2171 assert_eq!(mset, initial);
2172 }
2173 }
2174
2175 // ...except for split_off, which doesn't really care
2176 {
2177 let mut mset = initial.clone();
2178 let ge = mset.split_off(value);
2179 let lt = mset;
2180 let mut expected_lt = initial.clone();
2181 let ge_value_to_multiplicity = expected_lt.value_to_multiplicity.split_off(&value);
2182 expected_lt.reset_len();
2183 assert_eq!(lt, expected_lt);
2184 let expected_ge = NumericalMultiset::from_iter(ge_value_to_multiplicity);
2185 assert_eq!(ge, expected_ge);
2186 }
2187 }
2188
2189 /// Check operations that require a value and a multiplicity
2190 #[test]
2191 fn with_value_and_multiplicity((initial, value) in mset_and_value(),
2192 new_mul in multiplicity()) {
2193 // Most operations depend on whether the value was present...
2194 if let Some(&initial_mul) = initial.value_to_multiplicity.get(&value) {
2195 {
2196 let mut mset = initial.clone();
2197 assert_eq!(mset.insert_multiple(value, new_mul), Some(initial_mul));
2198 let mut expected = initial.clone();
2199 let Entry::Occupied(mut entry) = expected.value_to_multiplicity.entry(value) else {
2200 unreachable!();
2201 };
2202 *entry.get_mut() = initial_mul.checked_add(new_mul.get()).unwrap();
2203 expected.len += new_mul.get();
2204 assert_eq!(mset, expected);
2205 }
2206 {
2207 let mut mset = initial.clone();
2208 assert_eq!(mset.replace_all(value, new_mul), Some(initial_mul));
2209 let mut expected = initial.clone();
2210 let Entry::Occupied(mut entry) = expected.value_to_multiplicity.entry(value) else {
2211 unreachable!();
2212 };
2213 *entry.get_mut() = new_mul;
2214 expected.len = expected.len - initial_mul.get() + new_mul.get();
2215 assert_eq!(mset, expected);
2216 }
2217 } else {
2218 let mut inserted = initial.clone();
2219 assert_eq!(inserted.insert_multiple(value, new_mul), None);
2220 let mut expected = initial.clone();
2221 expected.value_to_multiplicity.insert(value, new_mul);
2222 expected.len += new_mul.get();
2223 assert_eq!(inserted, expected);
2224
2225 let mut replaced = initial.clone();
2226 assert_eq!(replaced.replace_all(value, new_mul), None);
2227 assert_eq!(replaced, expected);
2228 }
2229
2230 // ...but retain doesn't care much
2231 {
2232 let f = |v, m: &mut NonZeroUsize| {
2233 if v <= value && *m <= new_mul {
2234 *m = m.checked_add(42).unwrap();
2235 true
2236 } else {
2237 false
2238 }
2239 };
2240 let mut retained = initial.clone();
2241 retained.retain(f);
2242 let mut expected = initial.clone();
2243 expected.value_to_multiplicity.retain(|&v, m| f(v, m));
2244 expected.reset_len();
2245 assert_eq!(retained, expected);
2246 }
2247 }
2248 }
2249
2250 /// Build a multiset and pick a range of values that have a high chance of
2251 /// being from the multiset if it is not empty, and of being in sorted order
2252 fn mset_and_value_range() -> impl Strategy<Value = (NumericalMultiset<i32>, Range<i32>)> {
2253 let pair_to_range = |values: [i32; 2]| values[0]..values[1];
2254 mset().prop_flat_map(move |mset| {
2255 if mset.is_empty() {
2256 (Just(mset), any::<[i32; 2]>().prop_map(pair_to_range)).boxed()
2257 } else {
2258 let inner_value = || prop::sample::select(mset.values().collect::<Vec<_>>());
2259 let value = || prop_oneof![3 => inner_value(), 2 => any::<i32>()];
2260 let range = [value(), value()].prop_map(pair_to_range);
2261 (Just(mset), range).boxed()
2262 }
2263 })
2264 }
2265
2266 proptest! {
2267 #[test]
2268 fn range((mset, range) in mset_and_value_range()) {
2269 match std::panic::catch_unwind(|| {
2270 mset.range(range.clone()).collect::<Vec<_>>()
2271 }) {
2272 Ok(output) => check_equal_iterable(output, mset.value_to_multiplicity.range(range).map(|(&v, &m)| (v, m))),
2273 Err(_panicked) => assert!(range.start > range.end),
2274 }
2275 }
2276 }
2277
2278 /// Build a pair of multisets that have reasonable odds of having some
2279 /// simple set relationship with each other.
2280 fn mset_pair() -> impl Strategy<Value = (NumericalMultiset<i32>, NumericalMultiset<i32>)> {
2281 mset().prop_flat_map(|mset1| {
2282 if mset1.is_empty() {
2283 (Just(mset1), mset()).boxed()
2284 } else {
2285 // For related sets, we first extract a subsequence of the
2286 // (value, multiplicity) pairs contained inside mset1...
2287 let related = prop::sample::subsequence(
2288 mset1.iter().collect::<Vec<_>>(),
2289 0..mset1.num_values(),
2290 )
2291 .prop_flat_map(move |subseq| {
2292 // ...then, for each retained (value, multiplicity) pairs...
2293 subseq
2294 .into_iter()
2295 .map(|(v, m)| {
2296 let m = m.get();
2297 // ...we pick a multiplicity that has equal chance of being...
2298 // - 1: Common gotcha in tests
2299 // - 2..M: Less than in mset1
2300 // - M: As many as in mset1
2301 // - (M+1)..: More than in mset1
2302 let multiplicity = match m {
2303 1 => prop_oneof![Just(1), 2..max_multiplicity()].boxed(),
2304 2 => prop_oneof![Just(1), Just(2), 3..max_multiplicity()].boxed(),
2305 _ if m + 1 < max_multiplicity() => {
2306 prop_oneof![Just(1), 2..m, Just(m), (m + 1)..max_multiplicity()]
2307 .boxed()
2308 }
2309 _ => prop_oneof![Just(1), 2..max_multiplicity()].boxed(),
2310 }
2311 .prop_map(|m| NonZeroUsize::new(m).unwrap());
2312 (Just(v), multiplicity)
2313 })
2314 .collect::<Vec<_>>()
2315 })
2316 .prop_map(|elems| elems.into_iter().collect());
2317
2318 // As a result, mset2 convers less values than mset1, so their
2319 // roles are asymmetrical. To ensure this bias isn't exposed to
2320 // tests, we should randomly flip them.
2321 let related_pair = (Just(mset1.clone()), related, any::<bool>()).prop_map(
2322 |(mset1, mset2, flip)| {
2323 if flip { (mset2, mset1) } else { (mset1, mset2) }
2324 },
2325 );
2326
2327 // Finally, we can and should also sometimes pick unrelated sets
2328 // like we do when mset1 is empty
2329 prop_oneof![
2330 1 => (Just(mset1), mset()),
2331 4 => related_pair,
2332 ]
2333 .boxed()
2334 }
2335 })
2336 }
2337
2338 proptest! {
2339 /// Check properties of arbitrary pairs of multisets
2340 #[test]
2341 fn pair((mset1, mset2) in mset_pair()) {
2342 check_any_mset_pair(&mset1, &mset2);
2343 }
2344 }
2345}