1use crate::ids::Id;
3
4pub const NUM_BITS: usize = 256;
5const BITS_PER_BYTES: usize = 8;
6
7pub fn equal_subset(start: usize, stop: usize, id1: &Id, id2: &Id) -> bool {
11    if stop == 0 {
12        return true;
13    }
14
15    let stop = stop - 1; if start > stop {
17        return true;
18    }
19    if stop >= NUM_BITS {
20        return false;
21    }
22
23    let start_index = start / BITS_PER_BYTES;
24    let stop_index = stop / BITS_PER_BYTES;
25
26    if start_index + 1 < stop_index
27        && id1.0[(start_index + 1)..stop_index] != id2.0[(start_index + 1)..stop_index]
28    {
29        return false;
30    }
31
32    let start_bit = start % BITS_PER_BYTES; let stop_bit = stop % BITS_PER_BYTES; let start_mask: i32 = -1 << start_bit; let stop_mask: i32 = (1 << (stop_bit + 1)) - 1; if start_index == stop_index {
39        let mask = start_mask & stop_mask;
41
42        let b1 = mask & id1.0[start_index] as i32;
43        let b2 = mask & id2.0[start_index] as i32;
44
45        return b1 == b2;
46    }
47
48    let start1 = start_mask & id1.0[start_index] as i32;
49    let start2 = start_mask & id2.0[start_index] as i32;
50
51    let stop1 = stop_mask & id1.0[stop_index] as i32;
52    let stop2 = stop_mask & id2.0[stop_index] as i32;
53
54    start1 == start2 && stop1 == stop2
55}
56
57#[test]
59fn test_equal_subset() {
60    let id1 = Id::from_slice(&[0xf0, 0x0f]);
62    let id2 = Id::from_slice(&[0xf0, 0x1f]);
63
64    assert!(equal_subset(0, 12, &id1, &id2));
78    assert!(!equal_subset(0, 13, &id1, &id2));
79
80    let id1 = Id::from_slice(&[0x1f, 0xf8]);
82    let id2 = Id::from_slice(&[0x10, 0x08]);
83
84    assert!(equal_subset(4, 12, &id1, &id2));
98    assert!(!equal_subset(4, 13, &id1, &id2));
99}
100
101#[test]
104fn test_equal_subset_same_byte() {
105    let id1 = Id::from_slice(&[0x18]);
106    let id2 = Id::from_slice(&[0xfc]);
107
108    assert!(equal_subset(3, 5, &id1, &id2));
122    assert!(!equal_subset(2, 5, &id1, &id2));
123    assert!(!equal_subset(3, 6, &id1, &id2));
124}
125
126#[test]
129fn test_equal_subset_bad_middle() {
130    let id1 = Id::from_slice(&[0x18, 0xe8, 0x55]);
131    let id2 = Id::from_slice(&[0x18, 0x8e, 0x55]);
132
133    assert!(!equal_subset(0, 8 * 3, &id1, &id2));
147}
148
149#[test]
152fn test_equal_subset_out_of_bounds() {
153    let id1 = Id::from_slice(&[0x18, 0xe8, 0x55]);
154    let id2 = Id::from_slice(&[0x18, 0x8e, 0x55]);
155    assert!(!equal_subset(0, 500, &id1, &id2));
156}
157
158pub fn first_difference_subset(start: usize, stop: usize, id1: &Id, id2: &Id) -> (usize, bool) {
162    if stop == 0 {
163        return (0, false);
164    }
165
166    let stop = stop - 1; if start > stop {
168        return (0, false);
169    }
170    if stop >= NUM_BITS {
171        return (0, false);
172    }
173
174    let start_index = start / BITS_PER_BYTES;
175    let stop_index = stop / BITS_PER_BYTES;
176
177    let start_bit = start % BITS_PER_BYTES; let stop_bit = stop % BITS_PER_BYTES; let start_mask: i32 = -1 << start_bit; let stop_mask: i32 = (1 << (stop_bit + 1)) - 1; if start_index == stop_index {
184        let mask = start_mask & stop_mask;
186
187        let b1 = mask & id1.0[start_index] as i32;
188        let b2 = mask & id2.0[start_index] as i32;
189        if b1 == b2 {
190            return (0, false);
191        }
192
193        let bd = b1 ^ b2;
194        return (
195            bd.trailing_zeros() as usize + start_index * BITS_PER_BYTES,
196            true,
197        );
198    }
199
200    let start1 = start_mask & id1.0[start_index] as i32;
201    let start2 = start_mask & id2.0[start_index] as i32;
202    if start1 != start2 {
203        let bd = start1 ^ start2;
204        return (
205            bd.trailing_zeros() as usize + start_index * BITS_PER_BYTES,
206            true,
207        );
208    }
209
210    for idx in (start_index + 1)..stop_index {
212        let b1 = id1.0[idx];
213        let b2 = id2.0[idx];
214        if b1 != b2 {
215            let bd = b1 ^ b2;
216            return (bd.trailing_zeros() as usize + idx * BITS_PER_BYTES, true);
217        }
218    }
219
220    let stop1 = stop_mask & id1.0[stop_index] as i32;
221    let stop2 = stop_mask & id2.0[stop_index] as i32;
222    if stop1 != stop2 {
223        let bd = stop1 ^ stop2;
224        return (
225            bd.trailing_zeros() as usize + stop_index * BITS_PER_BYTES,
226            true,
227        );
228    }
229
230    (0, false) }
232
233#[test]
235fn test_first_difference_subset() {
236    let id1 = Id::from_slice(&[0xf0, 0x0f]);
238    let id2 = Id::from_slice(&[0xf0, 0x1f]);
239
240    assert_eq!(first_difference_subset(0, 12, &id1, &id2), (0, false));
254    assert_eq!(first_difference_subset(0, 13, &id1, &id2), (12, true));
255
256    let id1 = Id::from_slice(&[0x10]);
258    let id2 = Id::from_slice(&[0x00]);
259
260    assert_eq!(first_difference_subset(0, 4, &id1, &id2), (0, false));
274    assert_eq!(first_difference_subset(0, 5, &id1, &id2), (4, true));
275}
276
277#[test]
280fn test_first_difference_equal_byte_5() {
281    let id1 = Id::from_slice(&[0x20]);
282    let id2 = Id::from_slice(&[0x00]);
283
284    assert_eq!(first_difference_subset(0, 5, &id1, &id2), (0, false));
298    assert_eq!(first_difference_subset(0, 6, &id1, &id2), (5, true));
299}
300
301#[test]
304fn test_first_difference_subset_middle() {
305    let id1 = Id::from_slice(&[0xf0, 0x0f, 0x11]);
306    let id2 = Id::from_slice(&[0xf0, 0x1f, 0xff]);
307
308    assert_eq!(first_difference_subset(0, 24, &id1, &id2), (12, true));
322    assert_eq!(first_difference_subset(0, 12, &id1, &id2), (0, false));
323}
324
325#[test]
328fn test_first_difference_vacuous() {
329    let id1 = Id::from_slice(&[0xf0, 0x0f, 0x11]);
330    let id2 = Id::from_slice(&[0xf0, 0x1f, 0xff]);
331
332    assert_eq!(first_difference_subset(0, 0, &id1, &id2), (0, false));
346}
347
348#[derive(
349    std::clone::Clone,
350    std::cmp::Eq,
351    std::cmp::Ord,
352    std::cmp::PartialEq,
353    std::cmp::PartialOrd,
354    std::fmt::Debug,
355    std::hash::Hash,
356)]
357pub enum Bit {
358    Zero,
359    One,
360}
361
362impl std::convert::From<usize> for Bit {
363    fn from(v: usize) -> Self {
364        assert!(v <= 1);
365        match v {
366            0 => Bit::Zero,
367            1 => Bit::One,
368            _ => panic!("unexpected bit value {}", v),
369        }
370    }
371}
372
373impl Bit {
374    pub fn as_usize(&self) -> usize {
376        match self {
377            Bit::Zero => 0,
378            Bit::One => 1,
379        }
380    }
381}
382
383#[derive(Debug, Clone, Copy, Eq, PartialEq)]
387pub struct Set64(u64);
388
389impl Set64 {
390    pub fn new() -> Self {
391        Self(0_u64)
392    }
393
394    pub fn add(&mut self, i: u64) {
396        self.0 |= 1 << i;
397    }
398
399    pub fn union(&mut self, s: Set64) {
401        self.0 |= s.0;
402    }
403
404    pub fn intersection(&mut self, s: Set64) {
406        self.0 &= s.0;
407    }
408
409    pub fn difference(&mut self, s: Set64) {
411        self.0 &= !(s.0);
413    }
414
415    pub fn remove(&mut self, i: u64) {
417        self.0 &= !(1 << i);
419    }
420
421    pub fn clear(&mut self) {
423        self.0 = 0;
424    }
425
426    pub fn contains(&self, i: u64) -> bool {
428        (self.0 & (1 << i)) != 0
429    }
430
431    pub fn len(&self) -> u32 {
433        u64::count_ones(self.0)
435    }
436
437    pub fn is_empty(&self) -> bool {
439        self.len() == 0
440    }
441}
442
443impl Default for Set64 {
444    fn default() -> Self {
445        Self::new()
446    }
447}
448
449impl std::fmt::Display for Set64 {
453    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
454        write!(f, "{:#16x}", self.0)
455    }
456}
457
458#[test]
460fn test_bit_set() {
461    let mut bs1 = Set64::new();
462    assert!(bs1.is_empty());
463
464    bs1.add(5);
465    assert!(bs1.len() == 1);
466    assert!(bs1.contains(5));
467
468    bs1.add(10);
469    assert!(bs1.len() == 2);
470    assert!(bs1.contains(5));
471    assert!(bs1.contains(10));
472
473    bs1.add(10);
474    assert!(bs1.len() == 2);
475    assert!(bs1.contains(5));
476    assert!(bs1.contains(10));
477
478    let mut bs2 = Set64::new();
479    assert!(bs2.is_empty());
480
481    bs2.add(0);
482    assert!(bs2.len() == 1);
483    assert!(bs2.contains(0));
484
485    bs2.union(bs1);
486    assert!(bs1.len() == 2);
487    assert!(bs1.contains(5));
488    assert!(bs1.contains(10));
489    assert!(bs2.len() == 3);
490    assert!(bs2.contains(0));
491    assert!(bs2.contains(5));
492    assert!(bs2.contains(10));
493
494    bs1.clear();
495    assert!(bs1.is_empty());
496    assert!(bs2.len() == 3);
497    assert!(bs2.contains(0));
498    assert!(bs2.contains(5));
499    assert!(bs2.contains(10));
500
501    bs1.add(63);
502    assert!(bs1.len() == 1);
503    assert!(bs1.contains(63));
504
505    bs1.add(1);
506    assert!(bs1.len() == 2);
507    assert!(bs1.contains(1));
508    assert!(bs1.contains(63));
509
510    bs1.remove(63);
511    assert!(bs1.len() == 1);
512    assert!(bs1.contains(1));
513
514    let mut bs3 = Set64::new();
515    bs3.add(0);
516    bs3.add(2);
517    bs3.add(5);
518
519    let mut bs4 = Set64::new();
520    bs4.add(2);
521    bs4.add(5);
522
523    bs3.intersection(bs4);
524
525    assert!(bs3.len() == 2);
526    assert!(bs3.contains(2));
527    assert!(bs3.contains(5));
528    assert!(bs4.len() == 2);
529    assert!(bs4.contains(2));
530    assert!(bs4.contains(5));
531
532    let mut bs5 = Set64::new();
533    bs5.add(7);
534    bs5.add(11);
535    bs5.add(9);
536
537    let mut bs6 = Set64::new();
538    bs6.add(9);
539    bs6.add(11);
540
541    bs5.difference(bs6);
542
543    assert!(bs5.len() == 1);
544    assert!(bs5.contains(7));
545    assert!(bs6.len() == 2);
546    assert!(bs6.contains(9));
547    assert!(bs6.contains(11));
548}