rust_dense_bitset/
vec64impl.rs

1use crate::bitset::BitSet;
2use crate::u64impl::DenseBitSet;
3
4use std::cmp::{max, min};
5use std::fmt;
6use std::hash::{Hash, Hasher};
7
8/// Overload of &, &=, |, |=, ^, ^=, !, <<, <<=, >>, >>=
9use std::ops::{
10    BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Shl, ShlAssign, Shr,
11    ShrAssign,
12};
13
14/// Provides a dense `BitSet` implementation (only limited by available memory)
15///
16/// Internally, a `Vec<u64>` data structure is used to store information.
17///
18/// This structure implements `BitSet, Clone, Default, Debug, Hash, PartialEq, Eq` and bit operations.
19#[derive(Default, Clone)]
20pub struct DenseBitSetExtended {
21    state: Vec<u64>,
22    size: usize,
23}
24
25impl DenseBitSetExtended {
26    /// Returns a new empty `DenseBitsetExtended`
27    ///    
28    /// # Example
29    /// ```
30    /// # use rust_dense_bitset::DenseBitSetExtended;
31    /// let bs = DenseBitSetExtended::new();
32    /// ```
33    pub fn new() -> Self {
34        Self {
35            state: vec![],
36            size: 0,
37        }
38    }
39
40    /// Returns an empty `DenseBitsetExtended` with pre-allocated memory of `size` bits.
41    ///
42    /// This is useful to avoid additional allocations is situations where the bitset's
43    /// space requirements are known in advance.
44    ///
45    /// # Example
46    /// ```
47    /// # use rust_dense_bitset::{BitSet, DenseBitSetExtended};
48    /// let mut bs = DenseBitSetExtended::with_capacity(128);
49    /// bs.set_bit(127, true); // No additional allocation performed
50    /// ```
51    ///
52    pub fn with_capacity(size: usize) -> Self {
53        let state: Vec<u64> = Vec::with_capacity(1 + (size >> 6));
54        Self { state, size: 0 }
55    }
56
57    /// Returns a `DenseBitSetExtended` extending a given `DenseBitSet`.
58    ///
59    /// # Example
60    /// ```
61    /// # use rust_dense_bitset::{BitSet, DenseBitSet, DenseBitSetExtended};
62    /// let dbs = DenseBitSet::from_integer(0b111000111);
63    /// let dbse = DenseBitSetExtended::from_dense_bitset(dbs);
64    /// println!("{}", dbse.to_string())
65    /// ```
66    pub fn from_dense_bitset(dbs: DenseBitSet) -> Self {
67        let state = vec![dbs.to_integer()];
68        let size = 64;
69        Self { state, size }
70    }
71
72    /// Returns `true` if and only if all bits are set to `true`
73    pub fn all(&self) -> bool {
74        let l = self.state.len();
75        for i in 0..l - 1 {
76            if self.state[i] != u64::max_value() {
77                return false;
78            }
79        }
80        if self.size % 64 == 0 {
81            if self.state[l - 1] != u64::max_value() {
82                return false;
83            }
84        } else if self.state[l - 1] != ((1 << (self.size % 64)) - 1) {
85            return false;
86        }
87        true
88    }
89
90    /// Returns `true` if at least one bit is set to `true`
91    pub fn any(&self) -> bool {
92        for &s in &self.state {
93            if s > 0 {
94                return true;
95            }
96        }
97        false
98    }
99
100    /// Returns `true` if all the bits are set to `false`
101    pub fn none(&self) -> bool {
102        !self.any()
103    }
104
105    /// Returns the size (in bits) of the bitset
106    pub fn get_size(&self) -> usize {
107        self.size
108    }
109
110    /// Returns an integer representation of the bitsting starting at the given `position` with given `length` (little endian convention).
111    ///
112    /// Note: this method can extract up to 64 bits into an `u64`. For larger extractions, use `subset` instead.
113    ///
114    /// # Example
115    /// ```
116    /// # use rust_dense_bitset::{DenseBitSet, DenseBitSetExtended};
117    /// let dbs = DenseBitSet::from_integer(0b111000111);
118    /// let dbse = DenseBitSetExtended::from_dense_bitset(dbs);
119    /// println!("{}", dbse.extract_u64(2, 4)); // Extracts "0001" (displayed with leading zeros)
120    /// ```
121    ///
122    /// # Panics
123    ///
124    /// The function panics if `length` is zero
125    /// ```rust,should_panic
126    /// # use rust_dense_bitset::{DenseBitSet, DenseBitSetExtended};
127    /// # let dbs = DenseBitSet::from_integer(0b111000111);
128    /// # let dbse = DenseBitSetExtended::from_dense_bitset(dbs);
129    /// let panic_me = dbse.extract_u64(3, 0);
130    /// ```
131    pub fn extract_u64(&self, position: usize, length: usize) -> u64 {
132        assert!(
133            length <= 64,
134            "This implementation is currently limited to 64 bit bitsets."
135        );
136        assert!(length > 0, "Cannot extract a zero-width slice.");
137        if position >= self.size {
138            // The extraction is beyond any bit set to 1
139            return 0;
140        }
141
142        let idx = position >> 6;
143        let offset = position % 64;
144        let actual_length = if position + length > self.size {
145            self.size - position
146        } else {
147            length
148        };
149
150        if actual_length + offset < 64 {
151            // Remain within the boundary of an element
152            (self.get(idx) >> offset) & ((1 << actual_length) - 1)
153        } else if actual_length + offset == 64 {
154            // Special case to avoid masking overflow
155            self.get(idx) >> offset
156        } else {
157            // Possibly split between neighbour elements
158
159            // Number of bits to take from the next element
160            let remainder = actual_length + offset - 64;
161
162            let lsb = self.state[idx] >> offset;
163
164            if self.state.len() == idx + 1 {
165                // If there is no next element, assume it is zero
166                lsb
167            } else {
168                // Otherwise get the remaining bits and assemble the response
169                let msb = self.state[idx + 1] & ((1 << remainder) - 1);
170                (msb << (64 - offset)) | lsb
171            }
172        }
173    }
174
175    /// Returns a `DenseBitSetExtended` of given `length` whose bits are extracted from the given `position`.
176    ///
177    /// # Example
178    ///
179    /// ```
180    /// # use rust_dense_bitset::{BitSet, DenseBitSet, DenseBitSetExtended};
181    /// let dbs = DenseBitSet::from_integer(0b111000111);
182    /// let dbse = DenseBitSetExtended::from_dense_bitset(dbs);
183    /// println!("{}", dbse.subset(2, 4).to_string());
184    /// ```
185    pub fn subset(&self, position: usize, length: usize) -> Self {
186        if length == 0 {
187            return Self {
188                state: vec![],
189                size: 0,
190            };
191        }
192
193        let segments = 1 + ((length - 1) >> 6);
194        let mut state = vec![];
195
196        for l in 0..segments {
197            state.push(self.extract_u64(l * 64 + position, 64));
198        }
199        Self {
200            state,
201            size: length,
202        }
203    }
204
205    /// Inserts the first `length` bits of `other` at the given `position` in the current structure.
206    ///
207    ///  # Example
208    /// ```
209    /// # use rust_dense_bitset::{DenseBitSet, DenseBitSetExtended};
210    /// let mut bs = DenseBitSetExtended::new();
211    /// let bs2 =
212    ///    DenseBitSetExtended::from_dense_bitset(DenseBitSet::from_integer(0b1011011101111));
213    /// bs.insert(&bs2, 60, 13);
214    /// ```
215    pub fn insert(&mut self, other: &Self, position: usize, length: usize) {
216        let l = (length >> 6) + 1;
217        let size_before_insertion = self.size;
218        if length % 64 == 0 {
219            for i in 0..l {
220                self.insert_u64(other.state[i], position + i * 64, 64);
221            }
222        } else {
223            for i in 0..l - 1 {
224                self.insert_u64(other.state[i], position + i * 64, 64);
225            }
226            self.insert_u64(other.state[l - 1], position + (l - 1) * 64, length % 64);
227        }
228
229        self.size = max(size_before_insertion, position + length);
230    }
231
232    /// Inserts a `length`-bit integer as a bitset at the given `position`.
233    ///
234    /// # Example
235    /// ```
236    /// # use rust_dense_bitset::DenseBitSetExtended;
237    /// let mut bs = DenseBitSetExtended::new();
238    /// bs.insert_u64(0b1011011101111, 50, 64);
239    /// ```
240    pub fn insert_u64(&mut self, value: u64, position: usize, length: usize) {
241        let idx = position >> 6;
242        let offset = position % 64;
243
244        // First, resize the bitset if necessary
245        if 1 + ((position + length - 1) >> 6) > self.state.len() {
246            // We need to extend the bitset to accomodate this insertion
247            let num_seg = 1 + ((position + length - 1) >> 6) - self.state.len();
248
249            for _ in 0..num_seg {
250                self.state.push(0);
251            }
252        }
253        self.size = max(self.size, position + length);
254
255        // Second, perform the actual insertion
256        if offset == 0 && length == 64 {
257            // Easiest case
258            self.state[idx] = value;
259        } else if offset + length - 1 < 64 {
260            // Easy case: inserting fewer than 64 bits in an u64
261            let mut u = u64::max_value();
262            u ^= ((1 << length) - 1) << offset;
263            self.state[idx] &= u;
264            self.state[idx] |= value << offset;
265        } else {
266            // Not so easy case: we need to split `value` in twain, zero the appropriate bits in the
267            // two segments, and perform the insertion
268
269            let lsb = (value & ((1 << (64 - offset)) - 1)) << offset;
270            let mask_lsb = u64::max_value() >> (64 - offset);
271
272            let msb = value >> (64 - offset);
273            let mask_msb = u64::max_value() << ((position + length) % 64);
274
275            self.state[idx] = (self.state[idx] & mask_lsb) | lsb;
276            self.state[idx + 1] = (self.state[idx + 1] & mask_msb) | msb;
277        }
278    }
279
280    /// Returns a bit-reversed bitset.
281    ///
282    /// # Example
283    /// ```
284    /// # use rust_dense_bitset::{BitSet, DenseBitSet, DenseBitSetExtended};
285    /// let val = 66612301234;
286    /// let dbs = DenseBitSet::from_integer(val);
287    /// let ext_dbs = DenseBitSetExtended::from_dense_bitset(dbs);
288    /// println!("{}", dbs.to_string());
289    /// println!("{}", ext_dbs.reverse().to_string());
290    /// ```
291    pub fn reverse(&self) -> Self {
292        let mut state = vec![];
293        for &s in &self.state {
294            let bs = DenseBitSet::from_integer(s).reverse().to_integer();
295            state.push(bs);
296        }
297        state.reverse();
298        Self {
299            state,
300            size: self.size,
301        }
302    }
303
304    /// Returns a left rotation of the bitset by `shift` bits.
305    ///
306    /// Note: The bitset is extended by `shift` bits by this operation.
307    pub fn rotl(self, shift: usize) -> Self {
308        // Rotation is periodic
309        let shift_amount = shift % self.size;
310        let size_before_shift = self.size;
311
312        if shift_amount == 0 {
313            return self;
314        }
315
316        let mut shifted = (self.clone() << shift).subset(0, size_before_shift);
317        let extra = self.subset(size_before_shift - shift_amount, shift_amount);
318
319        shifted.insert(&extra, 0, shift_amount);
320
321        shifted
322    }
323
324    /// Returns a right rotation of the bitset by `shift` bits.
325    pub fn rotr(self, shift: usize) -> Self {
326        // Rotation is periodic
327        let shift_amount = shift % self.size;
328        let size_before_shift = self.size;
329
330        if shift_amount == 0 {
331            return self;
332        }
333
334        let extra = self.subset(0, shift_amount);
335        let mut shifted = self >> shift_amount;
336
337        shifted.insert(&extra, size_before_shift - shift_amount, shift_amount);
338
339        shifted
340    }
341
342    /// Constructs a `DenseBitSetExtended` from a provided `String`.
343    ///
344    /// # Example
345    /// ```
346    /// # use rust_dense_bitset::{DenseBitSetExtended};
347    /// let bs2 = DenseBitSetExtended::from_string(String::from("f8d5215a52b57ea0aeb294af576a0aeb"), 16);
348    /// ```
349    ///
350    /// # Panics
351    /// This function expects a radix between 2 and 32 included, and will otherwise panic.
352    /// This function will also panic if incorrect characters are provided.
353    pub fn from_string(s: String, radix: u32) -> Self {
354        assert!(
355            radix.is_power_of_two(),
356            "Only power of two radices are supported"
357        );
358        assert!(radix > 1, "Radix must be > 1");
359        assert!(radix <= 32, "Radix must be <= 32");
360
361        let log_radix = u64::from(radix).trailing_zeros();
362        let chunk_size = 64 / log_radix as usize;
363        let mut size = 0;
364
365        let mut state = vec![];
366        let mut cur = s;
367        while !cur.is_empty() {
368            if cur.len() > chunk_size {
369                let (ms, ls) = cur.split_at(cur.len() - chunk_size);
370                let val = u64::from_str_radix(ls, radix).expect("Error while parsing input.");
371                state.push(val);
372                cur = String::from(ms);
373                size += 64;
374            } else {
375                let val = u64::from_str_radix(&cur.to_string(), radix)
376                    .expect("Error while parsing input.");
377                state.push(val);
378                size += cur.len() * (log_radix as usize);
379                break;
380            }
381        }
382        Self { state, size }
383    }
384
385    /// Returns the position of the first set bit (little endian convention)
386    ///
387    /// # Example
388    /// ```
389    /// # use rust_dense_bitset::{DenseBitSet,DenseBitSetExtended};
390    /// let dbs = DenseBitSetExtended::from_dense_bitset( DenseBitSet::from_integer(256) ) << 12;
391    /// println!("{}", dbs.first_set());
392    /// ```
393    pub fn first_set(&self) -> usize {
394        for i in 0..self.state.len() {
395            let cur = self.state[i];
396            if cur != 0 {
397                return i * 64 + (cur.trailing_zeros() as usize);
398            }
399        }
400        self.size
401    }
402
403    fn get(&self, index: usize) -> u64 {
404        match index {
405            u if u < self.state.len() => self.state[u],
406            _ => 0,
407        }
408    }
409}
410
411/// This is an extended implementation of the `BitSet` trait. It dynamically resizes the bitset as necessary
412/// to accomodate growing or shrinking operations (e.g. left shifts) and is only limited by available memory.
413/// In practice however, we (arbitrarily) limited allocation to 64000 bits.
414///
415/// Note: The `BitSet` trait must be in scope in order to use methods from this trait.
416///
417/// Note: The `Copy` trait cannot be implemented for `DenseBitSetExtended` (for the same reasons avec `Vec`).
418impl BitSet for DenseBitSetExtended {
419    /// Sets the bit at index `position` to `value`.
420    fn set_bit(&mut self, position: usize, value: bool) {
421        let idx = position >> 6;
422        let offset = position % 64;
423
424        assert!(
425            idx < 1000,
426            "(Temporary?) We don't allow bitsets larger than 64k for now."
427        );
428
429        if idx >= self.state.len() {
430            if value {
431                // This triggers a resize, we only do it if we need to insert a 1
432                for _ in 0..=(idx - self.state.len()) {
433                    self.state.push(0);
434                }
435                self.state[idx] |= 1 << offset
436            }
437        // Note: To insert a zero, we do nothing, as the value is zero by default
438        } else if value {
439            self.state[idx] |= 1 << offset
440        } else {
441            self.state[idx] &= !(1 << offset)
442        }
443        if position >= self.size {
444            self.size = position + 1;
445        }
446    }
447
448    /// Get the bit at index `position`.
449    fn get_bit(&self, position: usize) -> bool {
450        if position > self.size {
451            return false;
452        }
453
454        let idx = position >> 6;
455        let offset = position % 64;
456
457        (self.state[idx] >> offset) & 1 == 1
458    }
459
460    /// Returns the bitset's Hamming weight (in other words, the number of bits set to true).
461    fn get_weight(&self) -> u32 {
462        let mut hw = 0;
463        for &s in &self.state {
464            hw += s.count_ones();
465        }
466        hw
467    }
468
469    /// This resets the bitset to its empty state.
470    fn reset(&mut self) {
471        self.state = vec![];
472        self.size = 0
473    }
474
475    /// Returns a representation of the bitset as a `String`.
476    fn to_string(self) -> String {
477        if self.state.is_empty() {
478            return format!("{:064b}", 0);
479        }
480
481        let mut bss = vec![];
482
483        if self.size % 64 == 0 {
484            for s in self.state {
485                bss.push(format!("{:064b}", s));
486            }
487        } else {
488            for i in 0..self.state.len() - 1 {
489                bss.push(format!("{:064b}", self.state[i]));
490            }
491            bss.push(format!(
492                "{:064b}",
493                self.state[self.state.len() - 1] & ((1 << (self.size % 64)) - 1)
494            ));
495        }
496        bss.reverse();
497        bss.join("")
498    }
499}
500
501impl fmt::Debug for DenseBitSetExtended {
502    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
503        let mut bss = String::new();
504
505        for i in 0..self.state.len() {
506            for j in 0..64 {
507                bss += if self.get_bit((self.state.len() - i - 1) * 64 + (63 - j)) {
508                    "1"
509                } else {
510                    "0"
511                };
512            }
513        }
514        write!(f, "0b{}", bss)
515    }
516}
517
518impl PartialEq for DenseBitSetExtended {
519    fn eq(&self, other: &Self) -> bool {
520        if self.size != other.size {
521            return false;
522        }
523        for i in 0..self.state.len() {
524            if self.state[i] != other.state[i] {
525                return false;
526            }
527        }
528        true
529    }
530}
531
532impl Hash for DenseBitSetExtended {
533    fn hash<H: Hasher>(&self, state: &mut H) {
534        for s in &self.state {
535            s.hash(state);
536        }
537    }
538}
539
540impl Eq for DenseBitSetExtended {}
541
542impl Not for DenseBitSetExtended {
543    type Output = Self;
544    fn not(self) -> Self {
545        let l = self.state.len();
546        let mut inv = Self {
547            state: Vec::with_capacity(l),
548            size: self.size,
549        };
550        for i in 0..l - 1 {
551            inv.state.push(!self.state[i])
552        }
553        if self.size % 64 == 0 {
554            inv.state.push(!self.state[l - 1]);
555        } else {
556            inv.state
557                .push((!self.state[l - 1]) & ((1 << (self.size % 64)) - 1));
558        }
559        inv
560    }
561}
562
563impl BitAnd for DenseBitSetExtended {
564    type Output = Self;
565    fn bitand(self, rhs: Self) -> Self {
566        let l = min(self.state.len(), rhs.state.len());
567        let mut v = Vec::with_capacity(l);
568
569        // Note: there is no need to go further because x & 0 == 0
570        for i in 0..l {
571            v.push(self.state[i] & rhs.state[i])
572        }
573
574        Self {
575            state: v,
576            size: min(self.size, rhs.size),
577        }
578    }
579}
580
581impl BitAndAssign for DenseBitSetExtended {
582    fn bitand_assign(&mut self, rhs: Self) {
583        // Note: there is no need to go further because x & 0 == 0
584        let l = min(self.state.len(), rhs.state.len());
585        for i in 0..l {
586            self.state[i] &= rhs.state[i];
587        }
588        self.size = min(self.size, rhs.size);
589    }
590}
591
592impl BitOr for DenseBitSetExtended {
593    type Output = Self;
594    fn bitor(self, rhs: Self) -> Self {
595        let l = max(self.state.len(), rhs.state.len());
596        let mut v = Vec::with_capacity(l);
597
598        for i in 0..l {
599            if i < self.state.len() && i < rhs.state.len() {
600                // x | y
601                v.push(self.state[i] | rhs.state[i])
602            } else if i >= self.state.len() {
603                // x | 0 == x
604                v.push(rhs.state[i])
605            } else {
606                // x | 0 == x
607                v.push(self.state[i])
608            }
609        }
610
611        Self {
612            state: v,
613            size: max(self.size, rhs.size),
614        }
615    }
616}
617
618impl BitOrAssign for DenseBitSetExtended {
619    fn bitor_assign(&mut self, rhs: Self) {
620        let l = max(self.state.len(), rhs.state.len());
621        for i in 0..l {
622            if i < self.state.len() && i < rhs.state.len() {
623                // x | y
624                self.state[i] |= rhs.state[i]
625            } else if i >= self.state.len() {
626                // x | 0 == x
627                self.state[i] = rhs.state[i]
628            }
629            // if rhs.state[i] == 0 we do nothing because x | 0 == x
630        }
631    }
632}
633
634impl BitXor for DenseBitSetExtended {
635    type Output = Self;
636    fn bitxor(self, rhs: Self) -> Self {
637        let l = max(self.state.len(), rhs.state.len());
638        let mut v = Vec::with_capacity(l);
639
640        for i in 0..l {
641            if i < self.state.len() && i < rhs.state.len() {
642                // x ^ y
643                v.push(self.state[i] ^ rhs.state[i])
644            } else if i >= self.state.len() {
645                // x ^ 0 == x
646                v.push(rhs.state[i])
647            } else {
648                // x ^ 0 == x
649                v.push(self.state[i])
650            }
651        }
652
653        Self {
654            state: v,
655            size: max(self.size, rhs.size),
656        }
657    }
658}
659
660impl BitXorAssign for DenseBitSetExtended {
661    fn bitxor_assign(&mut self, rhs: Self) {
662        let l = max(self.state.len(), rhs.state.len());
663        for i in 0..l {
664            if i < self.state.len() && i < rhs.state.len() {
665                // x ^ y
666                self.state[i] ^= rhs.state[i]
667            } else if i >= self.state.len() {
668                // x ^ 0 == x
669                self.state[i] = rhs.state[i]
670            }
671            // if rhs.state[i] == 0 we do nothing because x ^ 0 == x
672        }
673    }
674}
675
676impl Shl<usize> for DenseBitSetExtended {
677    type Output = Self;
678    fn shl(self, rhs: usize) -> Self {
679        let mut v = DenseBitSetExtended::with_capacity(self.size + rhs);
680
681        // Note: this may not be the most efficient implementation
682        for i in 0..self.size {
683            let source = i;
684            let dest = i + rhs;
685            v.set_bit(dest, self.get_bit(source));
686        }
687        v
688    }
689}
690
691impl ShlAssign<usize> for DenseBitSetExtended {
692    fn shl_assign(&mut self, rhs: usize) {
693        let trailing_zeros = rhs >> 6;
694        let actual_shift = rhs % 64;
695        if rhs > (self.state.len() * 64 - self.size) {
696            self.state.push(0);
697        }
698        let l = self.state.len();
699        for i in 0..(l - 1) {
700            self.state[l - i - 1] = (self.state[l - i - 1] << actual_shift)
701                | (self.state[l - i - 2] >> (64 - actual_shift))
702        }
703        self.state[0] <<= actual_shift;
704        for _ in 0..trailing_zeros {
705            self.state.insert(0, 0);
706        }
707        self.size += rhs;
708    }
709}
710
711impl Shr<usize> for DenseBitSetExtended {
712    type Output = Self;
713    fn shr(self, rhs: usize) -> Self {
714        if rhs >= self.size {
715            Self {
716                state: vec![],
717                size: 0,
718            }
719        } else {
720            let mut v = DenseBitSetExtended::with_capacity(self.size - rhs);
721
722            // Note: this may not be the most efficient implementation
723            for i in 0..(self.size - rhs) {
724                let source = i + rhs;
725                let dest = i;
726                v.set_bit(dest, self.get_bit(source));
727            }
728
729            v
730        }
731    }
732}
733
734impl ShrAssign<usize> for DenseBitSetExtended {
735    fn shr_assign(&mut self, rhs: usize) {
736        if rhs >= self.size {
737            self.reset();
738        }
739        let to_drop = rhs >> 6;
740        let actual_shift = rhs % 64;
741        for _ in 0..to_drop {
742            self.state.remove(0);
743        }
744        let l = self.state.len();
745        for i in 0..(l - 1) {
746            self.state[i] =
747                (self.state[i] >> actual_shift) | (self.state[i + 1] << (64 - actual_shift))
748        }
749        self.state[l - 1] >>= actual_shift;
750        self.size -= rhs;
751    }
752}