mod banded;
mod block_diagonal;
mod block_tridiagonal;
mod symmetric;
mod tridiagonal;
pub use self::banded::*;
pub use self::block_diagonal::*;
pub use self::block_tridiagonal::*;
pub use self::symmetric::*;
pub use self::tridiagonal::*;
pub use self::block_tridiagonal::block_tridiagonal_lu;
use scirs2_core::ndarray::{Array1, Array2, ArrayView1, ScalarOperand};
use scirs2_core::numeric::{Float, NumAssign, One, Zero};
use std::fmt::Debug;
use std::iter::Sum;
use crate::error::LinalgResult;
use crate::matrixfree::LinearOperator;
pub trait SpecializedMatrix<A>
where
A: Float + NumAssign + Zero + Sum + One + ScalarOperand + Send + Sync + Debug,
{
fn nrows(&self) -> usize;
fn ncols(&self) -> usize;
fn get(&self, i: usize, j: usize) -> LinalgResult<A>;
fn matvec(&self, x: &ArrayView1<A>) -> LinalgResult<Array1<A>>;
fn matvec_transpose(&self, x: &ArrayView1<A>) -> LinalgResult<Array1<A>>;
fn to_dense(&self) -> LinalgResult<Array2<A>>;
fn to_operator(&self) -> LinalgResult<LinearOperator<A>>
where
Self: Sync + 'static + Sized,
{
specialized_to_operator(self)
}
}
#[allow(dead_code)]
pub fn specialized_to_operator<A, S>(matrix: &S) -> LinalgResult<LinearOperator<A>>
where
A: Float + NumAssign + Zero + Sum + One + ScalarOperand + Send + Sync + Debug + 'static,
S: SpecializedMatrix<A> + Sync + 'static + Sized,
{
let nrows = matrix.nrows();
let ncols = matrix.ncols();
let matrix_clone = matrix.to_dense()?;
let matvec = move |x: &ArrayView1<A>| {
let mut result = Array1::zeros(nrows);
for i in 0..nrows {
for j in 0..ncols {
result[i] += matrix_clone[[i, j]] * x[j];
}
}
result
};
if nrows == ncols {
Ok(LinearOperator::new(nrows, matvec))
} else {
Ok(LinearOperator::new_rectangular(nrows, ncols, matvec))
}
}