Skip to main content

ruranges_core/
complement.rs

1use crate::{
2    ruranges_structs::{GroupType, PositionType},
3    sorts,
4};
5
6use rustc_hash::FxHashSet;
7
8pub fn sweep_line_non_overlaps<G: GroupType, T: PositionType>(
9    chrs: &[G],
10    starts: &[T],
11    ends: &[T],
12    chrs2: &[G],
13    starts2: &[T],
14    ends2: &[T],
15    slack: T,
16) -> Vec<u32> {
17    let mut no_overlaps = Vec::new();
18
19    // If either set is empty, none can overlap; return everything as “non-overlapping”.
20    if chrs.is_empty() || chrs2.is_empty() {
21        // Just return all indices as non-overlapping
22        return no_overlaps.to_vec();
23    }
24
25    // Build up the event list in ascending order (same as before)
26    let events = sorts::build_sorted_events_idxs(chrs, starts, ends, chrs2, starts2, ends2, slack);
27
28    let mut overlapped = FxHashSet::default();
29
30    // Active sets
31    let mut active1 = FxHashSet::default();
32    let mut active2 = FxHashSet::default();
33
34    // Assume the first event determines the “current” chr
35    let mut current_chr = events.first().unwrap().chr;
36
37    for e in events {
38        // If chromosome changed, clear active sets
39        if e.chr != current_chr {
40            active1.clear();
41            active2.clear();
42            current_chr = e.chr;
43        }
44
45        if e.is_start {
46            // Interval is starting
47            if e.first_set {
48                // Overlaps with all currently active intervals in set2
49                if !active2.is_empty() {
50                    overlapped.insert(e.idx);
51                }
52                // Insert into active1
53                active1.insert(e.idx);
54            } else {
55                // Overlaps with all currently active intervals in set1
56                for &idx1 in active1.iter() {
57                    overlapped.insert(idx1);
58                }
59                // Insert into active2
60                active2.insert(e.idx);
61            }
62        } else {
63            // Interval is ending
64            if e.first_set {
65                active1.remove(&e.idx);
66                if !overlapped.contains(&e.idx) {
67                    no_overlaps.push(e.idx);
68                }
69            } else {
70                active2.remove(&e.idx);
71            }
72
73            overlapped.remove(&e.idx);
74        }
75    }
76
77    radsort::sort(&mut no_overlaps);
78    no_overlaps
79}