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