triblespace_core/query/
variableset.rs1use std::fmt;
2
3#[derive(Eq, PartialEq, Clone, Copy)]
7#[repr(transparent)]
8pub struct VariableSet {
9 bits: u128,
10}
11
12impl VariableSet {
13 #[must_use]
15 pub const fn new_empty() -> Self {
16 VariableSet { bits: 0 }
17 }
18 #[must_use]
20 pub const fn new_full() -> Self {
21 VariableSet { bits: !0 }
22 }
23
24 #[must_use]
26 pub fn new_singleton(index: usize) -> Self {
27 let mut set = Self::new_empty();
28 set.set(index);
29 set
30 }
31
32 #[must_use]
34 pub fn is_empty(&self) -> bool {
35 self.bits == 0
36 }
37 #[must_use]
39 pub fn count(&self) -> usize {
40 self.bits.count_ones() as usize
41 }
42 pub fn set(&mut self, index: usize) {
44 self.bits |= 1 << index;
45 }
46 pub fn unset(&mut self, index: usize) {
48 self.bits &= !(1 << index);
49 }
50 pub fn set_value(&mut self, index: usize, value: bool) {
53 if value {
54 self.set(index);
55 } else {
56 self.unset(index);
57 }
58 }
59 pub fn set_all(&mut self) {
61 self.bits = !0;
62 }
63 pub fn unset_all(&mut self) {
65 self.bits = 0;
66 }
67 #[must_use]
69 pub fn is_set(&self, index: usize) -> bool {
70 0 != (self.bits & (1 << index))
71 }
72 #[must_use]
75 pub fn find_first_set(&self) -> Option<usize> {
76 if self.bits != 0 {
77 return Some(self.bits.trailing_zeros() as usize);
78 }
79 None
80 }
81 #[must_use]
84 pub fn find_last_set(&self) -> Option<usize> {
85 if self.bits != 0 {
86 return Some(127 - (self.bits.leading_zeros() as usize));
87 }
88 None
89 }
90 pub fn drain_next_ascending(&mut self) -> Option<usize> {
93 if let Some(next_index) = self.find_first_set() {
94 self.unset(next_index);
95 Some(next_index)
96 } else {
97 None
98 }
99 }
100 pub fn drain_next_descending(&mut self) -> Option<usize> {
103 if let Some(next_index) = self.find_last_set() {
104 self.unset(next_index);
105 Some(next_index)
106 } else {
107 None
108 }
109 }
110 #[must_use]
112 pub fn is_superset_of(&self, other: &Self) -> bool {
113 ((self.bits & other.bits) ^ other.bits) == 0
114 }
115 #[must_use]
117 pub fn is_subset_of(&self, other: &Self) -> bool {
118 ((self.bits & other.bits) ^ self.bits) == 0
119 }
120 #[must_use]
122 pub fn intersect(self, other: Self) -> Self {
123 Self {
124 bits: self.bits & other.bits,
125 }
126 }
127 #[must_use]
129 pub fn union(self, other: Self) -> Self {
130 Self {
131 bits: self.bits | other.bits,
132 }
133 }
134 #[must_use]
136 pub fn subtract(self, other: Self) -> Self {
137 Self {
138 bits: self.bits & !other.bits,
139 }
140 }
141 #[must_use]
143 pub fn difference(self, other: Self) -> Self {
144 Self {
145 bits: self.bits ^ other.bits,
146 }
147 }
148 #[must_use]
151 pub fn complement(self) -> Self {
152 Self { bits: !self.bits }
153 }
154 pub fn keep_single(&mut self, index: usize) {
157 let had_bit = self.is_set(index);
158 self.unset_all();
159 if had_bit {
160 self.set(index);
161 }
162 }
163
164 pub fn keep_range(&mut self, from_index: usize, to_index: usize) {
167 self.bits &= !0 << from_index;
168 self.bits &= !(!1 << to_index);
169 }
170}
171
172impl fmt::Debug for VariableSet {
173 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
174 write!(f, "VariableSet: {{")?;
175 let mut needs_comma = false;
176 for byte in 0..128 {
177 if self.is_set(byte) {
178 if needs_comma {
179 write!(f, ", ",)?;
180 }
181 write!(f, "{byte}")?;
182 needs_comma = true;
183 }
184 }
185 writeln!(f, "}}")?;
186 Ok(())
187 }
188}
189
190pub struct VariableSetIterator(VariableSet);
191
192impl Iterator for VariableSetIterator {
193 type Item = usize;
194
195 fn next(&mut self) -> Option<Self::Item> {
196 self.0.drain_next_ascending()
197 }
198}
199
200impl IntoIterator for VariableSet {
201 type Item = usize;
202 type IntoIter = VariableSetIterator;
203
204 fn into_iter(self) -> Self::IntoIter {
205 VariableSetIterator(self)
206 }
207}
208
209#[cfg(test)]
210mod tests {
211 use super::*;
212 use proptest::prelude::*;
213
214 #[test]
215 fn new_empty_is_empty() {
216 let set = VariableSet::new_empty();
217 assert!(set.is_empty());
218 }
219 #[test]
220 fn new_full_is_not_empty() {
221 let set = VariableSet::new_full();
222 assert!(!set.is_empty());
223 }
224 #[test]
225 fn after_set_is_not_empty() {
226 let mut set = VariableSet::new_empty();
227 set.set(5);
228 assert!(!set.is_empty());
229 }
230 #[test]
231 fn after_set_unset_is_empty() {
232 let mut set = VariableSet::new_empty();
233 set.set(5);
234 set.unset(5);
235 assert!(set.is_empty());
236 }
237 #[test]
238 fn after_set_is_set() {
239 let mut set = VariableSet::new_empty();
240 set.set(5);
241 assert!(set.is_set(5));
242 }
243 #[test]
244 fn after_unset_is_not_set() {
245 let mut set = VariableSet::new_full();
246 set.unset(5);
247 assert!(!set.is_set(5));
248 }
249 #[test]
250 fn find_first_set_none() {
251 let set = VariableSet::new_empty();
252 assert_eq!(None, set.find_first_set());
253 }
254 #[test]
255 fn find_last_set_none() {
256 let set = VariableSet::new_empty();
257 assert_eq!(None, set.find_last_set());
258 }
259 #[test]
260 fn superset_full_of_empty() {
261 let empty = VariableSet::new_empty();
262 let full = VariableSet::new_full();
263 assert!(full.is_superset_of(&empty));
264 }
265 #[test]
266 fn superset_not_empty_of_full() {
267 let empty = VariableSet::new_empty();
268 let full = VariableSet::new_full();
269 assert!(!empty.is_superset_of(&full));
270 }
271 #[test]
272 fn subset_empty_of_full() {
273 let empty = VariableSet::new_empty();
274 let full = VariableSet::new_full();
275 assert!(empty.is_subset_of(&full));
276 }
277 #[test]
278 fn subset_not_full_of_empty() {
279 let empty = VariableSet::new_empty();
280 let full = VariableSet::new_full();
281 assert!(!full.is_subset_of(&empty));
282 }
283 proptest! {
284 #[test]
285 fn find_first_set(n in 0..128usize) {
286 let mut set = VariableSet::new_empty();
287 set.set(n);
288 prop_assert_eq!(Some(n), set.find_first_set());
289 }
290 #[test]
291 fn find_last_set(n in 0..128usize) {
292 let mut set = VariableSet::new_empty();
293 set.set(n);
294 prop_assert_eq!(Some(n), set.find_last_set());
295 }
296 #[test]
297 fn drain_ascending_drains(n in 0..128usize) {
298 let mut set = VariableSet::new_empty();
299 set.set(n);
300 prop_assert_eq!(Some(n), set.drain_next_ascending());
301 prop_assert!(!set.is_set(n));
302 }
303 #[test]
304 fn drain_descending_drains(n in 0..128usize) {
305 let mut set = VariableSet::new_empty();
306 set.set(n);
307 prop_assert_eq!(Some(n), set.drain_next_descending());
308 prop_assert!(!set.is_set(n));
309 }
310 #[test]
311 fn intersect(n in 0..128usize, m in 0..128usize) {
312 let mut left = VariableSet::new_empty();
313 let mut right = VariableSet::new_empty();
314 left.set(n);
315 right.set(m);
316
317 let out = left.intersect(right);
318 prop_assert_eq!(n == m, out.is_set(n));
319 }
320 #[test]
321 fn union(n in 0..128usize, m in 0..128usize) {
322 let mut left = VariableSet::new_empty();
323 let mut right = VariableSet::new_empty();
324 left.set(n);
325 right.set(m);
326
327 let out = left.union(right);
328 prop_assert!(out.is_set(n));
329 prop_assert!(out.is_set(m));
330 }
331 #[test]
332 fn subtract(n in 0..128usize, m in 0..128usize) {
333 let mut left = VariableSet::new_empty();
334 let mut right = VariableSet::new_empty();
335 left.set(n);
336 right.set(m);
337
338 let out = left.subtract(right);
339 prop_assert_eq!(n != m, out.is_set(n));
340 }
341 #[test]
342 fn difference(n in 0..128usize, m in 0..128usize) {
343 let mut left = VariableSet::new_empty();
344 let mut right = VariableSet::new_empty();
345 left.set(n);
346 right.set(m);
347
348 let out = left.difference(right);
349 prop_assert_eq!(n != m, out.is_set(n));
350 prop_assert_eq!(n != m, out.is_set(m));
351 }
352 #[test]
353 fn complement(n in 0..128usize, m in 0..128usize) {
354 let mut input = VariableSet::new_empty();
355 input.set(n);
356
357 let out = input.complement();
358 prop_assert!(!out.is_set(n));
359 if n != m {
360 prop_assert!(out.is_set(m));
361 }
362 }
363 #[test]
364 fn keep_single(n in 0..128usize, m in 0..128usize) {
365 let mut set = VariableSet::new_full();
366 set.keep_single(n);
367 prop_assert!(set.is_set(n));
368 if n != m {
369 prop_assert!(!set.is_set(m));
370 }
371 }
372 #[test]
373 fn keep_range(from in 0..128usize, to in 0..128usize) {
374 let mut set = VariableSet::new_full();
375 set.keep_range(from, to);
376
377 for n in 0..128 {
378 prop_assert_eq!(from <= n && n <= to, set.is_set(n));
379 }
380 }
381 }
382}