use multi_ranged::{SimpleRange, Step};
use num_traits::{AsPrimitive, Zero};
use super::SquareMatrix;
use crate::traits::{Matrix, PositiveInteger};
pub trait Matrix2D:
Matrix<Coordinates = (<Self as Matrix2D>::RowIndex, <Self as Matrix2D>::ColumnIndex)>
{
type RowIndex: Step + PositiveInteger + AsPrimitive<usize>;
type ColumnIndex: Step + PositiveInteger + AsPrimitive<usize>;
fn number_of_rows(&self) -> Self::RowIndex;
fn number_of_columns(&self) -> Self::ColumnIndex;
#[inline]
fn row_indices(&self) -> SimpleRange<Self::RowIndex> {
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()))
.expect("zero <= number_of_rows - 1 holds when number_of_rows > 0")
}
}
#[inline]
fn column_indices(&self) -> SimpleRange<Self::ColumnIndex> {
let number_of_columns = self.number_of_columns();
if number_of_columns.is_zero() {
SimpleRange::default()
} else {
SimpleRange::try_from((Self::ColumnIndex::zero(), number_of_columns.prev()))
.expect("zero <= number_of_columns - 1 holds when number_of_columns > 0")
}
}
}
impl<M: Matrix2D> Matrix2D for &M {
type RowIndex = M::RowIndex;
type ColumnIndex = M::ColumnIndex;
#[inline]
fn number_of_rows(&self) -> Self::RowIndex {
(*self).number_of_rows()
}
#[inline]
fn number_of_columns(&self) -> Self::ColumnIndex {
(*self).number_of_columns()
}
}
pub trait Matrix2DRef: Matrix2D {
fn number_of_rows_ref(&self) -> &Self::RowIndex;
fn number_of_columns_ref(&self) -> &Self::ColumnIndex;
}
pub trait TransposableMatrix2D<
Transposed: Matrix2D<RowIndex = Self::ColumnIndex, ColumnIndex = Self::RowIndex>,
>: Matrix2D
{
fn transpose(&self) -> Transposed;
}
pub trait BiMatrix2D: Matrix2D {
type Matrix: Matrix2D<RowIndex = Self::RowIndex, ColumnIndex = Self::ColumnIndex>;
type TransposedMatrix: Matrix2D<RowIndex = Self::ColumnIndex, ColumnIndex = Self::RowIndex>;
fn matrix(&self) -> &Self::Matrix;
fn transposed(&self) -> &Self::TransposedMatrix;
}
pub trait SymmetricMatrix2D:
SquareMatrix
+ BiMatrix2D<
Matrix = <Self as SymmetricMatrix2D>::SymmetricMatrix,
TransposedMatrix = <Self as SymmetricMatrix2D>::SymmetricMatrix,
>
{
type SymmetricMatrix: Matrix2D<RowIndex = Self::Index, ColumnIndex = Self::Index>;
}
impl<M> SymmetricMatrix2D for M
where
M: SquareMatrix + BiMatrix2D<TransposedMatrix = <M as BiMatrix2D>::Matrix>,
M::Matrix: Matrix2D<RowIndex = Self::RowIndex, ColumnIndex = Self::ColumnIndex>,
{
type SymmetricMatrix = M::Matrix;
}