diff options
| author | Tyler Mandry <tmandry@gmail.com> | 2019-05-31 15:59:56 -0700 |
|---|---|---|
| committer | Tyler Mandry <tmandry@gmail.com> | 2019-06-10 14:46:40 -0700 |
| commit | 66e7493543bfef2bdd12454155670cc810de8ea9 (patch) | |
| tree | 3a2423868f61b7caffdc45ccc29c39249711e303 /src/librustc_data_structures | |
| parent | a38991f755e0180101d46351a63db7b6657f08b4 (diff) | |
| download | rust-66e7493543bfef2bdd12454155670cc810de8ea9.tar.gz rust-66e7493543bfef2bdd12454155670cc810de8ea9.zip | |
Add more functionality to BitMatrix
Diffstat (limited to 'src/librustc_data_structures')
| -rw-r--r-- | src/librustc_data_structures/bit_set.rs | 84 | ||||
| -rw-r--r-- | src/librustc_data_structures/stable_hasher.rs | 10 |
2 files changed, 93 insertions, 1 deletions
diff --git a/src/librustc_data_structures/bit_set.rs b/src/librustc_data_structures/bit_set.rs index ec7ff3bd813..7a11ca07007 100644 --- a/src/librustc_data_structures/bit_set.rs +++ b/src/librustc_data_structures/bit_set.rs @@ -636,7 +636,7 @@ impl<T: Idx> GrowableBitSet<T> { /// /// All operations that involve a row and/or column index will panic if the /// index exceeds the relevant bound. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq, RustcDecodable, RustcEncodable)] pub struct BitMatrix<R: Idx, C: Idx> { num_rows: usize, num_columns: usize, @@ -658,6 +658,23 @@ impl<R: Idx, C: Idx> BitMatrix<R, C> { } } + /// Creates a new matrix, with `row` used as the value for every row. + pub fn from_row_n(row: &BitSet<C>, num_rows: usize) -> BitMatrix<R, C> { + let num_columns = row.domain_size(); + let words_per_row = num_words(num_columns); + assert_eq!(words_per_row, row.words().len()); + BitMatrix { + num_rows, + num_columns, + words: iter::repeat(row.words()).take(num_rows).flatten().cloned().collect(), + marker: PhantomData, + } + } + + pub fn rows(&self) -> impl Iterator<Item = R> { + (0..self.num_rows).map(R::new) + } + /// The range of bits for a given row. fn range(&self, row: R) -> (usize, usize) { let words_per_row = num_words(self.num_columns); @@ -737,6 +754,49 @@ impl<R: Idx, C: Idx> BitMatrix<R, C> { changed } + /// Adds the bits from `with` to the bits from row `write`, and + /// returns `true` if anything changed. + pub fn union_row_with(&mut self, with: &BitSet<C>, write: R) -> bool { + assert!(write.index() < self.num_rows); + assert_eq!(with.domain_size(), self.num_columns); + let (write_start, write_end) = self.range(write); + let mut changed = false; + for (read_index, write_index) in (0..with.words().len()).zip(write_start..write_end) { + let word = self.words[write_index]; + let new_word = word | with.words()[read_index]; + self.words[write_index] = new_word; + changed |= word != new_word; + } + changed + } + + /// Sets every cell in `row` to true. + pub fn insert_all_into_row(&mut self, row: R) { + assert!(row.index() < self.num_rows); + let (start, end) = self.range(row); + let words = &mut self.words[..]; + for index in start..end { + words[index] = !0; + } + self.clear_excess_bits(row); + } + + /// Clear excess bits in the final word of the row. + fn clear_excess_bits(&mut self, row: R) { + let num_bits_in_final_word = self.num_columns % WORD_BITS; + if num_bits_in_final_word > 0 { + let mask = (1 << num_bits_in_final_word) - 1; + let (_, end) = self.range(row); + let final_word_idx = end - 1; + self.words[final_word_idx] &= mask; + } + } + + /// Gets a slice of the underlying words. + pub fn words(&self) -> &[Word] { + &self.words + } + /// Iterates through all the columns set to true in a given row of /// the matrix. pub fn iter<'a>(&'a self, row: R) -> BitIter<'a, C> { @@ -748,6 +808,12 @@ impl<R: Idx, C: Idx> BitMatrix<R, C> { marker: PhantomData, } } + + /// Returns the number of elements in `row`. + pub fn count(&self, row: R) -> usize { + let (start, end) = self.range(row); + self.words[start..end].iter().map(|e| e.count_ones() as usize).sum() + } } /// A fixed-column-size, variable-row-size 2D bit matrix with a moderately @@ -1057,6 +1123,7 @@ fn matrix_iter() { matrix.insert(2, 99); matrix.insert(4, 0); matrix.union_rows(3, 5); + matrix.insert_all_into_row(6); let expected = [99]; let mut iter = expected.iter(); @@ -1068,6 +1135,7 @@ fn matrix_iter() { let expected = [22, 75]; let mut iter = expected.iter(); + assert_eq!(matrix.count(3), expected.len()); for i in matrix.iter(3) { let j = *iter.next().unwrap(); assert_eq!(i, j); @@ -1076,6 +1144,7 @@ fn matrix_iter() { let expected = [0]; let mut iter = expected.iter(); + assert_eq!(matrix.count(4), expected.len()); for i in matrix.iter(4) { let j = *iter.next().unwrap(); assert_eq!(i, j); @@ -1084,11 +1153,24 @@ fn matrix_iter() { let expected = [22, 75]; let mut iter = expected.iter(); + assert_eq!(matrix.count(5), expected.len()); for i in matrix.iter(5) { let j = *iter.next().unwrap(); assert_eq!(i, j); } assert!(iter.next().is_none()); + + assert_eq!(matrix.count(6), 100); + let mut count = 0; + for (idx, i) in matrix.iter(6).enumerate() { + assert_eq!(idx, i); + count += 1; + } + assert_eq!(count, 100); + + if let Some(i) = matrix.iter(7).next() { + panic!("expected no elements in row, but contains element {:?}", i); + } } #[test] diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index 270d9520627..0c81c27a96e 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -503,6 +503,16 @@ impl<I: indexed_vec::Idx, CTX> HashStable<CTX> for bit_set::BitSet<I> } } +impl<R: indexed_vec::Idx, C: indexed_vec::Idx, CTX> HashStable<CTX> +for bit_set::BitMatrix<R, C> +{ + fn hash_stable<W: StableHasherResult>(&self, + ctx: &mut CTX, + hasher: &mut StableHasher<W>) { + self.words().hash_stable(ctx, hasher); + } +} + impl_stable_hash_via_hash!(::std::path::Path); impl_stable_hash_via_hash!(::std::path::PathBuf); |
