#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(test)]
mod tests;
pub mod prelude {
pub use crate::solver_error::SolverErrors;
pub use crate::compute_tridiag_determinant;
pub use crate::compute_solution_norm;
#[cfg(feature = "alloc")]
pub use crate::alloc::{TridiagonalSystemPrecomputed, precompute_givens, solve_givens};
#[cfg(not(feature = "alloc"))]
pub use crate::no_alloc::{TridiagonalSystemPrecomputed, precompute_givens, solve_givens};
}
use num_traits::Float;
pub mod solver_error;
mod solver_parts;
#[cfg(any(doc, feature = "alloc", feature = "std"))]
pub mod alloc;
#[cfg(any(doc, not(any(feature = "alloc", feature = "std"))))]
pub mod no_alloc;
pub fn compute_tridiag_determinant<T: Float>(sup: &[T], diag: &[T], sub: &[T]) -> T{
let mut dpp;
let mut dp = T::one();
let mut d = diag[0];
for ((&a, &b), &c) in diag.iter().skip(1).zip(sup).zip(sub){
dpp = dp;
dp = d;
d = a * dp - b * c * dpp;
}
d
}
pub fn compute_solution_norm<T: Float>(sup: &[T], diag: &[T], sub: &[T], rhs: &[T], x: &[T]) -> Result<T, solver_error::SolverErrors>{
if sup.len() != sub.len() || sup.len() + 1 != diag.len(){
return Err(solver_error::SolverErrors::InvalidDiagonals);
} else if diag.len() != rhs.len() {
return Err(solver_error::SolverErrors::InvalidRhsSizing);
}
let n = diag.len();
if diag.len() == 1{
return Ok((rhs[0] - diag[0] * x[0]).abs())
}
let mut nmax;
let mut max = (rhs[0] - diag[0] * x[0] - sup[0] * x[1]).abs();
for i in 1..n-1{
nmax = (rhs[i] - sub[i - 1] * x[i - 1] - diag[i] * x[i] - sup[i] * x[i + 1]).abs();
if nmax > max{
max = nmax;
}
}
nmax = (rhs[n-1] - diag[n-1]*x[n-1] - sub[n-2] * x[n-2]).abs();
if nmax > max{
max = nmax;
}
Ok(max)
}