use approx::assert_relative_eq;
use scirs2_sparse::csr::CsrMatrix;
use scirs2_sparse::linalg::{
cg, AsLinearOperator, CGOptions, JacobiPreconditioner, LinearOperator,
};
#[test]
#[allow(dead_code)]
fn test_cg_with_jacobi_preconditioner() {
let rows = vec![0, 0, 1, 1, 1, 2, 2];
let cols = vec![0, 1, 0, 1, 2, 1, 2];
let data = vec![4.0, -1.0, -1.0, 4.0, -1.0, -1.0, 4.0];
let matrix = CsrMatrix::new(data, rows, cols, (3, 3)).expect("Operation failed");
let precond = JacobiPreconditioner::new(&matrix).expect("Operation failed");
let op = matrix.as_linear_operator();
let b = vec![2.0, 1.0, 2.0];
let options = CGOptions::<f64> {
preconditioner: Some(Box::new(precond)),
..Default::default()
};
let result = cg(op.as_ref(), &b, options).expect("Operation failed");
assert!(result.converged);
assert!(result.iterations < 20);
let ax = op.matvec(&result.x).expect("Operation failed");
for i in 0..3 {
assert_relative_eq!(ax[i], b[i], epsilon = 1e-5);
}
}
#[test]
#[allow(dead_code)]
fn test_jacobi_preconditioner_simple() {
let rows = vec![0, 1, 2];
let cols = vec![0, 1, 2];
let data = vec![2.0, 3.0, 4.0];
let matrix = CsrMatrix::new(data, rows, cols, (3, 3)).expect("Operation failed");
let precond = JacobiPreconditioner::new(&matrix).expect("Operation failed");
let x = vec![2.0, 6.0, 12.0];
let result = precond.matvec(&x).expect("Operation failed");
assert_relative_eq!(result[0], 1.0, epsilon = 1e-10);
assert_relative_eq!(result[1], 2.0, epsilon = 1e-10);
assert_relative_eq!(result[2], 3.0, epsilon = 1e-10);
}