1use std::cmp::{Ordering, PartialOrd};
2use std::ops::*;
3
4#[derive(Debug, PartialEq)]
6pub enum Intersection {
7 Empty,
9
10 Overlap,
12
13 Full,
15}
16
17impl Intersection {
18 pub fn is_any(&self) -> bool {
20 match self {
21 Intersection::Empty => false,
22 _ => true,
23 }
24 }
25}
26
27#[derive(Debug, PartialEq)]
30pub enum IntersectionExt {
31 Empty,
33 Less,
35
36 LessOverlap,
38
39 Within,
41
42 Same,
44
45 Over,
47
48 GreaterOverlap,
50
51 Greater,
53}
54
55impl IntersectionExt {
56 pub fn intersection(&self) -> Intersection {
58 match self {
59 IntersectionExt::Empty => Intersection::Empty,
60 IntersectionExt::Less => Intersection::Empty,
61 IntersectionExt::LessOverlap => Intersection::Overlap,
62 IntersectionExt::Within => Intersection::Full,
63 IntersectionExt::Same => Intersection::Full,
64 IntersectionExt::Over => Intersection::Full,
65 IntersectionExt::GreaterOverlap => Intersection::Overlap,
66 IntersectionExt::Greater => Intersection::Empty,
67 }
68 }
69
70 pub fn is_any(&self) -> bool {
72 match self {
73 IntersectionExt::Empty |
74 IntersectionExt::Less |
75 IntersectionExt::Greater => false,
76 _ => true,
77 }
78 }
79
80 pub fn is_within(&self) -> bool {
82 match self {
83 IntersectionExt::Within | IntersectionExt::Same => true,
84 _ => false,
85 }
86 }
87}
88
89pub trait Intersect<T: PartialOrd, U: RangeBounds<T>>: RangeBounds<T> {
91 fn intersect_ext(&self, other: &U) -> IntersectionExt;
93 fn intersect(&self, other: &U) -> Intersection;
95 fn does_intersect(&self, other:&U) -> bool;
97}
98
99macro_rules! empty_and_reverse {
100 ($a: ident, $b: ident, $fun: ident, $empty: expr) => {
101 if $a.start == $a.end || $b.start == $b.end {
102 return $empty;
103 }
104 if $a.start > $a.end {
105 return ($a.end .. $a.start).$fun($b);
106 }
107 if $b.start > $b.end {
108 return $a.$fun(&($b.end .. $b.start));
109 }
110 }
111}
112
113fn do_intersect_ext<T: PartialOrd>(a: &T, b: &T, x: &T, y: &T) -> IntersectionExt {
114 if b == y {
115 if a < x {
116 IntersectionExt::Over
117 } else if a > x {
118 IntersectionExt::Within
119 } else {
120 IntersectionExt::Same
121 }
122 } else if b < y {
123 if b <= x {
124 IntersectionExt::Less
125 } else if a < x {
126 IntersectionExt::LessOverlap
127 } else {
128 IntersectionExt::Within
129 }
130 } else if a < y {
131 if a <= x {
132 IntersectionExt::Over
133 } else {
134 IntersectionExt::GreaterOverlap
135 }
136 } else {
137 IntersectionExt::Greater
138 }
139}
140
141impl<T: PartialOrd + Copy> Intersect<T, Range<T>> for Range<T> {
142 fn intersect_ext(&self, other: &Range<T>) -> IntersectionExt {
144 let (a, b) = match self.start.partial_cmp(&self.end) {
145 None | Some(Ordering::Equal) => return IntersectionExt::Empty,
146 Some(Ordering::Less) => (&self.start, &self.end),
147 Some(Ordering::Greater) => (&self.end, &self.start),
148 };
149 let (x, y) = match other.start.partial_cmp(&other.end) {
150 None | Some(Ordering::Equal) => return IntersectionExt::Empty,
151 Some(Ordering::Less) => (&other.start, &other.end),
152 Some(Ordering::Greater) => (&other.end, &other.start),
153 };
154 do_intersect_ext(a, b, x, y)
155 }
156
157 fn intersect(&self, other: &Range<T>) -> Intersection {
158 empty_and_reverse!(self, other, intersect, Intersection::Empty);
159 if self.end <= other.start || self.start >= other.end {
160 Intersection::Empty
161 } else {
162 match (self.start.partial_cmp(&other.start), self.end.partial_cmp(&other.end)) {
163 (None, _) => Intersection::Empty,
164 (_, None) => Intersection::Empty,
165 (Some(Ordering::Equal), _) => Intersection::Full,
166 (Some(Ordering::Less), Some(Ordering::Less)) => Intersection::Overlap,
167 (Some(Ordering::Less), _) => Intersection::Full,
168 (Some(Ordering::Greater), Some(Ordering::Greater)) => Intersection::Overlap,
169 (Some(Ordering::Greater), _) => Intersection::Full,
170 }
171 }
172 }
173
174 fn does_intersect(&self, other: &Range<T>) -> bool {
175 empty_and_reverse!(self, other, does_intersect, false);
176 if self.end <= other.start || self.start >= other.end {
177 false
178 } else {
179 match (self.start.partial_cmp(&other.start), self.end.partial_cmp(&other.end)) {
180 (None, _) => false,
181 (_, None) => false,
182 _ => true,
183 }
184 }
185 }
186}
187
188macro_rules! empty_and_reverse_a {
189 ($a: ident, $b: ident, $fun: ident, $empty: expr) => {
190 if $a.start == $a.end {
191 return $empty;
192 }
193 if $a.start > $a.end {
194 return ($a.end .. $a.start).$fun($b);
195 }
196 }
197}
198
199impl<T: PartialOrd + Copy> Intersect<T, RangeFrom<T>> for Range<T> {
200 fn intersect_ext(&self, other: &RangeFrom<T>) -> IntersectionExt {
202 empty_and_reverse_a!(self, other, intersect_ext, IntersectionExt::Empty);
203 if self.end <= other.start {
204 IntersectionExt::Less
205 } else if self.start >= other.start {
206 IntersectionExt::Within
207 } else {
208 IntersectionExt::LessOverlap
209 }
210 }
211
212 fn intersect(&self, other: &RangeFrom<T>) -> Intersection {
213 empty_and_reverse_a!(self, other, intersect, Intersection::Empty);
214 if self.end <= other.start {
215 Intersection::Empty
216 } else if self.start >= other.start {
217 Intersection::Full
218 } else {
219 Intersection::Overlap
220 }
221 }
222
223 fn does_intersect(&self, other: &RangeFrom<T>) -> bool {
224 empty_and_reverse_a!(self, other, does_intersect, false);
225 if self.end <= other.start {
226 false
227 } else {
228 true
229 }
230 }
231}
232
233impl<T: PartialOrd> Intersect<T, RangeFull> for Range<T> {
234 fn intersect_ext(&self, _: &RangeFull) -> IntersectionExt {
236 if self.start == self.end {
237 IntersectionExt::Empty
238 } else {
239 IntersectionExt::Within
240 }
241 }
242
243 fn intersect(&self, _: &RangeFull) -> Intersection {
244 if self.start == self.end {
245 Intersection::Empty
246 } else {
247
248 Intersection::Full
249 }
250 }
251
252 fn does_intersect(&self, _: &RangeFull) -> bool {
253 if self.start == self.end {
254 false
255 } else {
256 true
257 }
258 }
259}
260
261impl<T: PartialOrd + Copy> Intersect<T, RangeTo<T>> for Range<T> {
262 fn intersect_ext(&self, other: &RangeTo<T>) -> IntersectionExt {
264 empty_and_reverse_a!(self, other, intersect_ext, IntersectionExt::Empty);
265 if self.start >= other.end {
266 IntersectionExt::Greater
267 } else if self.end > other.end {
268 IntersectionExt::GreaterOverlap
269 } else {
270 IntersectionExt::Within
271 }
272 }
273
274 fn intersect(&self, other: &RangeTo<T>) -> Intersection {
275 empty_and_reverse_a!(self, other, intersect, Intersection::Empty);
276 if self.start >= other.end {
277 Intersection::Empty
278 } else if self.end > other.end {
279 Intersection::Overlap
280 } else {
281 Intersection::Full
282 }
283 }
284
285 fn does_intersect(&self, other: &RangeTo<T>) -> bool {
286 empty_and_reverse_a!(self, other, does_intersect, false);
287 if self.start >= other.end {
288 false
289 } else if self.end > other.end {
290 true
291 } else {
292 true
293 }
294 }
295}
296
297macro_rules! test_if_reverse {
298 ($a: expr, $b: expr, $x: expr, $y: expr, $empty: expr) => {{
299 let (a, b) = match $a.partial_cmp($b) {
300 None => return $empty,
301 Some(Ordering::Less) | Some(Ordering::Equal) => ($a, $b),
302 Some(Ordering::Greater) => ($b, $a),
303 };
304 let (x, y) = match $x.partial_cmp($y) {
305 None => return $empty,
306 Some(Ordering::Less) | Some(Ordering::Equal) => ($x, $y),
307 Some(Ordering::Greater) => ($y, $x),
308 };
309 (a, b, x, y)
310 } }
311}
312
313macro_rules! try_unwrap {
314 ($a: expr, $or: expr) => {
315 match $a {
316 Some(a) => a,
317 None => return $or,
318 }
319 }
320}
321impl<T: PartialOrd + Copy> Intersect<T, RangeInclusive<T>> for RangeInclusive<T> {
322 fn intersect_ext(&self, other: &RangeInclusive<T>) -> IntersectionExt {
323 let (a, b, x, y) = test_if_reverse!(self.start(), self.end(), other.start(), other.end(), IntersectionExt::Empty);
325 if b == y {
326 if a < x {
327 IntersectionExt::Over
328 } else if a > x {
329 IntersectionExt::Within
330 } else {
331 IntersectionExt::Same
332 }
333 } else if a == y {
334 IntersectionExt::GreaterOverlap
335 } else if b < y {
336 if b < x {
337 IntersectionExt::Less
338 } else if a < x {
339 IntersectionExt::LessOverlap
340 } else {
341 IntersectionExt::Within
342 }
343 } else if a < y {
344 if a <= x {
345 IntersectionExt::Over
346 } else {
347 IntersectionExt::GreaterOverlap
348 }
349 } else {
350 IntersectionExt::Greater
351 }
352 }
353
354 fn intersect(&self, other: &RangeInclusive<T>) -> Intersection {
355 let (a, b, x, y) = test_if_reverse!(self.start(), self.end(), other.start(), other.end(), Intersection::Empty);
357 let ax = try_unwrap!(a.partial_cmp(&x), Intersection::Empty);
358 let by = try_unwrap!(b.partial_cmp(&y), Intersection::Empty);
359 let ay = try_unwrap!(a.partial_cmp(&y), Intersection::Empty);
360 let bx = try_unwrap!(b.partial_cmp(&x), Intersection::Empty);
361
362 match (ax, ay, bx, by) {
363 (_, Ordering::Greater, _ , _) => Intersection::Empty,
364 (_, _, Ordering::Less, _) => Intersection::Empty,
365 (Ordering::Equal, _,_,_) => Intersection::Full,
366 (_, _, _, Ordering::Equal) => Intersection::Full,
367 (Ordering::Less, _,_,Ordering::Greater) => Intersection::Full,
368 (Ordering::Greater, _, _, Ordering::Less) => Intersection::Full,
369 _ => Intersection::Overlap,
370 }
371 }
372
373 fn does_intersect(&self, other: &RangeInclusive<T>) -> bool {
374 let (a, b, x, y) = test_if_reverse!(self.start(), self.end(), other.start(), other.end(), false);
375 let ay = try_unwrap!(a.partial_cmp(&y), false);
376 let bx = try_unwrap!(b.partial_cmp(&x), false);
377
378 match (ay, bx) {
379 (Ordering::Greater, _) => false,
380 (_, Ordering::Less) => false,
381 _ => true,
382 }
383 }
384}
385
386#[cfg(test)]
387mod tests {
388 use super::*;
389
390 #[test]
391 fn range_intersect() {
392 assert_eq!((5..10).intersect_ext(&(3..7)), IntersectionExt::GreaterOverlap);
394 assert_eq!((5..10).intersect_ext(&(8..15)), IntersectionExt::LessOverlap);
395 assert_eq!((10..5).intersect_ext(&(3..7)), IntersectionExt::GreaterOverlap);
396 assert_eq!((10..5).intersect_ext(&(8..15)), IntersectionExt::LessOverlap);
397 assert_eq!((10..5).intersect_ext(&(7..3)), IntersectionExt::GreaterOverlap);
398 assert_eq!((10..5).intersect_ext(&(15..8)), IntersectionExt::LessOverlap);
399
400 assert_eq!((5..10).intersect_ext(&(5..10)), IntersectionExt::Same);
402 assert_eq!((5..10).intersect_ext(&(4..11)), IntersectionExt::Within);
403 assert_eq!((5..10).intersect_ext(&(5..20)), IntersectionExt::Within);
404
405 assert_eq!((5..10).intersect_ext(&(6..9)), IntersectionExt::Over);
407 assert_eq!((5..10).intersect_ext(&(5..6)), IntersectionExt::Over);
408 assert_eq!((5..10).intersect_ext(&(6..10)), IntersectionExt::Over);
409
410 assert_eq!((5..10).intersect_ext(&(10..15)), IntersectionExt::Less);
412 assert_eq!((5..10).intersect_ext(&(0..5)), IntersectionExt::Greater);
413
414 assert_eq!((5..10).intersect_ext(&(5..5)), IntersectionExt::Empty);
416 assert_eq!((5..5).intersect_ext(&(3..7)), IntersectionExt::Empty);
417 assert_eq!((5..5).intersect_ext(&(6..6)), IntersectionExt::Empty);
418
419
420 assert_eq!((5..10).intersect(&(0..5)), Intersection::Empty);
421 assert_eq!((5..10).intersect(&(11..20)), Intersection::Empty);
422 assert_eq!((5..5).intersect(&(11..20)), Intersection::Empty);
423 assert_eq!((5..10).intersect(&(5..5)), Intersection::Empty);
424 assert_eq!((5..10).intersect(&(5..10)), Intersection::Full);
425 assert_eq!((5..10).intersect(&(4..10)), Intersection::Full);
426 assert_eq!((5..10).intersect(&(4..12)), Intersection::Full);
427 assert_eq!((5..10).intersect(&(5..12)), Intersection::Full);
428 assert_eq!((5..10).intersect(&(6..12)), Intersection::Overlap);
429 assert_eq!((5..10).intersect(&(4..8)), Intersection::Overlap);
430 assert_eq!((5..10).intersect(&(5..11)), Intersection::Full);
431
432
433 assert_eq!((5..10).does_intersect(&(5..10)), true);
434 assert_eq!((5..10).does_intersect(&(5..10)), true);
435 assert_eq!((5..5).does_intersect(&(5..10)), false);
436
437 assert_eq!((5..10).does_intersect(&(5..5)), false);
438 assert_eq!((5..10).does_intersect(&(5..10)), true);
439 assert_eq!((5..10).does_intersect(&(4..10)), true);
440 assert_eq!((5..10).does_intersect(&(4..12)), true);
441 assert_eq!((5..10).does_intersect(&(5..12)), true);
442 assert_eq!((5..10).does_intersect(&(6..12)), true);
443 assert_eq!((5..10).does_intersect(&(4..8)), true);
444 assert_eq!((5..10).does_intersect(&(5..11)), true);
445 }
446
447 #[test]
448 fn range_from_intersect() {
449 assert_eq!((1..10).intersect_ext(&(5..)), IntersectionExt::LessOverlap);
450 assert_eq!((1..10).intersect_ext(&(11..)), IntersectionExt::Less);
451 assert_eq!((1..10).intersect_ext(&(1..)), IntersectionExt::Within);
452 assert_eq!((1..10).intersect_ext(&(0..)), IntersectionExt::Within);
453 assert_eq!((1..10).intersect_ext(&(10..)), IntersectionExt::Less);
454
455 assert_eq!((10..1).intersect_ext(&(5..)), IntersectionExt::LessOverlap);
457 assert_eq!((10..1).intersect_ext(&(11..)), IntersectionExt::Less);
458 assert_eq!((10..1).intersect_ext(&(1..)), IntersectionExt::Within);
459 assert_eq!((10..1).intersect_ext(&(0..)), IntersectionExt::Within);
460
461 assert_eq!((1..1).intersect_ext(&(0..)), IntersectionExt::Empty);
462
463
464 assert_eq!((1..10).intersect(&(10..)), Intersection::Empty);
465 assert_eq!((1..10).intersect(&(5..)), Intersection::Overlap);
466 assert_eq!((1..10).intersect(&(11..)), Intersection::Empty);
467 assert_eq!((1..10).intersect(&(1..)), Intersection::Full);
468 assert_eq!((1..10).intersect(&(0..)), Intersection::Full);
469 assert_eq!((1..1).intersect(&(0..)), Intersection::Empty);
470 assert_eq!((10..1).intersect(&(5..)), Intersection::Overlap);
471 assert_eq!((10..1).intersect(&(11..)), Intersection::Empty);
472 assert_eq!((10..1).intersect(&(1..)), Intersection::Full);
473 assert_eq!((10..1).intersect(&(0..)), Intersection::Full);
474
475
476 assert_eq!((1..10).does_intersect(&(10..)), false);
477 assert_eq!((1..10).does_intersect(&(5..)), true);
478 assert_eq!((1..10).does_intersect(&(11..)), false);
479 assert_eq!((1..10).does_intersect(&(1..)), true);
480 assert_eq!((1..10).does_intersect(&(0..)), true);
481 assert_eq!((1..1) .does_intersect(&(0..)), false);
482 assert_eq!((10..1).does_intersect(&(5..)), true);
483 assert_eq!((10..1).does_intersect(&(11..)), false);
484 assert_eq!((10..1).does_intersect(&(1..)), true);
485 assert_eq!((10..1).does_intersect(&(0..)), true);
486 }
487
488 #[test]
489 fn range_full_intersect() {
490 assert_eq!((1..10).intersect_ext(&..), IntersectionExt::Within);
491 assert_eq!((1..1).intersect_ext(&..), IntersectionExt::Empty);
492
493 assert_eq!((1..10).intersect(&..), Intersection::Full);
494 assert_eq!((1..1).intersect(&..), Intersection::Empty);
495
496 assert_eq!((1..10).does_intersect(&..), true);
497 assert_eq!((1..1).does_intersect(&..), false);
498 }
499
500 #[test]
501 fn range_to_intersect() {
502 assert_eq!((1..1).intersect_ext(&(..0)), IntersectionExt::Empty);
503 assert_eq!((1..10).intersect_ext(&(..0)), IntersectionExt::Greater);
504 assert_eq!((1..10).intersect_ext(&(..1)), IntersectionExt::Greater);
505 assert_eq!((1..10).intersect_ext(&(..2)), IntersectionExt::GreaterOverlap);
506 assert_eq!((1..10).intersect_ext(&(..10)), IntersectionExt::Within);
507 assert_eq!((1..10).intersect_ext(&(..11)), IntersectionExt::Within);
508
509 assert_eq!((10..1).intersect_ext(&(..0)), IntersectionExt::Greater);
510 assert_eq!((10..1).intersect_ext(&(..1)), IntersectionExt::Greater);
511 assert_eq!((10..1).intersect_ext(&(..2)), IntersectionExt::GreaterOverlap);
512 assert_eq!((10..1).intersect_ext(&(..10)), IntersectionExt::Within);
513 assert_eq!((10..1).intersect_ext(&(..11)), IntersectionExt::Within);
514
515 assert_eq!((1..1). intersect(&(..0)), Intersection::Empty);
516 assert_eq!((1..10).intersect(&(..0)), Intersection::Empty);
517 assert_eq!((1..10).intersect(&(..1)), Intersection::Empty);
518 assert_eq!((1..10).intersect(&(..2)), Intersection::Overlap);
519 assert_eq!((1..10).intersect(&(..10)), Intersection::Full);
520 assert_eq!((1..10).intersect(&(..11)), Intersection::Full);
521
522 assert_eq!((10..1).intersect(&(..0)), Intersection::Empty);
523 assert_eq!((10..1).intersect(&(..1)), Intersection::Empty);
524 assert_eq!((10..1).intersect(&(..2)), Intersection::Overlap);
525 assert_eq!((10..1).intersect(&(..10)), Intersection::Full);
526 assert_eq!((10..1).intersect(&(..11)), Intersection::Full);
527 }
528
529 #[test]
530 fn functions_test() {
531 assert_eq!(Intersection::Overlap.is_any(), true);
532 assert_eq!(Intersection::Empty.is_any(), false);
533 assert_eq!(IntersectionExt::Less.is_any(), false);
534 assert_eq!(IntersectionExt::LessOverlap.is_any(), true);
535 assert_eq!(IntersectionExt::Within.is_any(), true);
536 assert_eq!(IntersectionExt::Same.is_any(), true);
537 assert_eq!(IntersectionExt::Over.is_any(), true);
538 assert_eq!(IntersectionExt::GreaterOverlap.is_any(), true);
539 assert_eq!(IntersectionExt::Greater.is_any(), false);
540 assert_eq!(IntersectionExt::Less.is_within(), false);
541 assert_eq!(IntersectionExt::LessOverlap.is_within(), false);
542 assert_eq!(IntersectionExt::Within.is_within(), true);
543 assert_eq!(IntersectionExt::Same.is_within(), true);
544 assert_eq!(IntersectionExt::Over.is_within(), false);
545 assert_eq!(IntersectionExt::GreaterOverlap.is_within(), false);
546 assert_eq!(IntersectionExt::Greater.is_within(), false);
547 }
548
549 #[test]
550 fn range_inclusive_test() {
551 assert_eq!((10..=1).intersect_ext(&(15..=1)), IntersectionExt::Within);
552 assert_eq!((10..=1).intersect_ext(&(10..=1)), IntersectionExt::Same);
553 assert_eq!((10..=1).intersect_ext(&(9..=1)), IntersectionExt::Over);
554 assert_eq!((10..=1).intersect_ext(&(10..=9)), IntersectionExt::Over);
555 assert_eq!((10..=1).intersect_ext(&(10..=0)), IntersectionExt::Within);
556 assert_eq!((10..=1).intersect_ext(&(1..=0)), IntersectionExt::GreaterOverlap);
557 assert_eq!((10..=1).intersect_ext(&(0..=-1)), IntersectionExt::Greater);
558 assert_eq!((10..=1).intersect_ext(&(11..=10)), IntersectionExt::LessOverlap);
559 assert_eq!((10..=1).intersect_ext(&(12..=11)), IntersectionExt::Less);
560
561 assert_eq!((10..=1).intersect(&(15..=1)), Intersection::Full);
562 assert_eq!((10..=1).intersect(&(10..=1)), Intersection::Full);
563 assert_eq!((10..=1).intersect(&(9..=1)), Intersection::Full);
564 assert_eq!((10..=1).intersect(&(10..=9)), Intersection::Full);
565 assert_eq!((10..=1).intersect(&(10..=0)), Intersection::Full);
566 assert_eq!((10..=1).intersect(&(1..=0)), Intersection::Overlap);
567 assert_eq!((10..=1).intersect(&(0..=-1)), Intersection::Empty);
568 assert_eq!((10..=1).intersect(&(11..=10)), Intersection::Overlap);
569 assert_eq!((10..=1).intersect(&(12..=11)), Intersection::Empty);
570
571 assert_eq!((10..=1).does_intersect(&(15..=1)), true);
572 assert_eq!((10..=1).does_intersect(&(10..=1)), true);
573 assert_eq!((10..=1).does_intersect(&(9..=1)), true);
574 assert_eq!((10..=1).does_intersect(&(10..=9)), true);
575 assert_eq!((10..=1).does_intersect(&(10..=0)), true);
576 assert_eq!((10..=1).does_intersect(&(1..=0)), true);
577 assert_eq!((10..=1).does_intersect(&(0..=-1)), false);
578 assert_eq!((10..=1).does_intersect(&(11..=10)), true);
579 assert_eq!((10..=1).does_intersect(&(12..=11)), false);
580 }
581}