scimath 0.1.2

A scientific computing library. WIP
Documentation
use crate::types::matrix::Matrix;

// solving system Ax = b by LU factorization
pub fn forward_sub(L: &Matrix, b: &Matrix) -> Matrix {
    let n: usize = L.shape().0;
    let mut x = Matrix::new(n, 1);
    let mut b_: Matrix = b.clone();
    for j in 0..n {
        if L[(j,j)] == 0.0 {
            panic!("Lower triangular matrix is singular!");
        }
        x[(j,0)] = b_[(j,0)] / L[(0,0)];
        for i in j + 1 .. n {
            b_[(i,0)] = b_[(i,0)] - L[(i,j)] * x[(j,0)];
        }
    }
    return x;
}

pub fn back_sub(U: &Matrix, b: &Matrix) -> Matrix {
    let n: usize = U.shape().0;
    let mut x = Matrix::new(n, 1);
    let mut b_ = b.clone();

    for j in (0..n).rev() {
        if U[(j,j)] == 0.0 {
            panic!("Upper triangular matrix is singular!");
        }
        x[(j,0)] = b_[(j,0)] / U[(j,j)];
        for i in 0..j {
            b_[(i,0)] = b_[(i,0)] - U[(i,j)] * x[(j,0)];
        }
    }
    return x;
}

pub fn lu(A: &Matrix, b:&Matrix) -> Matrix {
    let n = A.shape().0;
    let mut LU = A.clone();

    for k in 0..n {
        if LU[(k,k)] == 0.0 {
            panic!("LU factorization does not exist!");
        }
        for i in k + 1 .. n {
            LU[(i,k)] = LU[(i,k)] / LU[(k,k)];
        }
        for j in k + 1 .. n {
            for i in k + 1 .. n {
                LU[(i,j)] = LU[(i,j)] - LU[(i,k)] * LU[(k,j)];
            }
        }
    }

    return LU;
}

pub fn partial_lu(A: &Matrix, b:&Matrix) -> (Matrix, Matrix) {
    let n = A.shape().0;
    let mut LU = A.clone();
    let mut Pb = b.clone();

    for k in 0..n {
        // find p s.t. pivot
        let mut p: usize = 0;
        let mut max: f64 = 0.0;
        for i in k..n {
            if LU[(i,k)].abs() > max {
                p = i;
                max = LU[(i,k)].abs();
            }
        }
        if p != k {
            LU.swap_row(p,k);
            Pb.swap_row(p,k);
        }
        if LU[(k,k)] == 0.0 {
            continue;
        }
        for i in k + 1 .. n {
            LU[(i,k)] = LU[(i,k)] / LU[(k,k)];
        }
        for j in k + 1 .. n {
            for i in k + 1 .. n {
                LU[(i,j)] = LU[(i,j)] - LU[(i,k)] * LU[(k,j)];
                Pb[(i,0)] = Pb[(i,0)] - LU[(i,k)] * LU[(k,j)];
            }
        }
    }

    return (LU,Pb);
}

pub fn solve(A: &Matrix, b: &Matrix) -> Matrix {
    let LU = partial_lu(A, b);
    let x = back_sub(&LU.0, &LU.1);
    return x;
}