use ndarray::Array1;
use crate::matrix::QuadraticMatrix;
pub trait QuadraticOperator: Send + Sync {
fn n(&self) -> usize;
fn matvec_into(&self, x: &Array1<f64>, out: &mut Array1<f64>);
fn diagonal(&self) -> Option<Array1<f64>> {
None
}
fn gershgorin_upper_bound(&self) -> Option<f64> {
None
}
}
impl QuadraticOperator for QuadraticMatrix {
fn n(&self) -> usize {
self.n()
}
fn matvec_into(&self, x: &Array1<f64>, out: &mut Array1<f64>) {
self.matvec_into(x, out);
}
fn diagonal(&self) -> Option<Array1<f64>> {
Some(self.diagonal())
}
fn gershgorin_upper_bound(&self) -> Option<f64> {
Some(match self {
QuadraticMatrix::Dense(m) => {
let mut best: f64 = 1e-12;
for i in 0..m.nrows() {
let diag = m[[i, i]];
let abs_row_sum = (0..m.ncols()).map(|j| m[[i, j]].abs()).sum::<f64>();
best = best.max(diag + abs_row_sum - diag.abs());
}
best.max(1e-12)
}
QuadraticMatrix::Sparse(m) => {
let diag = m.diag();
let mut best: f64 = 1e-12;
for (i, row) in m.outer_iterator().enumerate() {
let abs_row_sum = row.iter().map(|(_, v)| v.abs()).sum::<f64>();
best = best.max(diag[i] + abs_row_sum - diag[i].abs());
}
best.max(1e-12)
}
})
}
}