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}