#[cfg(feature = "mem_dbg")]
use alloc::string::String;
use alloc::vec::Vec;
use num_traits::{AsPrimitive, Bounded, One, Zero};
use crate::traits::{
EmptyRows, Matrix, Matrix2D, SparseMatrix, SparseMatrix2D, SparseValuedMatrix,
SparseValuedMatrix2D, TryFromUsize, ValuedMatrix, ValuedMatrix2D,
};
mod sparse_row_with_padded_diagonal;
use sparse_row_with_padded_diagonal::SparseRowWithPaddedDiagonal;
mod sparse_rows_with_padded_diagonal;
use sparse_rows_with_padded_diagonal::SparseRowsWithPaddedDiagonal;
mod sparse_row_values_with_padded_diagonal;
use multi_ranged::{SimpleRange, Step};
use sparse_row_values_with_padded_diagonal::SparseRowValuesWithPaddedDiagonal;
use super::{
CSR2DColumns, CSR2DView, M2DValues, MutabilityError,
square_padding_utils::{padded_square_size, validate_padded_square_capacity},
};
#[cfg(feature = "arbitrary")]
mod arbitrary_impl;
#[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)]
pub struct GenericMatrix2DWithPaddedDiagonal<M, Map> {
matrix: M,
map: Map,
}
impl<M, Map> GenericMatrix2DWithPaddedDiagonal<M, Map>
where
M::RowIndex: AsPrimitive<usize> + Bounded,
M::ColumnIndex: AsPrimitive<usize> + TryFromUsize + Bounded,
M: SparseMatrix2D,
{
#[inline]
pub fn new(matrix: M, map: Map) -> Result<Self, MutabilityError<M>> {
validate_padded_square_capacity(&matrix)?;
Ok(Self { matrix, map })
}
#[inline]
pub fn matrix(&self) -> &M {
&self.matrix
}
#[inline]
pub fn is_diagonal_imputed(&self, row: M::RowIndex) -> bool {
if row >= self.matrix.number_of_rows() {
return true;
}
let Ok(row_as_column) = M::ColumnIndex::try_from_usize(row.as_()) else {
return true;
};
self.matrix.sparse_row(row).all(|column| column != row_as_column)
}
}
impl<M, Map> Matrix for GenericMatrix2DWithPaddedDiagonal<M, Map>
where
M: Matrix2D,
M::RowIndex: AsPrimitive<usize> + TryFromUsize,
M::ColumnIndex: AsPrimitive<usize> + TryFromUsize,
{
type Coordinates = M::Coordinates;
#[inline]
fn shape(&self) -> Vec<usize> {
vec![self.number_of_rows().as_(), self.number_of_columns().as_()]
}
}
impl<M, Map> Matrix2D for GenericMatrix2DWithPaddedDiagonal<M, Map>
where
M: Matrix2D,
M::RowIndex: AsPrimitive<usize> + TryFromUsize,
M::ColumnIndex: AsPrimitive<usize> + TryFromUsize,
{
type RowIndex = M::RowIndex;
type ColumnIndex = M::ColumnIndex;
#[inline]
fn number_of_columns(&self) -> Self::ColumnIndex {
let max = padded_square_size(&self.matrix);
let Ok(number_of_columns) = Self::ColumnIndex::try_from_usize(max) else {
panic!("The number of columns {max} is too large to be represented as a ColumnIndex")
};
number_of_columns
}
#[inline]
fn number_of_rows(&self) -> Self::RowIndex {
let max = padded_square_size(&self.matrix);
let Ok(number_of_rows) = Self::RowIndex::try_from_usize(max) else {
panic!("The number of rows {max} is too large to be represented as a RowIndex")
};
number_of_rows
}
}
impl<M, Map> SparseMatrix for GenericMatrix2DWithPaddedDiagonal<M, Map>
where
M: SparseMatrix2D,
M::RowIndex: AsPrimitive<usize> + TryFromUsize,
M::ColumnIndex: AsPrimitive<usize> + TryFromUsize,
{
type SparseIndex = M::SparseIndex;
type SparseCoordinates<'a>
= CSR2DView<'a, Self>
where
Self: 'a;
#[inline]
fn sparse_coordinates(&self) -> Self::SparseCoordinates<'_> {
CSR2DView::from(self)
}
#[inline]
fn last_sparse_coordinates(&self) -> Option<Self::Coordinates> {
if self.is_empty() {
return None;
}
Some((
self.number_of_rows() - M::RowIndex::one(),
self.number_of_columns() - M::ColumnIndex::one(),
))
}
#[inline]
fn is_empty(&self) -> bool {
self.number_of_rows() == M::RowIndex::zero()
&& self.number_of_columns() == M::ColumnIndex::zero()
}
}
impl<M, Map> SparseMatrix2D for GenericMatrix2DWithPaddedDiagonal<M, Map>
where
M: SparseMatrix2D,
M::RowIndex: AsPrimitive<usize> + TryFromUsize,
M::ColumnIndex: AsPrimitive<usize> + TryFromUsize,
{
type SparseRow<'a>
= SparseRowWithPaddedDiagonal<'a, M>
where
Self: 'a;
type SparseColumns<'a>
= CSR2DColumns<'a, Self>
where
Self: 'a;
type SparseRows<'a>
= SparseRowsWithPaddedDiagonal<'a, Self>
where
Self: 'a;
#[inline]
fn sparse_row(&self, row: Self::RowIndex) -> Self::SparseRow<'_> {
SparseRowWithPaddedDiagonal::new(&self.matrix, row)
}
#[inline]
fn sparse_rows(&self) -> Self::SparseRows<'_> {
SparseRowsWithPaddedDiagonal::from(self)
}
#[inline]
fn sparse_columns(&self) -> Self::SparseColumns<'_> {
CSR2DColumns::from(self)
}
}
impl<M, Map> EmptyRows for GenericMatrix2DWithPaddedDiagonal<M, Map>
where
M: EmptyRows,
M::RowIndex: AsPrimitive<usize> + TryFromUsize + Step,
M::ColumnIndex: AsPrimitive<usize> + TryFromUsize,
{
type EmptyRowIndices<'a>
= core::iter::Empty<Self::RowIndex>
where
Self: 'a;
type NonEmptyRowIndices<'a>
= SimpleRange<Self::RowIndex>
where
Self: 'a;
#[inline]
fn empty_row_indices(&self) -> Self::EmptyRowIndices<'_> {
core::iter::empty()
}
#[inline]
fn non_empty_row_indices(&self) -> Self::NonEmptyRowIndices<'_> {
let number_of_rows = self.number_of_rows();
if number_of_rows.is_zero() {
SimpleRange::default()
} else {
SimpleRange::try_from((Self::RowIndex::zero(), number_of_rows.prev())).unwrap_or_else(
|_| {
unreachable!(
"Row range must be valid because GenericMatrix2DWithPaddedDiagonal::new validates square padded capacity."
)
},
)
}
}
#[inline]
fn number_of_empty_rows(&self) -> Self::RowIndex {
Self::RowIndex::zero()
}
#[inline]
fn number_of_non_empty_rows(&self) -> Self::RowIndex {
self.number_of_rows()
}
}
impl<M, Map> ValuedMatrix for GenericMatrix2DWithPaddedDiagonal<M, Map>
where
M: ValuedMatrix2D,
M::RowIndex: AsPrimitive<usize> + TryFromUsize,
M::ColumnIndex: AsPrimitive<usize> + TryFromUsize,
{
type Value = M::Value;
}
impl<M, Map> ValuedMatrix2D for GenericMatrix2DWithPaddedDiagonal<M, Map>
where
M: ValuedMatrix2D,
M::RowIndex: AsPrimitive<usize> + TryFromUsize,
M::ColumnIndex: AsPrimitive<usize> + TryFromUsize,
{
}
impl<M, Map> SparseValuedMatrix for GenericMatrix2DWithPaddedDiagonal<M, Map>
where
M: SparseValuedMatrix2D,
M::RowIndex: AsPrimitive<usize> + TryFromUsize,
M::ColumnIndex: AsPrimitive<usize> + TryFromUsize,
Map: Fn(M::RowIndex) -> M::Value,
M::Value: Clone,
{
type SparseValues<'a>
= M2DValues<'a, Self>
where
Self: 'a;
#[inline]
fn sparse_values(&self) -> Self::SparseValues<'_> {
M2DValues::from(self)
}
}
impl<M, Map> SparseValuedMatrix2D for GenericMatrix2DWithPaddedDiagonal<M, Map>
where
M: SparseValuedMatrix2D,
M::RowIndex: AsPrimitive<usize> + TryFromUsize,
M::ColumnIndex: AsPrimitive<usize> + TryFromUsize,
Map: Fn(M::RowIndex) -> M::Value,
M::Value: Clone,
{
type SparseRowValues<'a>
= SparseRowValuesWithPaddedDiagonal<'a, M, &'a Map>
where
Self: 'a;
#[inline]
fn sparse_row_values(&self, row: Self::RowIndex) -> Self::SparseRowValues<'_> {
SparseRowValuesWithPaddedDiagonal::new(&self.matrix, row, &self.map)
}
}