math_utils_lib 0.4.1

A library providing math utilities such as a parser/evaluator and a LaTeX export to export a history of parsed expressions and solved equations to LaTeX.
Documentation
use crate::Value;

#[doc(hidden)]
pub fn det_m(a: &Vec<Vec<f64>>) -> Result<Value, String> {
    if a.iter().filter(|r| r.len() != a[0].len()).count() != 0 || a.len() != a[0].len() {
        return Err("Can't calculate determinant of a non-square matrix!".to_string());
    } else if a.len() == 1 {
        return Ok(Value::Scalar(a[0][0]));
    } else if a.len() == 2 {
        return Ok(Value::Scalar(a[0][0]*a[1][1]-a[0][1]*a[1][0]));
    } else {
        let mut sum: f64 = 0.0;
        for i in 0..a[0].len() {
            let new_matrix = a[1..].iter().map(|r| r[0..i].iter().cloned().chain(r[i+1..].iter().cloned()).collect()).collect::<Vec<Vec<f64>>>();
            sum += (-1f64).powi(i as i32)*a[0][i]*det_m(&new_matrix)?.get_scalar().unwrap();
        }
        return Ok(Value::Scalar(sum));
    }
}

#[doc(hidden)]
pub fn inv_m(a: &Vec<Vec<f64>>) -> Result<Value, String> {
    match det_m(a) {
        Err(_) => return Err("Can't calculate inverse of a non-square matrix!".to_string()),
        Ok(Value::Scalar(0.)) => return Err("Can't calculate inverse of a matrix with determinant 0!".to_string()),
        _ => {}
    };

    let n = a.len();

    let mut v = a.clone();

    for i in 0..n {
        for j in 0..n {
            if j == i {
                v[i].push(1.);
            } else {
                v[i].push(0.);
            }
        }
    }

    for i in 0..v.len() - 1{
        for j in (i+1)..v.len() {
            let divisor = v[i][i]/v[j][i];
            let mut zero_line = true;
            for k in i..v[j].len() {
                v[j][k] -= v[i][k]/divisor; 
                if v[j][k] != 0. {
                    zero_line = false;
                }
            }
            if zero_line {
                return Err("Infinite solutions".to_string());
            }
        }
    }

    v.reverse();

    v.iter_mut().for_each(|x| x.reverse());

    for i in 0..v.len() {
        for _ in 0..n {
            let value = v[i].remove(0);
            v[i].push(value);
        }
    }

    for i in 0..v.len() - 1 {
        for j in (i+1)..v.len() {
            let divisor = v[i][i]/v[j][i];
            let mut zero_line = true;
            for k in i..v[j].len() {
                v[j][k] -= v[i][k]/divisor;
                if v[j][k] != 0. {
                    zero_line = false;
                }
            }
            if zero_line {
                return Err("Infinite solutions".to_string());
            }
        }
    }

    let mut result_mat: Vec<Vec<f64>> = vec![];

    for i in 0..v.len() {
        let mut row = vec![];
        let mult = 1. / v[i][i];
        for j in v[i].len()-n..v[i].len() {
             row.insert(0, v[i][j]*mult);
        }
        result_mat.insert(0, row);
    }

    Ok(Value::Matrix(result_mat))
}