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}