range_set_blaze/
multiway_map.rs

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