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}