k2_tree/
matrix.rs

1
2use bitvec::vec::BitVec;
3use crate::error::BitMatrixError;
4
5type Result<T> = std::result::Result<T, BitMatrixError>;
6
7/// A 2-d bit-matrix.
8#[derive(Debug, Clone, PartialEq, Eq, Hash)]
9pub struct BitMatrix {
10  /// Width of the matrix.
11  pub width: usize,
12  /// Height of the matrix.
13  pub height: usize,
14  bits: BitVec,
15}
16impl BitMatrix {
17  /// Creates an empty BitMatrix with zero width or height.
18  pub fn new() -> Self {
19    BitMatrix {
20      width: 0,
21      height: 0,
22      bits: BitVec::new(),
23    }
24  }
25  /// Creates an empty BitMatrix with predefined dimensions.
26  pub fn with_dimensions(width: usize, height: usize) -> Self {
27    let mut bits = BitVec::with_capacity(width*height);
28    bits.resize_with(width*height, Default::default);
29    BitMatrix {
30      width,
31      height,
32      bits,
33    }
34  }
35  /// Builds a BitMatrix instance from another collection of bits.
36  /// 
37  /// If the data passed in contains more bits than will fit a matrix of the specified
38  /// height and width, excess data is discarded. If not enough bits are passed in, 0s
39  /// will be appended until the right size is reached.
40  pub fn from_bits(width: usize, height: usize, data: impl IntoIterator<Item=bool>) -> Self {
41    let mut bits: BitVec = data.into_iter().collect();
42    bits.resize_with(width*height, Default::default);
43    BitMatrix {
44      width,
45      height,
46      bits,
47    }
48  }
49  /// Returns the state of a bit at a specific coordinate.
50  pub fn get(&self, x: usize, y: usize) -> Result<bool> {
51    if x >= self.width || y >= self.height {
52      return Err(BitMatrixError::OutOfBounds {
53        x_y: [x, y],
54        max_x_y: [self.width-1, self.height-1],
55      })
56    }
57    let index = y*self.width + x;
58    return match self.bits.get(index) {
59      Some(&bit) => Ok(bit),
60      None => Err(BitMatrixError::OutOfBounds {
61        x_y: [x, y],
62        max_x_y: [self.width-1, self.height-1],
63      }),
64    };
65  }
66  /// Returns the state of all the bits at a specific x-coordinate.
67  /// 
68  /// Bits are ordered by row, starting at y-coordinate 0.
69  pub fn get_column(&self, x: usize) -> Result<Vec<bool>> {
70    if x >= self.width {
71      return Err(BitMatrixError::OutOfBounds {
72        x_y: [x, 0],
73        max_x_y: [self.width-1, self.height-1],
74      })
75    }
76    let mut column = Vec::new();
77    for row in 0..self.height {
78      column.push(self.bits[x + (row * self.width)]);
79    }
80    Ok(column)
81  }
82  /// Returns the state of all the bits at a specific y-coordinate.
83  /// 
84  /// Bits are ordered by column, starting at x-coordinate 0.
85  pub fn get_row(&self, y: usize) -> Result<Vec<bool>> {
86    if y >= self.height {
87      return Err(BitMatrixError::OutOfBounds {
88        x_y: [0, y],
89        max_x_y: [self.width-1, self.height-1],
90      })
91    }
92    let mut row = Vec::new();
93    for column in 0..self.width {
94      row.push(self.bits[(y * self.width) + column]);
95    }
96    Ok(row)
97  }
98  /// Changes the state of a bit at a specififc coordinate.
99  pub fn set(&mut self, x: usize, y: usize, state: bool) -> Result<()> {
100    if x >= self.width || y >= self.height {
101      return Err(BitMatrixError::OutOfBounds {
102        x_y: [x, y],
103        max_x_y: [self.width-1, self.height-1],
104      })
105    }
106    let index: usize = y*self.width + x;
107    self.bits.set(index, state);
108    Ok(())
109  }
110  /// Changes the width of the matrix.
111  /// 
112  /// If len is greater than matrix's width, each row is extended with 0s.
113  /// Otherwise, each row is concatenated.
114  pub fn resize_width(&mut self, len: usize) {
115    // Add or remove values at the correct spaces from the end backwards,
116    //  as to not change the index of insertion sites on other rows.
117    // Work out whether we're growing or shrinking
118    if len > self.width {
119      // Growing
120      let diff = len - self.width;
121      for row in (1..=self.height).rev() {
122        let row_end = self.width * row;
123        for _ in 0..diff { self.bits.insert(row_end, false); }
124      }
125    }
126    else if len < self.width {
127      // Shrinking
128      let diff = self.width - len;
129      for row in (1..=self.height).rev() {
130        let row_end = self.width * row;
131        for _ in 0..diff { self.bits.remove(row_end-diff); }
132      }
133    }
134    self.width = len;
135  }
136  /// Changes the hieght of the matrix.
137  /// 
138  /// If len is greater than matrix's height, it is extended with blank rows.
139  /// Otherwise, the number of rows is suitably concatenated.
140  pub fn resize_height(&mut self, len: usize) {
141    if len > self.height {
142      //Growing
143      let new_rows = len - self.height;
144      let new_bits = new_rows * self.width;
145      let end = self.bits.len();
146      for _ in 0..new_bits { self.bits.insert(end, false); }
147    }
148    else if len < self.height {
149      //Shrinking
150      let less_rows = self.height - len;
151      let less_bits = less_rows * self.width;
152      let new_end = self.bits.len() - less_bits;
153      for _ in 0..less_bits { self.bits.remove(new_end); }
154    }
155    self.height = len;
156  }
157  /// Produces the contents of the matrix as a flat vec of bits.
158  /// 
159  /// Vec contains each row one after another.
160  pub fn to_bits(&self) -> Vec<bool> {
161    let mut bits = Vec::with_capacity(self.bits.len());
162    bits.extend(&self.bits);
163    bits
164  }
165  /// Consumes the BitMatrix to produce its contents as a flat vec of bits.
166  /// 
167  /// Vec contains each row one after another.
168  pub fn into_bits(self) -> Vec<bool> {
169    let mut bits = Vec::with_capacity(self.bits.len());
170    bits.extend(&self.bits);
171    bits
172  }
173  /// Produces the contents of the matrix as a vec of its columns.
174  pub fn to_columns(&self) -> Vec<Vec<bool>> {
175    let mut vecs = vec![Vec::with_capacity(self.height); self.width];
176    for column in 0..self.width {
177      for row in 0..self.height {
178        vecs[column].push(self.bits[row*self.width + column]);
179      }
180    }
181    vecs
182  }
183  /// Consumes the BitMatrix to produce its contents as a vec of its columns.
184  pub fn into_columns(self) -> Vec<Vec<bool>> {
185    let mut vecs = vec![Vec::with_capacity(self.height); self.width];
186    for column in 0..self.width {
187      for row in 0..self.height {
188        vecs[column].push(self.bits[row*self.width + column]);
189      }
190    }
191    vecs
192  }
193  /// Produces the contents of the matrix as a vec of its rows.
194  pub fn to_rows(&self) -> Vec<Vec<bool>> {
195    let mut vecs = vec![Vec::with_capacity(self.width); self.height];
196    for row in 0..self.height {
197      vecs[row].extend(&self.bits[row*self.width..(row+1)*self.width]);
198    }
199    vecs
200  }
201  /// Consumes the BitMatrix to produce its contents as a vec of its rows.
202  pub fn into_rows(self) -> Vec<Vec<bool>> {
203    let mut vecs = vec![Vec::with_capacity(self.width); self.height];
204    for row in 0..self.height {
205      vecs[row].extend(&self.bits[row*self.width..(row+1)*self.width]);
206    }
207    vecs
208  }
209  /// Reduces the width and height such that there are no empty columns or rows
210  /// on the edges.
211  pub fn shrink_to_fit(&mut self) {
212    //Find the rightmost column containing a 1
213    //Find the lowest row containing a 1
214    //Set width and height to those positions
215    for col in (0..self.width).rev() {
216      let col_bits = {
217        let mut bv = BitVec::new();
218        bv.extend(self.get_column(col).unwrap());
219        bv
220      };
221      if !all_zeroes(&col_bits, 0, col_bits.len()) {
222        self.resize_width(col+1);
223        break
224      }
225    }
226    for row in (0..self.height).rev() {
227      let row_bits = {
228        let mut bv = BitVec::new();
229        bv.extend(self.get_row(row).unwrap());
230        bv
231      };
232      if !all_zeroes(&row_bits, 0, row_bits.len()) {
233        self.resize_height(row+1);
234        break
235      }
236    }
237  }
238}
239impl Default for BitMatrix {
240  fn default() -> Self {
241    BitMatrix::new()
242  }
243}
244
245fn all_zeroes(bits: &BitVec, begin: usize, end: usize) -> bool {
246  bits[begin..end].into_iter().fold(true, |total, bit| total & !bit)
247}
248
249#[cfg(test)]
250mod api {
251use super::*;
252  #[test]
253  fn new() {
254    let m = BitMatrix::new();
255    assert_eq!(0, m.width);
256    assert_eq!(0, m.height);
257    assert_eq!(Vec::<bool>::new(), m.into_bits());
258  }
259  #[test]
260  fn with_dimensions_0() {
261    let m = BitMatrix::with_dimensions(8, 8);
262    assert_eq!(8, m.width);
263    assert_eq!(8, m.height);
264    assert_eq!(vec![false; 64], m.into_bits());
265  }
266  #[test]
267  fn with_dimensions_1() {
268    let m = BitMatrix::with_dimensions(0, 0);
269    assert_eq!(0, m.width);
270    assert_eq!(0, m.height);
271    assert_eq!(vec![false; 0], m.to_bits());
272    assert_eq!(BitMatrix::new(), m);
273  }
274  #[test]
275  fn from_bit_0() {
276    let bits = vec![
277      false,false,false,true,
278      false,false,true,false,
279      false,true,false,false,
280      true,false,false,false,
281    ];
282    let m = BitMatrix::from_bits(4, 4, bits.clone());
283    assert_eq!(4, m.width);
284    assert_eq!(4, m.height);
285    assert_eq!(bits, m.into_bits());
286  }
287  #[test]
288  fn from_bits_1() {
289    let input_bits = vec![
290      false,false,false,true,
291      false,false,true,false,
292      false,true,false,false,
293      true,
294    ];
295    let expected_bits = vec![
296      false,false,false,true,
297      false,false,true,false,
298      false,true,false,false,
299      true,false,false,false,
300    ];
301    let m = BitMatrix::from_bits(4, 4, input_bits.clone());
302    assert_eq!(4, m.width);
303    assert_eq!(4, m.height);
304    assert_eq!(expected_bits, m.into_bits());
305  }
306  #[test]
307  fn from_bits_2() {
308    let input_bits = vec![
309      false,false,false,true,
310      false,false,true,false,
311      false,true,false,false,
312      true,false,false,false,true,true,false,false,true // excess bits to be discarded
313    ];
314    let expected_bits = vec![
315      false,false,false,true,
316      false,false,true,false,
317      false,true,false,false,
318      true,false,false,false,
319    ];
320    let m = BitMatrix::from_bits(4, 4, input_bits.clone());
321    assert_eq!(4, m.width);
322    assert_eq!(4, m.height);
323    assert_eq!(expected_bits, m.into_bits());
324  }
325  #[test]
326  fn get() -> Result<()> {
327    let bits = vec![
328      false,false,false,true,
329      false,false,true,false,
330      false,true,false,false,
331      true,false,false,false,
332    ];
333    let m = BitMatrix::from_bits(4, 4, bits.clone());
334    assert_eq!(false, m.get(0, 0)?);
335    assert_eq!(false, m.get(0, 1)?);
336    assert_eq!(true, m.get(3, 0)?);
337    assert_eq!(true, m.get(2, 1)?);
338    assert_eq!(true, m.get(1, 2)?);
339    assert_eq!(true, m.get(0, 3)?);
340    assert_eq!(false, m.get(3, 3)?);
341    assert_eq!(BitMatrixError::OutOfBounds {
342      x_y: [4, 4],
343      max_x_y: [3, 3]
344    },
345      m.get(4, 4).unwrap_err()
346    );
347    Ok(())
348  }
349  #[test]
350  fn set() -> Result<()> {
351    let mut m = BitMatrix::with_dimensions(8, 8);
352    assert_eq!(false, m.get(0, 0)?);
353    m.set(0, 0, true)?;
354    assert_eq!(true, m.get(0, 0)?);
355    m.set(0, 0, false)?;
356    assert_eq!(false, m.get(0, 0)?);
357    m.set(3, 3, true)?;
358    assert_eq!(true, m.get(3, 3)?);
359    assert_eq!(false, m.get(2, 3)?);
360    assert_eq!(false, m.get(3, 2)?);
361    assert_eq!(BitMatrixError::OutOfBounds {
362      x_y: [8, 8],
363      max_x_y: [7, 7]
364    },
365      m.set(8, 8, true).unwrap_err()
366    );
367    Ok(())
368  }
369  #[test]
370  fn resize_width_grow() -> Result<()> {
371    let bits = vec![
372      false,false,false,true,
373      false,false,true,false,
374      false,true,false,false,
375      true,false,false,false,
376    ];
377    let mut m = BitMatrix::from_bits(4, 4, bits);
378    assert_eq!(4, m.width);
379    assert_eq!(true, m.get(3, 0)?);
380    assert!(m.get(7, 0).is_err());
381    m.resize_width(8);
382    assert_eq!(8, m.width);
383    assert_eq!(true, m.get(3, 0)?);
384    assert_eq!(false, m.get(4, 0)?);
385    assert_eq!(false, m.get(7, 0)?);
386    Ok(())
387  }
388  #[test]
389  fn resize_width_shrink() -> Result<()> {
390    let bits = vec![
391      false,false,false,true,
392      false,true,true,false,
393      false,true,false,false,
394      true,false,false,false,
395    ];
396    let mut m = BitMatrix::from_bits(4, 4, bits);
397    assert_eq!(4, m.width);
398    assert_eq!(true, m.get(3, 0)?);
399    assert_eq!(true, m.get(1, 2)?);
400    m.resize_width(2);
401    assert_eq!(2, m.width);
402    assert!(m.get(3, 0).is_err());
403    assert_eq!(false, m.get(1, 0)?);
404    assert_eq!(true, m.get(1, 1)?);
405    assert_eq!(BitMatrixError::OutOfBounds {
406      x_y: [2, 3],
407      max_x_y: [1, 3]
408    },
409      m.get(2, 3).unwrap_err()
410    );
411    Ok(())
412  }
413  #[test]
414  fn resize_height_grow() -> Result<()> {
415    let bits = vec![
416      false,false,false,true,
417      false,false,true,false,
418      false,true,false,false,
419      true,false,false,false,
420    ];
421    let mut m = BitMatrix::from_bits(4, 4, bits);
422    assert_eq!(4, m.height);
423    assert_eq!(true, m.get(0, 3)?);
424    assert!(m.get(0, 5).is_err());
425    m.resize_height(8);
426    assert_eq!(8, m.height);
427    assert_eq!(true, m.get(0, 3)?);
428    assert_eq!(false, m.get(0, 5)?);
429    Ok(())
430  }
431  #[test]
432  fn resize_height_shrink() -> Result<()> {
433    let bits = vec![
434      false,false,false,true,
435      false,true,true,false,
436      false,true,false,false,
437      true,false,false,false,
438    ];
439    let mut m = BitMatrix::from_bits(4, 4, bits);
440    assert_eq!(4, m.height);
441    assert_eq!(true, m.get(0, 3)?);
442    assert_eq!(false, m.get(0, 1)?);
443    m.resize_height(2);
444    assert_eq!(2, m.height);
445    assert!(m.get(0, 3).is_err());
446    assert_eq!(false, m.get(0, 1)?);
447    assert_eq!(true, m.get(1, 1)?);
448    assert_eq!(BitMatrixError::OutOfBounds {
449      x_y: [3, 2],
450      max_x_y: [3, 1]
451    },
452      m.get(3, 2).unwrap_err()
453    );
454    Ok(())
455  }
456  #[test]
457  fn to_bits() {
458    let bits = vec![
459      false,false,false,true,
460      false,false,true,false,
461      false,true,false,false,
462      true,false,false,false,
463    ];
464    assert_eq!(bits, BitMatrix::from_bits(4, 4, bits.clone()).to_bits());
465  }
466  #[test]
467  fn into_bits() {
468    let bits = vec![
469      false,false,false,true,
470      false,false,true,false,
471      false,true,false,false,
472      true,false,false,false,
473    ];
474    assert_eq!(bits, BitMatrix::from_bits(4, 4, bits.clone()).into_bits());
475  }
476  #[test]
477  fn to_columns() {
478    let bits = vec![
479      false,false,false,true,
480      false,false,true,false,
481      false,true,false,false,
482      true,false,false,false,
483    ];
484    let vecs = BitMatrix::from_bits(4, 4, bits.clone()).to_columns();
485    assert_eq!(4, vecs.len());
486    for column in 0..4 { assert_eq!(4, vecs[column].len()); }
487    assert_eq!(vec![bits[0], bits[4], bits[8], bits[12]], vecs[0]);
488    assert_eq!(vec![bits[1], bits[5], bits[9], bits[13]], vecs[1]);
489    assert_eq!(vec![bits[2], bits[6], bits[10], bits[14]], vecs[2]);
490    assert_eq!(vec![bits[3], bits[7], bits[11], bits[15]], vecs[3]);
491  }
492  #[test]
493  fn into_columns() {
494    let bits = vec![
495      false,false,false,true,
496      false,false,true,false,
497      false,true,false,false,
498      true,false,false,false,
499    ];
500    let vecs = BitMatrix::from_bits(4, 4, bits.clone()).into_columns();
501    assert_eq!(4, vecs.len());
502    for column in 0..4 { assert_eq!(4, vecs[column].len()); }
503    assert_eq!(vec![bits[0], bits[4], bits[8], bits[12]], vecs[0]);
504    assert_eq!(vec![bits[1], bits[5], bits[9], bits[13]], vecs[1]);
505    assert_eq!(vec![bits[2], bits[6], bits[10], bits[14]], vecs[2]);
506    assert_eq!(vec![bits[3], bits[7], bits[11], bits[15]], vecs[3]);
507  }
508  #[test]
509  fn to_rows() {
510    let bits = vec![
511      false,false,false,true,
512      false,false,true,false,
513      false,true,false,false,
514      true,false,false,false,
515    ];
516    let rows = BitMatrix::from_bits(4, 4, bits.clone()).to_rows();
517    assert_eq!(4, rows.len());
518    for row in 0..4 { assert_eq!(4, rows[row].len()); }
519    assert_eq!(bits[0..4].to_vec(), rows[0]);
520    assert_eq!(bits[4..8].to_vec(), rows[1]);
521    assert_eq!(bits[8..12].to_vec(), rows[2]);
522    assert_eq!(bits[12..16].to_vec(), rows[3]);
523  }
524  #[test]
525  fn into_rows() {
526    let bits = vec![
527      false,false,false,true,
528      false,false,true,false,
529      false,true,false,false,
530      true,false,false,false,
531    ];
532    let rows = BitMatrix::from_bits(4, 4, bits.clone()).into_rows();
533    assert_eq!(4, rows.len());
534    for row in 0..4 { assert_eq!(4, rows[row].len()); }
535    assert_eq!(bits[0..4].to_vec(), rows[0]);
536    assert_eq!(bits[4..8].to_vec(), rows[1]);
537    assert_eq!(bits[8..12].to_vec(), rows[2]);
538    assert_eq!(bits[12..16].to_vec(), rows[3]);
539  }
540  #[test]
541  fn get_column() -> Result<()> {
542    let bits = vec![
543      false,false,false,true,
544      false,false,true,false,
545      false,true,false,false,
546      true,false,false,false,
547    ];
548    let m = BitMatrix::from_bits(4, 4, bits.clone());
549    assert_eq!(
550      vec![false,false,false,true],
551      m.get_column(0)?
552    );
553    assert_eq!(
554      vec![false,false,true,false],
555      m.get_column(1)?
556    );
557    assert_eq!(
558      vec![false,true,false,false],
559      m.get_column(2)?
560    );
561    assert_eq!(
562      vec![true,false,false,false],
563      m.get_column(3)?
564    );
565    Ok(())
566  }
567  #[test]
568  fn get_row() -> Result<()> {
569    let bits = vec![
570      false,false,false,true,
571      false,false,true,false,
572      false,true,false,false,
573      true,false,false,false,
574    ];
575    let m = BitMatrix::from_bits(4, 4, bits.clone());
576    assert_eq!(
577      vec![false,false,false,true],
578      m.get_row(0)?
579    );
580    assert_eq!(
581      vec![false,false,true,false],
582      m.get_row(1)?
583    );
584    assert_eq!(
585      vec![false,true,false,false],
586      m.get_row(2)?
587    );
588    assert_eq!(
589      vec![true,false,false,false],
590      m.get_row(3)?
591    );
592    Ok(())
593  }
594  #[test]
595  fn shrink_to_fit() {
596    let bits = vec![
597      true,true,false,false,
598      true,false,true,false,
599      false,false,false,false,
600      false,false,false,false,
601    ];
602    let mut m = BitMatrix::from_bits(4, 4, bits.clone());
603    assert_eq!(4, m.width);
604    assert_eq!(4, m.height);
605    m.shrink_to_fit();
606    assert_eq!(3, m.width);
607    assert_eq!(2, m.height);
608  }
609}