range_set_blaze/
dyn_sorted_disjoint.rs

1use core::ops::RangeInclusive;
2
3use crate::{Integer, SortedDisjoint, SortedStarts};
4use alloc::boxed::Box;
5
6#[must_use = "iterators are lazy and do nothing unless consumed"]
7/// Gives [`SortedDisjoint`] iterators a uniform type. Used by the [`union_dyn`] and [`intersection_dyn`] macros to give all
8/// their input iterators the same type.
9///
10/// [`union_dyn`]: crate::union_dyn
11/// [`intersection_dyn`]: crate::intersection_dyn
12///
13/// # Example
14/// ```
15/// use range_set_blaze::prelude::*;
16///
17/// let a = RangeSetBlaze::from_iter([1u8..=6, 8..=9, 11..=15]);
18/// let b = RangeSetBlaze::from_iter([5..=13, 18..=29]);
19/// let c = RangeSetBlaze::from_iter([38..=42]);
20/// let union = [
21///     DynSortedDisjoint::new(a.ranges()),
22///     DynSortedDisjoint::new(!b.ranges()),
23///     DynSortedDisjoint::new(c.ranges()),
24/// ]
25/// .union();
26/// assert_eq!(union.to_string(), "0..=6, 8..=9, 11..=17, 30..=255");
27/// ```
28
29pub struct DynSortedDisjoint<'a, T: Integer> {
30    iter: Box<dyn SortedDisjoint<T> + 'a>,
31}
32
33impl<'a, T: Integer> DynSortedDisjoint<'a, T> {
34    /// Create a [`DynSortedDisjoint`] from any [`SortedDisjoint`] iterator. See [`DynSortedDisjoint`] for an example.
35    pub fn new<I>(iter: I) -> Self
36    where
37        I: SortedDisjoint<T> + 'a,
38    {
39        Self {
40            iter: Box::new(iter),
41        }
42    }
43}
44
45// All DynSortedDisjoint's are SortedDisjoint's
46impl<'a, T: Integer> SortedStarts<T> for DynSortedDisjoint<'a, T> {}
47impl<'a, T: Integer> SortedDisjoint<T> for DynSortedDisjoint<'a, T> {}
48
49impl<'a, T: Integer> Iterator for DynSortedDisjoint<'a, T> {
50    type Item = RangeInclusive<T>;
51
52    fn next(&mut self) -> Option<Self::Item> {
53        self.iter.next()
54    }
55
56    fn size_hint(&self) -> (usize, Option<usize>) {
57        self.iter.size_hint()
58    }
59}
60
61/// Intersects one or more [`SortedDisjoint`] iterators, creating a new [`SortedDisjoint`] iterator.
62/// The input iterators need not to be of the same type.
63///
64/// For input iterators of the same type, [`intersection`] may be slightly faster.
65///
66/// # Performance
67///   All work is done on demand, in one pass through the input iterators. Minimal memory is used.
68///
69/// # Example: 3-Input Parity
70///
71/// Find the integers that appear an odd number of times in the [`SortedDisjoint`] iterators.
72///
73/// [`intersection`]: crate::MultiwaySortedDisjoint::intersection
74/// ```
75/// use range_set_blaze::prelude::*;
76///
77/// let a = RangeSetBlaze::from_iter([1..=6, 8..=9, 11..=15]);
78/// let b = RangeSetBlaze::from_iter([5..=13, 18..=29]);
79/// let c = RangeSetBlaze::from_iter([38..=42]);
80///
81/// let parity = union_dyn!(
82///     intersection_dyn!(a.ranges(), !b.ranges(), !c.ranges()),
83///     intersection_dyn!(!a.ranges(), b.ranges(), !c.ranges()),
84///     intersection_dyn!(!a.ranges(), !b.ranges(), c.ranges()),
85///     intersection_dyn!(a.ranges(), b.ranges(), c.ranges())
86/// );
87/// assert_eq!(
88///     parity.to_string(),
89///     "1..=4, 7..=7, 10..=10, 14..=15, 18..=29, 38..=42"
90/// );
91/// ```
92#[macro_export]
93macro_rules! intersection_dyn {
94    ($($val:expr),*) => {$crate::MultiwaySortedDisjoint::intersection([$($crate::DynSortedDisjoint::new($val)),*])}
95}
96
97/// Unions one or more [`SortedDisjoint`] iterators, creating a new [`SortedDisjoint`] iterator.
98/// The input iterators need not to be of the same type.
99///
100/// For input iterators of the same type, [`union`] may be slightly faster.
101///
102/// # Performance
103///   All work is done on demand, in one pass through the input iterators. Minimal memory is used.
104///
105/// # Example: 3-Input Parity
106///
107/// Find the integers that appear an odd number of times in the [`SortedDisjoint`] iterators.
108///
109/// [`union`]: crate::MultiwaySortedDisjoint::union
110/// ```
111/// use range_set_blaze::prelude::*;
112///
113/// let a = RangeSetBlaze::from_iter([1..=6, 8..=9, 11..=15]);
114/// let b = RangeSetBlaze::from_iter([5..=13, 18..=29]);
115/// let c = RangeSetBlaze::from_iter([38..=42]);
116///
117/// let parity = union_dyn!(
118///     intersection_dyn!(a.ranges(), !b.ranges(), !c.ranges()),
119///     intersection_dyn!(!a.ranges(), b.ranges(), !c.ranges()),
120///     intersection_dyn!(!a.ranges(), !b.ranges(), c.ranges()),
121///     intersection_dyn!(a.ranges(), b.ranges(), c.ranges())
122/// );
123/// assert_eq!(
124///     parity.to_string(),
125///     "1..=4, 7..=7, 10..=10, 14..=15, 18..=29, 38..=42"
126/// );
127/// ```
128#[macro_export]
129macro_rules! union_dyn {
130    ($($val:expr),*) => {
131                        $crate::MultiwaySortedDisjoint::union([$($crate::DynSortedDisjoint::new($val)),*])
132                        }
133}