use core::fmt::Debug;
#[cfg(feature = "alloc")]
use super::{CSR2D, SquareCSR2D, SymmetricCSR2D, UpperTriangularCSR2D, ValuedCSR2D};
use crate::traits::Matrix2D;
#[derive(Clone, PartialEq, Eq, thiserror::Error)]
pub enum Error<M: Matrix2D> {
#[error("Mutability error: {0}")]
Mutability(#[from] MutabilityError<M>),
}
impl<M: Matrix2D> Debug for Error<M> {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
<Self as core::fmt::Display>::fmt(self, f)
}
}
#[derive(Clone, PartialEq, Eq, thiserror::Error)]
pub enum MutabilityError<M: Matrix2D + ?Sized> {
#[error("Unordered coordinate: {0:?}")]
UnorderedCoordinate(M::Coordinates),
#[error("Duplicated entry: {0:?}")]
DuplicatedEntry(M::Coordinates),
#[error("Entry out of expected bounds: {0:?}, expected within: {1:?} - {2}")]
OutOfBounds(M::Coordinates, M::Coordinates, &'static str),
#[error("Row index type has been maxed out")]
MaxedOutRowIndex,
#[error("Column index type has been maxed out")]
MaxedOutColumnIndex,
#[error("Sparse index type has been maxed out")]
MaxedOutSparseIndex,
#[error("Requested shape is smaller than the current shape")]
IncompatibleShape,
}
impl<M: Matrix2D> Debug for MutabilityError<M> {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
<Self as core::fmt::Display>::fmt(self, f)
}
}
#[cfg(feature = "alloc")]
impl<M> From<MutabilityError<SquareCSR2D<M>>> for MutabilityError<UpperTriangularCSR2D<M>>
where
M: Matrix2D,
{
#[inline]
fn from(error: MutabilityError<SquareCSR2D<M>>) -> Self {
match error {
MutabilityError::UnorderedCoordinate(coordinates) => {
MutabilityError::UnorderedCoordinate(coordinates)
}
MutabilityError::DuplicatedEntry(coordinates) => {
MutabilityError::DuplicatedEntry(coordinates)
}
MutabilityError::OutOfBounds(coordinates, boundaries, context) => {
MutabilityError::OutOfBounds(coordinates, boundaries, context)
}
MutabilityError::MaxedOutRowIndex => MutabilityError::MaxedOutRowIndex,
MutabilityError::MaxedOutColumnIndex => MutabilityError::MaxedOutColumnIndex,
MutabilityError::MaxedOutSparseIndex => MutabilityError::MaxedOutSparseIndex,
MutabilityError::IncompatibleShape => MutabilityError::IncompatibleShape,
}
}
}
#[cfg(feature = "alloc")]
impl<M> From<MutabilityError<UpperTriangularCSR2D<M>>> for MutabilityError<SymmetricCSR2D<M>>
where
M: Matrix2D,
{
#[inline]
fn from(error: MutabilityError<UpperTriangularCSR2D<M>>) -> Self {
match error {
MutabilityError::UnorderedCoordinate(coordinates) => {
MutabilityError::UnorderedCoordinate(coordinates)
}
MutabilityError::DuplicatedEntry(coordinates) => {
MutabilityError::DuplicatedEntry(coordinates)
}
MutabilityError::OutOfBounds(coordinates, boundaries, context) => {
MutabilityError::OutOfBounds(coordinates, boundaries, context)
}
MutabilityError::MaxedOutRowIndex => MutabilityError::MaxedOutRowIndex,
MutabilityError::MaxedOutColumnIndex => MutabilityError::MaxedOutColumnIndex,
MutabilityError::MaxedOutSparseIndex => MutabilityError::MaxedOutSparseIndex,
MutabilityError::IncompatibleShape => MutabilityError::IncompatibleShape,
}
}
}
#[cfg(feature = "alloc")]
impl<M> From<MutabilityError<M>> for MutabilityError<SquareCSR2D<M>>
where
M: Matrix2D,
{
#[inline]
fn from(error: MutabilityError<M>) -> Self {
match error {
MutabilityError::UnorderedCoordinate(coordinates) => {
MutabilityError::UnorderedCoordinate(coordinates)
}
MutabilityError::DuplicatedEntry(coordinates) => {
MutabilityError::DuplicatedEntry(coordinates)
}
MutabilityError::OutOfBounds(coordinates, boundaries, context) => {
MutabilityError::OutOfBounds(coordinates, boundaries, context)
}
MutabilityError::MaxedOutRowIndex => MutabilityError::MaxedOutRowIndex,
MutabilityError::MaxedOutColumnIndex => MutabilityError::MaxedOutColumnIndex,
MutabilityError::MaxedOutSparseIndex => MutabilityError::MaxedOutSparseIndex,
MutabilityError::IncompatibleShape => MutabilityError::IncompatibleShape,
}
}
}
#[cfg(feature = "alloc")]
impl<SparseIndex, RowIndex, ColumnIndex, Value>
From<MutabilityError<CSR2D<SparseIndex, RowIndex, ColumnIndex>>>
for MutabilityError<ValuedCSR2D<SparseIndex, RowIndex, ColumnIndex, Value>>
where
CSR2D<SparseIndex, RowIndex, ColumnIndex>:
Matrix2D<RowIndex = RowIndex, ColumnIndex = ColumnIndex>,
ValuedCSR2D<SparseIndex, RowIndex, ColumnIndex, Value>:
Matrix2D<RowIndex = RowIndex, ColumnIndex = ColumnIndex>,
{
#[inline]
fn from(error: MutabilityError<CSR2D<SparseIndex, RowIndex, ColumnIndex>>) -> Self {
match error {
MutabilityError::UnorderedCoordinate(coordinates) => {
MutabilityError::UnorderedCoordinate(coordinates)
}
MutabilityError::DuplicatedEntry(coordinates) => {
MutabilityError::DuplicatedEntry(coordinates)
}
MutabilityError::OutOfBounds(coordinates, boundaries, context) => {
MutabilityError::OutOfBounds(coordinates, boundaries, context)
}
MutabilityError::MaxedOutRowIndex => MutabilityError::MaxedOutRowIndex,
MutabilityError::MaxedOutColumnIndex => MutabilityError::MaxedOutColumnIndex,
MutabilityError::MaxedOutSparseIndex => MutabilityError::MaxedOutSparseIndex,
MutabilityError::IncompatibleShape => MutabilityError::IncompatibleShape,
}
}
}
#[cfg(all(test, feature = "alloc"))]
mod tests {
use alloc::string::ToString;
use super::*;
#[derive(PartialEq, Eq)]
struct TestMatrix;
impl Matrix2D for TestMatrix {
type RowIndex = usize;
type ColumnIndex = usize;
fn number_of_rows(&self) -> Self::RowIndex {
0
}
fn number_of_columns(&self) -> Self::ColumnIndex {
0
}
}
impl crate::traits::Matrix for TestMatrix {
type Coordinates = (usize, usize);
fn shape(&self) -> alloc::vec::Vec<usize> {
alloc::vec![0, 0]
}
}
#[test]
fn test_mutability_error_unordered_coordinate_display() {
let error: MutabilityError<TestMatrix> = MutabilityError::UnorderedCoordinate((1, 2));
let display = error.to_string();
assert!(display.contains("Unordered coordinate"));
assert!(display.contains("(1, 2)"));
}
#[test]
fn test_mutability_error_duplicated_entry_display() {
let error: MutabilityError<TestMatrix> = MutabilityError::DuplicatedEntry((3, 4));
let display = error.to_string();
assert!(display.contains("Duplicated entry"));
assert!(display.contains("(3, 4)"));
}
#[test]
fn test_mutability_error_out_of_bounds_display() {
let error: MutabilityError<TestMatrix> =
MutabilityError::OutOfBounds((5, 6), (10, 10), "test context");
let display = error.to_string();
assert!(display.contains("out of"));
assert!(display.contains("bounds"));
assert!(display.contains("test context"));
}
#[test]
fn test_mutability_error_maxed_out_row_index_display() {
let error: MutabilityError<TestMatrix> = MutabilityError::MaxedOutRowIndex;
let display = error.to_string();
assert!(display.contains("Row index"));
assert!(display.contains("maxed out"));
}
#[test]
fn test_mutability_error_maxed_out_column_index_display() {
let error: MutabilityError<TestMatrix> = MutabilityError::MaxedOutColumnIndex;
let display = error.to_string();
assert!(display.contains("Column index"));
assert!(display.contains("maxed out"));
}
#[test]
fn test_mutability_error_maxed_out_sparse_index_display() {
let error: MutabilityError<TestMatrix> = MutabilityError::MaxedOutSparseIndex;
let display = error.to_string();
assert!(display.contains("Sparse index"));
assert!(display.contains("maxed out"));
}
#[test]
fn test_mutability_error_incompatible_shape_display() {
let error: MutabilityError<TestMatrix> = MutabilityError::IncompatibleShape;
let display = error.to_string();
assert!(display.contains("shape"));
assert!(display.contains("smaller"));
}
#[test]
fn test_error_display() {
let mutability_error: MutabilityError<TestMatrix> =
MutabilityError::UnorderedCoordinate((1, 2));
let error: Error<TestMatrix> = Error::Mutability(mutability_error);
let display = error.to_string();
assert!(display.contains("Mutability error"));
}
#[test]
fn test_error_from_mutability_error() {
let mutability_error: MutabilityError<TestMatrix> =
MutabilityError::DuplicatedEntry((1, 2));
let error: Error<TestMatrix> = mutability_error.into();
match error {
Error::Mutability(inner) => {
assert_eq!(inner, MutabilityError::DuplicatedEntry((1, 2)));
}
}
}
#[test]
fn test_mutability_error_equality() {
let error1: MutabilityError<TestMatrix> = MutabilityError::UnorderedCoordinate((1, 2));
let error2: MutabilityError<TestMatrix> = MutabilityError::UnorderedCoordinate((1, 2));
let error3: MutabilityError<TestMatrix> = MutabilityError::UnorderedCoordinate((3, 4));
assert_eq!(error1, error2);
assert_ne!(error1, error3);
}
#[test]
fn test_mutability_error_debug() {
let error: MutabilityError<TestMatrix> = MutabilityError::MaxedOutRowIndex;
let debug = alloc::format!("{error:?}");
assert!(debug.contains("Row index"));
}
#[test]
fn test_test_matrix_shape_helpers() {
let matrix = TestMatrix;
assert_eq!(matrix.number_of_rows(), 0);
assert_eq!(matrix.number_of_columns(), 0);
assert_eq!(crate::traits::Matrix::shape(&matrix), alloc::vec![0, 0]);
}
}