Skip to content

Commit 66e7493

Browse files
committed
Add more functionality to BitMatrix
1 parent a38991f commit 66e7493

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed

src/librustc_data_structures/bit_set.rs

+83-1
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,7 @@ impl<T: Idx> GrowableBitSet<T> {
636636
///
637637
/// All operations that involve a row and/or column index will panic if the
638638
/// index exceeds the relevant bound.
639-
#[derive(Clone, Debug)]
639+
#[derive(Clone, Debug, Eq, PartialEq, RustcDecodable, RustcEncodable)]
640640
pub struct BitMatrix<R: Idx, C: Idx> {
641641
num_rows: usize,
642642
num_columns: usize,
@@ -658,6 +658,23 @@ impl<R: Idx, C: Idx> BitMatrix<R, C> {
658658
}
659659
}
660660

661+
/// Creates a new matrix, with `row` used as the value for every row.
662+
pub fn from_row_n(row: &BitSet<C>, num_rows: usize) -> BitMatrix<R, C> {
663+
let num_columns = row.domain_size();
664+
let words_per_row = num_words(num_columns);
665+
assert_eq!(words_per_row, row.words().len());
666+
BitMatrix {
667+
num_rows,
668+
num_columns,
669+
words: iter::repeat(row.words()).take(num_rows).flatten().cloned().collect(),
670+
marker: PhantomData,
671+
}
672+
}
673+
674+
pub fn rows(&self) -> impl Iterator<Item = R> {
675+
(0..self.num_rows).map(R::new)
676+
}
677+
661678
/// The range of bits for a given row.
662679
fn range(&self, row: R) -> (usize, usize) {
663680
let words_per_row = num_words(self.num_columns);
@@ -737,6 +754,49 @@ impl<R: Idx, C: Idx> BitMatrix<R, C> {
737754
changed
738755
}
739756

757+
/// Adds the bits from `with` to the bits from row `write`, and
758+
/// returns `true` if anything changed.
759+
pub fn union_row_with(&mut self, with: &BitSet<C>, write: R) -> bool {
760+
assert!(write.index() < self.num_rows);
761+
assert_eq!(with.domain_size(), self.num_columns);
762+
let (write_start, write_end) = self.range(write);
763+
let mut changed = false;
764+
for (read_index, write_index) in (0..with.words().len()).zip(write_start..write_end) {
765+
let word = self.words[write_index];
766+
let new_word = word | with.words()[read_index];
767+
self.words[write_index] = new_word;
768+
changed |= word != new_word;
769+
}
770+
changed
771+
}
772+
773+
/// Sets every cell in `row` to true.
774+
pub fn insert_all_into_row(&mut self, row: R) {
775+
assert!(row.index() < self.num_rows);
776+
let (start, end) = self.range(row);
777+
let words = &mut self.words[..];
778+
for index in start..end {
779+
words[index] = !0;
780+
}
781+
self.clear_excess_bits(row);
782+
}
783+
784+
/// Clear excess bits in the final word of the row.
785+
fn clear_excess_bits(&mut self, row: R) {
786+
let num_bits_in_final_word = self.num_columns % WORD_BITS;
787+
if num_bits_in_final_word > 0 {
788+
let mask = (1 << num_bits_in_final_word) - 1;
789+
let (_, end) = self.range(row);
790+
let final_word_idx = end - 1;
791+
self.words[final_word_idx] &= mask;
792+
}
793+
}
794+
795+
/// Gets a slice of the underlying words.
796+
pub fn words(&self) -> &[Word] {
797+
&self.words
798+
}
799+
740800
/// Iterates through all the columns set to true in a given row of
741801
/// the matrix.
742802
pub fn iter<'a>(&'a self, row: R) -> BitIter<'a, C> {
@@ -748,6 +808,12 @@ impl<R: Idx, C: Idx> BitMatrix<R, C> {
748808
marker: PhantomData,
749809
}
750810
}
811+
812+
/// Returns the number of elements in `row`.
813+
pub fn count(&self, row: R) -> usize {
814+
let (start, end) = self.range(row);
815+
self.words[start..end].iter().map(|e| e.count_ones() as usize).sum()
816+
}
751817
}
752818

753819
/// A fixed-column-size, variable-row-size 2D bit matrix with a moderately
@@ -1057,6 +1123,7 @@ fn matrix_iter() {
10571123
matrix.insert(2, 99);
10581124
matrix.insert(4, 0);
10591125
matrix.union_rows(3, 5);
1126+
matrix.insert_all_into_row(6);
10601127

10611128
let expected = [99];
10621129
let mut iter = expected.iter();
@@ -1068,6 +1135,7 @@ fn matrix_iter() {
10681135

10691136
let expected = [22, 75];
10701137
let mut iter = expected.iter();
1138+
assert_eq!(matrix.count(3), expected.len());
10711139
for i in matrix.iter(3) {
10721140
let j = *iter.next().unwrap();
10731141
assert_eq!(i, j);
@@ -1076,6 +1144,7 @@ fn matrix_iter() {
10761144

10771145
let expected = [0];
10781146
let mut iter = expected.iter();
1147+
assert_eq!(matrix.count(4), expected.len());
10791148
for i in matrix.iter(4) {
10801149
let j = *iter.next().unwrap();
10811150
assert_eq!(i, j);
@@ -1084,11 +1153,24 @@ fn matrix_iter() {
10841153

10851154
let expected = [22, 75];
10861155
let mut iter = expected.iter();
1156+
assert_eq!(matrix.count(5), expected.len());
10871157
for i in matrix.iter(5) {
10881158
let j = *iter.next().unwrap();
10891159
assert_eq!(i, j);
10901160
}
10911161
assert!(iter.next().is_none());
1162+
1163+
assert_eq!(matrix.count(6), 100);
1164+
let mut count = 0;
1165+
for (idx, i) in matrix.iter(6).enumerate() {
1166+
assert_eq!(idx, i);
1167+
count += 1;
1168+
}
1169+
assert_eq!(count, 100);
1170+
1171+
if let Some(i) = matrix.iter(7).next() {
1172+
panic!("expected no elements in row, but contains element {:?}", i);
1173+
}
10921174
}
10931175

10941176
#[test]

src/librustc_data_structures/stable_hasher.rs

+10
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,16 @@ impl<I: indexed_vec::Idx, CTX> HashStable<CTX> for bit_set::BitSet<I>
503503
}
504504
}
505505

506+
impl<R: indexed_vec::Idx, C: indexed_vec::Idx, CTX> HashStable<CTX>
507+
for bit_set::BitMatrix<R, C>
508+
{
509+
fn hash_stable<W: StableHasherResult>(&self,
510+
ctx: &mut CTX,
511+
hasher: &mut StableHasher<W>) {
512+
self.words().hash_stable(ctx, hasher);
513+
}
514+
}
515+
506516
impl_stable_hash_via_hash!(::std::path::Path);
507517
impl_stable_hash_via_hash!(::std::path::PathBuf);
508518

0 commit comments

Comments
 (0)