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 fn bitand(self, rhs: &NumericalMultiset<T>) -> Self::Output {
1382 self.intersection(rhs).collect()
1383 }
1384}
1385
1386impl<T: Copy + Ord> BitOr<&NumericalMultiset<T>> for &NumericalMultiset<T> {
1387 type Output = NumericalMultiset<T>;
1388
1389 /// Returns the union of `self` and `rhs` as a new `NumericalMultiset<T>`.
1390 ///
1391 /// # Examples
1392 ///
1393 /// ```
1394 /// use numerical_multiset::NumericalMultiset;
1395 ///
1396 /// let a = NumericalMultiset::from_iter([1, 1, 2, 2, 3]);
1397 /// let b = NumericalMultiset::from_iter([2, 3, 4]);
1398 /// assert_eq!(
1399 /// &a | &b,
1400 /// NumericalMultiset::from_iter([1, 1, 2, 2, 3, 4])
1401 /// );
1402 /// ```
1403 fn bitor(self, rhs: &NumericalMultiset<T>) -> Self::Output {
1404 self.union(rhs).collect()
1405 }
1406}
1407
1408impl<T: Copy + Ord> BitXor<&NumericalMultiset<T>> for &NumericalMultiset<T> {
1409 type Output = NumericalMultiset<T>;
1410
1411 /// Returns the symmetric difference of `self` and `rhs` as a new `NumericalMultiset<T>`.
1412 ///
1413 /// # Examples
1414 ///
1415 /// ```
1416 /// use numerical_multiset::NumericalMultiset;
1417 ///
1418 /// let a = NumericalMultiset::from_iter([1, 1, 2, 2, 3]);
1419 /// let b = NumericalMultiset::from_iter([2, 3, 4]);
1420 /// assert_eq!(
1421 /// &a ^ &b,
1422 /// NumericalMultiset::from_iter([1, 1, 2, 4])
1423 /// );
1424 /// ```
1425 fn bitxor(self, rhs: &NumericalMultiset<T>) -> Self::Output {
1426 self.symmetric_difference(rhs).collect()
1427 }
1428}
1429
1430impl<T: Ord> Extend<T> for NumericalMultiset<T> {
1431 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1432 for element in iter {
1433 self.insert(element);
1434 }
1435 }
1436}
1437
1438impl<T: Ord> Extend<(T, NonZeroUsize)> for NumericalMultiset<T> {
1439 /// More efficient alternative to [`Extend<T>`] for cases where you know in
1440 /// advance that you are going to insert several copies of a value
1441 ///
1442 /// # Examples
1443 ///
1444 /// ```
1445 /// use numerical_multiset::NumericalMultiset;
1446 /// use std::num::NonZeroUsize;
1447 ///
1448 /// let mut mset = NumericalMultiset::from_iter([1, 2, 3]);
1449 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
1450 /// mset.extend([(3, nonzero(3)), (4, nonzero(2))]);
1451 /// assert_eq!(mset, NumericalMultiset::from_iter([1, 2, 3, 3, 3, 3, 4, 4]));
1452 /// ```
1453 fn extend<I: IntoIterator<Item = (T, NonZeroUsize)>>(&mut self, iter: I) {
1454 for (value, count) in iter {
1455 self.insert_multiple(value, count);
1456 }
1457 }
1458}
1459
1460impl<T: Ord> FromIterator<T> for NumericalMultiset<T> {
1461 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1462 let mut result = Self::new();
1463 result.extend(iter);
1464 result
1465 }
1466}
1467
1468impl<T: Ord> FromIterator<(T, NonZeroUsize)> for NumericalMultiset<T> {
1469 /// More efficient alternative to [`FromIterator<T>`] for cases where you
1470 /// know in advance that you are going to insert several copies of a value
1471 ///
1472 /// # Examples
1473 ///
1474 /// ```
1475 /// use numerical_multiset::NumericalMultiset;
1476 /// use std::num::NonZeroUsize;
1477 ///
1478 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
1479 /// assert_eq!(
1480 /// NumericalMultiset::from_iter([1, 2, 2, 2, 3, 3]),
1481 /// NumericalMultiset::from_iter([
1482 /// (1, nonzero(1)),
1483 /// (2, nonzero(3)),
1484 /// (3, nonzero(2)),
1485 /// ])
1486 /// );
1487 /// ```
1488 fn from_iter<I: IntoIterator<Item = (T, NonZeroUsize)>>(iter: I) -> Self {
1489 let mut result = Self::new();
1490 result.extend(iter);
1491 result
1492 }
1493}
1494
1495impl<T: Hash> Hash for NumericalMultiset<T> {
1496 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1497 self.value_to_multiplicity.hash(state)
1498 }
1499}
1500
1501impl<'a, T: Copy> IntoIterator for &'a NumericalMultiset<T> {
1502 type Item = (T, NonZeroUsize);
1503 type IntoIter = Iter<'a, T>;
1504
1505 fn into_iter(self) -> Self::IntoIter {
1506 Iter(self.value_to_multiplicity.iter())
1507 }
1508}
1509//
1510/// An iterator over the contents of an [`NumericalMultiset`], sorted by value.
1511///
1512/// This `struct` is created by the [`iter()`](NumericalMultiset::iter) method on
1513/// [`NumericalMultiset`]. See its documentation for more.
1514#[derive(Clone, Debug, Default)]
1515pub struct Iter<'a, T: Copy>(btree_map::Iter<'a, T, NonZeroUsize>);
1516//
1517impl<T: Copy> DoubleEndedIterator for Iter<'_, T> {
1518 #[inline]
1519 fn next_back(&mut self) -> Option<Self::Item> {
1520 self.0.next_back().map(|(&k, &v)| (k, v))
1521 }
1522
1523 #[inline]
1524 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1525 self.0.nth_back(n).map(|(&k, &v)| (k, v))
1526 }
1527}
1528//
1529impl<T: Copy> ExactSizeIterator for Iter<'_, T> {
1530 fn len(&self) -> usize {
1531 self.0.len()
1532 }
1533}
1534//
1535impl<T: Copy> FusedIterator for Iter<'_, T> {}
1536//
1537impl<T: Copy> Iterator for Iter<'_, T> {
1538 type Item = (T, NonZeroUsize);
1539
1540 #[inline]
1541 fn next(&mut self) -> Option<Self::Item> {
1542 self.0.next().map(|(&k, &v)| (k, v))
1543 }
1544
1545 fn size_hint(&self) -> (usize, Option<usize>) {
1546 self.0.size_hint()
1547 }
1548
1549 fn count(self) -> usize
1550 where
1551 Self: Sized,
1552 {
1553 self.0.count()
1554 }
1555
1556 fn last(mut self) -> Option<Self::Item>
1557 where
1558 Self: Sized,
1559 {
1560 self.0.next_back().map(|(&k, &v)| (k, v))
1561 }
1562
1563 #[inline]
1564 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1565 self.0.nth(n).map(|(&k, &v)| (k, v))
1566 }
1567
1568 fn is_sorted(self) -> bool
1569 where
1570 Self: Sized,
1571 Self::Item: PartialOrd,
1572 {
1573 true
1574 }
1575}
1576
1577impl<T> IntoIterator for NumericalMultiset<T> {
1578 type Item = (T, NonZeroUsize);
1579 type IntoIter = IntoIter<T>;
1580
1581 /// Gets an iterator for moving out the `NumericalMultiset`’s contents.
1582 ///
1583 /// Items are grouped by value and emitted in `(value, multiplicity)`
1584 /// format, in ascending value order.
1585 ///
1586 /// # Examples
1587 ///
1588 /// ```
1589 /// use numerical_multiset::NumericalMultiset;
1590 /// use std::num::NonZeroUsize;
1591 ///
1592 /// let mset = NumericalMultiset::from_iter([3, 1, 2, 2]);
1593 /// let nonzero = |x| NonZeroUsize::new(x).unwrap();
1594 /// assert!(mset.into_iter().eq([
1595 /// (1, nonzero(1)),
1596 /// (2, nonzero(2)),
1597 /// (3, nonzero(1))
1598 /// ]));
1599 /// ```
1600 fn into_iter(self) -> Self::IntoIter {
1601 IntoIter(self.value_to_multiplicity.into_iter())
1602 }
1603}
1604//
1605/// An owning iterator over the contents of an [`NumericalMultiset`], sorted by
1606/// value.
1607///
1608/// This struct is created by the `into_iter()` method on [`NumericalMultiset`]
1609/// (provided by the [`IntoIterator`] trait). See its documentation for more.
1610#[derive(Debug, Default)]
1611pub struct IntoIter<T>(btree_map::IntoIter<T, NonZeroUsize>);
1612//
1613impl<T> DoubleEndedIterator for IntoIter<T> {
1614 #[inline]
1615 fn next_back(&mut self) -> Option<Self::Item> {
1616 self.0.next_back()
1617 }
1618
1619 #[inline]
1620 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1621 self.0.nth_back(n)
1622 }
1623}
1624//
1625impl<T> ExactSizeIterator for IntoIter<T> {
1626 fn len(&self) -> usize {
1627 self.0.len()
1628 }
1629}
1630//
1631impl<T> FusedIterator for IntoIter<T> {}
1632//
1633impl<T> Iterator for IntoIter<T> {
1634 type Item = (T, NonZeroUsize);
1635
1636 #[inline]
1637 fn next(&mut self) -> Option<Self::Item> {
1638 self.0.next()
1639 }
1640
1641 fn size_hint(&self) -> (usize, Option<usize>) {
1642 self.0.size_hint()
1643 }
1644
1645 fn count(self) -> usize
1646 where
1647 Self: Sized,
1648 {
1649 self.0.count()
1650 }
1651
1652 fn last(mut self) -> Option<Self::Item>
1653 where
1654 Self: Sized,
1655 {
1656 self.0.next_back()
1657 }
1658
1659 #[inline]
1660 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1661 self.0.nth(n)
1662 }
1663
1664 fn is_sorted(self) -> bool
1665 where
1666 Self: Sized,
1667 Self::Item: PartialOrd,
1668 {
1669 true
1670 }
1671}
1672
1673impl<T: Ord> Ord for NumericalMultiset<T> {
1674 fn cmp(&self, other: &Self) -> Ordering {
1675 self.value_to_multiplicity.cmp(&other.value_to_multiplicity)
1676 }
1677}
1678
1679impl<T: PartialEq> PartialEq for NumericalMultiset<T> {
1680 fn eq(&self, other: &Self) -> bool {
1681 self.len == other.len && self.value_to_multiplicity == other.value_to_multiplicity
1682 }
1683}
1684
1685impl<T: PartialOrd> PartialOrd for NumericalMultiset<T> {
1686 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1687 self.value_to_multiplicity
1688 .partial_cmp(&other.value_to_multiplicity)
1689 }
1690}
1691
1692impl<T: Copy + Ord> Sub<&NumericalMultiset<T>> for &NumericalMultiset<T> {
1693 type Output = NumericalMultiset<T>;
1694
1695 /// Returns the difference of `self` and `rhs` as a new `NumericalMultiset<T>`.
1696 ///
1697 /// # Examples
1698 ///
1699 /// ```
1700 /// use numerical_multiset::NumericalMultiset;
1701 ///
1702 /// let a = NumericalMultiset::from_iter([1, 1, 2, 2, 3]);
1703 /// let b = NumericalMultiset::from_iter([2, 3, 4]);
1704 /// assert_eq!(
1705 /// &a - &b,
1706 /// NumericalMultiset::from_iter([1, 1, 2])
1707 /// );
1708 /// ```
1709 fn sub(self, rhs: &NumericalMultiset<T>) -> Self::Output {
1710 self.difference(rhs).collect()
1711 }
1712}
1713
1714#[cfg(test)]
1715mod test {
1716 use super::*;
1717 use proptest::{prelude::*, sample::SizeRange};
1718 use std::{
1719 cmp::Ordering,
1720 collections::HashSet,
1721 fmt::Debug,
1722 hash::{BuildHasher, RandomState},
1723 ops::Range,
1724 };
1725
1726 /// Clearer name for the constant 1 in NonZeroUsize format
1727 const ONE: NonZeroUsize = NonZeroUsize::MIN;
1728
1729 /// Alternative to Iterator::eq that prints a clearer message on failure
1730 fn check_equal_iterable<V, It1, It2>(it1: It1, it2: It2)
1731 where
1732 It1: IntoIterator<Item = V>,
1733 It2: IntoIterator<Item = V>,
1734 V: Debug + PartialEq,
1735 {
1736 assert_eq!(
1737 it1.into_iter().collect::<Vec<_>>(),
1738 it2.into_iter().collect::<Vec<_>>(),
1739 );
1740 }
1741
1742 /// Alternative to it.count() == 0 that prints a clearer message on failure
1743 fn check_empty_iterable<It>(it: It)
1744 where
1745 It: IntoIterator,
1746 It::Item: Debug + PartialEq,
1747 {
1748 check_equal_iterable(it, std::iter::empty());
1749 }
1750
1751 /// Check properties that should be true of any pair of multisets
1752 fn check_any_mset_pair(mset1: &NumericalMultiset<i32>, mset2: &NumericalMultiset<i32>) {
1753 let intersection = mset1 & mset2;
1754 for (val, mul) in &intersection {
1755 assert_eq!(
1756 mul,
1757 mset1
1758 .multiplicity(val)
1759 .unwrap()
1760 .min(mset2.multiplicity(val).unwrap()),
1761 );
1762 }
1763 for val1 in mset1.values() {
1764 assert!(intersection.contains(val1) || !mset2.contains(val1));
1765 }
1766 for val2 in mset2.values() {
1767 assert!(intersection.contains(val2) || !mset1.contains(val2));
1768 }
1769 check_equal_iterable(mset1.intersection(mset2), &intersection);
1770
1771 let union = mset1 | mset2;
1772 for (val, mul) in &union {
1773 assert_eq!(
1774 mul.get(),
1775 mset1
1776 .multiplicity(val)
1777 .map_or(0, |nz| nz.get())
1778 .max(mset2.multiplicity(val).map_or(0, |nz| nz.get()))
1779 );
1780 }
1781 for val in mset1.values().chain(mset2.values()) {
1782 assert!(union.contains(val));
1783 }
1784 check_equal_iterable(mset1.union(mset2), &union);
1785
1786 let difference = mset1 - mset2;
1787 for (val, mul) in &difference {
1788 assert_eq!(
1789 mul.get(),
1790 mset1
1791 .multiplicity(val)
1792 .unwrap()
1793 .get()
1794 .checked_sub(mset2.multiplicity(val).map_or(0, |nz| nz.get()))
1795 .unwrap()
1796 );
1797 }
1798 for (val, mul1) in mset1 {
1799 assert!(difference.contains(val) || mset2.multiplicity(val).unwrap() >= mul1);
1800 }
1801 check_equal_iterable(mset1.difference(mset2), difference);
1802
1803 let symmetric_difference = mset1 ^ mset2;
1804 for (val, mul) in &symmetric_difference {
1805 assert_eq!(
1806 mul.get(),
1807 mset1
1808 .multiplicity(val)
1809 .map_or(0, |nz| nz.get())
1810 .abs_diff(mset2.multiplicity(val).map_or(0, |nz| nz.get()))
1811 );
1812 }
1813 for (val1, mul1) in mset1 {
1814 assert!(
1815 symmetric_difference.contains(val1) || mset2.multiplicity(val1).unwrap() >= mul1
1816 );
1817 }
1818 for (val2, mul2) in mset2 {
1819 assert!(
1820 symmetric_difference.contains(val2) || mset1.multiplicity(val2).unwrap() >= mul2
1821 );
1822 }
1823 check_equal_iterable(mset1.symmetric_difference(mset2), symmetric_difference);
1824
1825 assert_eq!(mset1.is_disjoint(mset2), intersection.is_empty(),);
1826
1827 if mset1.is_subset(mset2) {
1828 for (val, mul1) in mset1 {
1829 assert!(mset2.multiplicity(val).unwrap() >= mul1);
1830 }
1831 } else {
1832 assert!(mset1
1833 .iter()
1834 .any(|(val1, mul1)| { mset2.multiplicity(val1).is_none_or(|mul2| mul2 < mul1) }))
1835 }
1836 assert_eq!(mset2.is_superset(mset1), mset1.is_subset(mset2));
1837
1838 let mut combined = mset1.clone();
1839 let mut appended = mset2.clone();
1840 combined.append(&mut appended);
1841 assert_eq!(
1842 combined,
1843 mset1
1844 .iter()
1845 .chain(mset2.iter())
1846 .collect::<NumericalMultiset<_>>()
1847 );
1848 assert!(appended.is_empty());
1849
1850 let mut extended_by_tuples = mset1.clone();
1851 extended_by_tuples.extend(mset2.iter());
1852 assert_eq!(extended_by_tuples, combined);
1853
1854 let mut extended_by_values = mset1.clone();
1855 extended_by_values.extend(
1856 mset2
1857 .iter()
1858 .flat_map(|(val, mul)| std::iter::repeat_n(val, mul.get())),
1859 );
1860 assert_eq!(
1861 extended_by_values, combined,
1862 "{mset1:?} + {mset2:?} != {extended_by_values:?}"
1863 );
1864
1865 assert_eq!(
1866 mset1.cmp(mset2),
1867 mset1
1868 .value_to_multiplicity
1869 .cmp(&mset2.value_to_multiplicity)
1870 );
1871 assert_eq!(mset1.partial_cmp(mset2), Some(mset1.cmp(mset2)));
1872 }
1873
1874 /// Check properties that should be true of any multiset, knowing its contents
1875 fn check_any_mset(mset: &NumericalMultiset<i32>, contents: &[(i32, NonZeroUsize)]) {
1876 let sorted_contents = contents
1877 .iter()
1878 .map(|(v, m)| (*v, m.get()))
1879 .collect::<BTreeMap<i32, usize>>();
1880
1881 check_equal_iterable(
1882 mset.iter().map(|(val, mul)| (val, mul.get())),
1883 sorted_contents.iter().map(|(&k, &v)| (k, v)),
1884 );
1885 check_equal_iterable(mset, mset.iter());
1886 check_equal_iterable(mset.clone(), mset.iter());
1887 check_equal_iterable(mset.range(..), mset.iter());
1888 check_equal_iterable(mset.values(), sorted_contents.keys().copied());
1889 check_equal_iterable(mset.clone().into_values(), mset.values());
1890
1891 assert_eq!(mset.len(), sorted_contents.values().sum());
1892 assert_eq!(mset.num_values(), contents.len());
1893 assert_eq!(mset.is_empty(), contents.is_empty());
1894
1895 for (&val, &mul) in &sorted_contents {
1896 assert!(mset.contains(val));
1897 assert_eq!(mset.multiplicity(val).unwrap().get(), mul);
1898 }
1899
1900 assert_eq!(
1901 mset.first().map(|(val, mul)| (val, mul.get())),
1902 sorted_contents.first_key_value().map(|(&k, &v)| (k, v)),
1903 );
1904 assert_eq!(
1905 mset.last().map(|(val, mul)| (val, mul.get())),
1906 sorted_contents.last_key_value().map(|(&k, &v)| (k, v)),
1907 );
1908
1909 #[allow(clippy::eq_op)]
1910 {
1911 assert_eq!(mset, mset);
1912 }
1913 assert_eq!(*mset, mset.clone());
1914 assert_eq!(mset.cmp(mset), Ordering::Equal);
1915 assert_eq!(mset.partial_cmp(mset), Some(mset.cmp(mset)));
1916
1917 let state = RandomState::new();
1918 assert_eq!(
1919 state.hash_one(mset),
1920 state.hash_one(&mset.value_to_multiplicity),
1921 );
1922
1923 let mut mutable = mset.clone();
1924 if let Some((first, first_mul)) = mset.first() {
1925 // Pop the smallest items...
1926 assert_eq!(mutable.pop_all_first(), Some((first, first_mul)));
1927 assert_eq!(mutable.len(), mset.len() - first_mul.get());
1928 assert_eq!(mutable.num_values(), mset.num_values() - 1);
1929 assert!(!mutable.contains(first));
1930 assert_eq!(mutable.multiplicity(first), None);
1931 assert_ne!(mutable, *mset);
1932
1933 // ...then insert them back
1934 assert_eq!(mutable.insert_multiple(first, first_mul), None);
1935 assert_eq!(mutable, *mset);
1936
1937 // Same with a single item
1938 assert_eq!(mutable.pop_first(), Some(first));
1939 assert_eq!(mutable.len(), mset.len() - 1);
1940 let new_first_mul = NonZeroUsize::new(first_mul.get() - 1);
1941 let first_is_single = new_first_mul.is_none();
1942 assert_eq!(
1943 mutable.num_values(),
1944 mset.num_values() - first_is_single as usize
1945 );
1946 assert_eq!(mutable.contains(first), !first_is_single);
1947 assert_eq!(mutable.multiplicity(first), new_first_mul);
1948 assert_ne!(mutable, *mset);
1949 assert_eq!(mutable.insert(first), new_first_mul);
1950 assert_eq!(mutable, *mset);
1951
1952 // If there is a first item, there is a last item
1953 let (last, last_mul) = mset.last().unwrap();
1954
1955 // And everything we checked for the smallest items should also
1956 // applies to the largest ones
1957 assert_eq!(mutable.pop_all_last(), Some((last, last_mul)));
1958 assert_eq!(mutable.len(), mset.len() - last_mul.get());
1959 assert_eq!(mutable.num_values(), mset.num_values() - 1);
1960 assert!(!mutable.contains(last));
1961 assert_eq!(mutable.multiplicity(last), None);
1962 assert_ne!(mutable, *mset);
1963 //
1964 assert_eq!(mutable.insert_multiple(last, last_mul), None);
1965 assert_eq!(mutable, *mset);
1966 //
1967 assert_eq!(mutable.pop_last(), Some(last));
1968 assert_eq!(mutable.len(), mset.len() - 1);
1969 let new_last_mul = NonZeroUsize::new(last_mul.get() - 1);
1970 let last_is_single = new_last_mul.is_none();
1971 assert_eq!(
1972 mutable.num_values(),
1973 mset.num_values() - last_is_single as usize
1974 );
1975 assert_eq!(mutable.contains(last), !last_is_single);
1976 assert_eq!(mutable.multiplicity(last), new_last_mul);
1977 assert_ne!(mutable, *mset);
1978 assert_eq!(mutable.insert(last), new_last_mul);
1979 assert_eq!(mutable, *mset);
1980 } else {
1981 assert!(mset.is_empty());
1982 assert_eq!(mutable.pop_first(), None);
1983 assert!(mutable.is_empty());
1984 assert_eq!(mutable.pop_all_first(), None);
1985 assert!(mutable.is_empty());
1986 assert_eq!(mutable.pop_last(), None);
1987 assert!(mutable.is_empty());
1988 assert_eq!(mutable.pop_all_last(), None);
1989 assert!(mutable.is_empty());
1990 }
1991
1992 let mut retain_all = mset.clone();
1993 retain_all.retain(|_, _| true);
1994 assert_eq!(retain_all, *mset);
1995
1996 let mut retain_nothing = mset.clone();
1997 retain_nothing.retain(|_, _| false);
1998 assert!(retain_nothing.is_empty());
1999 }
2000
2001 /// Check properties that should be true of an empty multiset
2002 fn check_empty_mset(empty: &NumericalMultiset<i32>) {
2003 check_any_mset(empty, &[]);
2004
2005 assert_eq!(empty.len(), 0);
2006 assert_eq!(empty.num_values(), 0);
2007 assert!(empty.is_empty());
2008 assert_eq!(empty.first(), None);
2009 assert_eq!(empty.last(), None);
2010
2011 check_empty_iterable(empty.iter());
2012 check_empty_iterable(empty.values());
2013 check_empty_iterable(empty.clone());
2014 check_empty_iterable(empty.clone().into_values());
2015
2016 let mut mutable = empty.clone();
2017 assert_eq!(mutable.pop_first(), None);
2018 assert_eq!(mutable.pop_last(), None);
2019 assert_eq!(mutable.pop_all_first(), None);
2020 assert_eq!(mutable.pop_all_last(), None);
2021 }
2022
2023 /// Check that clear() makes a multiset empty
2024 fn check_clear_outcome(mut mset: NumericalMultiset<i32>) {
2025 mset.clear();
2026 check_empty_mset(&mset);
2027 }
2028
2029 /// Check the various ways to build an empty multiset
2030 #[test]
2031 fn empty() {
2032 check_empty_mset(&NumericalMultiset::default());
2033 let mset = NumericalMultiset::<i32>::new();
2034 check_empty_mset(&mset);
2035 check_clear_outcome(mset);
2036 }
2037
2038 /// Maximal acceptable multiplicity value
2039 fn max_multiplicity() -> usize {
2040 SizeRange::default().end_excl()
2041 }
2042
2043 /// Generate a reasonably low multiplicity value
2044 fn multiplicity() -> impl Strategy<Value = NonZeroUsize> {
2045 prop_oneof![Just(1), Just(2), 3..max_multiplicity()]
2046 .prop_map(|m| NonZeroUsize::new(m).unwrap())
2047 }
2048
2049 /// Build an arbitrary multiset
2050 fn mset_contents() -> impl Strategy<Value = Vec<(i32, NonZeroUsize)>> {
2051 any::<HashSet<i32>>().prop_flat_map(|values| {
2052 prop::collection::vec(multiplicity(), values.len()).prop_map(move |multiplicities| {
2053 values.iter().copied().zip(multiplicities).collect()
2054 })
2055 })
2056 }
2057
2058 proptest! {
2059 /// Check properties of arbitrary multisets
2060 #[test]
2061 fn single(contents in mset_contents()) {
2062 for mset in [
2063 contents.iter().copied().collect(),
2064 contents.iter().flat_map(|(v, m)| {
2065 std::iter::repeat_n(*v, m.get())
2066 }).collect(),
2067 ] {
2068 check_any_mset(&mset, &contents);
2069 check_any_mset_pair(&mset, &mset);
2070 let empty = NumericalMultiset::default();
2071 check_any_mset_pair(&mset, &empty);
2072 check_any_mset_pair(&empty, &mset);
2073 check_clear_outcome(mset);
2074 }
2075 }
2076 }
2077
2078 /// Build an arbitrary multiset
2079 fn mset() -> impl Strategy<Value = NumericalMultiset<i32>> {
2080 mset_contents().prop_map(NumericalMultiset::from_iter)
2081 }
2082
2083 /// Build a multiset and pick a value that has a high chance of being from
2084 /// the multiset if it is not empty.
2085 fn mset_and_value() -> impl Strategy<Value = (NumericalMultiset<i32>, i32)> {
2086 mset().prop_flat_map(|mset| {
2087 if mset.is_empty() {
2088 (Just(mset), any::<i32>()).boxed()
2089 } else {
2090 let inner_value = prop::sample::select(mset.values().collect::<Vec<_>>());
2091 let value = prop_oneof![inner_value, any::<i32>()];
2092 (Just(mset), value).boxed()
2093 }
2094 })
2095 }
2096
2097 proptest! {
2098 /// Test operations that combine a multiset with a value
2099 #[test]
2100 fn with_value((initial, value) in mset_and_value()) {
2101 // Most operations depend on whether the value was present...
2102 if let Some(&mul) = initial.value_to_multiplicity.get(&value) {
2103 assert!(initial.contains(value));
2104 assert_eq!(initial.multiplicity(value), Some(mul));
2105 {
2106 let mut mset = initial.clone();
2107 assert_eq!(mset.insert(value), Some(mul));
2108 let mut expected = initial.clone();
2109 let Entry::Occupied(mut entry) = expected.value_to_multiplicity.entry(value) else {
2110 unreachable!();
2111 };
2112 *entry.get_mut() = mul.checked_add(1).unwrap();
2113 expected.len += 1;
2114 assert_eq!(mset, expected);
2115 }
2116 {
2117 let mut mset = initial.clone();
2118 assert_eq!(mset.remove(value), Some(mul));
2119 let mut expected = initial.clone();
2120 if mul == ONE {
2121 expected.value_to_multiplicity.remove(&value);
2122 } else {
2123 let Entry::Occupied(mut entry) = expected.value_to_multiplicity.entry(value) else {
2124 unreachable!();
2125 };
2126 *entry.get_mut() = NonZeroUsize::new(mul.get() - 1).unwrap();
2127 }
2128 expected.len -= 1;
2129 assert_eq!(mset, expected);
2130 }
2131 {
2132 let mut mset = initial.clone();
2133 assert_eq!(mset.remove_all(value), Some(mul));
2134 let mut expected = initial.clone();
2135 expected.value_to_multiplicity.remove(&value);
2136 expected.len -= mul.get();
2137 assert_eq!(mset, expected);
2138 }
2139 } else {
2140 assert!(!initial.contains(value));
2141 assert_eq!(initial.multiplicity(value), None);
2142 {
2143 let mut mset = initial.clone();
2144 assert_eq!(mset.insert(value), None);
2145 let mut expected = initial.clone();
2146 expected.value_to_multiplicity.insert(value, ONE);
2147 expected.len += 1;
2148 assert_eq!(mset, expected);
2149 }
2150 {
2151 let mut mset = initial.clone();
2152 assert_eq!(mset.remove(value), None);
2153 assert_eq!(mset, initial);
2154 assert_eq!(mset.remove_all(value), None);
2155 assert_eq!(mset, initial);
2156 }
2157 }
2158
2159 // ...except for split_off, which doesn't really care
2160 {
2161 let mut mset = initial.clone();
2162 let ge = mset.split_off(value);
2163 let lt = mset;
2164 let mut expected_lt = initial.clone();
2165 let ge_value_to_multiplicity = expected_lt.value_to_multiplicity.split_off(&value);
2166 expected_lt.reset_len();
2167 assert_eq!(lt, expected_lt);
2168 let expected_ge = NumericalMultiset::from_iter(ge_value_to_multiplicity);
2169 assert_eq!(ge, expected_ge);
2170 }
2171 }
2172
2173 /// Check operations that require a value and a multiplicity
2174 #[test]
2175 fn with_value_and_multiplicity((initial, value) in mset_and_value(),
2176 new_mul in multiplicity()) {
2177 // Most operations depend on whether the value was present...
2178 if let Some(&initial_mul) = initial.value_to_multiplicity.get(&value) {
2179 {
2180 let mut mset = initial.clone();
2181 assert_eq!(mset.insert_multiple(value, new_mul), Some(initial_mul));
2182 let mut expected = initial.clone();
2183 let Entry::Occupied(mut entry) = expected.value_to_multiplicity.entry(value) else {
2184 unreachable!();
2185 };
2186 *entry.get_mut() = initial_mul.checked_add(new_mul.get()).unwrap();
2187 expected.len += new_mul.get();
2188 assert_eq!(mset, expected);
2189 }
2190 {
2191 let mut mset = initial.clone();
2192 assert_eq!(mset.replace_all(value, new_mul), Some(initial_mul));
2193 let mut expected = initial.clone();
2194 let Entry::Occupied(mut entry) = expected.value_to_multiplicity.entry(value) else {
2195 unreachable!();
2196 };
2197 *entry.get_mut() = new_mul;
2198 expected.len = expected.len - initial_mul.get() + new_mul.get();
2199 assert_eq!(mset, expected);
2200 }
2201 } else {
2202 let mut inserted = initial.clone();
2203 assert_eq!(inserted.insert_multiple(value, new_mul), None);
2204 let mut expected = initial.clone();
2205 expected.value_to_multiplicity.insert(value, new_mul);
2206 expected.len += new_mul.get();
2207 assert_eq!(inserted, expected);
2208
2209 let mut replaced = initial.clone();
2210 assert_eq!(replaced.replace_all(value, new_mul), None);
2211 assert_eq!(replaced, expected);
2212 }
2213
2214 // ...but retain doesn't care much
2215 {
2216 let f = |v, m: &mut NonZeroUsize| {
2217 if v <= value && *m <= new_mul {
2218 *m = m.checked_add(42).unwrap();
2219 true
2220 } else {
2221 false
2222 }
2223 };
2224 let mut retained = initial.clone();
2225 retained.retain(f);
2226 let mut expected = initial.clone();
2227 expected.value_to_multiplicity.retain(|&v, m| f(v, m));
2228 expected.reset_len();
2229 assert_eq!(retained, expected);
2230 }
2231 }
2232 }
2233
2234 /// Build a multiset and pick a range of values that have a high chance of
2235 /// being from the multiset if it is not empty, and of being in sorted order
2236 fn mset_and_value_range() -> impl Strategy<Value = (NumericalMultiset<i32>, Range<i32>)> {
2237 let pair_to_range = |values: [i32; 2]| values[0]..values[1];
2238 mset().prop_flat_map(move |mset| {
2239 if mset.is_empty() {
2240 (Just(mset), any::<[i32; 2]>().prop_map(pair_to_range)).boxed()
2241 } else {
2242 let inner_value = || prop::sample::select(mset.values().collect::<Vec<_>>());
2243 let value = || prop_oneof![3 => inner_value(), 2 => any::<i32>()];
2244 let range = [value(), value()].prop_map(pair_to_range);
2245 (Just(mset), range).boxed()
2246 }
2247 })
2248 }
2249
2250 proptest! {
2251 #[test]
2252 fn range((mset, range) in mset_and_value_range()) {
2253 match std::panic::catch_unwind(|| {
2254 mset.range(range.clone()).collect::<Vec<_>>()
2255 }) {
2256 Ok(output) => check_equal_iterable(output, mset.value_to_multiplicity.range(range).map(|(&v, &m)| (v, m))),
2257 Err(_panicked) => assert!(range.start > range.end),
2258 }
2259 }
2260 }
2261
2262 /// Build a pair of multisets that have reasonable odds of having some
2263 /// simple set relationship with each other.
2264 fn mset_pair() -> impl Strategy<Value = (NumericalMultiset<i32>, NumericalMultiset<i32>)> {
2265 mset().prop_flat_map(|mset1| {
2266 if mset1.is_empty() {
2267 (Just(mset1), mset()).boxed()
2268 } else {
2269 // For related sets, we first extract a subsequence of the
2270 // (value, multiplicity) pairs contained inside mset1...
2271 let related = prop::sample::subsequence(
2272 mset1.iter().collect::<Vec<_>>(),
2273 0..mset1.num_values(),
2274 )
2275 .prop_flat_map(move |subseq| {
2276 // ...then, for each retained (value, multiplicity) pairs...
2277 subseq
2278 .into_iter()
2279 .map(|(v, m)| {
2280 let m = m.get();
2281 // ...we pick a multiplicity that has equal chance of being...
2282 // - 1: Common gotcha in tests
2283 // - 2..M: Less than in mset1
2284 // - M: As many as in mset1
2285 // - (M+1)..: More than in mset1
2286 let multiplicity = match m {
2287 1 => prop_oneof![Just(1), 2..max_multiplicity()].boxed(),
2288 2 => prop_oneof![Just(1), Just(2), 3..max_multiplicity()].boxed(),
2289 _ if m + 1 < max_multiplicity() => {
2290 prop_oneof![Just(1), 2..m, Just(m), (m + 1)..max_multiplicity()]
2291 .boxed()
2292 }
2293 _ => prop_oneof![Just(1), 2..max_multiplicity()].boxed(),
2294 }
2295 .prop_map(|m| NonZeroUsize::new(m).unwrap());
2296 (Just(v), multiplicity)
2297 })
2298 .collect::<Vec<_>>()
2299 })
2300 .prop_map(|elems| elems.into_iter().collect());
2301
2302 // As a result, mset2 convers less values than mset1, so their
2303 // roles are asymmetrical. To ensure this bias isn't exposed to
2304 // tests, we should randomly flip them.
2305 let related_pair = (Just(mset1.clone()), related, any::<bool>()).prop_map(
2306 |(mset1, mset2, flip)| {
2307 if flip {
2308 (mset2, mset1)
2309 } else {
2310 (mset1, mset2)
2311 }
2312 },
2313 );
2314
2315 // Finally, we can and should also sometimes pick unrelated sets
2316 // like we do when mset1 is empty
2317 prop_oneof![
2318 1 => (Just(mset1), mset()),
2319 4 => related_pair,
2320 ]
2321 .boxed()
2322 }
2323 })
2324 }
2325
2326 proptest! {
2327 /// Check properties of arbitrary pairs of multisets
2328 #[test]
2329 fn pair((mset1, mset2) in mset_pair()) {
2330 check_any_mset_pair(&mset1, &mset2);
2331 }
2332 }
2333}