linfa-linalg 0.2.1

Pure-Rust implementation of linear algebra routines for ndarray
Documentation
use approx::assert_abs_diff_eq;
use ndarray::{array, Array2};
use proptest::prelude::*;

use linfa_linalg::triangular::*;

mod common;

fn tri_system(uplo: UPLO) -> impl Strategy<Value = (Array2<f64>, Array2<f64>)> {
    let squares = common::square_arr().prop_map(move |a| {
        let mut a = a.into_triangular(uplo).unwrap();
        for e in a.diag_mut() {
            if e.abs() < 1.0 {
                *e = 1.0;
            }
        }
        a
    });
    common::system_of_arr(squares)
}

fn run_solve_triangular_test(a: Array2<f64>, x: Array2<f64>, uplo: UPLO) {
    let mut b = a.dot(&x);
    let out = a.solve_triangular(&b, uplo).unwrap();
    assert_abs_diff_eq!(out, x, epsilon = 1e-4);

    let out = a.solve_triangular_into(b.clone(), uplo).unwrap();
    assert_abs_diff_eq!(out, x, epsilon = 1e-4);

    let out = a.solve_triangular_inplace(&mut b, uplo).unwrap();
    assert_abs_diff_eq!(*out, x, epsilon = 1e-4);
}

proptest! {
    #![proptest_config(ProptestConfig::with_cases(1000))]
    #[test]
    fn solve_triangular_lower(system in tri_system(UPLO::Lower)) {
        let (a, x) = system;
        run_solve_triangular_test(a, x, UPLO::Lower);
    }

    #[test]
    fn solve_triangular_upper(system in tri_system(UPLO::Upper)) {
        let (a, x) = system;
        run_solve_triangular_test(a, x, UPLO::Upper);
    }
}

#[test]
fn known_failure() {
    let a = array![
        [
            3.3562218754086643,
            816.8378593548371,
            -470.72612882136764,
            336.4740568255552,
            654.2571917815051,
            795.9197872262403,
            687.6149593664059,
            -997.6505563244662,
            681.854510815619
        ],
        [
            0.0,
            131.15884945733683,
            -896.9056656026227,
            -73.40632816520974,
            611.318676608028,
            -790.7729067903583,
            995.0019153426838,
            444.63027937639754,
            -396.09160479446655
        ],
        [
            0.0,
            0.0,
            -565.1685049775538,
            588.4959814213651,
            511.3727699624353,
            595.7728287283007,
            924.8460315485909,
            170.01500035862023,
            661.2113982885169
        ],
        [
            0.0,
            0.0,
            0.0,
            -593.2837512804098,
            -887.4556343125483,
            -242.79784588272446,
            968.5909681725007,
            721.4017188483001,
            493.7638484101958
        ],
        [
            0.0,
            0.0,
            0.0,
            0.0,
            43.15642142769889,
            -731.963766509625,
            5.590841737202595,
            209.75382244557431,
            -894.7267077467912
        ],
        [
            0.0,
            0.0,
            0.0,
            0.0,
            0.0,
            1.0,
            -961.7702985603449,
            -127.20656830334167,
            -623.3087923506572
        ],
        [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0],
        [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
        [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]
    ];

    let x = array![
        [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
        [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
        [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
        [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
        [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
        [
            0.0,
            0.0,
            0.0,
            0.0,
            0.0,
            0.0,
            826.3385166487137,
            0.0,
            0.0,
            0.0
        ],
        [
            0.0,
            0.0,
            0.0,
            0.0,
            0.0,
            0.0,
            -942.7258981612537,
            0.0,
            0.0,
            0.0
        ],
        [
            0.0,
            0.0,
            0.0,
            0.0,
            0.0,
            0.0,
            548.7103157449269,
            0.0,
            0.0,
            0.0
        ],
        [
            0.0,
            0.0,
            0.0,
            0.0,
            0.0,
            0.0,
            -352.50397129849307,
            0.0,
            0.0,
            0.0
        ]
    ];

    run_solve_triangular_test(a, x, UPLO::Upper);
}