lair 0.8.0

Linear algebra in Rust
Documentation
use std::cmp;

use ndarray::{s, ArrayBase, Axis, Data, DataMut, Ix2};

use crate::Scalar;

#[allow(dead_code)]
pub fn lower<A, SA, SB>(a: &ArrayBase<SA, Ix2>, b: &mut ArrayBase<SB, Ix2>)
where
    A: Scalar,
    SA: Data<Elem = A>,
    SB: DataMut<Elem = A>,
{
    let ncols = cmp::min(a.ncols(), b.ncols());
    for (i, (a_row, mut b_row)) in a
        .lanes(Axis(1))
        .into_iter()
        .zip(b.lanes_mut(Axis(1)).into_iter())
        .enumerate()
    {
        let ncols = cmp::min(ncols, i + 1);
        for (a_v, b_v) in a_row
            .slice(s![..ncols])
            .iter()
            .zip(b_row.slice_mut(s![..ncols]).into_iter())
        {
            *b_v = *a_v;
        }
    }
}

#[allow(dead_code)]
pub fn upper<A, SA, SB>(a: &ArrayBase<SA, Ix2>, b: &mut ArrayBase<SB, Ix2>)
where
    A: Scalar,
    SA: Data<Elem = A>,
    SB: DataMut<Elem = A>,
{
    let col_min = cmp::min(a.ncols(), b.ncols());
    for (i, (a_row, mut b_row)) in a
        .lanes(Axis(1))
        .into_iter()
        .zip(b.lanes_mut(Axis(1)).into_iter())
        .enumerate()
        .take(col_min)
    {
        for (a_v, b_v) in a_row
            .slice(s![i..])
            .iter()
            .zip(b_row.slice_mut(s![i..]).into_iter())
        {
            *b_v = *a_v;
        }
    }
}

#[cfg(test)]
mod tests {
    use ndarray::{arr2, Array2};

    #[test]
    fn lower() {
        let a = Array2::<f64>::ones((0, 0));
        let mut b = Array2::<f64>::zeros((1, 2));
        super::lower(&a, &mut b);
        assert_eq!(b, Array2::<f64>::zeros((1, 2)));

        let a = Array2::<f64>::ones((1, 2));
        let mut b = Array2::<f64>::zeros((0, 0));
        super::lower(&a, &mut b);
        assert_eq!(b, Array2::<f64>::zeros((0, 0)));

        let a = Array2::<f64>::ones((2, 3));
        let mut b = Array2::<f64>::zeros((3, 2));
        super::lower(&a, &mut b);
        assert_eq!(b, arr2(&[[1., 0.], [1., 1.], [0., 0.]]));

        let a = Array2::<f64>::ones((3, 2));
        let mut b = Array2::<f64>::zeros((2, 3));
        super::lower(&a, &mut b);
        assert_eq!(b, arr2(&[[1., 0., 0.], [1., 1., 0.]]));
    }

    #[test]
    fn upper() {
        let a = Array2::<f64>::ones((0, 0));
        let mut b = Array2::<f64>::zeros((1, 2));
        super::upper(&a, &mut b);
        assert_eq!(b, Array2::<f64>::zeros((1, 2)));

        let a = Array2::<f64>::ones((1, 2));
        let mut b = Array2::<f64>::zeros((0, 0));
        super::upper(&a, &mut b);
        assert_eq!(b, Array2::<f64>::zeros((0, 0)));

        let a = Array2::<f64>::ones((2, 3));
        let mut b = Array2::<f64>::zeros((3, 2));
        super::upper(&a, &mut b);
        assert_eq!(b, arr2(&[[1., 1.], [0., 1.], [0., 0.]]));

        let a = Array2::<f64>::ones((3, 2));
        let mut b = Array2::<f64>::zeros((2, 3));
        super::upper(&a, &mut b);
        assert_eq!(b, arr2(&[[1., 1., 0.], [0., 1., 0.]]));
    }
}