A Vec of Bits
at workspace 282 lines 8.6 kB view raw
1//! Matrix of bits. 2//! 3//! # Examples 4//! 5//! Gets a mutable reference to the square bit matrix within this 6//! rectangular matrix, then performs a transitive closure. 7//! 8//! ```rust 9//! use bit_matrix::BitMatrix; 10//! 11//! let mut matrix = BitMatrix::new(7, 5); 12//! matrix.set(1, 2, true); 13//! matrix.set(2, 3, true); 14//! matrix.set(3, 4, true); 15//! 16//! { 17//! let mut sub_matrix = matrix.sub_matrix_mut(1 .. 6); 18//! sub_matrix.transitive_closure(); 19//! } 20//! assert!(matrix[(1, 4)]); 21//! 22//! matrix.reflexive_closure(); 23//! assert!(matrix[(0, 0)]); 24//! assert!(matrix[(1, 1)]); 25//! assert!(matrix[(2, 2)]); 26//! assert!(matrix[(3, 3)]); 27//! ``` 28 29use core::cmp; 30use core::ops::{Index, IndexMut, RangeBounds}; 31 32use bit_vec::BitVec; 33 34use super::{FALSE, TRUE}; 35use crate::local_prelude::*; 36use crate::util::round_up_to_next; 37 38/// A matrix of bits. 39#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] 40#[cfg_attr( 41 feature = "miniserde", 42 derive(miniserde::Serialize, miniserde::Deserialize) 43)] 44#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 45pub struct BitMatrix { 46 bit_vec: BitVec, 47 row_bits: usize, 48} 49 50// Matrix 51 52impl BitMatrix { 53 /// Create a new BitMatrix with specific numbers of bits in columns and rows. 54 pub fn new(rows: usize, row_bits: usize) -> Self { 55 BitMatrix { 56 bit_vec: BitVec::from_elem(round_up_to_next(row_bits, BITS) * rows, false), 57 row_bits, 58 } 59 } 60 61 /// Returns the number of rows. 62 #[inline] 63 fn num_rows(&self) -> usize { 64 if self.row_bits == 0 { 65 0 66 } else { 67 let row_blocks = round_up_to_next(self.row_bits, BITS) / BITS; 68 self.bit_vec.storage().len() / row_blocks 69 } 70 } 71 72 /// Returns the number of columns. 73 #[inline] 74 pub fn num_cols(&self) -> usize { 75 self.row_bits 76 } 77 78 /// Returns the matrix's size as `(rows, columns)`. 79 pub fn size(&self) -> (usize, usize) { 80 (self.num_rows(), self.row_bits) 81 } 82 83 /// Sets the value of a bit. 84 /// 85 /// # Panics 86 /// 87 /// Panics if `(row, col)` is out of bounds. 88 #[inline] 89 pub fn set(&mut self, row: usize, col: usize, enabled: bool) { 90 let row_size_in_bits = round_up_to_next(self.row_bits, BITS); 91 self.bit_vec.set(row * row_size_in_bits + col, enabled); 92 } 93 94 /// Sets the value of all bits. 95 #[inline] 96 pub fn set_all(&mut self, enabled: bool) { 97 self.bit_vec.fill(enabled); 98 } 99 100 /// Grows the matrix in-place, adding `num_rows` rows filled with `value`. 101 pub fn grow(&mut self, num_rows: usize, value: bool) { 102 self.bit_vec 103 .grow(round_up_to_next(self.row_bits, BITS) * num_rows, value); 104 } 105 106 /// Truncates the matrix. 107 pub fn truncate(&mut self, num_rows: usize) { 108 self.bit_vec 109 .truncate(round_up_to_next(self.row_bits, BITS) * num_rows); 110 } 111 112 /// Returns a slice of the matrix's rows. 113 #[inline] 114 pub fn sub_matrix<R: RangeBounds<usize>>(&self, range: R) -> BitSubMatrix<'_> { 115 let row_size = round_up_to_next(self.row_bits, BITS) / BITS; 116 BitSubMatrix { 117 slice: &self.bit_vec.storage()[( 118 range.start_bound().map(|&s| s * row_size), 119 range.end_bound().map(|&e| e * row_size), 120 )], 121 row_bits: self.row_bits, 122 } 123 } 124 125 /// Returns a slice of the matrix's rows. 126 #[inline] 127 pub fn sub_matrix_mut<R: RangeBounds<usize>>(&mut self, range: R) -> BitSubMatrixMut<'_> { 128 let row_size = self.row_size(); 129 // Safety: 130 // 131 unsafe { 132 BitSubMatrixMut { 133 slice: &mut self.bit_vec.storage_mut()[( 134 range.start_bound().map(|&s| s * row_size), 135 range.end_bound().map(|&e| e * row_size), 136 )], 137 row_bits: self.row_bits, 138 } 139 } 140 } 141 142 fn row_size(&self) -> usize { 143 round_up_to_next(self.row_bits, BITS) / BITS 144 } 145 146 /// Given a row's index, returns a slice of all rows above that row, a reference to said row, 147 /// and a slice of all rows below. 148 /// 149 /// Functionally equivalent to `(self.sub_matrix(0..row), &self[row], 150 /// self.sub_matrix(row..self.num_rows()))`. 151 #[inline] 152 pub fn split_at(&self, row: usize) -> (BitSubMatrix<'_>, BitSubMatrix<'_>) { 153 ( 154 self.sub_matrix(0..row), 155 self.sub_matrix(row..self.num_rows()), 156 ) 157 } 158 159 /// Given a row's index, returns a slice of all rows above that row, a reference to said row, 160 /// and a slice of all rows below. 161 #[inline] 162 pub fn split_at_mut(&mut self, row: usize) -> (BitSubMatrixMut<'_>, BitSubMatrixMut<'_>) { 163 let row_size = round_up_to_next(self.row_bits, BITS) / BITS; 164 let (first, second) = unsafe { self.bit_vec.storage_mut().split_at_mut(row * row_size) }; 165 ( 166 BitSubMatrixMut::new(first, self.row_bits), 167 BitSubMatrixMut::new(second, self.row_bits), 168 ) 169 } 170 171 /// Iterate over bits in the specified row. 172 pub fn iter_row(&self, row: usize) -> impl Iterator<Item = bool> + '_ { 173 BitSlice::new(&self[row].slice).iter_bits(self.row_bits) 174 } 175 176 /// Computes the transitive closure of the binary relation 177 /// represented by this square bit matrix. 178 /// 179 /// Modifies this matrix in place using Warshall's algorithm. 180 /// 181 /// After this operation, the matrix will describe a transitive 182 /// relation. This means that, for any indices `a`, `b`, `c`, 183 /// if `M[(a, b)]` and `M[(b, c)]`, then `M[(a, c)]`. 184 /// 185 /// # Complexity 186 /// 187 /// The time complexity is **O(n^3)**, where `n` is the number 188 /// of columns and rows. 189 /// 190 /// # Panics 191 /// 192 /// The matrix must be square for this operation to succeed. 193 pub fn transitive_closure(&mut self) { 194 Into::<BitSubMatrixMut>::into(self).transitive_closure(); 195 } 196 197 /// Determines whether the number of rows equals the number of columns. 198 /// 199 /// This means the matrix is square. 200 pub fn is_square(&self) -> bool { 201 self.num_rows() == self.row_bits 202 } 203 204 /// Determines whether the matrix is empty. 205 pub fn is_empty(&self) -> bool { 206 self.size() == (0, 0) 207 } 208 209 /// Computes the reflexive closure of the binary relation represented by 210 /// this bit matrix. The matrix can be rectangular. 211 /// 212 /// The reflexive closure means that for every `x`` that will be within bounds, 213 /// `M[(x, x)]` is true. 214 /// 215 /// In other words, modifies this matrix in-place by making all 216 /// bits on the diagonal set. 217 pub fn reflexive_closure(&mut self) { 218 for i in 0..cmp::min(self.row_bits, self.num_rows()) { 219 self.set(i, i, true); 220 } 221 } 222} 223 224/// Gains immutable access to the matrix's row in the form of a `BitSlice`. 225impl Index<usize> for BitMatrix { 226 type Output = BitSlice; 227 228 #[inline] 229 fn index(&self, row: usize) -> &BitSlice { 230 let row_size = round_up_to_next(self.row_bits, BITS) / BITS; 231 BitSlice::new(&self.bit_vec.storage()[row * row_size..(row + 1) * row_size]) 232 } 233} 234 235/// Gains mutable access to the matrix's row in the form of a `BitSlice`. 236impl IndexMut<usize> for BitMatrix { 237 #[inline] 238 fn index_mut(&mut self, row: usize) -> &mut BitSlice { 239 let row_size = round_up_to_next(self.row_bits, BITS) / BITS; 240 unsafe { 241 BitSlice::new_mut(&mut self.bit_vec.storage_mut()[row * row_size..(row + 1) * row_size]) 242 } 243 } 244} 245 246/// Returns `true` if a bit is enabled in the matrix, or `false` otherwise. 247/// 248/// The first index in the tuple is row number, and the second is column 249/// number. 250impl Index<(usize, usize)> for BitMatrix { 251 type Output = bool; 252 253 #[inline] 254 fn index(&self, (row, col): (usize, usize)) -> &bool { 255 let row_size_in_bits = round_up_to_next(self.row_bits, BITS); 256 if self.bit_vec.get(row * row_size_in_bits + col).unwrap() { 257 &TRUE 258 } else { 259 &FALSE 260 } 261 } 262} 263 264impl<'a> From<&'a mut BitMatrix> for BitSubMatrixMut<'a> { 265 fn from(value: &'a mut BitMatrix) -> Self { 266 unsafe { BitSubMatrixMut::new(value.bit_vec.storage_mut(), value.row_bits) } 267 } 268} 269 270// Tests 271 272#[test] 273fn test_empty() { 274 let mut matrix = BitMatrix::new(0, 0); 275 for _ in 0..3 { 276 assert_eq!(matrix.num_rows(), 0); 277 assert_eq!(matrix.size(), (0, 0)); 278 assert!(matrix.is_square()); 279 assert!(matrix.is_empty()); 280 matrix.transitive_closure(); 281 } 282}