lair 0.8.0

Linear algebra in Rust
Documentation
use ndarray::{s, ArrayBase, Axis, Data, DataMut, Ix1, Ix2};

use crate::{blas, lapack, Scalar};

#[allow(dead_code)]
pub fn unglq<A, SA, ST>(a: &mut ArrayBase<SA, Ix2>, tau: &ArrayBase<ST, Ix1>)
where
    A: Scalar,
    SA: DataMut<Elem = A>,
    ST: Data<Elem = A>,
{
    ungl2(a, tau);
}

fn ungl2<A, SA, ST>(a: &mut ArrayBase<SA, Ix2>, tau: &ArrayBase<ST, Ix1>)
where
    A: Scalar,
    SA: DataMut<Elem = A>,
    ST: Data<Elem = A>,
{
    assert!(a.ncols() >= a.nrows());
    assert!(a.nrows() >= tau.len());

    let a_nrows = a.nrows();
    let a_ncols = a.ncols();
    if tau.len() < a_nrows {
        for j in 0..a_ncols {
            for l in tau.len()..a_nrows {
                a[(l, j)] = A::zero();
            }
            if j >= tau.len() && j < a_nrows {
                a[(j, j)] = A::one();
            }
        }
    }

    for (i, &tau_i) in tau.iter().enumerate().rev() {
        let (mut upper, mut lower) = a.slice_mut(s![i.., i..]).split_at(Axis(0), 1);
        let mut row = upper.row_mut(0);
        if i < a_ncols {
            lapack::lacgv(&mut row);
            if i < a_nrows {
                row[0] = A::one();
                lapack::larf::right(&row, tau_i.conj(), &mut lower);
            }
            blas::scal(-tau_i, &mut row);
            lapack::lacgv(&mut row);
        }
        row[0] = A::one() - tau_i.conj();
        a.slice_mut(s![i, ..i]).fill(A::zero());
    }
}

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

    #[test]
    fn unglq() {
        let mut a = arr2(&[
            [
                Complex32::new(2., 1.),
                Complex32::new(3., -2.),
                Complex32::new(1., 3.),
            ],
            [
                Complex32::new(-1., -2.),
                Complex32::new(-3., 1.),
                Complex32::new(-2., -1.),
            ],
        ]);
        let tau = arr1(&[Complex32::new(1., -1.)]);
        super::unglq(&mut a, &tau);
        assert_eq!(
            a,
            arr2(&[
                [
                    Complex32::new(0., -1.),
                    Complex32::new(-5., -1.),
                    Complex32::new(2., -4.)
                ],
                [
                    Complex32::new(-1., -5.),
                    Complex32::new(-12., -13.),
                    Complex32::new(14., -8.)
                ],
            ])
        );
    }
}