mathru 0.16.2

Fundamental algorithms for scientific computing in Rust
Documentation
use crate::algebra::abstr::{AbsDiffEq, RelativeEq};
use crate::algebra::abstr::{Field, Scalar};
use crate::algebra::linear::matrix::substitute::SubstituteBackward;
use crate::algebra::linear::{
    matrix::{General, UpperTriangular},
    vector::Vector,
};
use crate::relative_eq;

impl<T> SubstituteBackward<Vector<T>> for UpperTriangular<T>
where
    T: Field + Scalar + AbsDiffEq<Epsilon = T> + RelativeEq,
{
    fn substitute_backward(&self, mut c: Vector<T>) -> Result<Vector<T>, ()> {
        let rows = self.matrix.nrows();

        for k in (0..rows).rev() {
            for l in (k + 1..rows).rev() {
                c[k] = c[k] - self[[k, l]] * c[l];
            }

            let div = c[k] / self[[k, k]];
            if div.to_f64().is_finite() {
                c[k] = div;
            } else if !relative_eq!(c[k], T::from_f64(0.000000000001) * T::default_epsilon()) {
                return Err(());
            } else {
                c[k] = T::one();
            }
        }

        Ok(c)
    }
}

impl<T> SubstituteBackward<General<T>> for UpperTriangular<T>
where
    T: Field + Scalar,
{
    fn substitute_backward(&self, mut c: General<T>) -> Result<General<T>, ()> {
        let (rows, cols) = c.dim();

        for j in 0..cols {
            for k in (0..rows).rev() {
                for i in (k + 1..rows).rev() {
                    c[[k, j]] = c[[k, j]] - c[[i, j]] * self[[k, i]];
                }

                c[[k, j]] /= self[[k, k]];
            }
        }

        Ok(c)
    }
}