#![cfg(not(target_os = "android"))]
use std::time::Instant;
use ndarray::{Array1, Array2};
use ndarray_linalg::Solve;
use outram_foam_basic_lib::matrix::SquareMatrix;
fn make_problem(n: usize) -> (SquareMatrix, Array2<f64>, Vec<f64>) {
let mut sq = SquareMatrix::new(n);
let mut nd = Array2::<f64>::zeros((n, n));
for i in 0..n {
for j in 0..n {
let v = ((i
.wrapping_mul(7)
.wrapping_add(j.wrapping_mul(13))
.wrapping_add(1))
% 17
+ 1) as f64;
sq.set(i, j, v);
nd[[i, j]] = v;
}
let diag_boost = 20.0 * n as f64;
sq.add(i, i, diag_boost);
nd[[i, i]] += diag_boost;
}
let rhs: Vec<f64> = (0..n).map(|i| (i + 1) as f64).collect();
(sq, nd, rhs)
}
fn iters(n: usize) -> usize {
match n {
0..=10 => 20_000,
11..=20 => 8_000,
21..=50 => 2_000,
51..=100 => 400,
_ => 80,
}
}
#[test]
fn bench_lu_solve_vs_ndarray_linalg() {
let sizes: &[usize] = &[5, 10, 20, 50, 100, 200];
eprintln!();
eprintln!(
"{:>6} {:>12} {:>12} {:>10} {:>8}",
"n", "sq_mat (ns)", "ndarray (ns)", "ratio", "iters"
);
eprintln!("{}", "-".repeat(58));
for &n in sizes {
let reps = iters(n);
let (sq, nd_ref, rhs) = make_problem(n);
let nd_rhs = Array1::from(rhs.clone());
for _ in 0..5 {
let _ = sq.solve(&rhs);
let _ = nd_ref.solve(&nd_rhs).unwrap();
}
let t0 = Instant::now();
for _ in 0..reps {
let _ = sq.solve(&rhs);
}
let sq_ns = t0.elapsed().as_nanos() / reps as u128;
let t0 = Instant::now();
for _ in 0..reps {
let _ = nd_ref.solve(&nd_rhs).unwrap();
}
let nd_ns = t0.elapsed().as_nanos() / reps as u128;
let ratio = sq_ns as f64 / nd_ns as f64;
eprintln!(
"{:>6} {:>12} {:>12} {:>10.2} {:>8}",
n, sq_ns, nd_ns, ratio, reps
);
}
eprintln!();
eprintln!("ratio < 1.0 → SquareMatrix faster; ratio > 1.0 → ndarray-linalg faster");
}