# CSVBinaryMatrix operations
This module defines the operations for [`CSVBinaryMatrix`].
[`CSVBinaryMatrix`]: crate::matrix::CSVBinaryMatrix
## Producing submatrices
Let say we want to obtain the submatrix of `matrix` without the second row and the first column.
```rust
use csvbinmatrix::prelude::CSVBinaryMatrix;
let matrix = CSVBinaryMatrix::try_from(&[
[0, 0, 0],
[0, 0, 1],
[0, 1, 1],
[1, 1, 1],
]).unwrap();
let expected_sub_matrix = CSVBinaryMatrix::try_from(&[
[0, 0],
[1, 1],
[1, 1],
]).unwrap();
```
### Without consuming the supermatrix
```rust
# use csvbinmatrix::prelude::CSVBinaryMatrix;
#
# let matrix = CSVBinaryMatrix::try_from(&[
# [0, 0, 0],
# [0, 0, 1],
# [0, 1, 1],
# [1, 1, 1],
# ])
# .unwrap();
#
# let expected_sub_matrix =
# CSVBinaryMatrix::try_from(&[[0, 0], [1, 1], [1, 1]]).unwrap();
use csvbinmatrix::prelude::{ClosureDimensionFilter};
let row_filter = ClosureDimensionFilter::new(|i| i != 1);
let column_filter = ClosureDimensionFilter::new(|j| j != 0);
// Generate submatrices according to the couples of row and column filters.
// `matrix` is not consumed.
match matrix.to_submatrix(&row_filter, &column_filter) {
Ok(sub_matrix) => assert_eq!(sub_matrix, expected_sub_matrix),
Err(err) => panic!("[ERROR] {err}"),
}
```
### With consuming the supermatrix
Here we show how to obtain an efficient submatrix while consuming the super binary matrix with the [`into_submatrices`] method.
The memory and the time complexities are linear according to the number ones of the super binary matrix.
As the supermatrix is consumed, `into_submatrices` take as input a vector of tuples of dimension filters, and return for each tuple of filters a submatrix.
[`into_submatrices`]: crate::matrix::CSVBinaryMatrix::into_submatrices
```rust
# use csvbinmatrix::prelude::CSVBinaryMatrix;
#
# let matrix = CSVBinaryMatrix::try_from(&[
# [0, 0, 0],
# [0, 0, 1],
# [0, 1, 1],
# [1, 1, 1],
# ])
# .unwrap();
#
# let expected_sub_matrix =
# CSVBinaryMatrix::try_from(&[[0, 0], [1, 1], [1, 1]]).unwrap();
use csvbinmatrix::prelude::{BoolVecDimensionFilter, ClosureDimensionFilter};
// Filter with a boolean vector:
// * to represent complex truth states
// * costly
let row_filter =
match BoolVecDimensionFilter::new(vec![true, false, true, true], matrix.number_of_rows()) {
Ok(filter) => filter,
Err(err) => panic!("[ERROR] {err}"),
};
// Filter with a closure
// * to represent simple truth states
// * efficient
let column_filter = ClosureDimensionFilter::new(|j| j != 0);
// Generate submatrices according to the couples of row and column filters.
// `matrix` is consumed.
let mut sub_matrices = matrix.into_submatrices(vec![(&row_filter, &column_filter)]);
// Iterate over the submatrices and check them
match sub_matrices.pop() {
Some(Ok(reversed_sub_matrix)) => {
assert_eq!(reversed_sub_matrix, expected_sub_matrix)
}
Some(Err(err)) => panic!("[ERROR] {err}"),
_ => unreachable!("There must be one resulting sub matrix."),
}
// We give only one filter couple, so there is only one resulting submatrix.
assert!(sub_matrices.pop().is_none());
// You can drop the row filter and take the ownership of the boolean vectors.
let boolvec_row = row_filter.into_boolean_vector();
println!("Boolean vector for the rows: {boolvec_row:?}");
```