range_set_blaze/
multiway.rs

1impl<T, I> MultiwayRangeSetBlaze<T> for I
2where
3    T: Integer,
4    I: IntoIterator<Item = RangeSetBlaze<T>>,
5{
6}
7
8/// Provides methods on zero or more [`RangeSetBlaze`]'s,
9/// specifically [`union`], [`intersection`] and [`symmetric_difference`].
10///
11/// Also see [`MultiwayRangeSetBlazeRef`].
12///
13/// [`union`]: MultiwayRangeSetBlaze::union
14/// [`intersection`]: MultiwayRangeSetBlaze::intersection
15/// [`symmetric_difference`]: MultiwayRangeSetBlaze::symmetric_difference
16#[allow(clippy::module_name_repetitions)]
17pub trait MultiwayRangeSetBlaze<T: Integer>: IntoIterator<Item = RangeSetBlaze<T>> + Sized {
18    /// Unions the given [`RangeSetBlaze`]'s', creating a new [`RangeSetBlaze`].
19    /// Any number of input can be given.
20    ///
21    /// For exactly two inputs, you can also use the '|' operator.
22    /// Also see [`MultiwayRangeSetBlazeRef::union`].
23    ///
24    /// # Performance
25    ///
26    ///  All work is done on demand, in one pass through the inputs. Minimal memory is used.
27    ///
28    /// # Example
29    ///
30    /// Find the integers that appear in any of the [`RangeSetBlaze`]'s.
31    ///
32    /// ```
33    /// use range_set_blaze::prelude::*;
34    ///
35    /// let a = RangeSetBlaze::from_iter([1..=6, 8..=9, 11..=15]);
36    /// let b = RangeSetBlaze::from_iter([5..=13, 18..=29]);
37    /// let c = RangeSetBlaze::from_iter([25..=100]);
38    ///
39    /// let union = [a, b, c].union();
40    ///
41    /// assert_eq!(union, RangeSetBlaze::from_iter([1..=15, 18..=100]));
42    /// ```
43    fn union(self) -> RangeSetBlaze<T> {
44        self.into_iter()
45            .map(RangeSetBlaze::into_ranges)
46            .union()
47            .into_range_set_blaze()
48    }
49
50    /// Intersects the given [`RangeSetBlaze`] references, creating a new [`RangeSetBlaze`].
51    /// Any number of input can be given.
52    ///
53    /// For exactly two inputs, you can also use the '&' operator.
54    /// Also see [`MultiwayRangeSetBlazeRef::intersection`].
55    ///
56    /// When given zero inputs, it returns the universal set.
57    ///
58    /// # Performance
59    ///
60    ///  All work is done on demand, in one pass through the inputs. Minimal memory is used.
61    ///
62    /// # Example
63    ///
64    /// Find the integers that appear in all the [`RangeSetBlaze`]'s.
65    ///
66    /// ```
67    /// use range_set_blaze::prelude::*;
68    ///
69    /// let a = RangeSetBlaze::from_iter([1..=6, 8..=9, 11..=15]);
70    /// let b = RangeSetBlaze::from_iter([5..=13, 18..=29]);
71    /// let c = RangeSetBlaze::from_iter([-100..=100]);
72    ///
73    /// let intersection = [a, b, c].intersection();
74    ///
75    /// assert_eq!(intersection, RangeSetBlaze::from_iter([5..=6, 8..=9, 11..=13]));
76    /// ```
77    fn intersection(self) -> RangeSetBlaze<T> {
78        self.into_iter()
79            .map(RangeSetBlaze::into_ranges)
80            .intersection()
81            .into_range_set_blaze()
82    }
83
84    /// Computes the symmetric difference of the given [`RangeSetBlaze`] references,
85    /// creating a new [`RangeSetBlaze`].
86    /// The symmetric difference is the set of elements that appear in an odd number
87    /// of the input sets.
88    ///
89    /// Any number of inputs can be given.
90    ///
91    /// For exactly two inputs, you can also use the '^' operator.
92    /// Also see [`MultiwayRangeSetBlazeRef::symmetric_difference`].
93    ///
94    /// # Performance
95    ///
96    /// All work is done on demand, in one pass through the inputs. Minimal memory is used.
97    ///
98    /// # Example
99    ///
100    /// Find the integers that appear in an odd number of the [`RangeSetBlaze`]s.
101    ///
102    /// ```
103    /// use range_set_blaze::prelude::*;
104    ///
105    /// let a = RangeSetBlaze::from_iter([1..=6, 8..=9, 11..=15]);
106    /// let b = RangeSetBlaze::from_iter([5..=13, 18..=29]);
107    /// let c = RangeSetBlaze::from_iter([-100..=100]);
108    ///
109    /// let symmetric_difference = [a, b, c].symmetric_difference();
110    ///
111    /// assert_eq!(
112    ///     symmetric_difference,
113    ///     RangeSetBlaze::from_iter([
114    ///         -100..=0, 5..=6, 8..=9, 11..=13, 16..=17, 30..=100
115    ///     ])
116    /// );
117    /// ```
118    fn symmetric_difference(self) -> RangeSetBlaze<T> {
119        self.into_iter()
120            .map(RangeSetBlaze::into_ranges)
121            .symmetric_difference()
122            .into_range_set_blaze()
123    }
124}
125impl<'a, T, I> MultiwayRangeSetBlazeRef<'a, T> for I
126where
127    T: Integer + 'a,
128    I: IntoIterator<Item = &'a RangeSetBlaze<T>>,
129{
130}
131/// Provides methods on zero or more [`RangeSetBlaze`] references,
132/// specifically [`union`], [`intersection`], and [`symmetric_difference`].
133///
134/// Also see [`MultiwayRangeSetBlaze`].
135///
136/// [`union`]: MultiwayRangeSetBlazeRef::union
137/// [`intersection`]: MultiwayRangeSetBlazeRef::intersection
138/// [`symmetric_difference`]: MultiwayRangeSetBlazeRef::symmetric_difference
139#[allow(clippy::module_name_repetitions)]
140pub trait MultiwayRangeSetBlazeRef<'a, T: Integer + 'a>:
141    IntoIterator<Item = &'a RangeSetBlaze<T>> + Sized
142{
143    /// Unions the given [`RangeSetBlaze`] references, creating a new [`RangeSetBlaze`].
144    /// Any number of input can be given.
145    ///
146    /// For exactly two inputs, you can also use the '|' operator.
147    /// Also see [`MultiwayRangeSetBlaze::union`].
148    ///
149    /// # Performance
150    ///
151    ///  All work is done on demand, in one pass through the inputs. Minimal memory is used.
152    ///
153    /// # Example
154    ///
155    /// Find the integers that appear in any of the [`RangeSetBlaze`]'s.
156    ///
157    /// ```
158    /// use range_set_blaze::prelude::*;
159    ///
160    /// let a = RangeSetBlaze::from_iter([1..=6, 8..=9, 11..=15]);
161    /// let b = RangeSetBlaze::from_iter([5..=13, 18..=29]);
162    /// let c = RangeSetBlaze::from_iter([25..=100]);
163    ///
164    /// let union = [&a, &b, &c].union();
165    ///
166    /// assert_eq!(union, RangeSetBlaze::from_iter([1..=15, 18..=100]));
167    /// ```
168    fn union(self) -> RangeSetBlaze<T> {
169        self.into_iter()
170            .map(RangeSetBlaze::ranges)
171            .union()
172            .into_range_set_blaze()
173    }
174
175    /// Intersects the given [`RangeSetBlaze`]'s, creating a new [`RangeSetBlaze`].
176    /// Any number of input can be given.
177    ///
178    /// For exactly two inputs, you can also use the '&' operator.
179    /// Also see [`MultiwayRangeSetBlaze::intersection`].
180    ///
181    /// When given zero inputs, it returns the universal set.
182    ///
183    /// # Performance
184    ///
185    ///  All work is done on demand, in one pass through the inputs. Minimal memory is used.
186    ///
187    /// # Example
188    ///
189    /// Find the integers that appear in all the [`RangeSetBlaze`]'s.
190    ///
191    /// ```
192    /// use range_set_blaze::prelude::*;
193    ///
194    /// let a = RangeSetBlaze::from_iter([1..=6, 8..=9, 11..=15]);
195    /// let b = RangeSetBlaze::from_iter([5..=13, 18..=29]);
196    /// let c = RangeSetBlaze::from_iter([-100..=100]);
197    ///
198    /// let intersection = [&a, &b, &c].intersection();
199    ///
200    /// assert_eq!(intersection, RangeSetBlaze::from_iter([5..=6, 8..=9, 11..=13]));
201    /// ```
202    fn intersection(self) -> RangeSetBlaze<T> {
203        self.into_iter()
204            .map(RangeSetBlaze::ranges)
205            .intersection()
206            .into_range_set_blaze()
207    }
208
209    /// Computes the symmetric difference of the given [`RangeSetBlaze`],
210    /// creating a new [`RangeSetBlaze`].
211    /// The symmetric difference is the set of elements that appear in an odd number
212    /// of the input sets.
213    ///
214    /// Any number of inputs can be given.
215    ///
216    /// For exactly two inputs, you can also use the '^' operator.
217    /// Also see [`MultiwayRangeSetBlaze::symmetric_difference`].
218    ///
219    /// # Performance
220    ///
221    /// All work is done on demand, in one pass through the inputs. Minimal memory is used.
222    ///
223    /// # Example
224    ///
225    /// Find the integers that appear in an odd number of the [`RangeSetBlaze`]s.
226    ///
227    /// ```
228    /// use range_set_blaze::prelude::*;
229    ///
230    /// let a = RangeSetBlaze::from_iter([1..=6, 8..=9, 11..=15]);
231    /// let b = RangeSetBlaze::from_iter([5..=13, 18..=29]);
232    /// let c = RangeSetBlaze::from_iter([-100..=100]);
233    ///
234    /// let symmetric_difference = [&a, &b, &c].symmetric_difference();
235    ///
236    /// assert_eq!(
237    ///     symmetric_difference,
238    ///     RangeSetBlaze::from_iter([
239    ///         -100..=0, 5..=6, 8..=9, 11..=13, 16..=17, 30..=100
240    ///     ])
241    /// );
242    /// ```
243    fn symmetric_difference(self) -> RangeSetBlaze<T> {
244        self.into_iter()
245            .map(RangeSetBlaze::ranges)
246            .symmetric_difference()
247            .into_range_set_blaze()
248    }
249}
250
251use crate::{
252    Integer, IntersectionMapInternal, RangeSetBlaze, SortedDisjoint, SymDiffIter, SymDiffKMerge,
253    UnionIter, UnionKMerge,
254};
255
256impl<T, II, I> MultiwaySortedDisjoint<T, I> for II
257where
258    T: Integer,
259    I: SortedDisjoint<T>,
260    II: IntoIterator<Item = I>,
261{
262}
263
264/// Provides methods on zero or more [`SortedDisjoint`] iterators,
265/// specifically [`union`], [`intersection`], and [`symmetric_difference`].
266///
267/// [SortedDisjoint]: crate::SortedDisjoint.html#table-of-contents
268/// [`union`]: crate::MultiwaySortedDisjoint::union
269/// [`intersection`]: crate::MultiwaySortedDisjoint::intersection
270/// [`symmetric_difference`]: crate::MultiwaySortedDisjoint::symmetric_difference
271#[allow(clippy::module_name_repetitions)]
272pub trait MultiwaySortedDisjoint<T: Integer, I>: IntoIterator<Item = I> + Sized
273where
274    I: SortedDisjoint<T>,
275{
276    /// Unions the given [`SortedDisjoint`] iterators, creating a new [`SortedDisjoint`] iterator.
277    /// The input iterators must be of the same type. Any number of input iterators can be given.
278    ///
279    /// For input iterators of different types, use the [`union_map_dyn!`] macro.
280    ///
281    /// [`union_map_dyn!`]: crate::union_map_dyn
282    /// [SortedDisjoint]: crate::SortedDisjoint.html#table-of-contents
283    ///
284    /// # Performance
285    ///
286    ///  All work is done on demand, in one pass through the input iterators. Minimal memory is used.
287    ///
288    /// # Example
289    ///
290    /// Find the integers that appear in any of the [`SortedDisjoint`] iterators.
291    ///
292    /// ```
293    /// use range_set_blaze::prelude::*;
294    ///
295    /// let a = RangeSetBlaze::from_iter([1..=6, 8..=9, 11..=15]).into_ranges();
296    /// let b = RangeSetBlaze::from_iter([5..=13, 18..=29]).into_ranges();
297    /// let c = RangeSetBlaze::from_iter([25..=100]).into_ranges();
298    ///
299    /// let union = [a, b, c].union();
300    ///
301    /// assert_eq!(union.into_string(), "1..=15, 18..=100");
302    /// ```
303    fn union(self) -> UnionKMerge<T, I> {
304        UnionIter::new_k(self)
305    }
306
307    /// Intersects the given [`SortedDisjoint`] iterators, creating a new [`SortedDisjoint`] iterator.
308    /// The input iterators must be of the same type. Any number of input iterators can be given.
309    ///
310    /// For input iterators of different types, use the [`intersection_map_dyn!`] macro.
311    ///
312    /// [`intersection_map_dyn!`]: crate::intersection_map_dyn
313    /// [SortedDisjoint]: crate::SortedDisjoint.html#table-of-contents
314    ///
315    /// For exactly two inputs, you can also use the `&` operator.
316    /// When given zero inputs, it returns the universal set.
317    ///
318    /// # Performance
319    ///
320    ///  All work is done on demand, in one pass through the input iterators. Minimal memory is used.
321    ///
322    /// # Example
323    ///
324    /// Find the integers that appear in all the [`SortedDisjoint`] iterators.
325    ///
326    /// ```
327    /// use range_set_blaze::prelude::*;
328    ///
329    /// let a = RangeSetBlaze::from_iter([1..=6, 8..=9, 11..=15]).into_ranges();
330    /// let b = RangeSetBlaze::from_iter([5..=13, 18..=29]).into_ranges();
331    /// let c = RangeSetBlaze::from_iter([-100..=100]).into_ranges();
332    ///
333    /// let intersection = [a, b, c].intersection();
334    ///
335    /// assert_eq!(intersection.into_string(), "5..=6, 8..=9, 11..=13");
336    /// ```
337    fn intersection(self) -> IntersectionMapInternal<T, I> {
338        // We define set intersection in terms of complement and (set/map) union.
339        // Elsewhere, map intersection is defined -- in part -- in terms of set intersection.
340        self.into_iter()
341            .map(|seq| seq.into_iter().complement())
342            .union()
343            .complement()
344    }
345
346    /// Computes the symmetric difference of the given [`SortedDisjoint`] iterators, creating a new [`SortedDisjoint`] iterator.
347    /// The symmetric difference is the set of elements that appear in an odd number of the input iterators.
348    /// The input iterators must be of the same type. Any number of input iterators can be given.
349    ///
350    /// For input iterators of different types, use the [`symmetric_difference_map_dyn!`] macro.
351    ///
352    /// [`symmetric_difference_map_dyn!`]: crate::symmetric_difference_map_dyn
353    /// [SortedDisjoint]: crate::SortedDisjoint.html#table-of-contents
354    ///
355    /// # Performance
356    ///
357    /// All work is done on demand, in one pass through the input iterators. Minimal memory is used.
358    ///
359    /// # Example
360    ///
361    /// Find the integers that appear in an odd number of the [`SortedDisjoint`] iterators.
362    ///
363    /// ```
364    /// use range_set_blaze::prelude::*;
365    ///
366    /// let a = RangeSetBlaze::from_iter([1..=6, 8..=9, 11..=15]).into_ranges();
367    /// let b = RangeSetBlaze::from_iter([5..=13, 18..=29]).into_ranges();
368    /// let c = RangeSetBlaze::from_iter([-100..=100]).into_ranges();
369    ///
370    /// let symmetric_difference = [a, b, c].symmetric_difference();
371    ///
372    /// assert_eq!(
373    ///     symmetric_difference.into_string(),
374    ///     "-100..=0, 5..=6, 8..=9, 11..=13, 16..=17, 30..=100"
375    /// );
376    /// ```
377    fn symmetric_difference(self) -> SymDiffKMerge<T, I> {
378        SymDiffIter::new_k(self)
379    }
380}