1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//! Submodule providing a padded matrix, which fills all of the values not
//! defined in the underlying sparse matrix with the value provided by the Map
//! function.
use alloc::{string::String, vec::Vec};
use core::fmt::Debug;
use num_traits::{AsPrimitive, Bounded};
use super::{MutabilityError, square_padding_utils::validate_padded_square_capacity};
use crate::traits::{Matrix2D, SparseMatrix2D, SparseValuedMatrix2D, ValuedMatrix};
mod imputed_row_values;
mod matrix;
pub mod padded_coordinates;
mod sparse_matrix;
mod valued_matrix;
#[cfg_attr(feature = "mem_size", derive(mem_dbg::MemSize))]
#[cfg_attr(feature = "mem_size", mem_size(rec))]
#[cfg_attr(feature = "mem_dbg", derive(mem_dbg::MemDbg))]
#[derive(Clone)]
/// A padded matrix that fills all of the values not defined in the
/// underlying sparse matrix with the value provided by the Map function.
pub struct PaddedMatrix2D<M, Map> {
/// The underlying sparse matrix.
matrix: M,
/// The function to map the values not defined in the underlying sparse
/// matrix.
map: Map,
}
impl<M, Map> Debug for PaddedMatrix2D<M, Map>
where
M: SparseMatrix2D,
Self: SparseValuedMatrix2D + Matrix2D<RowIndex = M::RowIndex, ColumnIndex = M::ColumnIndex>,
<Self as ValuedMatrix>::Value: Debug,
{
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let rows: Vec<Vec<String>> = self
.row_indices()
.map(|row_index| {
self.sparse_row(row_index)
.zip(self.sparse_row_values(row_index))
.map(|(column_index, value)| {
if self.is_imputed((row_index, column_index)) {
format!("I({value:?})")
} else {
format!("{value:?}")
}
})
.collect()
})
.collect();
rows.fmt(f)
}
}
impl<M: SparseMatrix2D, Map> PaddedMatrix2D<M, Map>
where
M: SparseMatrix2D,
M::RowIndex: AsPrimitive<usize> + Bounded,
M::ColumnIndex: AsPrimitive<usize> + Bounded,
{
/// Creates a new padded matrix with the given underlying sparse matrix and
/// map function.
///
/// # Arguments
///
/// * `matrix` - The underlying sparse matrix.
/// * `map` - The function to map the values not defined in the underlying
/// sparse matrix.
///
/// # Errors
///
/// * `MutabilityError::MaxedOutColumnIndex` - The number of columns in the
/// matrix exceeds the maximum column index.
/// * `MutabilityError::MaxedOutRowIndex` - The number of rows in the matrix
/// exceeds the maximum row index.
#[inline]
pub fn new(matrix: M, map: Map) -> Result<Self, MutabilityError<M>> {
validate_padded_square_capacity(&matrix)?;
Ok(Self { matrix, map })
}
#[inline]
/// Returns whether the value at the provided coordinates is imputed or
/// not.
///
/// # Arguments
///
/// * `coordinates` - The coordinates to check.
pub fn is_imputed(&self, (row_index, column_index): (M::RowIndex, M::ColumnIndex)) -> bool {
if row_index >= self.matrix.number_of_rows()
|| column_index >= self.matrix.number_of_columns()
{
return true;
}
self.matrix.sparse_row(row_index).all(|column| column != column_index)
}
}