molframe_core/selection/query/
operations.rs1use super::merge::{copy_selection, merge_positions, visit_positions};
4use super::representation::AtomSelection;
5use super::runs::{
6 RunCursor, complement_within, difference_runs, intersect_runs, retain_after, union_runs,
7};
8use std::ops::Range;
9
10impl AtomSelection {
11 #[must_use]
13 pub fn intersect(&self, other: &Self) -> Self {
14 match (self, other) {
15 (Self::Empty, _) | (_, Self::Empty) => return Self::Empty,
16 (Self::All(_), _) => return copy_selection(other),
17 (_, Self::All(_)) => return copy_selection(self),
18 _ => {}
19 }
20 if let (Some(left), Some(right)) = (RunCursor::new(self), RunCursor::new(other)) {
21 return intersect_runs(left, right);
22 }
23 let (smaller, larger) = if self.len() <= other.len() {
24 (self, other)
25 } else {
26 (other, self)
27 };
28 let mut kept = Vec::new();
29 visit_positions(smaller, |position| {
30 if larger.contains(position) {
31 kept.push(position);
32 }
33 });
34 Self::from_sorted(kept)
35 }
36
37 #[must_use]
39 pub fn union(&self, other: &Self) -> Self {
40 match (self, other) {
41 (Self::Empty, _) => return copy_selection(other),
42 (_, Self::Empty) => return copy_selection(self),
43 (Self::All(count), _) | (_, Self::All(count)) => return Self::All(*count),
44 _ => {}
45 }
46 if let (Some(left), Some(right)) = (RunCursor::new(self), RunCursor::new(other)) {
47 return union_runs(left, right);
48 }
49 merge_positions(self, other)
50 }
51
52 #[must_use]
54 pub fn difference(&self, other: &Self) -> Self {
55 if self.is_empty() {
56 return Self::Empty;
57 }
58 if other.is_empty() {
59 return copy_selection(self);
60 }
61 if let Self::All(count) = self {
62 return complement_within(other, *count);
63 }
64 if let Self::All(count) = other {
65 return retain_after(self, *count);
66 }
67 if let (Some(left), Some(right)) = (RunCursor::new(self), RunCursor::new(other)) {
68 return difference_runs(left, right);
69 }
70 let mut kept = Vec::new();
71 visit_positions(self, |position| {
72 if !other.contains(position) {
73 kept.push(position);
74 }
75 });
76 Self::from_sorted(kept)
77 }
78
79 #[must_use]
81 pub fn complement(&self, count: u32) -> Self {
82 if self.is_empty() {
83 return Self::All(count);
84 }
85 if count == 0 {
86 return Self::Empty;
87 }
88 complement_within(self, count)
89 }
90
91 #[must_use]
93 pub fn heap_bytes(&self) -> usize {
94 match self {
95 Self::Empty | Self::All(_) | Self::Range(_) => 0,
96 Self::Ranges(runs) => runs.len() * size_of::<Range<u32>>(),
97 Self::Sparse(positions) => positions.len() * size_of::<u32>(),
98 Self::Dense(mask) => (mask.len() as usize).div_ceil(8),
99 }
100 }
101}