grafeo_core/execution/
selection.rs1#[derive(Debug, Clone)]
7pub struct SelectionVector {
8 indices: Vec<u16>,
10}
11
12impl SelectionVector {
13 pub const MAX_CAPACITY: usize = u16::MAX as usize;
15
16 #[must_use]
22 pub fn new_all(count: usize) -> Self {
23 assert!(count <= Self::MAX_CAPACITY);
24 Self {
25 #[allow(clippy::cast_possible_truncation)]
27 indices: (0..count as u16).collect(),
28 }
29 }
30
31 #[must_use]
33 pub fn new_empty() -> Self {
34 Self {
35 indices: Vec::new(),
36 }
37 }
38
39 #[must_use]
41 pub fn with_capacity(capacity: usize) -> Self {
42 Self {
43 indices: Vec::with_capacity(capacity.min(Self::MAX_CAPACITY)),
44 }
45 }
46
47 #[must_use]
51 pub fn from_predicate<F>(count: usize, predicate: F) -> Self
52 where
53 F: Fn(usize) -> bool,
54 {
55 let indices: Vec<u16> = (0..count)
56 .filter(|&i| predicate(i))
57 .map(|i| {
59 #[allow(clippy::cast_possible_truncation)]
61 let idx = i as u16;
62 idx
63 })
64 .collect();
65 Self { indices }
66 }
67
68 #[must_use]
70 pub fn len(&self) -> usize {
71 self.indices.len()
72 }
73
74 #[must_use]
76 pub fn is_empty(&self) -> bool {
77 self.indices.is_empty()
78 }
79
80 #[must_use]
82 pub fn get(&self, position: usize) -> Option<usize> {
83 self.indices.get(position).map(|&i| i as usize)
84 }
85
86 pub fn push(&mut self, index: usize) {
92 assert!(index <= Self::MAX_CAPACITY);
93 #[allow(clippy::cast_possible_truncation)]
95 self.indices.push(index as u16);
96 }
97
98 #[must_use]
100 pub fn as_slice(&self) -> &[u16] {
101 &self.indices
102 }
103
104 pub fn clear(&mut self) {
106 self.indices.clear();
107 }
108
109 #[must_use]
113 pub fn filter<F>(&self, predicate: F) -> Self
114 where
115 F: Fn(usize) -> bool,
116 {
117 let indices: Vec<u16> = self
118 .indices
119 .iter()
120 .copied()
121 .filter(|&i| predicate(i as usize))
122 .collect();
123 Self { indices }
124 }
125
126 #[must_use]
128 pub fn intersect(&self, other: &Self) -> Self {
129 let mut result = Vec::new();
131 let mut i = 0;
132 let mut j = 0;
133
134 while i < self.indices.len() && j < other.indices.len() {
135 match self.indices[i].cmp(&other.indices[j]) {
136 std::cmp::Ordering::Less => i += 1,
137 std::cmp::Ordering::Greater => j += 1,
138 std::cmp::Ordering::Equal => {
139 result.push(self.indices[i]);
140 i += 1;
141 j += 1;
142 }
143 }
144 }
145
146 Self { indices: result }
147 }
148
149 #[must_use]
151 pub fn union(&self, other: &Self) -> Self {
152 let mut result = Vec::new();
153 let mut i = 0;
154 let mut j = 0;
155
156 while i < self.indices.len() && j < other.indices.len() {
157 match self.indices[i].cmp(&other.indices[j]) {
158 std::cmp::Ordering::Less => {
159 result.push(self.indices[i]);
160 i += 1;
161 }
162 std::cmp::Ordering::Greater => {
163 result.push(other.indices[j]);
164 j += 1;
165 }
166 std::cmp::Ordering::Equal => {
167 result.push(self.indices[i]);
168 i += 1;
169 j += 1;
170 }
171 }
172 }
173
174 result.extend_from_slice(&self.indices[i..]);
175 result.extend_from_slice(&other.indices[j..]);
176
177 Self { indices: result }
178 }
179
180 pub fn iter(&self) -> impl Iterator<Item = usize> + '_ {
182 self.indices.iter().map(|&i| i as usize)
183 }
184
185 #[must_use]
187 pub fn contains(&self, index: usize) -> bool {
188 if index > u16::MAX as usize {
189 return false;
190 }
191 #[allow(clippy::cast_possible_truncation)]
194 self.indices.binary_search(&(index as u16)).is_ok()
195 }
196}
197
198impl Default for SelectionVector {
199 fn default() -> Self {
200 Self::new_empty()
201 }
202}
203
204impl IntoIterator for SelectionVector {
205 type Item = usize;
206 type IntoIter = std::iter::Map<std::vec::IntoIter<u16>, fn(u16) -> usize>;
207
208 fn into_iter(self) -> Self::IntoIter {
209 self.indices.into_iter().map(|i| i as usize)
210 }
211}
212
213#[cfg(test)]
214mod tests {
215 use super::*;
216
217 #[test]
218 fn test_selection_all() {
219 let sel = SelectionVector::new_all(10);
220 assert_eq!(sel.len(), 10);
221
222 for i in 0..10 {
223 assert_eq!(sel.get(i), Some(i));
224 }
225 }
226
227 #[test]
228 fn test_selection_from_predicate() {
229 let sel = SelectionVector::from_predicate(10, |i| i % 2 == 0);
230
231 assert_eq!(sel.len(), 5);
232 assert_eq!(sel.get(0), Some(0));
233 assert_eq!(sel.get(1), Some(2));
234 assert_eq!(sel.get(2), Some(4));
235 }
236
237 #[test]
238 fn test_selection_filter() {
239 let sel = SelectionVector::new_all(10);
240 let filtered = sel.filter(|i| i >= 5);
241
242 assert_eq!(filtered.len(), 5);
243 assert_eq!(filtered.get(0), Some(5));
244 }
245
246 #[test]
247 fn test_selection_intersect() {
248 let sel1 = SelectionVector::from_predicate(10, |i| i % 2 == 0); let sel2 = SelectionVector::from_predicate(10, |i| i % 3 == 0); let intersection = sel1.intersect(&sel2);
252 assert_eq!(intersection.len(), 2);
255 assert_eq!(intersection.get(0), Some(0));
256 assert_eq!(intersection.get(1), Some(6));
257 }
258
259 #[test]
260 fn test_selection_union() {
261 let sel1 = SelectionVector::from_predicate(10, |i| i == 1 || i == 3); let sel2 = SelectionVector::from_predicate(10, |i| i == 2 || i == 3); let union = sel1.union(&sel2);
265 assert_eq!(union.len(), 3);
268 assert_eq!(union.get(0), Some(1));
269 assert_eq!(union.get(1), Some(2));
270 assert_eq!(union.get(2), Some(3));
271 }
272
273 #[test]
274 fn test_selection_iterator() {
275 let sel = SelectionVector::from_predicate(5, |i| i < 3);
276 let collected: Vec<_> = sel.iter().collect();
277
278 assert_eq!(collected, vec![0, 1, 2]);
279 }
280}