Skip to main content

BitSet

Struct BitSet 

Source
pub struct BitSet {
    size: usize,
    bits: Vec<Block>,
}

Fields§

§size: usize§bits: Vec<Block>

Implementations§

Source§

impl BitSet

Source

pub fn new(size: usize) -> Self

Examples found in repository?
crates/competitive/src/math/bit_matrix.rs (line 23)
20    pub fn zeros(shape: (usize, usize)) -> Self {
21        Self {
22            shape,
23            data: vec![BitSet::new(shape.1); shape.0],
24        }
25    }
26
27    pub fn from_vec(data: Vec<BitSet>) -> Self {
28        let shape = (data.len(), data.first().map_or(0, BitSet::len));
29        assert!(data.iter().all(|row| row.len() == shape.1));
30        Self { shape, data }
31    }
32
33    pub fn new_with(shape: (usize, usize), mut f: impl FnMut(usize, usize) -> bool) -> Self {
34        let mut a = Self::zeros(shape);
35        for (i, row) in a.data.iter_mut().enumerate() {
36            for (w, word) in row.words_mut().iter_mut().enumerate() {
37                for j in w * 64..shape.1.min((w + 1) * 64) {
38                    *word |= u64::from(f(i, j)) << (j & 63);
39                }
40            }
41        }
42        a
43    }
44
45    pub fn eye(shape: (usize, usize)) -> Self {
46        let mut a = Self::zeros(shape);
47        for i in 0..shape.0.min(shape.1) {
48            a[i].set(i, true);
49        }
50        a
51    }
52
53    pub fn transpose(&self) -> Self {
54        let mut a = Self::zeros((self.shape.1, self.shape.0));
55        for (i, row) in self.data.iter().enumerate() {
56            for j in row.iter_ones() {
57                a[j].set(i, true);
58            }
59        }
60        a
61    }
62
63    /// Replaces the matrix with reduced row echelon form and returns its pivot columns.
64    pub fn row_reduction(&mut self) -> Vec<usize> {
65        self.eliminate(self.shape.1, true, false)
66    }
67
68    /// Replaces the matrix with row echelon form and returns its rank.
69    pub fn rank(&mut self) -> usize {
70        self.eliminate(self.shape.1, false, false).len()
71    }
72
73    /// Computes the determinant in place. The matrix must be square.
74    pub fn determinant(&mut self) -> bool {
75        assert_eq!(self.shape.0, self.shape.1);
76        self.eliminate(self.shape.1, false, true).len() == self.shape.0
77    }
78
79    /// Returns the inverse, or `None` if singular. The matrix must be square.
80    pub fn inverse(&self) -> Option<Self> {
81        let (n, m) = self.shape;
82        assert_eq!(n, m);
83        let mut a = Self::zeros((n, 2 * n));
84        for i in 0..n {
85            a[i].words_mut()[..self[i].words().len()].copy_from_slice(self[i].words());
86            a[i].set(n + i, true);
87        }
88        if a.eliminate(n, true, true).len() != n {
89            return None;
90        }
91        for row in &mut a.data {
92            *row >>= n;
93        }
94        let mut inverse = Self::zeros((n, n));
95        for (row, source) in inverse.data.iter_mut().zip(&a.data) {
96            let len = row.words().len();
97            row.words_mut().copy_from_slice(&source.words()[..len]);
98        }
99        Some(inverse)
100    }
101
102    /// Returns a particular solution and a basis of the kernel, or `None` if inconsistent.
103    /// `b.len()` must equal the number of rows.
104    pub fn solve_system_of_linear_equations(&self, b: &BitSet) -> Option<BitMatrixSolution> {
105        let (n, m) = self.shape;
106        assert_eq!(b.len(), n);
107        let mut a = Self::zeros((n, m + 1));
108        for i in 0..n {
109            a[i].words_mut()[..self[i].words().len()].copy_from_slice(self[i].words());
110            a[i].set(m, b.get(i));
111        }
112        let pivots = a.eliminate(m, true, false);
113        if a.data[pivots.len()..].iter().any(|row| row.get(m)) {
114            return None;
115        }
116        let mut particular = BitSet::new(m);
117        let mut free = BitSet::ones(m);
118        for (i, &c) in pivots.iter().enumerate() {
119            particular.set(c, a[i].get(m));
120            free.set(c, false);
121        }
122        let columns: Vec<_> = free.iter_ones().collect();
123        let mut basis: Vec<_> = columns
124            .iter()
125            .map(|&c| {
126                let mut row = BitSet::new(m);
127                row.set(c, true);
128                row
129            })
130            .collect();
131        for (i, &p) in pivots.iter().enumerate() {
132            for (row, &c) in basis.iter_mut().zip(&columns) {
133                row.words_mut()[p / 64] |= u64::from(a[i].get(c)) << (p & 63);
134            }
135        }
136        Some(BitMatrixSolution { particular, basis })
137    }
138
139    pub fn pow(self, mut n: usize) -> Self {
140        assert_eq!(self.shape.0, self.shape.1);
141        let mut result = Self::eye(self.shape);
142        let mut a = self;
143        while n != 0 {
144            if n & 1 != 0 {
145                result = &result * &a;
146            }
147            n >>= 1;
148            if n != 0 {
149                a = &a * &a;
150            }
151        }
152        result
153    }
154
155    fn eliminate(&mut self, cols: usize, full: bool, require_full_rank: bool) -> Vec<usize> {
156        #[cfg(target_arch = "x86_64")]
157        match simd_backend() {
158            // SAFETY: the dispatcher checks the required CPU features.
159            SimdBackend::Avx512 => {
160                return unsafe { self.eliminate_avx512(cols, full, require_full_rank) };
161            }
162            // SAFETY: the dispatcher checks AVX2 support.
163            SimdBackend::Avx2 => {
164                return unsafe { self.eliminate_avx2(cols, full, require_full_rank) };
165            }
166            SimdBackend::Scalar => {}
167        }
168        self.eliminate_impl(cols, full, require_full_rank)
169    }
170
171    // Inlined into each target-feature entry point to vectorize the row operations.
172    #[inline(always)]
173    fn eliminate_impl(&mut self, cols: usize, full: bool, require_full_rank: bool) -> Vec<usize> {
174        let n = self.shape.0;
175        let mut pivots = Vec::with_capacity(n.min(cols));
176        if n < 32 {
177            let mut c = 0;
178            while c < cols {
179                let r = pivots.len();
180                if r == n {
181                    break;
182                }
183                let Some(p) = (r..n).find(|&i| self[i].get(c)) else {
184                    if require_full_rank {
185                        return pivots;
186                    }
187                    c = self.next_column(r, c + 1, cols);
188                    continue;
189                };
190                self.data.swap(r, p);
191                let (upper, lower) = self.data.split_at_mut(r);
192                let (pivot, lower) = lower.split_first_mut().unwrap();
193                for row in lower
194                    .iter_mut()
195                    .chain(upper.iter_mut().take(if full { r } else { 0 }))
196                {
197                    if row.get(c) {
198                        xor(&mut row.words_mut()[c / 64..], &pivot.words()[c / 64..]);
199                    }
200                }
201                pivots.push(c);
202                c += 1;
203            }
204            return pivots;
205        }
206        // Eliminating a shared leading coefficient preserves the two-coefficient bound.
207        if self
208            .data
209            .iter()
210            .all(|row| row.iter_ones().take_while(|&c| c < cols).take(3).count() <= 2)
211        {
212            return self.eliminate_sparse(cols, full, require_full_rank);
213        }
214        let block: usize = if n < 512 {
215            4
216        } else if n < 1536 {
217            8
218        } else {
219            32
220        };
221        let mut table = vec![BitSet::new(self.shape.1); (1 << block.min(8)) * block.div_ceil(8)];
222        let mut reduced = vec![0; n];
223        let mut start = 0;
224        while start < cols {
225            let first = pivots.len();
226            let word = start / 64;
227            reduced.fill(first);
228            let end = cols.min(start + block);
229            let mut c = start;
230            while c < end {
231                let r = pivots.len();
232                let mut pivot = None;
233                for (i, reduced) in reduced.iter_mut().enumerate().skip(r) {
234                    let (upper, lower) = self.data.split_at_mut(i);
235                    let row = &mut lower[0];
236                    for p in *reduced..r {
237                        if row.get(pivots[p]) {
238                            xor(&mut row.words_mut()[word..], &upper[p].words()[word..]);
239                        }
240                    }
241                    *reduced = r;
242                    if row.get(c) {
243                        pivot = Some(i);
244                        break;
245                    }
246                }
247                if let Some(p) = pivot {
248                    self.data.swap(r, p);
249                    reduced.swap(r, p);
250                    pivots.push(c);
251                    c += 1;
252                } else if require_full_rank {
253                    return pivots;
254                } else {
255                    c = self.next_column(r, c + 1, end);
256                }
257            }
258            let rank = pivots.len();
259            if first == rank {
260                let next = self.next_column(rank, start + block, cols);
261                if next == cols {
262                    break;
263                }
264                start = next / block * block;
265                continue;
266            }
267            // Make the panel's pivot columns an identity matrix before indexing its table.
268            for r in (first..rank).rev() {
269                let (upper, lower) = self.data.split_at_mut(r);
270                for row in &mut upper[first..] {
271                    if row.get(pivots[r]) {
272                        xor(&mut row.words_mut()[word..], &lower[0].words()[word..]);
273                    }
274                }
275            }
276            let mut indices = [[0usize; 256]; 4];
277            let mut masks = [0usize; 4];
278            for group in 0..block.div_ceil(8) {
279                let mut keys = [0usize; 256];
280                let mut count = 0;
281                for (row, &c) in pivots[first..].iter().enumerate() {
282                    if (c - start) / 8 != group {
283                        continue;
284                    }
285                    let half = 1 << count;
286                    count += 1;
287                    for index in 0..half {
288                        keys[index + half] = keys[index] | (1 << ((c - start) % 8));
289                        let (lower, upper) = table.split_at_mut(group * 256 + index + half);
290                        let target = &mut upper[0].words_mut()[word..];
291                        let source = &lower[group * 256 + index].words()[word..];
292                        let pivot = &self[first + row].words()[word..];
293                        for ((x, y), z) in target.iter_mut().zip(source).zip(pivot) {
294                            *x = y ^ z;
295                        }
296                    }
297                }
298                masks[group] = keys[(1 << count) - 1];
299                for (i, &key) in keys[..1 << count].iter().enumerate() {
300                    indices[group][key] = i;
301                }
302            }
303            for i in (rank..n).chain(0..if full { first } else { 0 }) {
304                let key = (self[i].words()[word] >> (start & 63)) as usize;
305                let x = indices[0][key & masks[0]];
306                if block <= 8 {
307                    if x != 0 {
308                        xor(&mut self[i].words_mut()[word..], &table[x].words()[word..]);
309                    }
310                    continue;
311                }
312                let y = indices[1][(key >> 8) & masks[1]];
313                let z = indices[2][(key >> 16) & masks[2]];
314                let w = indices[3][(key >> 24) & masks[3]];
315                if x | y | z | w != 0 {
316                    let p = &table[x].words()[word..];
317                    let q = &table[256 + y].words()[word..];
318                    let r = &table[512 + z].words()[word..];
319                    let s = &table[768 + w].words()[word..];
320                    for ((((x, y), z), r), s) in self[i].words_mut()[word..]
321                        .iter_mut()
322                        .zip(p)
323                        .zip(q)
324                        .zip(r)
325                        .zip(s)
326                    {
327                        *x ^= y ^ z ^ r ^ s;
328                    }
329                }
330            }
331            if rank == n {
332                break;
333            }
334            start += block;
335        }
336        pivots
337    }
338
339    fn next_column(&self, row: usize, mut start: usize, cols: usize) -> usize {
340        while start < cols {
341            let word = start / 64;
342            let bits = self.data[row..]
343                .iter()
344                .fold(0, |x, row| x | row.words()[word])
345                & (u64::MAX << (start & 63));
346            if bits != 0 {
347                return (word * 64 + bits.trailing_zeros() as usize).min(cols);
348            }
349            start = (word + 1) * 64;
350        }
351        cols
352    }
353
354    #[inline(always)]
355    fn eliminate_sparse(&mut self, cols: usize, full: bool, require_full_rank: bool) -> Vec<usize> {
356        let n = self.shape.0;
357        let mut basis = vec![n; cols];
358        let mut pivots = Vec::new();
359        for i in 0..n {
360            loop {
361                let Some(c) = self[i].iter_ones().next().filter(|&c| c < cols) else {
362                    if require_full_rank {
363                        return pivots;
364                    }
365                    break;
366                };
367                if basis[c] == n {
368                    basis[c] = i;
369                    pivots.push(c);
370                    break;
371                }
372                let (upper, lower) = self.data.split_at_mut(i);
373                xor(
374                    &mut lower[0].words_mut()[c / 64..],
375                    &upper[basis[c]].words()[c / 64..],
376                );
377            }
378        }
379        pivots.sort_unstable();
380        self.data
381            .sort_by_cached_key(|row| row.iter_ones().next().filter(|&c| c < cols).unwrap_or(cols));
382        if full {
383            for (i, &c) in pivots.iter().enumerate() {
384                basis[c] = i;
385            }
386            for i in (0..pivots.len()).rev() {
387                let next = self[i].iter_ones().take_while(|&c| c < cols).nth(1);
388                if let Some(c) = next
389                    && basis[c] != n
390                {
391                    let (upper, lower) = self.data.split_at_mut(basis[c]);
392                    xor(
393                        &mut upper[i].words_mut()[c / 64..],
394                        &lower[0].words()[c / 64..],
395                    );
396                }
397            }
398        }
399        pivots
400    }
401
402    #[inline(always)]
403    fn mul_impl(&self, rhs: &Self) -> Self {
404        let mut result = Self::zeros((self.shape.0, rhs.shape.1));
405        let ones = self.data.iter().map(BitSet::count_ones).sum::<u64>();
406        let size = self.shape.0 as u64 * self.shape.1 as u64;
407        if self.shape.0 < 256 || self.shape.1 < 32 || ones <= size / 8 {
408            for (a, c) in self.data.iter().zip(&mut result.data) {
409                for j in a.iter_ones() {
410                    xor(c.words_mut(), rhs[j].words());
411                }
412            }
413            return result;
414        }
415        if size - ones <= size / 8 {
416            let mut sum = BitSet::new(rhs.shape.1);
417            for row in &rhs.data {
418                sum ^= row;
419            }
420            for (a, c) in self.data.iter().zip(&mut result.data) {
421                c.words_mut().copy_from_slice(sum.words());
422                for j in (!a.clone()).iter_ones() {
423                    xor(c.words_mut(), rhs[j].words());
424                }
425            }
426            return result;
427        }
428        let width = rhs.shape.1.div_ceil(64);
429        if width == 0 {
430            return result;
431        }
432
433        // Separate the table groups by a cache line to avoid mapping them to the same sets.
434        let group = 256 * width + 8;
435        let mut storage = BitSet::new(8 * group * 64);
436        let table = storage.words_mut();
437        for start in (0..self.shape.1).step_by(64) {
438            for (t, table) in table.chunks_exact_mut(group).enumerate() {
439                let col = start + t * 8;
440                for bit in 0..self.shape.1.saturating_sub(col).min(8) {
441                    let row = rhs[col + bit].words();
442                    let half = (1 << bit) * width;
443                    let (lower, upper) = table.split_at_mut(half);
444                    for (source, dest) in
445                        lower.chunks_exact(width).zip(upper.chunks_exact_mut(width))
446                    {
447                        for ((x, y), z) in dest.iter_mut().zip(source).zip(row) {
448                            *x = y ^ z;
449                        }
450                    }
451                }
452            }
453            for (a, c) in self.data.iter().zip(&mut result.data) {
454                let key = a.words()[start / 64];
455                let offset = (key & 255) as usize * width;
456                let p0 = &table[offset..offset + width];
457                let offset = group + (key >> 8 & 255) as usize * width;
458                let p1 = &table[offset..offset + width];
459                let offset = 2 * group + (key >> 16 & 255) as usize * width;
460                let p2 = &table[offset..offset + width];
461                let offset = 3 * group + (key >> 24 & 255) as usize * width;
462                let p3 = &table[offset..offset + width];
463                let offset = 4 * group + (key >> 32 & 255) as usize * width;
464                let p4 = &table[offset..offset + width];
465                let offset = 5 * group + (key >> 40 & 255) as usize * width;
466                let p5 = &table[offset..offset + width];
467                let offset = 6 * group + (key >> 48 & 255) as usize * width;
468                let p6 = &table[offset..offset + width];
469                let offset = 7 * group + (key >> 56 & 255) as usize * width;
470                let p7 = &table[offset..offset + width];
471                for ((((((((x, p0), p1), p2), p3), p4), p5), p6), p7) in c
472                    .words_mut()
473                    .iter_mut()
474                    .zip(p0)
475                    .zip(p1)
476                    .zip(p2)
477                    .zip(p3)
478                    .zip(p4)
479                    .zip(p5)
480                    .zip(p6)
481                    .zip(p7)
482                {
483                    *x ^= p0 ^ p1 ^ p2 ^ p3 ^ p4 ^ p5 ^ p6 ^ p7;
484                }
485            }
486        }
487        result
488    }
More examples
Hide additional examples
crates/competitive/src/combinatorial_optimization/subset_sum_problem.rs (line 13)
12    pub fn new(size: usize) -> Self {
13        let mut dp = BitSet::new(if size == !0 { 0 } else { size } + 1);
14        dp.set(0, true);
15        Self {
16            size,
17            dp,
18            pending_weights: vec![],
19        }
20    }
crates/competitive/src/data_structure/bitset.rs (line 47)
45    pub fn from_binary(s: &str) -> Option<Self> {
46        let bytes = s.as_bytes();
47        let mut bits = Self::new(bytes.len());
48        let end = bytes.len() / 64 * 64;
49        #[cfg(target_arch = "x86_64")]
50        let parsed = if avx512_enabled() && is_x86_feature_detected!("avx512bw") {
51            // SAFETY: AVX-512BW is available; each complete chunk contains 64 bytes.
52            unsafe { simd::parse_binary_avx512(&bytes[..end], bits.words_mut()) }
53        } else if is_x86_feature_detected!("avx2") {
54            // SAFETY: AVX2 is available; each complete chunk contains 64 bytes.
55            unsafe { simd::parse_binary_avx2(&bytes[..end], bits.words_mut()) }
56        } else {
57            Self::parse_binary_scalar(&bytes[..end], bits.words_mut())
58        };
59        #[cfg(not(target_arch = "x86_64"))]
60        let parsed = Self::parse_binary_scalar(&bytes[..end], bits.words_mut());
61        if !parsed {
62            return None;
63        }
64        if end != bytes.len() {
65            let mut word = 0;
66            for (i, &b) in bytes[end..].iter().enumerate() {
67                if b != b'0' && b != b'1' {
68                    return None;
69                }
70                word |= u64::from(b & 1) << i;
71            }
72            bits.words_mut()[end / 64] = word;
73        }
74        Some(bits)
75    }
76
77    fn parse_binary_scalar(bytes: &[u8], words: &mut [u64]) -> bool {
78        for (chunk, word) in bytes.as_chunks::<64>().0.iter().zip(words) {
79            for (i, byte) in chunk.as_chunks::<8>().0.iter().enumerate() {
80                let x = u64::from_le_bytes(*byte);
81                if x & 0xfefe_fefe_fefe_fefe != 0x3030_3030_3030_3030 {
82                    return false;
83                }
84                *word |= ((x & 0x0101_0101_0101_0101).wrapping_mul(0x0102_0408_1020_4080) >> 56)
85                    << (i * 8);
86            }
87        }
88        true
89    }
90
91    /// Returns ASCII `0` and `1` in increasing bit-index order.
92    pub fn to_binary(&self) -> String {
93        const TABLE: [[u8; 8]; 256] = {
94            let mut table = [[b'0'; 8]; 256];
95            let mut i = 0;
96            while i < 256 {
97                let mut j = 0;
98                while j < 8 {
99                    table[i][j] |= ((i >> j) & 1) as u8;
100                    j += 1;
101                }
102                i += 1;
103            }
104            table
105        };
106        let mut bytes = vec![b'0'; self.size.div_ceil(8) * 8];
107        #[cfg(target_arch = "x86_64")]
108        let end = if self.size >= 64 && avx512_enabled() && is_x86_feature_detected!("avx512bw") {
109            let end = self.size / 64 * 64;
110            // SAFETY: AVX-512BW is available; each output chunk holds one 64-bit word.
111            unsafe {
112                simd::write_binary_avx512(&mut bytes[..end], self.words());
113            }
114            end
115        } else if self.size >= 64 && is_x86_feature_detected!("avx2") {
116            let end = self.size / 64 * 64;
117            // SAFETY: AVX2 is available; each output chunk holds one complete 64-bit word.
118            unsafe {
119                simd::write_binary_avx2(&mut bytes[..end], self.words());
120            }
121            end
122        } else {
123            0
124        };
125        #[cfg(not(target_arch = "x86_64"))]
126        let end = 0;
127        for (chunk, &word) in bytes[end..].chunks_mut(64).zip(&self.words()[end / 64..]) {
128            for (i, byte) in chunk.as_chunks_mut::<8>().0.iter_mut().enumerate() {
129                byte.copy_from_slice(&TABLE[(word >> (i * 8) & 255) as usize]);
130            }
131        }
132        bytes.truncate(self.size);
133        // SAFETY: every output byte is ASCII `0` or `1`.
134        unsafe { String::from_utf8_unchecked(bytes) }
135    }
136
137    pub fn ones(size: usize) -> Self {
138        let mut self_ = Self {
139            size,
140            bits: vec![Block([u64::MAX; 8]); size.div_ceil(512)],
141        };
142        self_.trim();
143        self_
144    }
145
146    pub fn get(&self, i: usize) -> bool {
147        self.bits[i >> 9].0[i >> 6 & 7] & (1 << (i & 63)) != 0
148    }
149
150    pub fn set(&mut self, i: usize, b: bool) {
151        let word = &mut self.bits[i >> 9].0[i >> 6 & 7];
152        if b {
153            *word |= 1 << (i & 63);
154        } else {
155            *word &= !(1 << (i & 63));
156        }
157    }
158
159    /// Clears all bits.
160    pub fn reset(&mut self) {
161        self.bits.fill(Block::default());
162    }
163
164    /// Sets all bits to `value`.
165    pub fn fill(&mut self, value: bool) {
166        self.bits.fill(Block([if value { u64::MAX } else { 0 }; 8]));
167        self.trim();
168    }
169
170    /// Tests whether any bit is set.
171    #[inline]
172    pub fn any(&self) -> bool {
173        !self.none()
174    }
175
176    /// Tests whether all bits are unset.
177    #[inline]
178    pub fn none(&self) -> bool {
179        #[cfg(target_arch = "x86_64")]
180        if self.bits.len() >= SIMD_MIN_BLOCKS {
181            if self.bits[0].0[0] != 0 {
182                return false;
183            }
184            if avx512_enabled() && is_x86_feature_detected!("avx512f") {
185                // SAFETY: blocks are 64-byte aligned and feature detection checked AVX-512F.
186                return unsafe { simd::none_avx512(&self.bits) };
187            }
188            if is_x86_feature_detected!("avx2") {
189                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
190                return unsafe { simd::none_avx2(&self.bits) };
191            }
192        }
193        self.words().iter().all(|&word| word == 0)
194    }
195
196    /// Tests whether all bits are set.
197    #[inline(always)]
198    pub fn all(&self) -> bool {
199        let words = self.words();
200        let full_words = self.size >> 6;
201        #[cfg(target_arch = "x86_64")]
202        if self.size >> 9 >= SIMD_MIN_BLOCKS {
203            let full_blocks = self.size >> 9;
204            if words[0] != u64::MAX {
205                return false;
206            }
207            let full_blocks_are_set = if avx512_enabled() && is_x86_feature_detected!("avx512f") {
208                // SAFETY: blocks are 64-byte aligned and feature detection checked AVX-512F.
209                Some(unsafe { simd::all_avx512(&self.bits[..full_blocks]) })
210            } else if is_x86_feature_detected!("avx2") {
211                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
212                Some(unsafe { simd::all_avx2(&self.bits[..full_blocks]) })
213            } else {
214                None
215            };
216            if let Some(full_blocks_are_set) = full_blocks_are_set {
217                return full_blocks_are_set
218                    && words[full_blocks * 8..full_words]
219                        .iter()
220                        .all(|&word| word == u64::MAX)
221                    && (self.size & 63 == 0
222                        || words[full_words] == u64::MAX >> (64 - (self.size & 63)));
223            }
224        }
225        if self.size & 63 == 0 {
226            return words.iter().all(|&word| word == u64::MAX);
227        }
228        words[..full_words].iter().all(|&word| word == u64::MAX)
229            && words[full_words] == u64::MAX >> (64 - (self.size & 63))
230    }
231
232    /// Iterates over set-bit indices in ascending order.
233    pub fn iter_ones(&self) -> impl Iterator<Item = usize> + '_ {
234        self.words()
235            .iter()
236            .copied()
237            .enumerate()
238            .flat_map(|(word_index, mut word)| {
239                std::iter::from_fn(move || {
240                    if word == 0 {
241                        None
242                    } else {
243                        let bit = word.trailing_zeros() as usize;
244                        word &= word - 1;
245                        Some((word_index << 6) | bit)
246                    }
247                })
248            })
249    }
250
251    /// Counts set bits.
252    #[inline]
253    pub fn count_ones(&self) -> u64 {
254        let words = self.words();
255        #[cfg(target_arch = "x86_64")]
256        if words.len() >= 8 {
257            if avx512_enabled()
258                && is_x86_feature_detected!("avx512f")
259                && is_x86_feature_detected!("avx512vpopcntdq")
260            {
261                // SAFETY: blocks are aligned and feature detection checked both requirements.
262                return unsafe { simd::count_ones_avx512(&self.bits) };
263            }
264            if is_x86_feature_detected!("avx2") {
265                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
266                return unsafe { simd::count_ones_avx2(&self.bits) };
267            }
268        }
269        words.iter().map(|word| word.count_ones() as u64).sum()
270    }
271
272    /// Counts unset bits.
273    #[inline]
274    pub fn count_zeros(&self) -> u64 {
275        self.size as u64 - self.count_ones()
276    }
277
278    pub fn push(&mut self, b: bool) {
279        if self.size & 511 == 0 {
280            self.bits.push(Block::default());
281        }
282        if b {
283            self.bits[self.size >> 9].0[self.size >> 6 & 7] |= 1 << (self.size & 63);
284        }
285        self.size += 1;
286    }
287
288    pub fn resize(&mut self, new_size: usize) {
289        match self.size.cmp(&new_size) {
290            Ordering::Less => self.bits.resize(new_size.div_ceil(512), Block::default()),
291            Ordering::Equal => {}
292            Ordering::Greater => self.bits.truncate(new_size.div_ceil(512)),
293        }
294        self.size = new_size;
295        self.trim();
296    }
297
298    /// Assigns `self | (self << rhs)` to `self`.
299    #[inline]
300    pub fn shl_bitor_assign(&mut self, rhs: usize) {
301        self.shift_left::<true>(rhs);
302    }
303
304    /// Assigns `self | (self >> rhs)` to `self`.
305    #[inline]
306    pub fn shr_bitor_assign(&mut self, rhs: usize) {
307        self.shift_right::<true>(rhs);
308    }
309
310    /// Returns words in increasing bit-index order; unused high bits in the last word are zero.
311    pub fn words(&self) -> &[u64] {
312        // SAFETY: `Block` is exactly eight contiguous `u64`s, with no trailing padding.
313        unsafe { std::slice::from_raw_parts(self.bits.as_ptr().cast(), self.size.div_ceil(64)) }
314    }
315
316    /// Returns mutable words in increasing bit-index order.
317    /// Callers must keep unused high bits in the last word zero.
318    pub fn words_mut(&mut self) -> &mut [u64] {
319        let len = self.size.div_ceil(64);
320        // SAFETY: `Block` is exactly eight contiguous `u64`s, with no trailing padding.
321        unsafe { std::slice::from_raw_parts_mut(self.bits.as_mut_ptr().cast(), len) }
322    }
323
324    fn trim(&mut self) {
325        let used_words = self.size.div_ceil(64) & 7;
326        if let Some(last) = self.bits.last_mut() {
327            if self.size & 63 != 0 {
328                last.0[(self.size >> 6) & 7] &= u64::MAX >> (64 - (self.size & 63));
329            }
330            if used_words != 0 {
331                last.0[used_words..].fill(0);
332            }
333        }
334    }
335
336    #[inline]
337    fn bitop_assign<const OP: u8>(&mut self, rhs: &Self) {
338        assert_eq!(
339            self.size, rhs.size,
340            "bitwise operations require equal lengths"
341        );
342        #[cfg(target_arch = "x86_64")]
343        if self.bits.len() >= SIMD_MIN_BLOCKS {
344            if avx512_enabled() && is_x86_feature_detected!("avx512f") {
345                // SAFETY: blocks are 64-byte aligned and feature detection checked AVX-512F.
346                unsafe { simd::bitop_avx512::<OP>(&mut self.bits, &rhs.bits) };
347                return;
348            }
349            if is_x86_feature_detected!("avx2") {
350                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
351                unsafe { simd::bitop_avx2::<OP>(&mut self.bits, &rhs.bits) };
352                return;
353            }
354        }
355        for (lhs, &rhs) in self.words_mut().iter_mut().zip(rhs.words()) {
356            *lhs = match OP {
357                BIT_AND => *lhs & rhs,
358                BIT_OR => *lhs | rhs,
359                BIT_XOR => *lhs ^ rhs,
360                _ => unreachable!(),
361            };
362        }
363    }
364
365    #[inline]
366    fn shift_left<const OR_ASSIGN: bool>(&mut self, rhs: usize) {
367        if rhs == 0 {
368            return;
369        }
370        if rhs >= self.size {
371            if !OR_ASSIGN {
372                self.reset();
373            }
374            return;
375        }
376        #[cfg(target_arch = "x86_64")]
377        if self.bits.len() >= SIMD_MIN_BLOCKS {
378            if avx512_enabled()
379                && is_x86_feature_detected!("avx512f")
380                && is_x86_feature_detected!("avx512vbmi2")
381            {
382                // SAFETY: blocks are aligned and feature detection checked AVX-512F and VBMI2.
383                unsafe { simd::shift_left_avx512::<OR_ASSIGN>(&mut self.bits, rhs) };
384                if self.size & 511 != 0 {
385                    self.trim();
386                }
387                return;
388            }
389            if is_x86_feature_detected!("avx2") {
390                // SAFETY: feature detection checked AVX2 support.
391                unsafe { simd::shift_left_avx2::<OR_ASSIGN>(self.words_mut(), rhs) };
392                if self.size & 63 != 0 {
393                    self.trim();
394                }
395                return;
396            }
397        }
398
399        let bits = self.words_mut();
400        let word_shift = rhs >> 6;
401        let bit_shift = rhs & 63;
402        if bit_shift == 0 {
403            for i in (0..bits.len() - word_shift).rev() {
404                if OR_ASSIGN {
405                    bits[i + word_shift] |= bits[i];
406                } else {
407                    bits[i + word_shift] = bits[i];
408                }
409            }
410        } else {
411            for i in (1..bits.len() - word_shift).rev() {
412                let value = (bits[i] << bit_shift) | (bits[i - 1] >> (64 - bit_shift));
413                if OR_ASSIGN {
414                    bits[i + word_shift] |= value;
415                } else {
416                    bits[i + word_shift] = value;
417                }
418            }
419            if OR_ASSIGN {
420                bits[word_shift] |= bits[0] << bit_shift;
421            } else {
422                bits[word_shift] = bits[0] << bit_shift;
423            }
424        }
425        if !OR_ASSIGN {
426            bits[..word_shift].fill(0);
427        }
428        if self.size & 63 != 0 {
429            self.trim();
430        }
431    }
432
433    #[inline]
434    fn shift_right<const OR_ASSIGN: bool>(&mut self, rhs: usize) {
435        if rhs == 0 {
436            return;
437        }
438        if rhs >= self.size {
439            if !OR_ASSIGN {
440                self.reset();
441            }
442            return;
443        }
444        #[cfg(target_arch = "x86_64")]
445        if self.bits.len() >= SIMD_MIN_BLOCKS {
446            if avx512_enabled()
447                && is_x86_feature_detected!("avx512f")
448                && is_x86_feature_detected!("avx512vbmi2")
449            {
450                // SAFETY: blocks are aligned and feature detection checked AVX-512F and VBMI2.
451                unsafe { simd::shift_right_avx512::<OR_ASSIGN>(&mut self.bits, rhs) };
452                return;
453            }
454            if is_x86_feature_detected!("avx2") {
455                // SAFETY: feature detection checked AVX2 support.
456                unsafe { simd::shift_right_avx2::<OR_ASSIGN>(self.words_mut(), rhs) };
457                return;
458            }
459        }
460
461        let bits = self.words_mut();
462        let word_shift = rhs >> 6;
463        let bit_shift = rhs & 63;
464        if bit_shift == 0 {
465            for i in word_shift..bits.len() {
466                if OR_ASSIGN {
467                    bits[i - word_shift] |= bits[i];
468                } else {
469                    bits[i - word_shift] = bits[i];
470                }
471            }
472        } else {
473            for i in word_shift..bits.len() - 1 {
474                let value = (bits[i] >> bit_shift) | (bits[i + 1] << (64 - bit_shift));
475                if OR_ASSIGN {
476                    bits[i - word_shift] |= value;
477                } else {
478                    bits[i - word_shift] = value;
479                }
480            }
481            if OR_ASSIGN {
482                bits[bits.len() - word_shift - 1] |= bits[bits.len() - 1] >> bit_shift;
483            } else {
484                bits[bits.len() - word_shift - 1] = bits[bits.len() - 1] >> bit_shift;
485            }
486        }
487        if !OR_ASSIGN {
488            let end = bits.len() - word_shift;
489            bits[end..].fill(0);
490        }
491    }
492}
493
494impl Extend<bool> for BitSet {
495    fn extend<T: IntoIterator<Item = bool>>(&mut self, iter: T) {
496        for bit in iter {
497            self.push(bit);
498        }
499    }
500}
501
502impl FromIterator<bool> for BitSet {
503    fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
504        let mut set = BitSet::new(0);
505        set.extend(iter);
506        set
507    }
Source

pub fn len(&self) -> usize

Examples found in repository?
crates/competitive/src/combinatorial_optimization/subset_sum_problem.rs (line 40)
38    pub fn contains(&mut self, sum: usize) -> bool {
39        self.rebuild();
40        if sum < self.dp.len() {
41            self.dp.get(sum)
42        } else {
43            false
44        }
45    }
46
47    fn rebuild(&mut self) {
48        if self.pending_weights.is_empty() {
49            return;
50        }
51        let mut heap = BinaryHeap::from(take(&mut self.pending_weights));
52        let (mut current_weight, mut count) = match heap.pop() {
53            Some(Reverse(w)) => (w, 1),
54            None => return,
55        };
56        while let Some(Reverse(weight)) = heap.pop() {
57            if weight == current_weight {
58                count += 1;
59                if count >= 3 {
60                    if let Some(w) = current_weight.checked_mul(2) {
61                        heap.push(Reverse(w));
62                    }
63                    count -= 2;
64                }
65                continue;
66            }
67            for _ in 0..count {
68                if self.size == !0 {
69                    self.dp.resize(self.dp.len() + current_weight);
70                }
71                self.dp.shl_bitor_assign(current_weight);
72            }
73            (current_weight, count) = (weight, 1);
74        }
75        for _ in 0..count {
76            if self.size == !0 {
77                self.dp.resize(self.dp.len() + current_weight);
78            }
79            self.dp.shl_bitor_assign(current_weight);
80        }
81    }
More examples
Hide additional examples
crates/competitive/src/math/bit_matrix.rs (line 29)
27    pub fn from_vec(data: Vec<BitSet>) -> Self {
28        let shape = (data.len(), data.first().map_or(0, BitSet::len));
29        assert!(data.iter().all(|row| row.len() == shape.1));
30        Self { shape, data }
31    }
32
33    pub fn new_with(shape: (usize, usize), mut f: impl FnMut(usize, usize) -> bool) -> Self {
34        let mut a = Self::zeros(shape);
35        for (i, row) in a.data.iter_mut().enumerate() {
36            for (w, word) in row.words_mut().iter_mut().enumerate() {
37                for j in w * 64..shape.1.min((w + 1) * 64) {
38                    *word |= u64::from(f(i, j)) << (j & 63);
39                }
40            }
41        }
42        a
43    }
44
45    pub fn eye(shape: (usize, usize)) -> Self {
46        let mut a = Self::zeros(shape);
47        for i in 0..shape.0.min(shape.1) {
48            a[i].set(i, true);
49        }
50        a
51    }
52
53    pub fn transpose(&self) -> Self {
54        let mut a = Self::zeros((self.shape.1, self.shape.0));
55        for (i, row) in self.data.iter().enumerate() {
56            for j in row.iter_ones() {
57                a[j].set(i, true);
58            }
59        }
60        a
61    }
62
63    /// Replaces the matrix with reduced row echelon form and returns its pivot columns.
64    pub fn row_reduction(&mut self) -> Vec<usize> {
65        self.eliminate(self.shape.1, true, false)
66    }
67
68    /// Replaces the matrix with row echelon form and returns its rank.
69    pub fn rank(&mut self) -> usize {
70        self.eliminate(self.shape.1, false, false).len()
71    }
72
73    /// Computes the determinant in place. The matrix must be square.
74    pub fn determinant(&mut self) -> bool {
75        assert_eq!(self.shape.0, self.shape.1);
76        self.eliminate(self.shape.1, false, true).len() == self.shape.0
77    }
78
79    /// Returns the inverse, or `None` if singular. The matrix must be square.
80    pub fn inverse(&self) -> Option<Self> {
81        let (n, m) = self.shape;
82        assert_eq!(n, m);
83        let mut a = Self::zeros((n, 2 * n));
84        for i in 0..n {
85            a[i].words_mut()[..self[i].words().len()].copy_from_slice(self[i].words());
86            a[i].set(n + i, true);
87        }
88        if a.eliminate(n, true, true).len() != n {
89            return None;
90        }
91        for row in &mut a.data {
92            *row >>= n;
93        }
94        let mut inverse = Self::zeros((n, n));
95        for (row, source) in inverse.data.iter_mut().zip(&a.data) {
96            let len = row.words().len();
97            row.words_mut().copy_from_slice(&source.words()[..len]);
98        }
99        Some(inverse)
100    }
101
102    /// Returns a particular solution and a basis of the kernel, or `None` if inconsistent.
103    /// `b.len()` must equal the number of rows.
104    pub fn solve_system_of_linear_equations(&self, b: &BitSet) -> Option<BitMatrixSolution> {
105        let (n, m) = self.shape;
106        assert_eq!(b.len(), n);
107        let mut a = Self::zeros((n, m + 1));
108        for i in 0..n {
109            a[i].words_mut()[..self[i].words().len()].copy_from_slice(self[i].words());
110            a[i].set(m, b.get(i));
111        }
112        let pivots = a.eliminate(m, true, false);
113        if a.data[pivots.len()..].iter().any(|row| row.get(m)) {
114            return None;
115        }
116        let mut particular = BitSet::new(m);
117        let mut free = BitSet::ones(m);
118        for (i, &c) in pivots.iter().enumerate() {
119            particular.set(c, a[i].get(m));
120            free.set(c, false);
121        }
122        let columns: Vec<_> = free.iter_ones().collect();
123        let mut basis: Vec<_> = columns
124            .iter()
125            .map(|&c| {
126                let mut row = BitSet::new(m);
127                row.set(c, true);
128                row
129            })
130            .collect();
131        for (i, &p) in pivots.iter().enumerate() {
132            for (row, &c) in basis.iter_mut().zip(&columns) {
133                row.words_mut()[p / 64] |= u64::from(a[i].get(c)) << (p & 63);
134            }
135        }
136        Some(BitMatrixSolution { particular, basis })
137    }
Source

pub fn is_empty(&self) -> bool

Source

pub fn from_binary(s: &str) -> Option<Self>

Parses ASCII 0 and 1, with the first character at bit index zero. Returns None if any other character occurs.

Examples found in repository?
crates/library_checker/src/linear_algebra/matrix_rank_mod_2.rs (line 29)
5pub fn matrix_rank_mod_2(reader: impl Read, writer: impl Write) {
6    prepare_io!(reader, writer);
7    sc!(n, m);
8    // Transpose very tall matrices to avoid allocating millions of short rows.
9    let transpose = n / 2 > m;
10    let mut a = BitMatrix::zeros(if transpose { (m, n) } else { (n, m) });
11    if transpose && m >= 64 {
12        let mut words = vec![0u64; m];
13        for first in (0..n).step_by(64) {
14            words.fill(0);
15            for i in 0..64.min(n - first) {
16                sc!(row: &str);
17                for (word, b) in words.iter_mut().zip(row.bytes()) {
18                    *word |= u64::from(b == b'1') << i;
19                }
20            }
21            for (row, &word) in a.data.iter_mut().zip(&words) {
22                row.words_mut()[first / 64] = word;
23            }
24        }
25    } else {
26        for i in 0..if m == 0 { 0 } else { n } {
27            sc!(row: &str);
28            if !transpose {
29                a.data[i] = BitSet::from_binary(row).unwrap();
30            } else {
31                for (j, b) in row.bytes().enumerate() {
32                    a[j].words_mut()[i / 64] |= u64::from(b == b'1') << (i % 64);
33                }
34            }
35            if transpose
36                && i == 63
37                && BitMatrix::new_with((m, 64), |row, col| a[row].get(col)).rank() == m
38            {
39                pp!(m);
40                return;
41            }
42        }
43    }
44    pp!(a.rank());
45}
Source

fn parse_binary_scalar(bytes: &[u8], words: &mut [u64]) -> bool

Examples found in repository?
crates/competitive/src/data_structure/bitset.rs (line 57)
45    pub fn from_binary(s: &str) -> Option<Self> {
46        let bytes = s.as_bytes();
47        let mut bits = Self::new(bytes.len());
48        let end = bytes.len() / 64 * 64;
49        #[cfg(target_arch = "x86_64")]
50        let parsed = if avx512_enabled() && is_x86_feature_detected!("avx512bw") {
51            // SAFETY: AVX-512BW is available; each complete chunk contains 64 bytes.
52            unsafe { simd::parse_binary_avx512(&bytes[..end], bits.words_mut()) }
53        } else if is_x86_feature_detected!("avx2") {
54            // SAFETY: AVX2 is available; each complete chunk contains 64 bytes.
55            unsafe { simd::parse_binary_avx2(&bytes[..end], bits.words_mut()) }
56        } else {
57            Self::parse_binary_scalar(&bytes[..end], bits.words_mut())
58        };
59        #[cfg(not(target_arch = "x86_64"))]
60        let parsed = Self::parse_binary_scalar(&bytes[..end], bits.words_mut());
61        if !parsed {
62            return None;
63        }
64        if end != bytes.len() {
65            let mut word = 0;
66            for (i, &b) in bytes[end..].iter().enumerate() {
67                if b != b'0' && b != b'1' {
68                    return None;
69                }
70                word |= u64::from(b & 1) << i;
71            }
72            bits.words_mut()[end / 64] = word;
73        }
74        Some(bits)
75    }
Source

pub fn to_binary(&self) -> String

Returns ASCII 0 and 1 in increasing bit-index order.

Examples found in repository?
crates/library_checker/src/linear_algebra/inverse_matrix_mod_2.rs (line 11)
5pub fn inverse_matrix_mod_2(reader: impl Read, writer: impl Write) {
6    prepare_io!(reader, writer);
7    sc!(n, a: [@BitSet::from_binary; n]);
8    let a = BitMatrix::from_vec(a);
9    if let Some(b) = a.inverse() {
10        for row in b.data {
11            pp!(row.to_binary());
12        }
13    } else {
14        pp!(-1);
15    }
16}
More examples
Hide additional examples
crates/library_checker/src/linear_algebra/matrix_product_mod_2.rs (line 12)
5pub fn matrix_product_mod_2(reader: impl Read, writer: impl Write) {
6    prepare_io!(reader, writer);
7    sc!(n, m, _k, a: [@BitSet::from_binary; n], b: [@BitSet::from_binary; m]);
8    let a = BitMatrix::from_vec(a);
9    let b = BitMatrix::from_vec(b);
10    let c = &a * &b;
11    for row in c.data {
12        pp!(row.to_binary());
13    }
14}
crates/library_checker/src/linear_algebra/system_of_linear_equations_mod_2.rs (line 12)
5pub fn system_of_linear_equations_mod_2(reader: impl Read, writer: impl Write) {
6    prepare_io!(reader, writer);
7    sc!(n, _m, a: [@BitSet::from_binary; n], b: @BitSet::from_binary);
8    let a = BitMatrix::from_vec(a);
9    if let Some(sol) = a.solve_system_of_linear_equations(&b) {
10        pp!(sol.basis.len());
11        for row in std::iter::once(sol.particular).chain(sol.basis) {
12            pp!(row.to_binary());
13        }
14    } else {
15        pp!(-1);
16    }
17}
Source

pub fn ones(size: usize) -> Self

Examples found in repository?
crates/competitive/src/math/bit_matrix.rs (line 117)
104    pub fn solve_system_of_linear_equations(&self, b: &BitSet) -> Option<BitMatrixSolution> {
105        let (n, m) = self.shape;
106        assert_eq!(b.len(), n);
107        let mut a = Self::zeros((n, m + 1));
108        for i in 0..n {
109            a[i].words_mut()[..self[i].words().len()].copy_from_slice(self[i].words());
110            a[i].set(m, b.get(i));
111        }
112        let pivots = a.eliminate(m, true, false);
113        if a.data[pivots.len()..].iter().any(|row| row.get(m)) {
114            return None;
115        }
116        let mut particular = BitSet::new(m);
117        let mut free = BitSet::ones(m);
118        for (i, &c) in pivots.iter().enumerate() {
119            particular.set(c, a[i].get(m));
120            free.set(c, false);
121        }
122        let columns: Vec<_> = free.iter_ones().collect();
123        let mut basis: Vec<_> = columns
124            .iter()
125            .map(|&c| {
126                let mut row = BitSet::new(m);
127                row.set(c, true);
128                row
129            })
130            .collect();
131        for (i, &p) in pivots.iter().enumerate() {
132            for (row, &c) in basis.iter_mut().zip(&columns) {
133                row.words_mut()[p / 64] |= u64::from(a[i].get(c)) << (p & 63);
134            }
135        }
136        Some(BitMatrixSolution { particular, basis })
137    }
Source

pub fn get(&self, i: usize) -> bool

Examples found in repository?
crates/competitive/src/combinatorial_optimization/subset_sum_problem.rs (line 41)
38    pub fn contains(&mut self, sum: usize) -> bool {
39        self.rebuild();
40        if sum < self.dp.len() {
41            self.dp.get(sum)
42        } else {
43            false
44        }
45    }
More examples
Hide additional examples
crates/competitive/src/algorithm/automata_learning.rs (line 372)
355    pub fn construct_dfa(&mut self) -> DeterministicFiniteAutomaton {
356        let sigma = self.automaton.sigma();
357        let mut dfa = DeterministicFiniteAutomaton {
358            states: vec![],
359            initial_state: 0,
360        };
361        let mut i_prefix = 0;
362        while i_prefix < self.prefixes.len() {
363            let mut delta = vec![];
364            for x in 0..sigma {
365                let prefix: Vec<usize> =
366                    self.prefixes[i_prefix].iter().cloned().chain([x]).collect();
367                let index = self.add_prefix(prefix);
368                delta.push(index);
369            }
370            dfa.states.push(DfaState {
371                delta,
372                accept: self.table[i_prefix].get(0),
373            });
374            i_prefix += 1;
375        }
376        dfa
377    }
crates/competitive/src/math/bit_matrix.rs (line 110)
104    pub fn solve_system_of_linear_equations(&self, b: &BitSet) -> Option<BitMatrixSolution> {
105        let (n, m) = self.shape;
106        assert_eq!(b.len(), n);
107        let mut a = Self::zeros((n, m + 1));
108        for i in 0..n {
109            a[i].words_mut()[..self[i].words().len()].copy_from_slice(self[i].words());
110            a[i].set(m, b.get(i));
111        }
112        let pivots = a.eliminate(m, true, false);
113        if a.data[pivots.len()..].iter().any(|row| row.get(m)) {
114            return None;
115        }
116        let mut particular = BitSet::new(m);
117        let mut free = BitSet::ones(m);
118        for (i, &c) in pivots.iter().enumerate() {
119            particular.set(c, a[i].get(m));
120            free.set(c, false);
121        }
122        let columns: Vec<_> = free.iter_ones().collect();
123        let mut basis: Vec<_> = columns
124            .iter()
125            .map(|&c| {
126                let mut row = BitSet::new(m);
127                row.set(c, true);
128                row
129            })
130            .collect();
131        for (i, &p) in pivots.iter().enumerate() {
132            for (row, &c) in basis.iter_mut().zip(&columns) {
133                row.words_mut()[p / 64] |= u64::from(a[i].get(c)) << (p & 63);
134            }
135        }
136        Some(BitMatrixSolution { particular, basis })
137    }
138
139    pub fn pow(self, mut n: usize) -> Self {
140        assert_eq!(self.shape.0, self.shape.1);
141        let mut result = Self::eye(self.shape);
142        let mut a = self;
143        while n != 0 {
144            if n & 1 != 0 {
145                result = &result * &a;
146            }
147            n >>= 1;
148            if n != 0 {
149                a = &a * &a;
150            }
151        }
152        result
153    }
154
155    fn eliminate(&mut self, cols: usize, full: bool, require_full_rank: bool) -> Vec<usize> {
156        #[cfg(target_arch = "x86_64")]
157        match simd_backend() {
158            // SAFETY: the dispatcher checks the required CPU features.
159            SimdBackend::Avx512 => {
160                return unsafe { self.eliminate_avx512(cols, full, require_full_rank) };
161            }
162            // SAFETY: the dispatcher checks AVX2 support.
163            SimdBackend::Avx2 => {
164                return unsafe { self.eliminate_avx2(cols, full, require_full_rank) };
165            }
166            SimdBackend::Scalar => {}
167        }
168        self.eliminate_impl(cols, full, require_full_rank)
169    }
170
171    // Inlined into each target-feature entry point to vectorize the row operations.
172    #[inline(always)]
173    fn eliminate_impl(&mut self, cols: usize, full: bool, require_full_rank: bool) -> Vec<usize> {
174        let n = self.shape.0;
175        let mut pivots = Vec::with_capacity(n.min(cols));
176        if n < 32 {
177            let mut c = 0;
178            while c < cols {
179                let r = pivots.len();
180                if r == n {
181                    break;
182                }
183                let Some(p) = (r..n).find(|&i| self[i].get(c)) else {
184                    if require_full_rank {
185                        return pivots;
186                    }
187                    c = self.next_column(r, c + 1, cols);
188                    continue;
189                };
190                self.data.swap(r, p);
191                let (upper, lower) = self.data.split_at_mut(r);
192                let (pivot, lower) = lower.split_first_mut().unwrap();
193                for row in lower
194                    .iter_mut()
195                    .chain(upper.iter_mut().take(if full { r } else { 0 }))
196                {
197                    if row.get(c) {
198                        xor(&mut row.words_mut()[c / 64..], &pivot.words()[c / 64..]);
199                    }
200                }
201                pivots.push(c);
202                c += 1;
203            }
204            return pivots;
205        }
206        // Eliminating a shared leading coefficient preserves the two-coefficient bound.
207        if self
208            .data
209            .iter()
210            .all(|row| row.iter_ones().take_while(|&c| c < cols).take(3).count() <= 2)
211        {
212            return self.eliminate_sparse(cols, full, require_full_rank);
213        }
214        let block: usize = if n < 512 {
215            4
216        } else if n < 1536 {
217            8
218        } else {
219            32
220        };
221        let mut table = vec![BitSet::new(self.shape.1); (1 << block.min(8)) * block.div_ceil(8)];
222        let mut reduced = vec![0; n];
223        let mut start = 0;
224        while start < cols {
225            let first = pivots.len();
226            let word = start / 64;
227            reduced.fill(first);
228            let end = cols.min(start + block);
229            let mut c = start;
230            while c < end {
231                let r = pivots.len();
232                let mut pivot = None;
233                for (i, reduced) in reduced.iter_mut().enumerate().skip(r) {
234                    let (upper, lower) = self.data.split_at_mut(i);
235                    let row = &mut lower[0];
236                    for p in *reduced..r {
237                        if row.get(pivots[p]) {
238                            xor(&mut row.words_mut()[word..], &upper[p].words()[word..]);
239                        }
240                    }
241                    *reduced = r;
242                    if row.get(c) {
243                        pivot = Some(i);
244                        break;
245                    }
246                }
247                if let Some(p) = pivot {
248                    self.data.swap(r, p);
249                    reduced.swap(r, p);
250                    pivots.push(c);
251                    c += 1;
252                } else if require_full_rank {
253                    return pivots;
254                } else {
255                    c = self.next_column(r, c + 1, end);
256                }
257            }
258            let rank = pivots.len();
259            if first == rank {
260                let next = self.next_column(rank, start + block, cols);
261                if next == cols {
262                    break;
263                }
264                start = next / block * block;
265                continue;
266            }
267            // Make the panel's pivot columns an identity matrix before indexing its table.
268            for r in (first..rank).rev() {
269                let (upper, lower) = self.data.split_at_mut(r);
270                for row in &mut upper[first..] {
271                    if row.get(pivots[r]) {
272                        xor(&mut row.words_mut()[word..], &lower[0].words()[word..]);
273                    }
274                }
275            }
276            let mut indices = [[0usize; 256]; 4];
277            let mut masks = [0usize; 4];
278            for group in 0..block.div_ceil(8) {
279                let mut keys = [0usize; 256];
280                let mut count = 0;
281                for (row, &c) in pivots[first..].iter().enumerate() {
282                    if (c - start) / 8 != group {
283                        continue;
284                    }
285                    let half = 1 << count;
286                    count += 1;
287                    for index in 0..half {
288                        keys[index + half] = keys[index] | (1 << ((c - start) % 8));
289                        let (lower, upper) = table.split_at_mut(group * 256 + index + half);
290                        let target = &mut upper[0].words_mut()[word..];
291                        let source = &lower[group * 256 + index].words()[word..];
292                        let pivot = &self[first + row].words()[word..];
293                        for ((x, y), z) in target.iter_mut().zip(source).zip(pivot) {
294                            *x = y ^ z;
295                        }
296                    }
297                }
298                masks[group] = keys[(1 << count) - 1];
299                for (i, &key) in keys[..1 << count].iter().enumerate() {
300                    indices[group][key] = i;
301                }
302            }
303            for i in (rank..n).chain(0..if full { first } else { 0 }) {
304                let key = (self[i].words()[word] >> (start & 63)) as usize;
305                let x = indices[0][key & masks[0]];
306                if block <= 8 {
307                    if x != 0 {
308                        xor(&mut self[i].words_mut()[word..], &table[x].words()[word..]);
309                    }
310                    continue;
311                }
312                let y = indices[1][(key >> 8) & masks[1]];
313                let z = indices[2][(key >> 16) & masks[2]];
314                let w = indices[3][(key >> 24) & masks[3]];
315                if x | y | z | w != 0 {
316                    let p = &table[x].words()[word..];
317                    let q = &table[256 + y].words()[word..];
318                    let r = &table[512 + z].words()[word..];
319                    let s = &table[768 + w].words()[word..];
320                    for ((((x, y), z), r), s) in self[i].words_mut()[word..]
321                        .iter_mut()
322                        .zip(p)
323                        .zip(q)
324                        .zip(r)
325                        .zip(s)
326                    {
327                        *x ^= y ^ z ^ r ^ s;
328                    }
329                }
330            }
331            if rank == n {
332                break;
333            }
334            start += block;
335        }
336        pivots
337    }
crates/library_checker/src/linear_algebra/matrix_rank_mod_2.rs (line 37)
5pub fn matrix_rank_mod_2(reader: impl Read, writer: impl Write) {
6    prepare_io!(reader, writer);
7    sc!(n, m);
8    // Transpose very tall matrices to avoid allocating millions of short rows.
9    let transpose = n / 2 > m;
10    let mut a = BitMatrix::zeros(if transpose { (m, n) } else { (n, m) });
11    if transpose && m >= 64 {
12        let mut words = vec![0u64; m];
13        for first in (0..n).step_by(64) {
14            words.fill(0);
15            for i in 0..64.min(n - first) {
16                sc!(row: &str);
17                for (word, b) in words.iter_mut().zip(row.bytes()) {
18                    *word |= u64::from(b == b'1') << i;
19                }
20            }
21            for (row, &word) in a.data.iter_mut().zip(&words) {
22                row.words_mut()[first / 64] = word;
23            }
24        }
25    } else {
26        for i in 0..if m == 0 { 0 } else { n } {
27            sc!(row: &str);
28            if !transpose {
29                a.data[i] = BitSet::from_binary(row).unwrap();
30            } else {
31                for (j, b) in row.bytes().enumerate() {
32                    a[j].words_mut()[i / 64] |= u64::from(b == b'1') << (i % 64);
33                }
34            }
35            if transpose
36                && i == 63
37                && BitMatrix::new_with((m, 64), |row, col| a[row].get(col)).rank() == m
38            {
39                pp!(m);
40                return;
41            }
42        }
43    }
44    pp!(a.rank());
45}
Source

pub fn set(&mut self, i: usize, b: bool)

Examples found in repository?
crates/competitive/src/math/bit_matrix.rs (line 48)
45    pub fn eye(shape: (usize, usize)) -> Self {
46        let mut a = Self::zeros(shape);
47        for i in 0..shape.0.min(shape.1) {
48            a[i].set(i, true);
49        }
50        a
51    }
52
53    pub fn transpose(&self) -> Self {
54        let mut a = Self::zeros((self.shape.1, self.shape.0));
55        for (i, row) in self.data.iter().enumerate() {
56            for j in row.iter_ones() {
57                a[j].set(i, true);
58            }
59        }
60        a
61    }
62
63    /// Replaces the matrix with reduced row echelon form and returns its pivot columns.
64    pub fn row_reduction(&mut self) -> Vec<usize> {
65        self.eliminate(self.shape.1, true, false)
66    }
67
68    /// Replaces the matrix with row echelon form and returns its rank.
69    pub fn rank(&mut self) -> usize {
70        self.eliminate(self.shape.1, false, false).len()
71    }
72
73    /// Computes the determinant in place. The matrix must be square.
74    pub fn determinant(&mut self) -> bool {
75        assert_eq!(self.shape.0, self.shape.1);
76        self.eliminate(self.shape.1, false, true).len() == self.shape.0
77    }
78
79    /// Returns the inverse, or `None` if singular. The matrix must be square.
80    pub fn inverse(&self) -> Option<Self> {
81        let (n, m) = self.shape;
82        assert_eq!(n, m);
83        let mut a = Self::zeros((n, 2 * n));
84        for i in 0..n {
85            a[i].words_mut()[..self[i].words().len()].copy_from_slice(self[i].words());
86            a[i].set(n + i, true);
87        }
88        if a.eliminate(n, true, true).len() != n {
89            return None;
90        }
91        for row in &mut a.data {
92            *row >>= n;
93        }
94        let mut inverse = Self::zeros((n, n));
95        for (row, source) in inverse.data.iter_mut().zip(&a.data) {
96            let len = row.words().len();
97            row.words_mut().copy_from_slice(&source.words()[..len]);
98        }
99        Some(inverse)
100    }
101
102    /// Returns a particular solution and a basis of the kernel, or `None` if inconsistent.
103    /// `b.len()` must equal the number of rows.
104    pub fn solve_system_of_linear_equations(&self, b: &BitSet) -> Option<BitMatrixSolution> {
105        let (n, m) = self.shape;
106        assert_eq!(b.len(), n);
107        let mut a = Self::zeros((n, m + 1));
108        for i in 0..n {
109            a[i].words_mut()[..self[i].words().len()].copy_from_slice(self[i].words());
110            a[i].set(m, b.get(i));
111        }
112        let pivots = a.eliminate(m, true, false);
113        if a.data[pivots.len()..].iter().any(|row| row.get(m)) {
114            return None;
115        }
116        let mut particular = BitSet::new(m);
117        let mut free = BitSet::ones(m);
118        for (i, &c) in pivots.iter().enumerate() {
119            particular.set(c, a[i].get(m));
120            free.set(c, false);
121        }
122        let columns: Vec<_> = free.iter_ones().collect();
123        let mut basis: Vec<_> = columns
124            .iter()
125            .map(|&c| {
126                let mut row = BitSet::new(m);
127                row.set(c, true);
128                row
129            })
130            .collect();
131        for (i, &p) in pivots.iter().enumerate() {
132            for (row, &c) in basis.iter_mut().zip(&columns) {
133                row.words_mut()[p / 64] |= u64::from(a[i].get(c)) << (p & 63);
134            }
135        }
136        Some(BitMatrixSolution { particular, basis })
137    }
More examples
Hide additional examples
crates/competitive/src/combinatorial_optimization/subset_sum_problem.rs (line 14)
12    pub fn new(size: usize) -> Self {
13        let mut dp = BitSet::new(if size == !0 { 0 } else { size } + 1);
14        dp.set(0, true);
15        Self {
16            size,
17            dp,
18            pending_weights: vec![],
19        }
20    }
Source

pub fn reset(&mut self)

Clears all bits.

Examples found in repository?
crates/competitive/src/data_structure/bitset.rs (line 372)
366    fn shift_left<const OR_ASSIGN: bool>(&mut self, rhs: usize) {
367        if rhs == 0 {
368            return;
369        }
370        if rhs >= self.size {
371            if !OR_ASSIGN {
372                self.reset();
373            }
374            return;
375        }
376        #[cfg(target_arch = "x86_64")]
377        if self.bits.len() >= SIMD_MIN_BLOCKS {
378            if avx512_enabled()
379                && is_x86_feature_detected!("avx512f")
380                && is_x86_feature_detected!("avx512vbmi2")
381            {
382                // SAFETY: blocks are aligned and feature detection checked AVX-512F and VBMI2.
383                unsafe { simd::shift_left_avx512::<OR_ASSIGN>(&mut self.bits, rhs) };
384                if self.size & 511 != 0 {
385                    self.trim();
386                }
387                return;
388            }
389            if is_x86_feature_detected!("avx2") {
390                // SAFETY: feature detection checked AVX2 support.
391                unsafe { simd::shift_left_avx2::<OR_ASSIGN>(self.words_mut(), rhs) };
392                if self.size & 63 != 0 {
393                    self.trim();
394                }
395                return;
396            }
397        }
398
399        let bits = self.words_mut();
400        let word_shift = rhs >> 6;
401        let bit_shift = rhs & 63;
402        if bit_shift == 0 {
403            for i in (0..bits.len() - word_shift).rev() {
404                if OR_ASSIGN {
405                    bits[i + word_shift] |= bits[i];
406                } else {
407                    bits[i + word_shift] = bits[i];
408                }
409            }
410        } else {
411            for i in (1..bits.len() - word_shift).rev() {
412                let value = (bits[i] << bit_shift) | (bits[i - 1] >> (64 - bit_shift));
413                if OR_ASSIGN {
414                    bits[i + word_shift] |= value;
415                } else {
416                    bits[i + word_shift] = value;
417                }
418            }
419            if OR_ASSIGN {
420                bits[word_shift] |= bits[0] << bit_shift;
421            } else {
422                bits[word_shift] = bits[0] << bit_shift;
423            }
424        }
425        if !OR_ASSIGN {
426            bits[..word_shift].fill(0);
427        }
428        if self.size & 63 != 0 {
429            self.trim();
430        }
431    }
432
433    #[inline]
434    fn shift_right<const OR_ASSIGN: bool>(&mut self, rhs: usize) {
435        if rhs == 0 {
436            return;
437        }
438        if rhs >= self.size {
439            if !OR_ASSIGN {
440                self.reset();
441            }
442            return;
443        }
444        #[cfg(target_arch = "x86_64")]
445        if self.bits.len() >= SIMD_MIN_BLOCKS {
446            if avx512_enabled()
447                && is_x86_feature_detected!("avx512f")
448                && is_x86_feature_detected!("avx512vbmi2")
449            {
450                // SAFETY: blocks are aligned and feature detection checked AVX-512F and VBMI2.
451                unsafe { simd::shift_right_avx512::<OR_ASSIGN>(&mut self.bits, rhs) };
452                return;
453            }
454            if is_x86_feature_detected!("avx2") {
455                // SAFETY: feature detection checked AVX2 support.
456                unsafe { simd::shift_right_avx2::<OR_ASSIGN>(self.words_mut(), rhs) };
457                return;
458            }
459        }
460
461        let bits = self.words_mut();
462        let word_shift = rhs >> 6;
463        let bit_shift = rhs & 63;
464        if bit_shift == 0 {
465            for i in word_shift..bits.len() {
466                if OR_ASSIGN {
467                    bits[i - word_shift] |= bits[i];
468                } else {
469                    bits[i - word_shift] = bits[i];
470                }
471            }
472        } else {
473            for i in word_shift..bits.len() - 1 {
474                let value = (bits[i] >> bit_shift) | (bits[i + 1] << (64 - bit_shift));
475                if OR_ASSIGN {
476                    bits[i - word_shift] |= value;
477                } else {
478                    bits[i - word_shift] = value;
479                }
480            }
481            if OR_ASSIGN {
482                bits[bits.len() - word_shift - 1] |= bits[bits.len() - 1] >> bit_shift;
483            } else {
484                bits[bits.len() - word_shift - 1] = bits[bits.len() - 1] >> bit_shift;
485            }
486        }
487        if !OR_ASSIGN {
488            let end = bits.len() - word_shift;
489            bits[end..].fill(0);
490        }
491    }
Source

pub fn fill(&mut self, value: bool)

Sets all bits to value.

Source

pub fn any(&self) -> bool

Tests whether any bit is set.

Source

pub fn none(&self) -> bool

Tests whether all bits are unset.

Examples found in repository?
crates/competitive/src/data_structure/bitset.rs (line 173)
172    pub fn any(&self) -> bool {
173        !self.none()
174    }
Source

pub fn all(&self) -> bool

Tests whether all bits are set.

Source

pub fn iter_ones(&self) -> impl Iterator<Item = usize> + '_

Iterates over set-bit indices in ascending order.

Examples found in repository?
crates/competitive/src/math/bit_matrix.rs (line 56)
53    pub fn transpose(&self) -> Self {
54        let mut a = Self::zeros((self.shape.1, self.shape.0));
55        for (i, row) in self.data.iter().enumerate() {
56            for j in row.iter_ones() {
57                a[j].set(i, true);
58            }
59        }
60        a
61    }
62
63    /// Replaces the matrix with reduced row echelon form and returns its pivot columns.
64    pub fn row_reduction(&mut self) -> Vec<usize> {
65        self.eliminate(self.shape.1, true, false)
66    }
67
68    /// Replaces the matrix with row echelon form and returns its rank.
69    pub fn rank(&mut self) -> usize {
70        self.eliminate(self.shape.1, false, false).len()
71    }
72
73    /// Computes the determinant in place. The matrix must be square.
74    pub fn determinant(&mut self) -> bool {
75        assert_eq!(self.shape.0, self.shape.1);
76        self.eliminate(self.shape.1, false, true).len() == self.shape.0
77    }
78
79    /// Returns the inverse, or `None` if singular. The matrix must be square.
80    pub fn inverse(&self) -> Option<Self> {
81        let (n, m) = self.shape;
82        assert_eq!(n, m);
83        let mut a = Self::zeros((n, 2 * n));
84        for i in 0..n {
85            a[i].words_mut()[..self[i].words().len()].copy_from_slice(self[i].words());
86            a[i].set(n + i, true);
87        }
88        if a.eliminate(n, true, true).len() != n {
89            return None;
90        }
91        for row in &mut a.data {
92            *row >>= n;
93        }
94        let mut inverse = Self::zeros((n, n));
95        for (row, source) in inverse.data.iter_mut().zip(&a.data) {
96            let len = row.words().len();
97            row.words_mut().copy_from_slice(&source.words()[..len]);
98        }
99        Some(inverse)
100    }
101
102    /// Returns a particular solution and a basis of the kernel, or `None` if inconsistent.
103    /// `b.len()` must equal the number of rows.
104    pub fn solve_system_of_linear_equations(&self, b: &BitSet) -> Option<BitMatrixSolution> {
105        let (n, m) = self.shape;
106        assert_eq!(b.len(), n);
107        let mut a = Self::zeros((n, m + 1));
108        for i in 0..n {
109            a[i].words_mut()[..self[i].words().len()].copy_from_slice(self[i].words());
110            a[i].set(m, b.get(i));
111        }
112        let pivots = a.eliminate(m, true, false);
113        if a.data[pivots.len()..].iter().any(|row| row.get(m)) {
114            return None;
115        }
116        let mut particular = BitSet::new(m);
117        let mut free = BitSet::ones(m);
118        for (i, &c) in pivots.iter().enumerate() {
119            particular.set(c, a[i].get(m));
120            free.set(c, false);
121        }
122        let columns: Vec<_> = free.iter_ones().collect();
123        let mut basis: Vec<_> = columns
124            .iter()
125            .map(|&c| {
126                let mut row = BitSet::new(m);
127                row.set(c, true);
128                row
129            })
130            .collect();
131        for (i, &p) in pivots.iter().enumerate() {
132            for (row, &c) in basis.iter_mut().zip(&columns) {
133                row.words_mut()[p / 64] |= u64::from(a[i].get(c)) << (p & 63);
134            }
135        }
136        Some(BitMatrixSolution { particular, basis })
137    }
138
139    pub fn pow(self, mut n: usize) -> Self {
140        assert_eq!(self.shape.0, self.shape.1);
141        let mut result = Self::eye(self.shape);
142        let mut a = self;
143        while n != 0 {
144            if n & 1 != 0 {
145                result = &result * &a;
146            }
147            n >>= 1;
148            if n != 0 {
149                a = &a * &a;
150            }
151        }
152        result
153    }
154
155    fn eliminate(&mut self, cols: usize, full: bool, require_full_rank: bool) -> Vec<usize> {
156        #[cfg(target_arch = "x86_64")]
157        match simd_backend() {
158            // SAFETY: the dispatcher checks the required CPU features.
159            SimdBackend::Avx512 => {
160                return unsafe { self.eliminate_avx512(cols, full, require_full_rank) };
161            }
162            // SAFETY: the dispatcher checks AVX2 support.
163            SimdBackend::Avx2 => {
164                return unsafe { self.eliminate_avx2(cols, full, require_full_rank) };
165            }
166            SimdBackend::Scalar => {}
167        }
168        self.eliminate_impl(cols, full, require_full_rank)
169    }
170
171    // Inlined into each target-feature entry point to vectorize the row operations.
172    #[inline(always)]
173    fn eliminate_impl(&mut self, cols: usize, full: bool, require_full_rank: bool) -> Vec<usize> {
174        let n = self.shape.0;
175        let mut pivots = Vec::with_capacity(n.min(cols));
176        if n < 32 {
177            let mut c = 0;
178            while c < cols {
179                let r = pivots.len();
180                if r == n {
181                    break;
182                }
183                let Some(p) = (r..n).find(|&i| self[i].get(c)) else {
184                    if require_full_rank {
185                        return pivots;
186                    }
187                    c = self.next_column(r, c + 1, cols);
188                    continue;
189                };
190                self.data.swap(r, p);
191                let (upper, lower) = self.data.split_at_mut(r);
192                let (pivot, lower) = lower.split_first_mut().unwrap();
193                for row in lower
194                    .iter_mut()
195                    .chain(upper.iter_mut().take(if full { r } else { 0 }))
196                {
197                    if row.get(c) {
198                        xor(&mut row.words_mut()[c / 64..], &pivot.words()[c / 64..]);
199                    }
200                }
201                pivots.push(c);
202                c += 1;
203            }
204            return pivots;
205        }
206        // Eliminating a shared leading coefficient preserves the two-coefficient bound.
207        if self
208            .data
209            .iter()
210            .all(|row| row.iter_ones().take_while(|&c| c < cols).take(3).count() <= 2)
211        {
212            return self.eliminate_sparse(cols, full, require_full_rank);
213        }
214        let block: usize = if n < 512 {
215            4
216        } else if n < 1536 {
217            8
218        } else {
219            32
220        };
221        let mut table = vec![BitSet::new(self.shape.1); (1 << block.min(8)) * block.div_ceil(8)];
222        let mut reduced = vec![0; n];
223        let mut start = 0;
224        while start < cols {
225            let first = pivots.len();
226            let word = start / 64;
227            reduced.fill(first);
228            let end = cols.min(start + block);
229            let mut c = start;
230            while c < end {
231                let r = pivots.len();
232                let mut pivot = None;
233                for (i, reduced) in reduced.iter_mut().enumerate().skip(r) {
234                    let (upper, lower) = self.data.split_at_mut(i);
235                    let row = &mut lower[0];
236                    for p in *reduced..r {
237                        if row.get(pivots[p]) {
238                            xor(&mut row.words_mut()[word..], &upper[p].words()[word..]);
239                        }
240                    }
241                    *reduced = r;
242                    if row.get(c) {
243                        pivot = Some(i);
244                        break;
245                    }
246                }
247                if let Some(p) = pivot {
248                    self.data.swap(r, p);
249                    reduced.swap(r, p);
250                    pivots.push(c);
251                    c += 1;
252                } else if require_full_rank {
253                    return pivots;
254                } else {
255                    c = self.next_column(r, c + 1, end);
256                }
257            }
258            let rank = pivots.len();
259            if first == rank {
260                let next = self.next_column(rank, start + block, cols);
261                if next == cols {
262                    break;
263                }
264                start = next / block * block;
265                continue;
266            }
267            // Make the panel's pivot columns an identity matrix before indexing its table.
268            for r in (first..rank).rev() {
269                let (upper, lower) = self.data.split_at_mut(r);
270                for row in &mut upper[first..] {
271                    if row.get(pivots[r]) {
272                        xor(&mut row.words_mut()[word..], &lower[0].words()[word..]);
273                    }
274                }
275            }
276            let mut indices = [[0usize; 256]; 4];
277            let mut masks = [0usize; 4];
278            for group in 0..block.div_ceil(8) {
279                let mut keys = [0usize; 256];
280                let mut count = 0;
281                for (row, &c) in pivots[first..].iter().enumerate() {
282                    if (c - start) / 8 != group {
283                        continue;
284                    }
285                    let half = 1 << count;
286                    count += 1;
287                    for index in 0..half {
288                        keys[index + half] = keys[index] | (1 << ((c - start) % 8));
289                        let (lower, upper) = table.split_at_mut(group * 256 + index + half);
290                        let target = &mut upper[0].words_mut()[word..];
291                        let source = &lower[group * 256 + index].words()[word..];
292                        let pivot = &self[first + row].words()[word..];
293                        for ((x, y), z) in target.iter_mut().zip(source).zip(pivot) {
294                            *x = y ^ z;
295                        }
296                    }
297                }
298                masks[group] = keys[(1 << count) - 1];
299                for (i, &key) in keys[..1 << count].iter().enumerate() {
300                    indices[group][key] = i;
301                }
302            }
303            for i in (rank..n).chain(0..if full { first } else { 0 }) {
304                let key = (self[i].words()[word] >> (start & 63)) as usize;
305                let x = indices[0][key & masks[0]];
306                if block <= 8 {
307                    if x != 0 {
308                        xor(&mut self[i].words_mut()[word..], &table[x].words()[word..]);
309                    }
310                    continue;
311                }
312                let y = indices[1][(key >> 8) & masks[1]];
313                let z = indices[2][(key >> 16) & masks[2]];
314                let w = indices[3][(key >> 24) & masks[3]];
315                if x | y | z | w != 0 {
316                    let p = &table[x].words()[word..];
317                    let q = &table[256 + y].words()[word..];
318                    let r = &table[512 + z].words()[word..];
319                    let s = &table[768 + w].words()[word..];
320                    for ((((x, y), z), r), s) in self[i].words_mut()[word..]
321                        .iter_mut()
322                        .zip(p)
323                        .zip(q)
324                        .zip(r)
325                        .zip(s)
326                    {
327                        *x ^= y ^ z ^ r ^ s;
328                    }
329                }
330            }
331            if rank == n {
332                break;
333            }
334            start += block;
335        }
336        pivots
337    }
338
339    fn next_column(&self, row: usize, mut start: usize, cols: usize) -> usize {
340        while start < cols {
341            let word = start / 64;
342            let bits = self.data[row..]
343                .iter()
344                .fold(0, |x, row| x | row.words()[word])
345                & (u64::MAX << (start & 63));
346            if bits != 0 {
347                return (word * 64 + bits.trailing_zeros() as usize).min(cols);
348            }
349            start = (word + 1) * 64;
350        }
351        cols
352    }
353
354    #[inline(always)]
355    fn eliminate_sparse(&mut self, cols: usize, full: bool, require_full_rank: bool) -> Vec<usize> {
356        let n = self.shape.0;
357        let mut basis = vec![n; cols];
358        let mut pivots = Vec::new();
359        for i in 0..n {
360            loop {
361                let Some(c) = self[i].iter_ones().next().filter(|&c| c < cols) else {
362                    if require_full_rank {
363                        return pivots;
364                    }
365                    break;
366                };
367                if basis[c] == n {
368                    basis[c] = i;
369                    pivots.push(c);
370                    break;
371                }
372                let (upper, lower) = self.data.split_at_mut(i);
373                xor(
374                    &mut lower[0].words_mut()[c / 64..],
375                    &upper[basis[c]].words()[c / 64..],
376                );
377            }
378        }
379        pivots.sort_unstable();
380        self.data
381            .sort_by_cached_key(|row| row.iter_ones().next().filter(|&c| c < cols).unwrap_or(cols));
382        if full {
383            for (i, &c) in pivots.iter().enumerate() {
384                basis[c] = i;
385            }
386            for i in (0..pivots.len()).rev() {
387                let next = self[i].iter_ones().take_while(|&c| c < cols).nth(1);
388                if let Some(c) = next
389                    && basis[c] != n
390                {
391                    let (upper, lower) = self.data.split_at_mut(basis[c]);
392                    xor(
393                        &mut upper[i].words_mut()[c / 64..],
394                        &lower[0].words()[c / 64..],
395                    );
396                }
397            }
398        }
399        pivots
400    }
401
402    #[inline(always)]
403    fn mul_impl(&self, rhs: &Self) -> Self {
404        let mut result = Self::zeros((self.shape.0, rhs.shape.1));
405        let ones = self.data.iter().map(BitSet::count_ones).sum::<u64>();
406        let size = self.shape.0 as u64 * self.shape.1 as u64;
407        if self.shape.0 < 256 || self.shape.1 < 32 || ones <= size / 8 {
408            for (a, c) in self.data.iter().zip(&mut result.data) {
409                for j in a.iter_ones() {
410                    xor(c.words_mut(), rhs[j].words());
411                }
412            }
413            return result;
414        }
415        if size - ones <= size / 8 {
416            let mut sum = BitSet::new(rhs.shape.1);
417            for row in &rhs.data {
418                sum ^= row;
419            }
420            for (a, c) in self.data.iter().zip(&mut result.data) {
421                c.words_mut().copy_from_slice(sum.words());
422                for j in (!a.clone()).iter_ones() {
423                    xor(c.words_mut(), rhs[j].words());
424                }
425            }
426            return result;
427        }
428        let width = rhs.shape.1.div_ceil(64);
429        if width == 0 {
430            return result;
431        }
432
433        // Separate the table groups by a cache line to avoid mapping them to the same sets.
434        let group = 256 * width + 8;
435        let mut storage = BitSet::new(8 * group * 64);
436        let table = storage.words_mut();
437        for start in (0..self.shape.1).step_by(64) {
438            for (t, table) in table.chunks_exact_mut(group).enumerate() {
439                let col = start + t * 8;
440                for bit in 0..self.shape.1.saturating_sub(col).min(8) {
441                    let row = rhs[col + bit].words();
442                    let half = (1 << bit) * width;
443                    let (lower, upper) = table.split_at_mut(half);
444                    for (source, dest) in
445                        lower.chunks_exact(width).zip(upper.chunks_exact_mut(width))
446                    {
447                        for ((x, y), z) in dest.iter_mut().zip(source).zip(row) {
448                            *x = y ^ z;
449                        }
450                    }
451                }
452            }
453            for (a, c) in self.data.iter().zip(&mut result.data) {
454                let key = a.words()[start / 64];
455                let offset = (key & 255) as usize * width;
456                let p0 = &table[offset..offset + width];
457                let offset = group + (key >> 8 & 255) as usize * width;
458                let p1 = &table[offset..offset + width];
459                let offset = 2 * group + (key >> 16 & 255) as usize * width;
460                let p2 = &table[offset..offset + width];
461                let offset = 3 * group + (key >> 24 & 255) as usize * width;
462                let p3 = &table[offset..offset + width];
463                let offset = 4 * group + (key >> 32 & 255) as usize * width;
464                let p4 = &table[offset..offset + width];
465                let offset = 5 * group + (key >> 40 & 255) as usize * width;
466                let p5 = &table[offset..offset + width];
467                let offset = 6 * group + (key >> 48 & 255) as usize * width;
468                let p6 = &table[offset..offset + width];
469                let offset = 7 * group + (key >> 56 & 255) as usize * width;
470                let p7 = &table[offset..offset + width];
471                for ((((((((x, p0), p1), p2), p3), p4), p5), p6), p7) in c
472                    .words_mut()
473                    .iter_mut()
474                    .zip(p0)
475                    .zip(p1)
476                    .zip(p2)
477                    .zip(p3)
478                    .zip(p4)
479                    .zip(p5)
480                    .zip(p6)
481                    .zip(p7)
482                {
483                    *x ^= p0 ^ p1 ^ p2 ^ p3 ^ p4 ^ p5 ^ p6 ^ p7;
484                }
485            }
486        }
487        result
488    }
Source

pub fn count_ones(&self) -> u64

Counts set bits.

Examples found in repository?
crates/competitive/src/data_structure/bitset.rs (line 275)
274    pub fn count_zeros(&self) -> u64 {
275        self.size as u64 - self.count_ones()
276    }
Source

pub fn count_zeros(&self) -> u64

Counts unset bits.

Source

pub fn push(&mut self, b: bool)

Examples found in repository?
crates/competitive/src/data_structure/bitset.rs (line 497)
495    fn extend<T: IntoIterator<Item = bool>>(&mut self, iter: T) {
496        for bit in iter {
497            self.push(bit);
498        }
499    }
More examples
Hide additional examples
crates/competitive/src/algorithm/automata_learning.rs (lines 344-347)
339    fn add_suffix(&mut self, suffix: Vec<usize>) {
340        if self.suffixes.contains(&suffix) {
341            return;
342        }
343        for (prefix, table) in self.prefixes.iter_mut().zip(&mut self.table) {
344            table.push(
345                self.automaton
346                    .behavior(prefix.iter().cloned().chain(suffix.iter().cloned())),
347            );
348        }
349        self.suffixes.push(suffix);
350        self.row_map.clear();
351        for (i_prefix, row) in self.table.iter().enumerate() {
352            self.row_map.insert(row.clone(), i_prefix);
353        }
354    }
Source

pub fn resize(&mut self, new_size: usize)

Examples found in repository?
crates/competitive/src/combinatorial_optimization/subset_sum_problem.rs (line 69)
47    fn rebuild(&mut self) {
48        if self.pending_weights.is_empty() {
49            return;
50        }
51        let mut heap = BinaryHeap::from(take(&mut self.pending_weights));
52        let (mut current_weight, mut count) = match heap.pop() {
53            Some(Reverse(w)) => (w, 1),
54            None => return,
55        };
56        while let Some(Reverse(weight)) = heap.pop() {
57            if weight == current_weight {
58                count += 1;
59                if count >= 3 {
60                    if let Some(w) = current_weight.checked_mul(2) {
61                        heap.push(Reverse(w));
62                    }
63                    count -= 2;
64                }
65                continue;
66            }
67            for _ in 0..count {
68                if self.size == !0 {
69                    self.dp.resize(self.dp.len() + current_weight);
70                }
71                self.dp.shl_bitor_assign(current_weight);
72            }
73            (current_weight, count) = (weight, 1);
74        }
75        for _ in 0..count {
76            if self.size == !0 {
77                self.dp.resize(self.dp.len() + current_weight);
78            }
79            self.dp.shl_bitor_assign(current_weight);
80        }
81    }
Source

pub fn shl_bitor_assign(&mut self, rhs: usize)

Assigns self | (self << rhs) to self.

Examples found in repository?
crates/competitive/src/combinatorial_optimization/subset_sum_problem.rs (line 71)
47    fn rebuild(&mut self) {
48        if self.pending_weights.is_empty() {
49            return;
50        }
51        let mut heap = BinaryHeap::from(take(&mut self.pending_weights));
52        let (mut current_weight, mut count) = match heap.pop() {
53            Some(Reverse(w)) => (w, 1),
54            None => return,
55        };
56        while let Some(Reverse(weight)) = heap.pop() {
57            if weight == current_weight {
58                count += 1;
59                if count >= 3 {
60                    if let Some(w) = current_weight.checked_mul(2) {
61                        heap.push(Reverse(w));
62                    }
63                    count -= 2;
64                }
65                continue;
66            }
67            for _ in 0..count {
68                if self.size == !0 {
69                    self.dp.resize(self.dp.len() + current_weight);
70                }
71                self.dp.shl_bitor_assign(current_weight);
72            }
73            (current_weight, count) = (weight, 1);
74        }
75        for _ in 0..count {
76            if self.size == !0 {
77                self.dp.resize(self.dp.len() + current_weight);
78            }
79            self.dp.shl_bitor_assign(current_weight);
80        }
81    }
Source

pub fn shr_bitor_assign(&mut self, rhs: usize)

Assigns self | (self >> rhs) to self.

Source

pub fn words(&self) -> &[u64]

Returns words in increasing bit-index order; unused high bits in the last word are zero.

Examples found in repository?
crates/competitive/src/math/bit_matrix.rs (line 85)
80    pub fn inverse(&self) -> Option<Self> {
81        let (n, m) = self.shape;
82        assert_eq!(n, m);
83        let mut a = Self::zeros((n, 2 * n));
84        for i in 0..n {
85            a[i].words_mut()[..self[i].words().len()].copy_from_slice(self[i].words());
86            a[i].set(n + i, true);
87        }
88        if a.eliminate(n, true, true).len() != n {
89            return None;
90        }
91        for row in &mut a.data {
92            *row >>= n;
93        }
94        let mut inverse = Self::zeros((n, n));
95        for (row, source) in inverse.data.iter_mut().zip(&a.data) {
96            let len = row.words().len();
97            row.words_mut().copy_from_slice(&source.words()[..len]);
98        }
99        Some(inverse)
100    }
101
102    /// Returns a particular solution and a basis of the kernel, or `None` if inconsistent.
103    /// `b.len()` must equal the number of rows.
104    pub fn solve_system_of_linear_equations(&self, b: &BitSet) -> Option<BitMatrixSolution> {
105        let (n, m) = self.shape;
106        assert_eq!(b.len(), n);
107        let mut a = Self::zeros((n, m + 1));
108        for i in 0..n {
109            a[i].words_mut()[..self[i].words().len()].copy_from_slice(self[i].words());
110            a[i].set(m, b.get(i));
111        }
112        let pivots = a.eliminate(m, true, false);
113        if a.data[pivots.len()..].iter().any(|row| row.get(m)) {
114            return None;
115        }
116        let mut particular = BitSet::new(m);
117        let mut free = BitSet::ones(m);
118        for (i, &c) in pivots.iter().enumerate() {
119            particular.set(c, a[i].get(m));
120            free.set(c, false);
121        }
122        let columns: Vec<_> = free.iter_ones().collect();
123        let mut basis: Vec<_> = columns
124            .iter()
125            .map(|&c| {
126                let mut row = BitSet::new(m);
127                row.set(c, true);
128                row
129            })
130            .collect();
131        for (i, &p) in pivots.iter().enumerate() {
132            for (row, &c) in basis.iter_mut().zip(&columns) {
133                row.words_mut()[p / 64] |= u64::from(a[i].get(c)) << (p & 63);
134            }
135        }
136        Some(BitMatrixSolution { particular, basis })
137    }
138
139    pub fn pow(self, mut n: usize) -> Self {
140        assert_eq!(self.shape.0, self.shape.1);
141        let mut result = Self::eye(self.shape);
142        let mut a = self;
143        while n != 0 {
144            if n & 1 != 0 {
145                result = &result * &a;
146            }
147            n >>= 1;
148            if n != 0 {
149                a = &a * &a;
150            }
151        }
152        result
153    }
154
155    fn eliminate(&mut self, cols: usize, full: bool, require_full_rank: bool) -> Vec<usize> {
156        #[cfg(target_arch = "x86_64")]
157        match simd_backend() {
158            // SAFETY: the dispatcher checks the required CPU features.
159            SimdBackend::Avx512 => {
160                return unsafe { self.eliminate_avx512(cols, full, require_full_rank) };
161            }
162            // SAFETY: the dispatcher checks AVX2 support.
163            SimdBackend::Avx2 => {
164                return unsafe { self.eliminate_avx2(cols, full, require_full_rank) };
165            }
166            SimdBackend::Scalar => {}
167        }
168        self.eliminate_impl(cols, full, require_full_rank)
169    }
170
171    // Inlined into each target-feature entry point to vectorize the row operations.
172    #[inline(always)]
173    fn eliminate_impl(&mut self, cols: usize, full: bool, require_full_rank: bool) -> Vec<usize> {
174        let n = self.shape.0;
175        let mut pivots = Vec::with_capacity(n.min(cols));
176        if n < 32 {
177            let mut c = 0;
178            while c < cols {
179                let r = pivots.len();
180                if r == n {
181                    break;
182                }
183                let Some(p) = (r..n).find(|&i| self[i].get(c)) else {
184                    if require_full_rank {
185                        return pivots;
186                    }
187                    c = self.next_column(r, c + 1, cols);
188                    continue;
189                };
190                self.data.swap(r, p);
191                let (upper, lower) = self.data.split_at_mut(r);
192                let (pivot, lower) = lower.split_first_mut().unwrap();
193                for row in lower
194                    .iter_mut()
195                    .chain(upper.iter_mut().take(if full { r } else { 0 }))
196                {
197                    if row.get(c) {
198                        xor(&mut row.words_mut()[c / 64..], &pivot.words()[c / 64..]);
199                    }
200                }
201                pivots.push(c);
202                c += 1;
203            }
204            return pivots;
205        }
206        // Eliminating a shared leading coefficient preserves the two-coefficient bound.
207        if self
208            .data
209            .iter()
210            .all(|row| row.iter_ones().take_while(|&c| c < cols).take(3).count() <= 2)
211        {
212            return self.eliminate_sparse(cols, full, require_full_rank);
213        }
214        let block: usize = if n < 512 {
215            4
216        } else if n < 1536 {
217            8
218        } else {
219            32
220        };
221        let mut table = vec![BitSet::new(self.shape.1); (1 << block.min(8)) * block.div_ceil(8)];
222        let mut reduced = vec![0; n];
223        let mut start = 0;
224        while start < cols {
225            let first = pivots.len();
226            let word = start / 64;
227            reduced.fill(first);
228            let end = cols.min(start + block);
229            let mut c = start;
230            while c < end {
231                let r = pivots.len();
232                let mut pivot = None;
233                for (i, reduced) in reduced.iter_mut().enumerate().skip(r) {
234                    let (upper, lower) = self.data.split_at_mut(i);
235                    let row = &mut lower[0];
236                    for p in *reduced..r {
237                        if row.get(pivots[p]) {
238                            xor(&mut row.words_mut()[word..], &upper[p].words()[word..]);
239                        }
240                    }
241                    *reduced = r;
242                    if row.get(c) {
243                        pivot = Some(i);
244                        break;
245                    }
246                }
247                if let Some(p) = pivot {
248                    self.data.swap(r, p);
249                    reduced.swap(r, p);
250                    pivots.push(c);
251                    c += 1;
252                } else if require_full_rank {
253                    return pivots;
254                } else {
255                    c = self.next_column(r, c + 1, end);
256                }
257            }
258            let rank = pivots.len();
259            if first == rank {
260                let next = self.next_column(rank, start + block, cols);
261                if next == cols {
262                    break;
263                }
264                start = next / block * block;
265                continue;
266            }
267            // Make the panel's pivot columns an identity matrix before indexing its table.
268            for r in (first..rank).rev() {
269                let (upper, lower) = self.data.split_at_mut(r);
270                for row in &mut upper[first..] {
271                    if row.get(pivots[r]) {
272                        xor(&mut row.words_mut()[word..], &lower[0].words()[word..]);
273                    }
274                }
275            }
276            let mut indices = [[0usize; 256]; 4];
277            let mut masks = [0usize; 4];
278            for group in 0..block.div_ceil(8) {
279                let mut keys = [0usize; 256];
280                let mut count = 0;
281                for (row, &c) in pivots[first..].iter().enumerate() {
282                    if (c - start) / 8 != group {
283                        continue;
284                    }
285                    let half = 1 << count;
286                    count += 1;
287                    for index in 0..half {
288                        keys[index + half] = keys[index] | (1 << ((c - start) % 8));
289                        let (lower, upper) = table.split_at_mut(group * 256 + index + half);
290                        let target = &mut upper[0].words_mut()[word..];
291                        let source = &lower[group * 256 + index].words()[word..];
292                        let pivot = &self[first + row].words()[word..];
293                        for ((x, y), z) in target.iter_mut().zip(source).zip(pivot) {
294                            *x = y ^ z;
295                        }
296                    }
297                }
298                masks[group] = keys[(1 << count) - 1];
299                for (i, &key) in keys[..1 << count].iter().enumerate() {
300                    indices[group][key] = i;
301                }
302            }
303            for i in (rank..n).chain(0..if full { first } else { 0 }) {
304                let key = (self[i].words()[word] >> (start & 63)) as usize;
305                let x = indices[0][key & masks[0]];
306                if block <= 8 {
307                    if x != 0 {
308                        xor(&mut self[i].words_mut()[word..], &table[x].words()[word..]);
309                    }
310                    continue;
311                }
312                let y = indices[1][(key >> 8) & masks[1]];
313                let z = indices[2][(key >> 16) & masks[2]];
314                let w = indices[3][(key >> 24) & masks[3]];
315                if x | y | z | w != 0 {
316                    let p = &table[x].words()[word..];
317                    let q = &table[256 + y].words()[word..];
318                    let r = &table[512 + z].words()[word..];
319                    let s = &table[768 + w].words()[word..];
320                    for ((((x, y), z), r), s) in self[i].words_mut()[word..]
321                        .iter_mut()
322                        .zip(p)
323                        .zip(q)
324                        .zip(r)
325                        .zip(s)
326                    {
327                        *x ^= y ^ z ^ r ^ s;
328                    }
329                }
330            }
331            if rank == n {
332                break;
333            }
334            start += block;
335        }
336        pivots
337    }
338
339    fn next_column(&self, row: usize, mut start: usize, cols: usize) -> usize {
340        while start < cols {
341            let word = start / 64;
342            let bits = self.data[row..]
343                .iter()
344                .fold(0, |x, row| x | row.words()[word])
345                & (u64::MAX << (start & 63));
346            if bits != 0 {
347                return (word * 64 + bits.trailing_zeros() as usize).min(cols);
348            }
349            start = (word + 1) * 64;
350        }
351        cols
352    }
353
354    #[inline(always)]
355    fn eliminate_sparse(&mut self, cols: usize, full: bool, require_full_rank: bool) -> Vec<usize> {
356        let n = self.shape.0;
357        let mut basis = vec![n; cols];
358        let mut pivots = Vec::new();
359        for i in 0..n {
360            loop {
361                let Some(c) = self[i].iter_ones().next().filter(|&c| c < cols) else {
362                    if require_full_rank {
363                        return pivots;
364                    }
365                    break;
366                };
367                if basis[c] == n {
368                    basis[c] = i;
369                    pivots.push(c);
370                    break;
371                }
372                let (upper, lower) = self.data.split_at_mut(i);
373                xor(
374                    &mut lower[0].words_mut()[c / 64..],
375                    &upper[basis[c]].words()[c / 64..],
376                );
377            }
378        }
379        pivots.sort_unstable();
380        self.data
381            .sort_by_cached_key(|row| row.iter_ones().next().filter(|&c| c < cols).unwrap_or(cols));
382        if full {
383            for (i, &c) in pivots.iter().enumerate() {
384                basis[c] = i;
385            }
386            for i in (0..pivots.len()).rev() {
387                let next = self[i].iter_ones().take_while(|&c| c < cols).nth(1);
388                if let Some(c) = next
389                    && basis[c] != n
390                {
391                    let (upper, lower) = self.data.split_at_mut(basis[c]);
392                    xor(
393                        &mut upper[i].words_mut()[c / 64..],
394                        &lower[0].words()[c / 64..],
395                    );
396                }
397            }
398        }
399        pivots
400    }
401
402    #[inline(always)]
403    fn mul_impl(&self, rhs: &Self) -> Self {
404        let mut result = Self::zeros((self.shape.0, rhs.shape.1));
405        let ones = self.data.iter().map(BitSet::count_ones).sum::<u64>();
406        let size = self.shape.0 as u64 * self.shape.1 as u64;
407        if self.shape.0 < 256 || self.shape.1 < 32 || ones <= size / 8 {
408            for (a, c) in self.data.iter().zip(&mut result.data) {
409                for j in a.iter_ones() {
410                    xor(c.words_mut(), rhs[j].words());
411                }
412            }
413            return result;
414        }
415        if size - ones <= size / 8 {
416            let mut sum = BitSet::new(rhs.shape.1);
417            for row in &rhs.data {
418                sum ^= row;
419            }
420            for (a, c) in self.data.iter().zip(&mut result.data) {
421                c.words_mut().copy_from_slice(sum.words());
422                for j in (!a.clone()).iter_ones() {
423                    xor(c.words_mut(), rhs[j].words());
424                }
425            }
426            return result;
427        }
428        let width = rhs.shape.1.div_ceil(64);
429        if width == 0 {
430            return result;
431        }
432
433        // Separate the table groups by a cache line to avoid mapping them to the same sets.
434        let group = 256 * width + 8;
435        let mut storage = BitSet::new(8 * group * 64);
436        let table = storage.words_mut();
437        for start in (0..self.shape.1).step_by(64) {
438            for (t, table) in table.chunks_exact_mut(group).enumerate() {
439                let col = start + t * 8;
440                for bit in 0..self.shape.1.saturating_sub(col).min(8) {
441                    let row = rhs[col + bit].words();
442                    let half = (1 << bit) * width;
443                    let (lower, upper) = table.split_at_mut(half);
444                    for (source, dest) in
445                        lower.chunks_exact(width).zip(upper.chunks_exact_mut(width))
446                    {
447                        for ((x, y), z) in dest.iter_mut().zip(source).zip(row) {
448                            *x = y ^ z;
449                        }
450                    }
451                }
452            }
453            for (a, c) in self.data.iter().zip(&mut result.data) {
454                let key = a.words()[start / 64];
455                let offset = (key & 255) as usize * width;
456                let p0 = &table[offset..offset + width];
457                let offset = group + (key >> 8 & 255) as usize * width;
458                let p1 = &table[offset..offset + width];
459                let offset = 2 * group + (key >> 16 & 255) as usize * width;
460                let p2 = &table[offset..offset + width];
461                let offset = 3 * group + (key >> 24 & 255) as usize * width;
462                let p3 = &table[offset..offset + width];
463                let offset = 4 * group + (key >> 32 & 255) as usize * width;
464                let p4 = &table[offset..offset + width];
465                let offset = 5 * group + (key >> 40 & 255) as usize * width;
466                let p5 = &table[offset..offset + width];
467                let offset = 6 * group + (key >> 48 & 255) as usize * width;
468                let p6 = &table[offset..offset + width];
469                let offset = 7 * group + (key >> 56 & 255) as usize * width;
470                let p7 = &table[offset..offset + width];
471                for ((((((((x, p0), p1), p2), p3), p4), p5), p6), p7) in c
472                    .words_mut()
473                    .iter_mut()
474                    .zip(p0)
475                    .zip(p1)
476                    .zip(p2)
477                    .zip(p3)
478                    .zip(p4)
479                    .zip(p5)
480                    .zip(p6)
481                    .zip(p7)
482                {
483                    *x ^= p0 ^ p1 ^ p2 ^ p3 ^ p4 ^ p5 ^ p6 ^ p7;
484                }
485            }
486        }
487        result
488    }
More examples
Hide additional examples
crates/competitive/src/data_structure/bitset.rs (line 112)
92    pub fn to_binary(&self) -> String {
93        const TABLE: [[u8; 8]; 256] = {
94            let mut table = [[b'0'; 8]; 256];
95            let mut i = 0;
96            while i < 256 {
97                let mut j = 0;
98                while j < 8 {
99                    table[i][j] |= ((i >> j) & 1) as u8;
100                    j += 1;
101                }
102                i += 1;
103            }
104            table
105        };
106        let mut bytes = vec![b'0'; self.size.div_ceil(8) * 8];
107        #[cfg(target_arch = "x86_64")]
108        let end = if self.size >= 64 && avx512_enabled() && is_x86_feature_detected!("avx512bw") {
109            let end = self.size / 64 * 64;
110            // SAFETY: AVX-512BW is available; each output chunk holds one 64-bit word.
111            unsafe {
112                simd::write_binary_avx512(&mut bytes[..end], self.words());
113            }
114            end
115        } else if self.size >= 64 && is_x86_feature_detected!("avx2") {
116            let end = self.size / 64 * 64;
117            // SAFETY: AVX2 is available; each output chunk holds one complete 64-bit word.
118            unsafe {
119                simd::write_binary_avx2(&mut bytes[..end], self.words());
120            }
121            end
122        } else {
123            0
124        };
125        #[cfg(not(target_arch = "x86_64"))]
126        let end = 0;
127        for (chunk, &word) in bytes[end..].chunks_mut(64).zip(&self.words()[end / 64..]) {
128            for (i, byte) in chunk.as_chunks_mut::<8>().0.iter_mut().enumerate() {
129                byte.copy_from_slice(&TABLE[(word >> (i * 8) & 255) as usize]);
130            }
131        }
132        bytes.truncate(self.size);
133        // SAFETY: every output byte is ASCII `0` or `1`.
134        unsafe { String::from_utf8_unchecked(bytes) }
135    }
136
137    pub fn ones(size: usize) -> Self {
138        let mut self_ = Self {
139            size,
140            bits: vec![Block([u64::MAX; 8]); size.div_ceil(512)],
141        };
142        self_.trim();
143        self_
144    }
145
146    pub fn get(&self, i: usize) -> bool {
147        self.bits[i >> 9].0[i >> 6 & 7] & (1 << (i & 63)) != 0
148    }
149
150    pub fn set(&mut self, i: usize, b: bool) {
151        let word = &mut self.bits[i >> 9].0[i >> 6 & 7];
152        if b {
153            *word |= 1 << (i & 63);
154        } else {
155            *word &= !(1 << (i & 63));
156        }
157    }
158
159    /// Clears all bits.
160    pub fn reset(&mut self) {
161        self.bits.fill(Block::default());
162    }
163
164    /// Sets all bits to `value`.
165    pub fn fill(&mut self, value: bool) {
166        self.bits.fill(Block([if value { u64::MAX } else { 0 }; 8]));
167        self.trim();
168    }
169
170    /// Tests whether any bit is set.
171    #[inline]
172    pub fn any(&self) -> bool {
173        !self.none()
174    }
175
176    /// Tests whether all bits are unset.
177    #[inline]
178    pub fn none(&self) -> bool {
179        #[cfg(target_arch = "x86_64")]
180        if self.bits.len() >= SIMD_MIN_BLOCKS {
181            if self.bits[0].0[0] != 0 {
182                return false;
183            }
184            if avx512_enabled() && is_x86_feature_detected!("avx512f") {
185                // SAFETY: blocks are 64-byte aligned and feature detection checked AVX-512F.
186                return unsafe { simd::none_avx512(&self.bits) };
187            }
188            if is_x86_feature_detected!("avx2") {
189                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
190                return unsafe { simd::none_avx2(&self.bits) };
191            }
192        }
193        self.words().iter().all(|&word| word == 0)
194    }
195
196    /// Tests whether all bits are set.
197    #[inline(always)]
198    pub fn all(&self) -> bool {
199        let words = self.words();
200        let full_words = self.size >> 6;
201        #[cfg(target_arch = "x86_64")]
202        if self.size >> 9 >= SIMD_MIN_BLOCKS {
203            let full_blocks = self.size >> 9;
204            if words[0] != u64::MAX {
205                return false;
206            }
207            let full_blocks_are_set = if avx512_enabled() && is_x86_feature_detected!("avx512f") {
208                // SAFETY: blocks are 64-byte aligned and feature detection checked AVX-512F.
209                Some(unsafe { simd::all_avx512(&self.bits[..full_blocks]) })
210            } else if is_x86_feature_detected!("avx2") {
211                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
212                Some(unsafe { simd::all_avx2(&self.bits[..full_blocks]) })
213            } else {
214                None
215            };
216            if let Some(full_blocks_are_set) = full_blocks_are_set {
217                return full_blocks_are_set
218                    && words[full_blocks * 8..full_words]
219                        .iter()
220                        .all(|&word| word == u64::MAX)
221                    && (self.size & 63 == 0
222                        || words[full_words] == u64::MAX >> (64 - (self.size & 63)));
223            }
224        }
225        if self.size & 63 == 0 {
226            return words.iter().all(|&word| word == u64::MAX);
227        }
228        words[..full_words].iter().all(|&word| word == u64::MAX)
229            && words[full_words] == u64::MAX >> (64 - (self.size & 63))
230    }
231
232    /// Iterates over set-bit indices in ascending order.
233    pub fn iter_ones(&self) -> impl Iterator<Item = usize> + '_ {
234        self.words()
235            .iter()
236            .copied()
237            .enumerate()
238            .flat_map(|(word_index, mut word)| {
239                std::iter::from_fn(move || {
240                    if word == 0 {
241                        None
242                    } else {
243                        let bit = word.trailing_zeros() as usize;
244                        word &= word - 1;
245                        Some((word_index << 6) | bit)
246                    }
247                })
248            })
249    }
250
251    /// Counts set bits.
252    #[inline]
253    pub fn count_ones(&self) -> u64 {
254        let words = self.words();
255        #[cfg(target_arch = "x86_64")]
256        if words.len() >= 8 {
257            if avx512_enabled()
258                && is_x86_feature_detected!("avx512f")
259                && is_x86_feature_detected!("avx512vpopcntdq")
260            {
261                // SAFETY: blocks are aligned and feature detection checked both requirements.
262                return unsafe { simd::count_ones_avx512(&self.bits) };
263            }
264            if is_x86_feature_detected!("avx2") {
265                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
266                return unsafe { simd::count_ones_avx2(&self.bits) };
267            }
268        }
269        words.iter().map(|word| word.count_ones() as u64).sum()
270    }
271
272    /// Counts unset bits.
273    #[inline]
274    pub fn count_zeros(&self) -> u64 {
275        self.size as u64 - self.count_ones()
276    }
277
278    pub fn push(&mut self, b: bool) {
279        if self.size & 511 == 0 {
280            self.bits.push(Block::default());
281        }
282        if b {
283            self.bits[self.size >> 9].0[self.size >> 6 & 7] |= 1 << (self.size & 63);
284        }
285        self.size += 1;
286    }
287
288    pub fn resize(&mut self, new_size: usize) {
289        match self.size.cmp(&new_size) {
290            Ordering::Less => self.bits.resize(new_size.div_ceil(512), Block::default()),
291            Ordering::Equal => {}
292            Ordering::Greater => self.bits.truncate(new_size.div_ceil(512)),
293        }
294        self.size = new_size;
295        self.trim();
296    }
297
298    /// Assigns `self | (self << rhs)` to `self`.
299    #[inline]
300    pub fn shl_bitor_assign(&mut self, rhs: usize) {
301        self.shift_left::<true>(rhs);
302    }
303
304    /// Assigns `self | (self >> rhs)` to `self`.
305    #[inline]
306    pub fn shr_bitor_assign(&mut self, rhs: usize) {
307        self.shift_right::<true>(rhs);
308    }
309
310    /// Returns words in increasing bit-index order; unused high bits in the last word are zero.
311    pub fn words(&self) -> &[u64] {
312        // SAFETY: `Block` is exactly eight contiguous `u64`s, with no trailing padding.
313        unsafe { std::slice::from_raw_parts(self.bits.as_ptr().cast(), self.size.div_ceil(64)) }
314    }
315
316    /// Returns mutable words in increasing bit-index order.
317    /// Callers must keep unused high bits in the last word zero.
318    pub fn words_mut(&mut self) -> &mut [u64] {
319        let len = self.size.div_ceil(64);
320        // SAFETY: `Block` is exactly eight contiguous `u64`s, with no trailing padding.
321        unsafe { std::slice::from_raw_parts_mut(self.bits.as_mut_ptr().cast(), len) }
322    }
323
324    fn trim(&mut self) {
325        let used_words = self.size.div_ceil(64) & 7;
326        if let Some(last) = self.bits.last_mut() {
327            if self.size & 63 != 0 {
328                last.0[(self.size >> 6) & 7] &= u64::MAX >> (64 - (self.size & 63));
329            }
330            if used_words != 0 {
331                last.0[used_words..].fill(0);
332            }
333        }
334    }
335
336    #[inline]
337    fn bitop_assign<const OP: u8>(&mut self, rhs: &Self) {
338        assert_eq!(
339            self.size, rhs.size,
340            "bitwise operations require equal lengths"
341        );
342        #[cfg(target_arch = "x86_64")]
343        if self.bits.len() >= SIMD_MIN_BLOCKS {
344            if avx512_enabled() && is_x86_feature_detected!("avx512f") {
345                // SAFETY: blocks are 64-byte aligned and feature detection checked AVX-512F.
346                unsafe { simd::bitop_avx512::<OP>(&mut self.bits, &rhs.bits) };
347                return;
348            }
349            if is_x86_feature_detected!("avx2") {
350                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
351                unsafe { simd::bitop_avx2::<OP>(&mut self.bits, &rhs.bits) };
352                return;
353            }
354        }
355        for (lhs, &rhs) in self.words_mut().iter_mut().zip(rhs.words()) {
356            *lhs = match OP {
357                BIT_AND => *lhs & rhs,
358                BIT_OR => *lhs | rhs,
359                BIT_XOR => *lhs ^ rhs,
360                _ => unreachable!(),
361            };
362        }
363    }
Source

pub fn words_mut(&mut self) -> &mut [u64]

Returns mutable words in increasing bit-index order. Callers must keep unused high bits in the last word zero.

Examples found in repository?
crates/competitive/src/math/bit_matrix.rs (line 36)
33    pub fn new_with(shape: (usize, usize), mut f: impl FnMut(usize, usize) -> bool) -> Self {
34        let mut a = Self::zeros(shape);
35        for (i, row) in a.data.iter_mut().enumerate() {
36            for (w, word) in row.words_mut().iter_mut().enumerate() {
37                for j in w * 64..shape.1.min((w + 1) * 64) {
38                    *word |= u64::from(f(i, j)) << (j & 63);
39                }
40            }
41        }
42        a
43    }
44
45    pub fn eye(shape: (usize, usize)) -> Self {
46        let mut a = Self::zeros(shape);
47        for i in 0..shape.0.min(shape.1) {
48            a[i].set(i, true);
49        }
50        a
51    }
52
53    pub fn transpose(&self) -> Self {
54        let mut a = Self::zeros((self.shape.1, self.shape.0));
55        for (i, row) in self.data.iter().enumerate() {
56            for j in row.iter_ones() {
57                a[j].set(i, true);
58            }
59        }
60        a
61    }
62
63    /// Replaces the matrix with reduced row echelon form and returns its pivot columns.
64    pub fn row_reduction(&mut self) -> Vec<usize> {
65        self.eliminate(self.shape.1, true, false)
66    }
67
68    /// Replaces the matrix with row echelon form and returns its rank.
69    pub fn rank(&mut self) -> usize {
70        self.eliminate(self.shape.1, false, false).len()
71    }
72
73    /// Computes the determinant in place. The matrix must be square.
74    pub fn determinant(&mut self) -> bool {
75        assert_eq!(self.shape.0, self.shape.1);
76        self.eliminate(self.shape.1, false, true).len() == self.shape.0
77    }
78
79    /// Returns the inverse, or `None` if singular. The matrix must be square.
80    pub fn inverse(&self) -> Option<Self> {
81        let (n, m) = self.shape;
82        assert_eq!(n, m);
83        let mut a = Self::zeros((n, 2 * n));
84        for i in 0..n {
85            a[i].words_mut()[..self[i].words().len()].copy_from_slice(self[i].words());
86            a[i].set(n + i, true);
87        }
88        if a.eliminate(n, true, true).len() != n {
89            return None;
90        }
91        for row in &mut a.data {
92            *row >>= n;
93        }
94        let mut inverse = Self::zeros((n, n));
95        for (row, source) in inverse.data.iter_mut().zip(&a.data) {
96            let len = row.words().len();
97            row.words_mut().copy_from_slice(&source.words()[..len]);
98        }
99        Some(inverse)
100    }
101
102    /// Returns a particular solution and a basis of the kernel, or `None` if inconsistent.
103    /// `b.len()` must equal the number of rows.
104    pub fn solve_system_of_linear_equations(&self, b: &BitSet) -> Option<BitMatrixSolution> {
105        let (n, m) = self.shape;
106        assert_eq!(b.len(), n);
107        let mut a = Self::zeros((n, m + 1));
108        for i in 0..n {
109            a[i].words_mut()[..self[i].words().len()].copy_from_slice(self[i].words());
110            a[i].set(m, b.get(i));
111        }
112        let pivots = a.eliminate(m, true, false);
113        if a.data[pivots.len()..].iter().any(|row| row.get(m)) {
114            return None;
115        }
116        let mut particular = BitSet::new(m);
117        let mut free = BitSet::ones(m);
118        for (i, &c) in pivots.iter().enumerate() {
119            particular.set(c, a[i].get(m));
120            free.set(c, false);
121        }
122        let columns: Vec<_> = free.iter_ones().collect();
123        let mut basis: Vec<_> = columns
124            .iter()
125            .map(|&c| {
126                let mut row = BitSet::new(m);
127                row.set(c, true);
128                row
129            })
130            .collect();
131        for (i, &p) in pivots.iter().enumerate() {
132            for (row, &c) in basis.iter_mut().zip(&columns) {
133                row.words_mut()[p / 64] |= u64::from(a[i].get(c)) << (p & 63);
134            }
135        }
136        Some(BitMatrixSolution { particular, basis })
137    }
138
139    pub fn pow(self, mut n: usize) -> Self {
140        assert_eq!(self.shape.0, self.shape.1);
141        let mut result = Self::eye(self.shape);
142        let mut a = self;
143        while n != 0 {
144            if n & 1 != 0 {
145                result = &result * &a;
146            }
147            n >>= 1;
148            if n != 0 {
149                a = &a * &a;
150            }
151        }
152        result
153    }
154
155    fn eliminate(&mut self, cols: usize, full: bool, require_full_rank: bool) -> Vec<usize> {
156        #[cfg(target_arch = "x86_64")]
157        match simd_backend() {
158            // SAFETY: the dispatcher checks the required CPU features.
159            SimdBackend::Avx512 => {
160                return unsafe { self.eliminate_avx512(cols, full, require_full_rank) };
161            }
162            // SAFETY: the dispatcher checks AVX2 support.
163            SimdBackend::Avx2 => {
164                return unsafe { self.eliminate_avx2(cols, full, require_full_rank) };
165            }
166            SimdBackend::Scalar => {}
167        }
168        self.eliminate_impl(cols, full, require_full_rank)
169    }
170
171    // Inlined into each target-feature entry point to vectorize the row operations.
172    #[inline(always)]
173    fn eliminate_impl(&mut self, cols: usize, full: bool, require_full_rank: bool) -> Vec<usize> {
174        let n = self.shape.0;
175        let mut pivots = Vec::with_capacity(n.min(cols));
176        if n < 32 {
177            let mut c = 0;
178            while c < cols {
179                let r = pivots.len();
180                if r == n {
181                    break;
182                }
183                let Some(p) = (r..n).find(|&i| self[i].get(c)) else {
184                    if require_full_rank {
185                        return pivots;
186                    }
187                    c = self.next_column(r, c + 1, cols);
188                    continue;
189                };
190                self.data.swap(r, p);
191                let (upper, lower) = self.data.split_at_mut(r);
192                let (pivot, lower) = lower.split_first_mut().unwrap();
193                for row in lower
194                    .iter_mut()
195                    .chain(upper.iter_mut().take(if full { r } else { 0 }))
196                {
197                    if row.get(c) {
198                        xor(&mut row.words_mut()[c / 64..], &pivot.words()[c / 64..]);
199                    }
200                }
201                pivots.push(c);
202                c += 1;
203            }
204            return pivots;
205        }
206        // Eliminating a shared leading coefficient preserves the two-coefficient bound.
207        if self
208            .data
209            .iter()
210            .all(|row| row.iter_ones().take_while(|&c| c < cols).take(3).count() <= 2)
211        {
212            return self.eliminate_sparse(cols, full, require_full_rank);
213        }
214        let block: usize = if n < 512 {
215            4
216        } else if n < 1536 {
217            8
218        } else {
219            32
220        };
221        let mut table = vec![BitSet::new(self.shape.1); (1 << block.min(8)) * block.div_ceil(8)];
222        let mut reduced = vec![0; n];
223        let mut start = 0;
224        while start < cols {
225            let first = pivots.len();
226            let word = start / 64;
227            reduced.fill(first);
228            let end = cols.min(start + block);
229            let mut c = start;
230            while c < end {
231                let r = pivots.len();
232                let mut pivot = None;
233                for (i, reduced) in reduced.iter_mut().enumerate().skip(r) {
234                    let (upper, lower) = self.data.split_at_mut(i);
235                    let row = &mut lower[0];
236                    for p in *reduced..r {
237                        if row.get(pivots[p]) {
238                            xor(&mut row.words_mut()[word..], &upper[p].words()[word..]);
239                        }
240                    }
241                    *reduced = r;
242                    if row.get(c) {
243                        pivot = Some(i);
244                        break;
245                    }
246                }
247                if let Some(p) = pivot {
248                    self.data.swap(r, p);
249                    reduced.swap(r, p);
250                    pivots.push(c);
251                    c += 1;
252                } else if require_full_rank {
253                    return pivots;
254                } else {
255                    c = self.next_column(r, c + 1, end);
256                }
257            }
258            let rank = pivots.len();
259            if first == rank {
260                let next = self.next_column(rank, start + block, cols);
261                if next == cols {
262                    break;
263                }
264                start = next / block * block;
265                continue;
266            }
267            // Make the panel's pivot columns an identity matrix before indexing its table.
268            for r in (first..rank).rev() {
269                let (upper, lower) = self.data.split_at_mut(r);
270                for row in &mut upper[first..] {
271                    if row.get(pivots[r]) {
272                        xor(&mut row.words_mut()[word..], &lower[0].words()[word..]);
273                    }
274                }
275            }
276            let mut indices = [[0usize; 256]; 4];
277            let mut masks = [0usize; 4];
278            for group in 0..block.div_ceil(8) {
279                let mut keys = [0usize; 256];
280                let mut count = 0;
281                for (row, &c) in pivots[first..].iter().enumerate() {
282                    if (c - start) / 8 != group {
283                        continue;
284                    }
285                    let half = 1 << count;
286                    count += 1;
287                    for index in 0..half {
288                        keys[index + half] = keys[index] | (1 << ((c - start) % 8));
289                        let (lower, upper) = table.split_at_mut(group * 256 + index + half);
290                        let target = &mut upper[0].words_mut()[word..];
291                        let source = &lower[group * 256 + index].words()[word..];
292                        let pivot = &self[first + row].words()[word..];
293                        for ((x, y), z) in target.iter_mut().zip(source).zip(pivot) {
294                            *x = y ^ z;
295                        }
296                    }
297                }
298                masks[group] = keys[(1 << count) - 1];
299                for (i, &key) in keys[..1 << count].iter().enumerate() {
300                    indices[group][key] = i;
301                }
302            }
303            for i in (rank..n).chain(0..if full { first } else { 0 }) {
304                let key = (self[i].words()[word] >> (start & 63)) as usize;
305                let x = indices[0][key & masks[0]];
306                if block <= 8 {
307                    if x != 0 {
308                        xor(&mut self[i].words_mut()[word..], &table[x].words()[word..]);
309                    }
310                    continue;
311                }
312                let y = indices[1][(key >> 8) & masks[1]];
313                let z = indices[2][(key >> 16) & masks[2]];
314                let w = indices[3][(key >> 24) & masks[3]];
315                if x | y | z | w != 0 {
316                    let p = &table[x].words()[word..];
317                    let q = &table[256 + y].words()[word..];
318                    let r = &table[512 + z].words()[word..];
319                    let s = &table[768 + w].words()[word..];
320                    for ((((x, y), z), r), s) in self[i].words_mut()[word..]
321                        .iter_mut()
322                        .zip(p)
323                        .zip(q)
324                        .zip(r)
325                        .zip(s)
326                    {
327                        *x ^= y ^ z ^ r ^ s;
328                    }
329                }
330            }
331            if rank == n {
332                break;
333            }
334            start += block;
335        }
336        pivots
337    }
338
339    fn next_column(&self, row: usize, mut start: usize, cols: usize) -> usize {
340        while start < cols {
341            let word = start / 64;
342            let bits = self.data[row..]
343                .iter()
344                .fold(0, |x, row| x | row.words()[word])
345                & (u64::MAX << (start & 63));
346            if bits != 0 {
347                return (word * 64 + bits.trailing_zeros() as usize).min(cols);
348            }
349            start = (word + 1) * 64;
350        }
351        cols
352    }
353
354    #[inline(always)]
355    fn eliminate_sparse(&mut self, cols: usize, full: bool, require_full_rank: bool) -> Vec<usize> {
356        let n = self.shape.0;
357        let mut basis = vec![n; cols];
358        let mut pivots = Vec::new();
359        for i in 0..n {
360            loop {
361                let Some(c) = self[i].iter_ones().next().filter(|&c| c < cols) else {
362                    if require_full_rank {
363                        return pivots;
364                    }
365                    break;
366                };
367                if basis[c] == n {
368                    basis[c] = i;
369                    pivots.push(c);
370                    break;
371                }
372                let (upper, lower) = self.data.split_at_mut(i);
373                xor(
374                    &mut lower[0].words_mut()[c / 64..],
375                    &upper[basis[c]].words()[c / 64..],
376                );
377            }
378        }
379        pivots.sort_unstable();
380        self.data
381            .sort_by_cached_key(|row| row.iter_ones().next().filter(|&c| c < cols).unwrap_or(cols));
382        if full {
383            for (i, &c) in pivots.iter().enumerate() {
384                basis[c] = i;
385            }
386            for i in (0..pivots.len()).rev() {
387                let next = self[i].iter_ones().take_while(|&c| c < cols).nth(1);
388                if let Some(c) = next
389                    && basis[c] != n
390                {
391                    let (upper, lower) = self.data.split_at_mut(basis[c]);
392                    xor(
393                        &mut upper[i].words_mut()[c / 64..],
394                        &lower[0].words()[c / 64..],
395                    );
396                }
397            }
398        }
399        pivots
400    }
401
402    #[inline(always)]
403    fn mul_impl(&self, rhs: &Self) -> Self {
404        let mut result = Self::zeros((self.shape.0, rhs.shape.1));
405        let ones = self.data.iter().map(BitSet::count_ones).sum::<u64>();
406        let size = self.shape.0 as u64 * self.shape.1 as u64;
407        if self.shape.0 < 256 || self.shape.1 < 32 || ones <= size / 8 {
408            for (a, c) in self.data.iter().zip(&mut result.data) {
409                for j in a.iter_ones() {
410                    xor(c.words_mut(), rhs[j].words());
411                }
412            }
413            return result;
414        }
415        if size - ones <= size / 8 {
416            let mut sum = BitSet::new(rhs.shape.1);
417            for row in &rhs.data {
418                sum ^= row;
419            }
420            for (a, c) in self.data.iter().zip(&mut result.data) {
421                c.words_mut().copy_from_slice(sum.words());
422                for j in (!a.clone()).iter_ones() {
423                    xor(c.words_mut(), rhs[j].words());
424                }
425            }
426            return result;
427        }
428        let width = rhs.shape.1.div_ceil(64);
429        if width == 0 {
430            return result;
431        }
432
433        // Separate the table groups by a cache line to avoid mapping them to the same sets.
434        let group = 256 * width + 8;
435        let mut storage = BitSet::new(8 * group * 64);
436        let table = storage.words_mut();
437        for start in (0..self.shape.1).step_by(64) {
438            for (t, table) in table.chunks_exact_mut(group).enumerate() {
439                let col = start + t * 8;
440                for bit in 0..self.shape.1.saturating_sub(col).min(8) {
441                    let row = rhs[col + bit].words();
442                    let half = (1 << bit) * width;
443                    let (lower, upper) = table.split_at_mut(half);
444                    for (source, dest) in
445                        lower.chunks_exact(width).zip(upper.chunks_exact_mut(width))
446                    {
447                        for ((x, y), z) in dest.iter_mut().zip(source).zip(row) {
448                            *x = y ^ z;
449                        }
450                    }
451                }
452            }
453            for (a, c) in self.data.iter().zip(&mut result.data) {
454                let key = a.words()[start / 64];
455                let offset = (key & 255) as usize * width;
456                let p0 = &table[offset..offset + width];
457                let offset = group + (key >> 8 & 255) as usize * width;
458                let p1 = &table[offset..offset + width];
459                let offset = 2 * group + (key >> 16 & 255) as usize * width;
460                let p2 = &table[offset..offset + width];
461                let offset = 3 * group + (key >> 24 & 255) as usize * width;
462                let p3 = &table[offset..offset + width];
463                let offset = 4 * group + (key >> 32 & 255) as usize * width;
464                let p4 = &table[offset..offset + width];
465                let offset = 5 * group + (key >> 40 & 255) as usize * width;
466                let p5 = &table[offset..offset + width];
467                let offset = 6 * group + (key >> 48 & 255) as usize * width;
468                let p6 = &table[offset..offset + width];
469                let offset = 7 * group + (key >> 56 & 255) as usize * width;
470                let p7 = &table[offset..offset + width];
471                for ((((((((x, p0), p1), p2), p3), p4), p5), p6), p7) in c
472                    .words_mut()
473                    .iter_mut()
474                    .zip(p0)
475                    .zip(p1)
476                    .zip(p2)
477                    .zip(p3)
478                    .zip(p4)
479                    .zip(p5)
480                    .zip(p6)
481                    .zip(p7)
482                {
483                    *x ^= p0 ^ p1 ^ p2 ^ p3 ^ p4 ^ p5 ^ p6 ^ p7;
484                }
485            }
486        }
487        result
488    }
More examples
Hide additional examples
crates/competitive/src/data_structure/bitset.rs (line 52)
45    pub fn from_binary(s: &str) -> Option<Self> {
46        let bytes = s.as_bytes();
47        let mut bits = Self::new(bytes.len());
48        let end = bytes.len() / 64 * 64;
49        #[cfg(target_arch = "x86_64")]
50        let parsed = if avx512_enabled() && is_x86_feature_detected!("avx512bw") {
51            // SAFETY: AVX-512BW is available; each complete chunk contains 64 bytes.
52            unsafe { simd::parse_binary_avx512(&bytes[..end], bits.words_mut()) }
53        } else if is_x86_feature_detected!("avx2") {
54            // SAFETY: AVX2 is available; each complete chunk contains 64 bytes.
55            unsafe { simd::parse_binary_avx2(&bytes[..end], bits.words_mut()) }
56        } else {
57            Self::parse_binary_scalar(&bytes[..end], bits.words_mut())
58        };
59        #[cfg(not(target_arch = "x86_64"))]
60        let parsed = Self::parse_binary_scalar(&bytes[..end], bits.words_mut());
61        if !parsed {
62            return None;
63        }
64        if end != bytes.len() {
65            let mut word = 0;
66            for (i, &b) in bytes[end..].iter().enumerate() {
67                if b != b'0' && b != b'1' {
68                    return None;
69                }
70                word |= u64::from(b & 1) << i;
71            }
72            bits.words_mut()[end / 64] = word;
73        }
74        Some(bits)
75    }
76
77    fn parse_binary_scalar(bytes: &[u8], words: &mut [u64]) -> bool {
78        for (chunk, word) in bytes.as_chunks::<64>().0.iter().zip(words) {
79            for (i, byte) in chunk.as_chunks::<8>().0.iter().enumerate() {
80                let x = u64::from_le_bytes(*byte);
81                if x & 0xfefe_fefe_fefe_fefe != 0x3030_3030_3030_3030 {
82                    return false;
83                }
84                *word |= ((x & 0x0101_0101_0101_0101).wrapping_mul(0x0102_0408_1020_4080) >> 56)
85                    << (i * 8);
86            }
87        }
88        true
89    }
90
91    /// Returns ASCII `0` and `1` in increasing bit-index order.
92    pub fn to_binary(&self) -> String {
93        const TABLE: [[u8; 8]; 256] = {
94            let mut table = [[b'0'; 8]; 256];
95            let mut i = 0;
96            while i < 256 {
97                let mut j = 0;
98                while j < 8 {
99                    table[i][j] |= ((i >> j) & 1) as u8;
100                    j += 1;
101                }
102                i += 1;
103            }
104            table
105        };
106        let mut bytes = vec![b'0'; self.size.div_ceil(8) * 8];
107        #[cfg(target_arch = "x86_64")]
108        let end = if self.size >= 64 && avx512_enabled() && is_x86_feature_detected!("avx512bw") {
109            let end = self.size / 64 * 64;
110            // SAFETY: AVX-512BW is available; each output chunk holds one 64-bit word.
111            unsafe {
112                simd::write_binary_avx512(&mut bytes[..end], self.words());
113            }
114            end
115        } else if self.size >= 64 && is_x86_feature_detected!("avx2") {
116            let end = self.size / 64 * 64;
117            // SAFETY: AVX2 is available; each output chunk holds one complete 64-bit word.
118            unsafe {
119                simd::write_binary_avx2(&mut bytes[..end], self.words());
120            }
121            end
122        } else {
123            0
124        };
125        #[cfg(not(target_arch = "x86_64"))]
126        let end = 0;
127        for (chunk, &word) in bytes[end..].chunks_mut(64).zip(&self.words()[end / 64..]) {
128            for (i, byte) in chunk.as_chunks_mut::<8>().0.iter_mut().enumerate() {
129                byte.copy_from_slice(&TABLE[(word >> (i * 8) & 255) as usize]);
130            }
131        }
132        bytes.truncate(self.size);
133        // SAFETY: every output byte is ASCII `0` or `1`.
134        unsafe { String::from_utf8_unchecked(bytes) }
135    }
136
137    pub fn ones(size: usize) -> Self {
138        let mut self_ = Self {
139            size,
140            bits: vec![Block([u64::MAX; 8]); size.div_ceil(512)],
141        };
142        self_.trim();
143        self_
144    }
145
146    pub fn get(&self, i: usize) -> bool {
147        self.bits[i >> 9].0[i >> 6 & 7] & (1 << (i & 63)) != 0
148    }
149
150    pub fn set(&mut self, i: usize, b: bool) {
151        let word = &mut self.bits[i >> 9].0[i >> 6 & 7];
152        if b {
153            *word |= 1 << (i & 63);
154        } else {
155            *word &= !(1 << (i & 63));
156        }
157    }
158
159    /// Clears all bits.
160    pub fn reset(&mut self) {
161        self.bits.fill(Block::default());
162    }
163
164    /// Sets all bits to `value`.
165    pub fn fill(&mut self, value: bool) {
166        self.bits.fill(Block([if value { u64::MAX } else { 0 }; 8]));
167        self.trim();
168    }
169
170    /// Tests whether any bit is set.
171    #[inline]
172    pub fn any(&self) -> bool {
173        !self.none()
174    }
175
176    /// Tests whether all bits are unset.
177    #[inline]
178    pub fn none(&self) -> bool {
179        #[cfg(target_arch = "x86_64")]
180        if self.bits.len() >= SIMD_MIN_BLOCKS {
181            if self.bits[0].0[0] != 0 {
182                return false;
183            }
184            if avx512_enabled() && is_x86_feature_detected!("avx512f") {
185                // SAFETY: blocks are 64-byte aligned and feature detection checked AVX-512F.
186                return unsafe { simd::none_avx512(&self.bits) };
187            }
188            if is_x86_feature_detected!("avx2") {
189                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
190                return unsafe { simd::none_avx2(&self.bits) };
191            }
192        }
193        self.words().iter().all(|&word| word == 0)
194    }
195
196    /// Tests whether all bits are set.
197    #[inline(always)]
198    pub fn all(&self) -> bool {
199        let words = self.words();
200        let full_words = self.size >> 6;
201        #[cfg(target_arch = "x86_64")]
202        if self.size >> 9 >= SIMD_MIN_BLOCKS {
203            let full_blocks = self.size >> 9;
204            if words[0] != u64::MAX {
205                return false;
206            }
207            let full_blocks_are_set = if avx512_enabled() && is_x86_feature_detected!("avx512f") {
208                // SAFETY: blocks are 64-byte aligned and feature detection checked AVX-512F.
209                Some(unsafe { simd::all_avx512(&self.bits[..full_blocks]) })
210            } else if is_x86_feature_detected!("avx2") {
211                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
212                Some(unsafe { simd::all_avx2(&self.bits[..full_blocks]) })
213            } else {
214                None
215            };
216            if let Some(full_blocks_are_set) = full_blocks_are_set {
217                return full_blocks_are_set
218                    && words[full_blocks * 8..full_words]
219                        .iter()
220                        .all(|&word| word == u64::MAX)
221                    && (self.size & 63 == 0
222                        || words[full_words] == u64::MAX >> (64 - (self.size & 63)));
223            }
224        }
225        if self.size & 63 == 0 {
226            return words.iter().all(|&word| word == u64::MAX);
227        }
228        words[..full_words].iter().all(|&word| word == u64::MAX)
229            && words[full_words] == u64::MAX >> (64 - (self.size & 63))
230    }
231
232    /// Iterates over set-bit indices in ascending order.
233    pub fn iter_ones(&self) -> impl Iterator<Item = usize> + '_ {
234        self.words()
235            .iter()
236            .copied()
237            .enumerate()
238            .flat_map(|(word_index, mut word)| {
239                std::iter::from_fn(move || {
240                    if word == 0 {
241                        None
242                    } else {
243                        let bit = word.trailing_zeros() as usize;
244                        word &= word - 1;
245                        Some((word_index << 6) | bit)
246                    }
247                })
248            })
249    }
250
251    /// Counts set bits.
252    #[inline]
253    pub fn count_ones(&self) -> u64 {
254        let words = self.words();
255        #[cfg(target_arch = "x86_64")]
256        if words.len() >= 8 {
257            if avx512_enabled()
258                && is_x86_feature_detected!("avx512f")
259                && is_x86_feature_detected!("avx512vpopcntdq")
260            {
261                // SAFETY: blocks are aligned and feature detection checked both requirements.
262                return unsafe { simd::count_ones_avx512(&self.bits) };
263            }
264            if is_x86_feature_detected!("avx2") {
265                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
266                return unsafe { simd::count_ones_avx2(&self.bits) };
267            }
268        }
269        words.iter().map(|word| word.count_ones() as u64).sum()
270    }
271
272    /// Counts unset bits.
273    #[inline]
274    pub fn count_zeros(&self) -> u64 {
275        self.size as u64 - self.count_ones()
276    }
277
278    pub fn push(&mut self, b: bool) {
279        if self.size & 511 == 0 {
280            self.bits.push(Block::default());
281        }
282        if b {
283            self.bits[self.size >> 9].0[self.size >> 6 & 7] |= 1 << (self.size & 63);
284        }
285        self.size += 1;
286    }
287
288    pub fn resize(&mut self, new_size: usize) {
289        match self.size.cmp(&new_size) {
290            Ordering::Less => self.bits.resize(new_size.div_ceil(512), Block::default()),
291            Ordering::Equal => {}
292            Ordering::Greater => self.bits.truncate(new_size.div_ceil(512)),
293        }
294        self.size = new_size;
295        self.trim();
296    }
297
298    /// Assigns `self | (self << rhs)` to `self`.
299    #[inline]
300    pub fn shl_bitor_assign(&mut self, rhs: usize) {
301        self.shift_left::<true>(rhs);
302    }
303
304    /// Assigns `self | (self >> rhs)` to `self`.
305    #[inline]
306    pub fn shr_bitor_assign(&mut self, rhs: usize) {
307        self.shift_right::<true>(rhs);
308    }
309
310    /// Returns words in increasing bit-index order; unused high bits in the last word are zero.
311    pub fn words(&self) -> &[u64] {
312        // SAFETY: `Block` is exactly eight contiguous `u64`s, with no trailing padding.
313        unsafe { std::slice::from_raw_parts(self.bits.as_ptr().cast(), self.size.div_ceil(64)) }
314    }
315
316    /// Returns mutable words in increasing bit-index order.
317    /// Callers must keep unused high bits in the last word zero.
318    pub fn words_mut(&mut self) -> &mut [u64] {
319        let len = self.size.div_ceil(64);
320        // SAFETY: `Block` is exactly eight contiguous `u64`s, with no trailing padding.
321        unsafe { std::slice::from_raw_parts_mut(self.bits.as_mut_ptr().cast(), len) }
322    }
323
324    fn trim(&mut self) {
325        let used_words = self.size.div_ceil(64) & 7;
326        if let Some(last) = self.bits.last_mut() {
327            if self.size & 63 != 0 {
328                last.0[(self.size >> 6) & 7] &= u64::MAX >> (64 - (self.size & 63));
329            }
330            if used_words != 0 {
331                last.0[used_words..].fill(0);
332            }
333        }
334    }
335
336    #[inline]
337    fn bitop_assign<const OP: u8>(&mut self, rhs: &Self) {
338        assert_eq!(
339            self.size, rhs.size,
340            "bitwise operations require equal lengths"
341        );
342        #[cfg(target_arch = "x86_64")]
343        if self.bits.len() >= SIMD_MIN_BLOCKS {
344            if avx512_enabled() && is_x86_feature_detected!("avx512f") {
345                // SAFETY: blocks are 64-byte aligned and feature detection checked AVX-512F.
346                unsafe { simd::bitop_avx512::<OP>(&mut self.bits, &rhs.bits) };
347                return;
348            }
349            if is_x86_feature_detected!("avx2") {
350                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
351                unsafe { simd::bitop_avx2::<OP>(&mut self.bits, &rhs.bits) };
352                return;
353            }
354        }
355        for (lhs, &rhs) in self.words_mut().iter_mut().zip(rhs.words()) {
356            *lhs = match OP {
357                BIT_AND => *lhs & rhs,
358                BIT_OR => *lhs | rhs,
359                BIT_XOR => *lhs ^ rhs,
360                _ => unreachable!(),
361            };
362        }
363    }
364
365    #[inline]
366    fn shift_left<const OR_ASSIGN: bool>(&mut self, rhs: usize) {
367        if rhs == 0 {
368            return;
369        }
370        if rhs >= self.size {
371            if !OR_ASSIGN {
372                self.reset();
373            }
374            return;
375        }
376        #[cfg(target_arch = "x86_64")]
377        if self.bits.len() >= SIMD_MIN_BLOCKS {
378            if avx512_enabled()
379                && is_x86_feature_detected!("avx512f")
380                && is_x86_feature_detected!("avx512vbmi2")
381            {
382                // SAFETY: blocks are aligned and feature detection checked AVX-512F and VBMI2.
383                unsafe { simd::shift_left_avx512::<OR_ASSIGN>(&mut self.bits, rhs) };
384                if self.size & 511 != 0 {
385                    self.trim();
386                }
387                return;
388            }
389            if is_x86_feature_detected!("avx2") {
390                // SAFETY: feature detection checked AVX2 support.
391                unsafe { simd::shift_left_avx2::<OR_ASSIGN>(self.words_mut(), rhs) };
392                if self.size & 63 != 0 {
393                    self.trim();
394                }
395                return;
396            }
397        }
398
399        let bits = self.words_mut();
400        let word_shift = rhs >> 6;
401        let bit_shift = rhs & 63;
402        if bit_shift == 0 {
403            for i in (0..bits.len() - word_shift).rev() {
404                if OR_ASSIGN {
405                    bits[i + word_shift] |= bits[i];
406                } else {
407                    bits[i + word_shift] = bits[i];
408                }
409            }
410        } else {
411            for i in (1..bits.len() - word_shift).rev() {
412                let value = (bits[i] << bit_shift) | (bits[i - 1] >> (64 - bit_shift));
413                if OR_ASSIGN {
414                    bits[i + word_shift] |= value;
415                } else {
416                    bits[i + word_shift] = value;
417                }
418            }
419            if OR_ASSIGN {
420                bits[word_shift] |= bits[0] << bit_shift;
421            } else {
422                bits[word_shift] = bits[0] << bit_shift;
423            }
424        }
425        if !OR_ASSIGN {
426            bits[..word_shift].fill(0);
427        }
428        if self.size & 63 != 0 {
429            self.trim();
430        }
431    }
432
433    #[inline]
434    fn shift_right<const OR_ASSIGN: bool>(&mut self, rhs: usize) {
435        if rhs == 0 {
436            return;
437        }
438        if rhs >= self.size {
439            if !OR_ASSIGN {
440                self.reset();
441            }
442            return;
443        }
444        #[cfg(target_arch = "x86_64")]
445        if self.bits.len() >= SIMD_MIN_BLOCKS {
446            if avx512_enabled()
447                && is_x86_feature_detected!("avx512f")
448                && is_x86_feature_detected!("avx512vbmi2")
449            {
450                // SAFETY: blocks are aligned and feature detection checked AVX-512F and VBMI2.
451                unsafe { simd::shift_right_avx512::<OR_ASSIGN>(&mut self.bits, rhs) };
452                return;
453            }
454            if is_x86_feature_detected!("avx2") {
455                // SAFETY: feature detection checked AVX2 support.
456                unsafe { simd::shift_right_avx2::<OR_ASSIGN>(self.words_mut(), rhs) };
457                return;
458            }
459        }
460
461        let bits = self.words_mut();
462        let word_shift = rhs >> 6;
463        let bit_shift = rhs & 63;
464        if bit_shift == 0 {
465            for i in word_shift..bits.len() {
466                if OR_ASSIGN {
467                    bits[i - word_shift] |= bits[i];
468                } else {
469                    bits[i - word_shift] = bits[i];
470                }
471            }
472        } else {
473            for i in word_shift..bits.len() - 1 {
474                let value = (bits[i] >> bit_shift) | (bits[i + 1] << (64 - bit_shift));
475                if OR_ASSIGN {
476                    bits[i - word_shift] |= value;
477                } else {
478                    bits[i - word_shift] = value;
479                }
480            }
481            if OR_ASSIGN {
482                bits[bits.len() - word_shift - 1] |= bits[bits.len() - 1] >> bit_shift;
483            } else {
484                bits[bits.len() - word_shift - 1] = bits[bits.len() - 1] >> bit_shift;
485            }
486        }
487        if !OR_ASSIGN {
488            let end = bits.len() - word_shift;
489            bits[end..].fill(0);
490        }
491    }
492}
493
494impl Extend<bool> for BitSet {
495    fn extend<T: IntoIterator<Item = bool>>(&mut self, iter: T) {
496        for bit in iter {
497            self.push(bit);
498        }
499    }
500}
501
502impl FromIterator<bool> for BitSet {
503    fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
504        let mut set = BitSet::new(0);
505        set.extend(iter);
506        set
507    }
508}
509
510impl ShlAssign<usize> for BitSet {
511    #[inline]
512    fn shl_assign(&mut self, rhs: usize) {
513        self.shift_left::<false>(rhs);
514    }
515}
516
517impl Shl<usize> for BitSet {
518    type Output = Self;
519    fn shl(mut self, rhs: usize) -> Self::Output {
520        self <<= rhs;
521        self
522    }
523}
524
525impl ShrAssign<usize> for BitSet {
526    #[inline]
527    fn shr_assign(&mut self, rhs: usize) {
528        self.shift_right::<false>(rhs);
529    }
530}
531
532impl Shr<usize> for BitSet {
533    type Output = Self;
534    fn shr(mut self, rhs: usize) -> Self::Output {
535        self >>= rhs;
536        self
537    }
538}
539
540impl BitOrAssign<&BitSet> for BitSet {
541    #[inline]
542    fn bitor_assign(&mut self, rhs: &Self) {
543        self.bitop_assign::<BIT_OR>(rhs);
544    }
545}
546
547impl BitOr<&BitSet> for BitSet {
548    type Output = Self;
549    fn bitor(mut self, rhs: &Self) -> Self::Output {
550        self |= rhs;
551        self
552    }
553}
554
555impl BitOr<&BitSet> for &BitSet {
556    type Output = BitSet;
557    fn bitor(self, rhs: &BitSet) -> Self::Output {
558        let mut res = self.clone();
559        res |= rhs;
560        res
561    }
562}
563
564impl BitAndAssign<&BitSet> for BitSet {
565    #[inline]
566    fn bitand_assign(&mut self, rhs: &Self) {
567        self.bitop_assign::<BIT_AND>(rhs);
568    }
569}
570
571impl BitAnd<&BitSet> for BitSet {
572    type Output = Self;
573    fn bitand(mut self, rhs: &Self) -> Self::Output {
574        self &= rhs;
575        self
576    }
577}
578
579impl BitAnd<&BitSet> for &BitSet {
580    type Output = BitSet;
581    fn bitand(self, rhs: &BitSet) -> Self::Output {
582        let mut res = self.clone();
583        res &= rhs;
584        res
585    }
586}
587
588impl BitXorAssign<&BitSet> for BitSet {
589    #[inline]
590    fn bitxor_assign(&mut self, rhs: &Self) {
591        self.bitop_assign::<BIT_XOR>(rhs);
592    }
593}
594
595impl BitXor<&BitSet> for BitSet {
596    type Output = Self;
597    fn bitxor(mut self, rhs: &Self) -> Self::Output {
598        self ^= rhs;
599        self
600    }
601}
602
603impl BitXor<&BitSet> for &BitSet {
604    type Output = BitSet;
605    fn bitxor(self, rhs: &BitSet) -> Self::Output {
606        let mut res = self.clone();
607        res ^= rhs;
608        res
609    }
610}
611
612impl Not for BitSet {
613    type Output = Self;
614    fn not(mut self) -> Self::Output {
615        for word in self.words_mut() {
616            *word = !*word;
617        }
618        self.trim();
619        self
620    }
crates/library_checker/src/linear_algebra/matrix_rank_mod_2.rs (line 22)
5pub fn matrix_rank_mod_2(reader: impl Read, writer: impl Write) {
6    prepare_io!(reader, writer);
7    sc!(n, m);
8    // Transpose very tall matrices to avoid allocating millions of short rows.
9    let transpose = n / 2 > m;
10    let mut a = BitMatrix::zeros(if transpose { (m, n) } else { (n, m) });
11    if transpose && m >= 64 {
12        let mut words = vec![0u64; m];
13        for first in (0..n).step_by(64) {
14            words.fill(0);
15            for i in 0..64.min(n - first) {
16                sc!(row: &str);
17                for (word, b) in words.iter_mut().zip(row.bytes()) {
18                    *word |= u64::from(b == b'1') << i;
19                }
20            }
21            for (row, &word) in a.data.iter_mut().zip(&words) {
22                row.words_mut()[first / 64] = word;
23            }
24        }
25    } else {
26        for i in 0..if m == 0 { 0 } else { n } {
27            sc!(row: &str);
28            if !transpose {
29                a.data[i] = BitSet::from_binary(row).unwrap();
30            } else {
31                for (j, b) in row.bytes().enumerate() {
32                    a[j].words_mut()[i / 64] |= u64::from(b == b'1') << (i % 64);
33                }
34            }
35            if transpose
36                && i == 63
37                && BitMatrix::new_with((m, 64), |row, col| a[row].get(col)).rank() == m
38            {
39                pp!(m);
40                return;
41            }
42        }
43    }
44    pp!(a.rank());
45}
Source

fn trim(&mut self)

Examples found in repository?
crates/competitive/src/data_structure/bitset.rs (line 142)
137    pub fn ones(size: usize) -> Self {
138        let mut self_ = Self {
139            size,
140            bits: vec![Block([u64::MAX; 8]); size.div_ceil(512)],
141        };
142        self_.trim();
143        self_
144    }
145
146    pub fn get(&self, i: usize) -> bool {
147        self.bits[i >> 9].0[i >> 6 & 7] & (1 << (i & 63)) != 0
148    }
149
150    pub fn set(&mut self, i: usize, b: bool) {
151        let word = &mut self.bits[i >> 9].0[i >> 6 & 7];
152        if b {
153            *word |= 1 << (i & 63);
154        } else {
155            *word &= !(1 << (i & 63));
156        }
157    }
158
159    /// Clears all bits.
160    pub fn reset(&mut self) {
161        self.bits.fill(Block::default());
162    }
163
164    /// Sets all bits to `value`.
165    pub fn fill(&mut self, value: bool) {
166        self.bits.fill(Block([if value { u64::MAX } else { 0 }; 8]));
167        self.trim();
168    }
169
170    /// Tests whether any bit is set.
171    #[inline]
172    pub fn any(&self) -> bool {
173        !self.none()
174    }
175
176    /// Tests whether all bits are unset.
177    #[inline]
178    pub fn none(&self) -> bool {
179        #[cfg(target_arch = "x86_64")]
180        if self.bits.len() >= SIMD_MIN_BLOCKS {
181            if self.bits[0].0[0] != 0 {
182                return false;
183            }
184            if avx512_enabled() && is_x86_feature_detected!("avx512f") {
185                // SAFETY: blocks are 64-byte aligned and feature detection checked AVX-512F.
186                return unsafe { simd::none_avx512(&self.bits) };
187            }
188            if is_x86_feature_detected!("avx2") {
189                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
190                return unsafe { simd::none_avx2(&self.bits) };
191            }
192        }
193        self.words().iter().all(|&word| word == 0)
194    }
195
196    /// Tests whether all bits are set.
197    #[inline(always)]
198    pub fn all(&self) -> bool {
199        let words = self.words();
200        let full_words = self.size >> 6;
201        #[cfg(target_arch = "x86_64")]
202        if self.size >> 9 >= SIMD_MIN_BLOCKS {
203            let full_blocks = self.size >> 9;
204            if words[0] != u64::MAX {
205                return false;
206            }
207            let full_blocks_are_set = if avx512_enabled() && is_x86_feature_detected!("avx512f") {
208                // SAFETY: blocks are 64-byte aligned and feature detection checked AVX-512F.
209                Some(unsafe { simd::all_avx512(&self.bits[..full_blocks]) })
210            } else if is_x86_feature_detected!("avx2") {
211                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
212                Some(unsafe { simd::all_avx2(&self.bits[..full_blocks]) })
213            } else {
214                None
215            };
216            if let Some(full_blocks_are_set) = full_blocks_are_set {
217                return full_blocks_are_set
218                    && words[full_blocks * 8..full_words]
219                        .iter()
220                        .all(|&word| word == u64::MAX)
221                    && (self.size & 63 == 0
222                        || words[full_words] == u64::MAX >> (64 - (self.size & 63)));
223            }
224        }
225        if self.size & 63 == 0 {
226            return words.iter().all(|&word| word == u64::MAX);
227        }
228        words[..full_words].iter().all(|&word| word == u64::MAX)
229            && words[full_words] == u64::MAX >> (64 - (self.size & 63))
230    }
231
232    /// Iterates over set-bit indices in ascending order.
233    pub fn iter_ones(&self) -> impl Iterator<Item = usize> + '_ {
234        self.words()
235            .iter()
236            .copied()
237            .enumerate()
238            .flat_map(|(word_index, mut word)| {
239                std::iter::from_fn(move || {
240                    if word == 0 {
241                        None
242                    } else {
243                        let bit = word.trailing_zeros() as usize;
244                        word &= word - 1;
245                        Some((word_index << 6) | bit)
246                    }
247                })
248            })
249    }
250
251    /// Counts set bits.
252    #[inline]
253    pub fn count_ones(&self) -> u64 {
254        let words = self.words();
255        #[cfg(target_arch = "x86_64")]
256        if words.len() >= 8 {
257            if avx512_enabled()
258                && is_x86_feature_detected!("avx512f")
259                && is_x86_feature_detected!("avx512vpopcntdq")
260            {
261                // SAFETY: blocks are aligned and feature detection checked both requirements.
262                return unsafe { simd::count_ones_avx512(&self.bits) };
263            }
264            if is_x86_feature_detected!("avx2") {
265                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
266                return unsafe { simd::count_ones_avx2(&self.bits) };
267            }
268        }
269        words.iter().map(|word| word.count_ones() as u64).sum()
270    }
271
272    /// Counts unset bits.
273    #[inline]
274    pub fn count_zeros(&self) -> u64 {
275        self.size as u64 - self.count_ones()
276    }
277
278    pub fn push(&mut self, b: bool) {
279        if self.size & 511 == 0 {
280            self.bits.push(Block::default());
281        }
282        if b {
283            self.bits[self.size >> 9].0[self.size >> 6 & 7] |= 1 << (self.size & 63);
284        }
285        self.size += 1;
286    }
287
288    pub fn resize(&mut self, new_size: usize) {
289        match self.size.cmp(&new_size) {
290            Ordering::Less => self.bits.resize(new_size.div_ceil(512), Block::default()),
291            Ordering::Equal => {}
292            Ordering::Greater => self.bits.truncate(new_size.div_ceil(512)),
293        }
294        self.size = new_size;
295        self.trim();
296    }
297
298    /// Assigns `self | (self << rhs)` to `self`.
299    #[inline]
300    pub fn shl_bitor_assign(&mut self, rhs: usize) {
301        self.shift_left::<true>(rhs);
302    }
303
304    /// Assigns `self | (self >> rhs)` to `self`.
305    #[inline]
306    pub fn shr_bitor_assign(&mut self, rhs: usize) {
307        self.shift_right::<true>(rhs);
308    }
309
310    /// Returns words in increasing bit-index order; unused high bits in the last word are zero.
311    pub fn words(&self) -> &[u64] {
312        // SAFETY: `Block` is exactly eight contiguous `u64`s, with no trailing padding.
313        unsafe { std::slice::from_raw_parts(self.bits.as_ptr().cast(), self.size.div_ceil(64)) }
314    }
315
316    /// Returns mutable words in increasing bit-index order.
317    /// Callers must keep unused high bits in the last word zero.
318    pub fn words_mut(&mut self) -> &mut [u64] {
319        let len = self.size.div_ceil(64);
320        // SAFETY: `Block` is exactly eight contiguous `u64`s, with no trailing padding.
321        unsafe { std::slice::from_raw_parts_mut(self.bits.as_mut_ptr().cast(), len) }
322    }
323
324    fn trim(&mut self) {
325        let used_words = self.size.div_ceil(64) & 7;
326        if let Some(last) = self.bits.last_mut() {
327            if self.size & 63 != 0 {
328                last.0[(self.size >> 6) & 7] &= u64::MAX >> (64 - (self.size & 63));
329            }
330            if used_words != 0 {
331                last.0[used_words..].fill(0);
332            }
333        }
334    }
335
336    #[inline]
337    fn bitop_assign<const OP: u8>(&mut self, rhs: &Self) {
338        assert_eq!(
339            self.size, rhs.size,
340            "bitwise operations require equal lengths"
341        );
342        #[cfg(target_arch = "x86_64")]
343        if self.bits.len() >= SIMD_MIN_BLOCKS {
344            if avx512_enabled() && is_x86_feature_detected!("avx512f") {
345                // SAFETY: blocks are 64-byte aligned and feature detection checked AVX-512F.
346                unsafe { simd::bitop_avx512::<OP>(&mut self.bits, &rhs.bits) };
347                return;
348            }
349            if is_x86_feature_detected!("avx2") {
350                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
351                unsafe { simd::bitop_avx2::<OP>(&mut self.bits, &rhs.bits) };
352                return;
353            }
354        }
355        for (lhs, &rhs) in self.words_mut().iter_mut().zip(rhs.words()) {
356            *lhs = match OP {
357                BIT_AND => *lhs & rhs,
358                BIT_OR => *lhs | rhs,
359                BIT_XOR => *lhs ^ rhs,
360                _ => unreachable!(),
361            };
362        }
363    }
364
365    #[inline]
366    fn shift_left<const OR_ASSIGN: bool>(&mut self, rhs: usize) {
367        if rhs == 0 {
368            return;
369        }
370        if rhs >= self.size {
371            if !OR_ASSIGN {
372                self.reset();
373            }
374            return;
375        }
376        #[cfg(target_arch = "x86_64")]
377        if self.bits.len() >= SIMD_MIN_BLOCKS {
378            if avx512_enabled()
379                && is_x86_feature_detected!("avx512f")
380                && is_x86_feature_detected!("avx512vbmi2")
381            {
382                // SAFETY: blocks are aligned and feature detection checked AVX-512F and VBMI2.
383                unsafe { simd::shift_left_avx512::<OR_ASSIGN>(&mut self.bits, rhs) };
384                if self.size & 511 != 0 {
385                    self.trim();
386                }
387                return;
388            }
389            if is_x86_feature_detected!("avx2") {
390                // SAFETY: feature detection checked AVX2 support.
391                unsafe { simd::shift_left_avx2::<OR_ASSIGN>(self.words_mut(), rhs) };
392                if self.size & 63 != 0 {
393                    self.trim();
394                }
395                return;
396            }
397        }
398
399        let bits = self.words_mut();
400        let word_shift = rhs >> 6;
401        let bit_shift = rhs & 63;
402        if bit_shift == 0 {
403            for i in (0..bits.len() - word_shift).rev() {
404                if OR_ASSIGN {
405                    bits[i + word_shift] |= bits[i];
406                } else {
407                    bits[i + word_shift] = bits[i];
408                }
409            }
410        } else {
411            for i in (1..bits.len() - word_shift).rev() {
412                let value = (bits[i] << bit_shift) | (bits[i - 1] >> (64 - bit_shift));
413                if OR_ASSIGN {
414                    bits[i + word_shift] |= value;
415                } else {
416                    bits[i + word_shift] = value;
417                }
418            }
419            if OR_ASSIGN {
420                bits[word_shift] |= bits[0] << bit_shift;
421            } else {
422                bits[word_shift] = bits[0] << bit_shift;
423            }
424        }
425        if !OR_ASSIGN {
426            bits[..word_shift].fill(0);
427        }
428        if self.size & 63 != 0 {
429            self.trim();
430        }
431    }
432
433    #[inline]
434    fn shift_right<const OR_ASSIGN: bool>(&mut self, rhs: usize) {
435        if rhs == 0 {
436            return;
437        }
438        if rhs >= self.size {
439            if !OR_ASSIGN {
440                self.reset();
441            }
442            return;
443        }
444        #[cfg(target_arch = "x86_64")]
445        if self.bits.len() >= SIMD_MIN_BLOCKS {
446            if avx512_enabled()
447                && is_x86_feature_detected!("avx512f")
448                && is_x86_feature_detected!("avx512vbmi2")
449            {
450                // SAFETY: blocks are aligned and feature detection checked AVX-512F and VBMI2.
451                unsafe { simd::shift_right_avx512::<OR_ASSIGN>(&mut self.bits, rhs) };
452                return;
453            }
454            if is_x86_feature_detected!("avx2") {
455                // SAFETY: feature detection checked AVX2 support.
456                unsafe { simd::shift_right_avx2::<OR_ASSIGN>(self.words_mut(), rhs) };
457                return;
458            }
459        }
460
461        let bits = self.words_mut();
462        let word_shift = rhs >> 6;
463        let bit_shift = rhs & 63;
464        if bit_shift == 0 {
465            for i in word_shift..bits.len() {
466                if OR_ASSIGN {
467                    bits[i - word_shift] |= bits[i];
468                } else {
469                    bits[i - word_shift] = bits[i];
470                }
471            }
472        } else {
473            for i in word_shift..bits.len() - 1 {
474                let value = (bits[i] >> bit_shift) | (bits[i + 1] << (64 - bit_shift));
475                if OR_ASSIGN {
476                    bits[i - word_shift] |= value;
477                } else {
478                    bits[i - word_shift] = value;
479                }
480            }
481            if OR_ASSIGN {
482                bits[bits.len() - word_shift - 1] |= bits[bits.len() - 1] >> bit_shift;
483            } else {
484                bits[bits.len() - word_shift - 1] = bits[bits.len() - 1] >> bit_shift;
485            }
486        }
487        if !OR_ASSIGN {
488            let end = bits.len() - word_shift;
489            bits[end..].fill(0);
490        }
491    }
492}
493
494impl Extend<bool> for BitSet {
495    fn extend<T: IntoIterator<Item = bool>>(&mut self, iter: T) {
496        for bit in iter {
497            self.push(bit);
498        }
499    }
500}
501
502impl FromIterator<bool> for BitSet {
503    fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
504        let mut set = BitSet::new(0);
505        set.extend(iter);
506        set
507    }
508}
509
510impl ShlAssign<usize> for BitSet {
511    #[inline]
512    fn shl_assign(&mut self, rhs: usize) {
513        self.shift_left::<false>(rhs);
514    }
515}
516
517impl Shl<usize> for BitSet {
518    type Output = Self;
519    fn shl(mut self, rhs: usize) -> Self::Output {
520        self <<= rhs;
521        self
522    }
523}
524
525impl ShrAssign<usize> for BitSet {
526    #[inline]
527    fn shr_assign(&mut self, rhs: usize) {
528        self.shift_right::<false>(rhs);
529    }
530}
531
532impl Shr<usize> for BitSet {
533    type Output = Self;
534    fn shr(mut self, rhs: usize) -> Self::Output {
535        self >>= rhs;
536        self
537    }
538}
539
540impl BitOrAssign<&BitSet> for BitSet {
541    #[inline]
542    fn bitor_assign(&mut self, rhs: &Self) {
543        self.bitop_assign::<BIT_OR>(rhs);
544    }
545}
546
547impl BitOr<&BitSet> for BitSet {
548    type Output = Self;
549    fn bitor(mut self, rhs: &Self) -> Self::Output {
550        self |= rhs;
551        self
552    }
553}
554
555impl BitOr<&BitSet> for &BitSet {
556    type Output = BitSet;
557    fn bitor(self, rhs: &BitSet) -> Self::Output {
558        let mut res = self.clone();
559        res |= rhs;
560        res
561    }
562}
563
564impl BitAndAssign<&BitSet> for BitSet {
565    #[inline]
566    fn bitand_assign(&mut self, rhs: &Self) {
567        self.bitop_assign::<BIT_AND>(rhs);
568    }
569}
570
571impl BitAnd<&BitSet> for BitSet {
572    type Output = Self;
573    fn bitand(mut self, rhs: &Self) -> Self::Output {
574        self &= rhs;
575        self
576    }
577}
578
579impl BitAnd<&BitSet> for &BitSet {
580    type Output = BitSet;
581    fn bitand(self, rhs: &BitSet) -> Self::Output {
582        let mut res = self.clone();
583        res &= rhs;
584        res
585    }
586}
587
588impl BitXorAssign<&BitSet> for BitSet {
589    #[inline]
590    fn bitxor_assign(&mut self, rhs: &Self) {
591        self.bitop_assign::<BIT_XOR>(rhs);
592    }
593}
594
595impl BitXor<&BitSet> for BitSet {
596    type Output = Self;
597    fn bitxor(mut self, rhs: &Self) -> Self::Output {
598        self ^= rhs;
599        self
600    }
601}
602
603impl BitXor<&BitSet> for &BitSet {
604    type Output = BitSet;
605    fn bitxor(self, rhs: &BitSet) -> Self::Output {
606        let mut res = self.clone();
607        res ^= rhs;
608        res
609    }
610}
611
612impl Not for BitSet {
613    type Output = Self;
614    fn not(mut self) -> Self::Output {
615        for word in self.words_mut() {
616            *word = !*word;
617        }
618        self.trim();
619        self
620    }
Source

fn bitop_assign<const OP: u8>(&mut self, rhs: &Self)

Examples found in repository?
crates/competitive/src/data_structure/bitset.rs (line 543)
542    fn bitor_assign(&mut self, rhs: &Self) {
543        self.bitop_assign::<BIT_OR>(rhs);
544    }
545}
546
547impl BitOr<&BitSet> for BitSet {
548    type Output = Self;
549    fn bitor(mut self, rhs: &Self) -> Self::Output {
550        self |= rhs;
551        self
552    }
553}
554
555impl BitOr<&BitSet> for &BitSet {
556    type Output = BitSet;
557    fn bitor(self, rhs: &BitSet) -> Self::Output {
558        let mut res = self.clone();
559        res |= rhs;
560        res
561    }
562}
563
564impl BitAndAssign<&BitSet> for BitSet {
565    #[inline]
566    fn bitand_assign(&mut self, rhs: &Self) {
567        self.bitop_assign::<BIT_AND>(rhs);
568    }
569}
570
571impl BitAnd<&BitSet> for BitSet {
572    type Output = Self;
573    fn bitand(mut self, rhs: &Self) -> Self::Output {
574        self &= rhs;
575        self
576    }
577}
578
579impl BitAnd<&BitSet> for &BitSet {
580    type Output = BitSet;
581    fn bitand(self, rhs: &BitSet) -> Self::Output {
582        let mut res = self.clone();
583        res &= rhs;
584        res
585    }
586}
587
588impl BitXorAssign<&BitSet> for BitSet {
589    #[inline]
590    fn bitxor_assign(&mut self, rhs: &Self) {
591        self.bitop_assign::<BIT_XOR>(rhs);
592    }
Source

fn shift_left<const OR_ASSIGN: bool>(&mut self, rhs: usize)

Examples found in repository?
crates/competitive/src/data_structure/bitset.rs (line 301)
300    pub fn shl_bitor_assign(&mut self, rhs: usize) {
301        self.shift_left::<true>(rhs);
302    }
303
304    /// Assigns `self | (self >> rhs)` to `self`.
305    #[inline]
306    pub fn shr_bitor_assign(&mut self, rhs: usize) {
307        self.shift_right::<true>(rhs);
308    }
309
310    /// Returns words in increasing bit-index order; unused high bits in the last word are zero.
311    pub fn words(&self) -> &[u64] {
312        // SAFETY: `Block` is exactly eight contiguous `u64`s, with no trailing padding.
313        unsafe { std::slice::from_raw_parts(self.bits.as_ptr().cast(), self.size.div_ceil(64)) }
314    }
315
316    /// Returns mutable words in increasing bit-index order.
317    /// Callers must keep unused high bits in the last word zero.
318    pub fn words_mut(&mut self) -> &mut [u64] {
319        let len = self.size.div_ceil(64);
320        // SAFETY: `Block` is exactly eight contiguous `u64`s, with no trailing padding.
321        unsafe { std::slice::from_raw_parts_mut(self.bits.as_mut_ptr().cast(), len) }
322    }
323
324    fn trim(&mut self) {
325        let used_words = self.size.div_ceil(64) & 7;
326        if let Some(last) = self.bits.last_mut() {
327            if self.size & 63 != 0 {
328                last.0[(self.size >> 6) & 7] &= u64::MAX >> (64 - (self.size & 63));
329            }
330            if used_words != 0 {
331                last.0[used_words..].fill(0);
332            }
333        }
334    }
335
336    #[inline]
337    fn bitop_assign<const OP: u8>(&mut self, rhs: &Self) {
338        assert_eq!(
339            self.size, rhs.size,
340            "bitwise operations require equal lengths"
341        );
342        #[cfg(target_arch = "x86_64")]
343        if self.bits.len() >= SIMD_MIN_BLOCKS {
344            if avx512_enabled() && is_x86_feature_detected!("avx512f") {
345                // SAFETY: blocks are 64-byte aligned and feature detection checked AVX-512F.
346                unsafe { simd::bitop_avx512::<OP>(&mut self.bits, &rhs.bits) };
347                return;
348            }
349            if is_x86_feature_detected!("avx2") {
350                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
351                unsafe { simd::bitop_avx2::<OP>(&mut self.bits, &rhs.bits) };
352                return;
353            }
354        }
355        for (lhs, &rhs) in self.words_mut().iter_mut().zip(rhs.words()) {
356            *lhs = match OP {
357                BIT_AND => *lhs & rhs,
358                BIT_OR => *lhs | rhs,
359                BIT_XOR => *lhs ^ rhs,
360                _ => unreachable!(),
361            };
362        }
363    }
364
365    #[inline]
366    fn shift_left<const OR_ASSIGN: bool>(&mut self, rhs: usize) {
367        if rhs == 0 {
368            return;
369        }
370        if rhs >= self.size {
371            if !OR_ASSIGN {
372                self.reset();
373            }
374            return;
375        }
376        #[cfg(target_arch = "x86_64")]
377        if self.bits.len() >= SIMD_MIN_BLOCKS {
378            if avx512_enabled()
379                && is_x86_feature_detected!("avx512f")
380                && is_x86_feature_detected!("avx512vbmi2")
381            {
382                // SAFETY: blocks are aligned and feature detection checked AVX-512F and VBMI2.
383                unsafe { simd::shift_left_avx512::<OR_ASSIGN>(&mut self.bits, rhs) };
384                if self.size & 511 != 0 {
385                    self.trim();
386                }
387                return;
388            }
389            if is_x86_feature_detected!("avx2") {
390                // SAFETY: feature detection checked AVX2 support.
391                unsafe { simd::shift_left_avx2::<OR_ASSIGN>(self.words_mut(), rhs) };
392                if self.size & 63 != 0 {
393                    self.trim();
394                }
395                return;
396            }
397        }
398
399        let bits = self.words_mut();
400        let word_shift = rhs >> 6;
401        let bit_shift = rhs & 63;
402        if bit_shift == 0 {
403            for i in (0..bits.len() - word_shift).rev() {
404                if OR_ASSIGN {
405                    bits[i + word_shift] |= bits[i];
406                } else {
407                    bits[i + word_shift] = bits[i];
408                }
409            }
410        } else {
411            for i in (1..bits.len() - word_shift).rev() {
412                let value = (bits[i] << bit_shift) | (bits[i - 1] >> (64 - bit_shift));
413                if OR_ASSIGN {
414                    bits[i + word_shift] |= value;
415                } else {
416                    bits[i + word_shift] = value;
417                }
418            }
419            if OR_ASSIGN {
420                bits[word_shift] |= bits[0] << bit_shift;
421            } else {
422                bits[word_shift] = bits[0] << bit_shift;
423            }
424        }
425        if !OR_ASSIGN {
426            bits[..word_shift].fill(0);
427        }
428        if self.size & 63 != 0 {
429            self.trim();
430        }
431    }
432
433    #[inline]
434    fn shift_right<const OR_ASSIGN: bool>(&mut self, rhs: usize) {
435        if rhs == 0 {
436            return;
437        }
438        if rhs >= self.size {
439            if !OR_ASSIGN {
440                self.reset();
441            }
442            return;
443        }
444        #[cfg(target_arch = "x86_64")]
445        if self.bits.len() >= SIMD_MIN_BLOCKS {
446            if avx512_enabled()
447                && is_x86_feature_detected!("avx512f")
448                && is_x86_feature_detected!("avx512vbmi2")
449            {
450                // SAFETY: blocks are aligned and feature detection checked AVX-512F and VBMI2.
451                unsafe { simd::shift_right_avx512::<OR_ASSIGN>(&mut self.bits, rhs) };
452                return;
453            }
454            if is_x86_feature_detected!("avx2") {
455                // SAFETY: feature detection checked AVX2 support.
456                unsafe { simd::shift_right_avx2::<OR_ASSIGN>(self.words_mut(), rhs) };
457                return;
458            }
459        }
460
461        let bits = self.words_mut();
462        let word_shift = rhs >> 6;
463        let bit_shift = rhs & 63;
464        if bit_shift == 0 {
465            for i in word_shift..bits.len() {
466                if OR_ASSIGN {
467                    bits[i - word_shift] |= bits[i];
468                } else {
469                    bits[i - word_shift] = bits[i];
470                }
471            }
472        } else {
473            for i in word_shift..bits.len() - 1 {
474                let value = (bits[i] >> bit_shift) | (bits[i + 1] << (64 - bit_shift));
475                if OR_ASSIGN {
476                    bits[i - word_shift] |= value;
477                } else {
478                    bits[i - word_shift] = value;
479                }
480            }
481            if OR_ASSIGN {
482                bits[bits.len() - word_shift - 1] |= bits[bits.len() - 1] >> bit_shift;
483            } else {
484                bits[bits.len() - word_shift - 1] = bits[bits.len() - 1] >> bit_shift;
485            }
486        }
487        if !OR_ASSIGN {
488            let end = bits.len() - word_shift;
489            bits[end..].fill(0);
490        }
491    }
492}
493
494impl Extend<bool> for BitSet {
495    fn extend<T: IntoIterator<Item = bool>>(&mut self, iter: T) {
496        for bit in iter {
497            self.push(bit);
498        }
499    }
500}
501
502impl FromIterator<bool> for BitSet {
503    fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
504        let mut set = BitSet::new(0);
505        set.extend(iter);
506        set
507    }
508}
509
510impl ShlAssign<usize> for BitSet {
511    #[inline]
512    fn shl_assign(&mut self, rhs: usize) {
513        self.shift_left::<false>(rhs);
514    }
Source

fn shift_right<const OR_ASSIGN: bool>(&mut self, rhs: usize)

Examples found in repository?
crates/competitive/src/data_structure/bitset.rs (line 307)
306    pub fn shr_bitor_assign(&mut self, rhs: usize) {
307        self.shift_right::<true>(rhs);
308    }
309
310    /// Returns words in increasing bit-index order; unused high bits in the last word are zero.
311    pub fn words(&self) -> &[u64] {
312        // SAFETY: `Block` is exactly eight contiguous `u64`s, with no trailing padding.
313        unsafe { std::slice::from_raw_parts(self.bits.as_ptr().cast(), self.size.div_ceil(64)) }
314    }
315
316    /// Returns mutable words in increasing bit-index order.
317    /// Callers must keep unused high bits in the last word zero.
318    pub fn words_mut(&mut self) -> &mut [u64] {
319        let len = self.size.div_ceil(64);
320        // SAFETY: `Block` is exactly eight contiguous `u64`s, with no trailing padding.
321        unsafe { std::slice::from_raw_parts_mut(self.bits.as_mut_ptr().cast(), len) }
322    }
323
324    fn trim(&mut self) {
325        let used_words = self.size.div_ceil(64) & 7;
326        if let Some(last) = self.bits.last_mut() {
327            if self.size & 63 != 0 {
328                last.0[(self.size >> 6) & 7] &= u64::MAX >> (64 - (self.size & 63));
329            }
330            if used_words != 0 {
331                last.0[used_words..].fill(0);
332            }
333        }
334    }
335
336    #[inline]
337    fn bitop_assign<const OP: u8>(&mut self, rhs: &Self) {
338        assert_eq!(
339            self.size, rhs.size,
340            "bitwise operations require equal lengths"
341        );
342        #[cfg(target_arch = "x86_64")]
343        if self.bits.len() >= SIMD_MIN_BLOCKS {
344            if avx512_enabled() && is_x86_feature_detected!("avx512f") {
345                // SAFETY: blocks are 64-byte aligned and feature detection checked AVX-512F.
346                unsafe { simd::bitop_avx512::<OP>(&mut self.bits, &rhs.bits) };
347                return;
348            }
349            if is_x86_feature_detected!("avx2") {
350                // SAFETY: 64-byte alignment also satisfies AVX2 and feature detection checked it.
351                unsafe { simd::bitop_avx2::<OP>(&mut self.bits, &rhs.bits) };
352                return;
353            }
354        }
355        for (lhs, &rhs) in self.words_mut().iter_mut().zip(rhs.words()) {
356            *lhs = match OP {
357                BIT_AND => *lhs & rhs,
358                BIT_OR => *lhs | rhs,
359                BIT_XOR => *lhs ^ rhs,
360                _ => unreachable!(),
361            };
362        }
363    }
364
365    #[inline]
366    fn shift_left<const OR_ASSIGN: bool>(&mut self, rhs: usize) {
367        if rhs == 0 {
368            return;
369        }
370        if rhs >= self.size {
371            if !OR_ASSIGN {
372                self.reset();
373            }
374            return;
375        }
376        #[cfg(target_arch = "x86_64")]
377        if self.bits.len() >= SIMD_MIN_BLOCKS {
378            if avx512_enabled()
379                && is_x86_feature_detected!("avx512f")
380                && is_x86_feature_detected!("avx512vbmi2")
381            {
382                // SAFETY: blocks are aligned and feature detection checked AVX-512F and VBMI2.
383                unsafe { simd::shift_left_avx512::<OR_ASSIGN>(&mut self.bits, rhs) };
384                if self.size & 511 != 0 {
385                    self.trim();
386                }
387                return;
388            }
389            if is_x86_feature_detected!("avx2") {
390                // SAFETY: feature detection checked AVX2 support.
391                unsafe { simd::shift_left_avx2::<OR_ASSIGN>(self.words_mut(), rhs) };
392                if self.size & 63 != 0 {
393                    self.trim();
394                }
395                return;
396            }
397        }
398
399        let bits = self.words_mut();
400        let word_shift = rhs >> 6;
401        let bit_shift = rhs & 63;
402        if bit_shift == 0 {
403            for i in (0..bits.len() - word_shift).rev() {
404                if OR_ASSIGN {
405                    bits[i + word_shift] |= bits[i];
406                } else {
407                    bits[i + word_shift] = bits[i];
408                }
409            }
410        } else {
411            for i in (1..bits.len() - word_shift).rev() {
412                let value = (bits[i] << bit_shift) | (bits[i - 1] >> (64 - bit_shift));
413                if OR_ASSIGN {
414                    bits[i + word_shift] |= value;
415                } else {
416                    bits[i + word_shift] = value;
417                }
418            }
419            if OR_ASSIGN {
420                bits[word_shift] |= bits[0] << bit_shift;
421            } else {
422                bits[word_shift] = bits[0] << bit_shift;
423            }
424        }
425        if !OR_ASSIGN {
426            bits[..word_shift].fill(0);
427        }
428        if self.size & 63 != 0 {
429            self.trim();
430        }
431    }
432
433    #[inline]
434    fn shift_right<const OR_ASSIGN: bool>(&mut self, rhs: usize) {
435        if rhs == 0 {
436            return;
437        }
438        if rhs >= self.size {
439            if !OR_ASSIGN {
440                self.reset();
441            }
442            return;
443        }
444        #[cfg(target_arch = "x86_64")]
445        if self.bits.len() >= SIMD_MIN_BLOCKS {
446            if avx512_enabled()
447                && is_x86_feature_detected!("avx512f")
448                && is_x86_feature_detected!("avx512vbmi2")
449            {
450                // SAFETY: blocks are aligned and feature detection checked AVX-512F and VBMI2.
451                unsafe { simd::shift_right_avx512::<OR_ASSIGN>(&mut self.bits, rhs) };
452                return;
453            }
454            if is_x86_feature_detected!("avx2") {
455                // SAFETY: feature detection checked AVX2 support.
456                unsafe { simd::shift_right_avx2::<OR_ASSIGN>(self.words_mut(), rhs) };
457                return;
458            }
459        }
460
461        let bits = self.words_mut();
462        let word_shift = rhs >> 6;
463        let bit_shift = rhs & 63;
464        if bit_shift == 0 {
465            for i in word_shift..bits.len() {
466                if OR_ASSIGN {
467                    bits[i - word_shift] |= bits[i];
468                } else {
469                    bits[i - word_shift] = bits[i];
470                }
471            }
472        } else {
473            for i in word_shift..bits.len() - 1 {
474                let value = (bits[i] >> bit_shift) | (bits[i + 1] << (64 - bit_shift));
475                if OR_ASSIGN {
476                    bits[i - word_shift] |= value;
477                } else {
478                    bits[i - word_shift] = value;
479                }
480            }
481            if OR_ASSIGN {
482                bits[bits.len() - word_shift - 1] |= bits[bits.len() - 1] >> bit_shift;
483            } else {
484                bits[bits.len() - word_shift - 1] = bits[bits.len() - 1] >> bit_shift;
485            }
486        }
487        if !OR_ASSIGN {
488            let end = bits.len() - word_shift;
489            bits[end..].fill(0);
490        }
491    }
492}
493
494impl Extend<bool> for BitSet {
495    fn extend<T: IntoIterator<Item = bool>>(&mut self, iter: T) {
496        for bit in iter {
497            self.push(bit);
498        }
499    }
500}
501
502impl FromIterator<bool> for BitSet {
503    fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
504        let mut set = BitSet::new(0);
505        set.extend(iter);
506        set
507    }
508}
509
510impl ShlAssign<usize> for BitSet {
511    #[inline]
512    fn shl_assign(&mut self, rhs: usize) {
513        self.shift_left::<false>(rhs);
514    }
515}
516
517impl Shl<usize> for BitSet {
518    type Output = Self;
519    fn shl(mut self, rhs: usize) -> Self::Output {
520        self <<= rhs;
521        self
522    }
523}
524
525impl ShrAssign<usize> for BitSet {
526    #[inline]
527    fn shr_assign(&mut self, rhs: usize) {
528        self.shift_right::<false>(rhs);
529    }

Trait Implementations§

Source§

impl BitAnd<&BitSet> for BitSet

Source§

type Output = BitSet

The resulting type after applying the & operator.
Source§

fn bitand(self, rhs: &Self) -> Self::Output

Performs the & operation. Read more
Source§

impl BitAnd<&BitSet> for &BitSet

Source§

type Output = BitSet

The resulting type after applying the & operator.
Source§

fn bitand(self, rhs: &BitSet) -> Self::Output

Performs the & operation. Read more
Source§

impl BitAndAssign<&BitSet> for BitSet

Source§

fn bitand_assign(&mut self, rhs: &Self)

Performs the &= operation. Read more
Source§

impl BitOr<&BitSet> for BitSet

Source§

type Output = BitSet

The resulting type after applying the | operator.
Source§

fn bitor(self, rhs: &Self) -> Self::Output

Performs the | operation. Read more
Source§

impl BitOr<&BitSet> for &BitSet

Source§

type Output = BitSet

The resulting type after applying the | operator.
Source§

fn bitor(self, rhs: &BitSet) -> Self::Output

Performs the | operation. Read more
Source§

impl BitOrAssign<&BitSet> for BitSet

Source§

fn bitor_assign(&mut self, rhs: &Self)

Performs the |= operation. Read more
Source§

impl BitXor<&BitSet> for BitSet

Source§

type Output = BitSet

The resulting type after applying the ^ operator.
Source§

fn bitxor(self, rhs: &Self) -> Self::Output

Performs the ^ operation. Read more
Source§

impl BitXor<&BitSet> for &BitSet

Source§

type Output = BitSet

The resulting type after applying the ^ operator.
Source§

fn bitxor(self, rhs: &BitSet) -> Self::Output

Performs the ^ operation. Read more
Source§

impl BitXorAssign<&BitSet> for BitSet

Source§

fn bitxor_assign(&mut self, rhs: &Self)

Performs the ^= operation. Read more
Source§

impl Clone for BitSet

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for BitSet

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for BitSet

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Eq for BitSet

Source§

impl Extend<bool> for BitSet

Source§

fn extend<T: IntoIterator<Item = bool>>(&mut self, iter: T)

Extends a collection with the contents of an iterator. Read more
Source§

fn extend_one(&mut self, item: T)

🔬This is a nightly-only experimental API. (extend_one)
Extends a collection with exactly one element.
Source§

fn extend_reserve(&mut self, additional: usize)

🔬This is a nightly-only experimental API. (extend_one)
Reserves capacity in a collection for the given number of additional elements. Read more
Source§

impl FromIterator<bool> for BitSet

Source§

fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self

Creates a value from an iterator. Read more
Source§

impl Hash for BitSet

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Not for BitSet

Source§

type Output = BitSet

The resulting type after applying the ! operator.
Source§

fn not(self) -> Self::Output

Performs the unary ! operation. Read more
Source§

impl Not for &BitSet

Source§

type Output = BitSet

The resulting type after applying the ! operator.
Source§

fn not(self) -> Self::Output

Performs the unary ! operation. Read more
Source§

impl Ord for BitSet

Source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 (const: unstable) · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 (const: unstable) · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 (const: unstable) · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

fn clamp_to<R>(self, range: R) -> Self
where Self: Sized, R: ClampBounds<Self>,

🔬This is a nightly-only experimental API. (clamp_to)
Restrict a value to a certain range. Read more
Source§

impl PartialEq for BitSet

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl PartialOrd for BitSet

Source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 (const: unstable) · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 (const: unstable) · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 (const: unstable) · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 (const: unstable) · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl Shl<usize> for BitSet

Source§

type Output = BitSet

The resulting type after applying the << operator.
Source§

fn shl(self, rhs: usize) -> Self::Output

Performs the << operation. Read more
Source§

impl ShlAssign<usize> for BitSet

Source§

fn shl_assign(&mut self, rhs: usize)

Performs the <<= operation. Read more
Source§

impl Shr<usize> for BitSet

Source§

type Output = BitSet

The resulting type after applying the >> operator.
Source§

fn shr(self, rhs: usize) -> Self::Output

Performs the >> operation. Read more
Source§

impl ShrAssign<usize> for BitSet

Source§

fn shr_assign(&mut self, rhs: usize)

Performs the >>= operation. Read more
Source§

impl StructuralPartialEq for BitSet

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> AsTotalOrd for T
where T: PartialOrd,

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PartialOrdExt for T
where T: PartialOrd,

Source§

fn chmin(&mut self, other: T)

Source§

fn chmax(&mut self, other: T)

Source§

fn minmax(self, other: T) -> (T, T)

Source§

impl<T> ToArrayVecScalar for T

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.