A Vec of Bits
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}