You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: qr.rs
    path of file: ./repos/faer-rs/src/sparse/linalg
    
    the code of the file until where you have to start completion: //! Computes the QR decomposition of a given sparse matrix. See [`crate::linalg::qr`] for more info.
//!
//! The entry point in this module is [`SymbolicQr`] and [`factorize_symbolic_qr`].
//!
//! # Warning
//! The functions in this module accept unsorted input, and always produce unsorted decomposition
//! factors.

use super::{
    cholesky::{
        ghost_postorder,
        simplicial::EliminationTreeRef,
        supernodal::{SupernodalLltRef, SymbolicSupernodalCholesky},
    },
    colamd::{self, Control},
    ghost::{self, Array, Idx, MaybeIdx},
    mem::{self, NONE},
    nomem, try_zeroed, FaerError, Index, SupernodalThreshold, SymbolicSupernodalParams,
};
use crate::{
    assert,
    linalg::{
        householder::apply_block_householder_sequence_transpose_on_the_left_in_place_with_conj,
        temp_mat_req, temp_mat_uninit,
    },
    perm::PermRef,
    sparse::{SparseColMatRef, SymbolicSparseColMatRef},
    unzipped,
    utils::{constrained::Size, slice::*},
    zipped, Conj, MatMut, Parallelism, SignedIndex,
};
use core::iter::zip;
use dyn_stack::{PodStack, SizeOverflow, StackReq};
use faer_entity::*;
use reborrow::*;

#[inline]
pub(crate) fn ghost_col_etree<'n, I: Index>(
    A: ghost::SymbolicSparseColMatRef<'_, 'n, '_, I>,
    col_perm: Option<ghost::PermRef<'n, '_, I>>,
    etree: &mut Array<'n, I::Signed>,
    stack: PodStack<'_>,
) {
    let I = I::truncate;

    let N = A.ncols();
    let M = A.nrows();

    let (ancestor, stack) = stack.make_raw::<I::Signed>(*N);
    let (prev, _) = stack.make_raw::<I::Signed>(*M);

    let ancestor = Array::from_mut(ghost::fill_none::<I>(ancestor, N), N);
    let prev = Array::from_mut(ghost::fill_none::<I>(prev, N), M);

    mem::fill_none(etree.as_mut());
    for j in N.indices() {
        let pj = col_perm.map(|perm| perm.arrays().0[j].zx()).unwrap_or(j);
        for i_ in A.row_indices_of_col(pj) {
            let mut i = prev[i_].sx();
            while let Some(i_) = i.idx() {
                if i_ == j {
                    break;
                }
                let next_i = ancestor[i_];
                ancestor[i_] = MaybeIdx::from_index(j.truncate());
                if next_i.idx().is_none() {
                    etree[i_] = I(*j).to_signed();
                    break;
                }
                i = next_i.sx();
            }
            prev[i_] = MaybeIdx::from_index(j.truncate());
        }
    }
}

/// Computes the size and alignment of the workspace required to compute the column elimination tree
/// of a matrix $A$ with dimensions `(nrows, ncols)`.
#[inline]
pub fn col_etree_req<I: Index>(nrows: usize, ncols: usize) -> Result<StackReq, SizeOverflow> {
    StackReq::try_all_of([
        StackReq::try_new::<I>(nrows)?,
        StackReq::try_new::<I>(ncols)?,
    ])
}

/// Computes the column elimination tree of $A$, which is the same as the elimination tree of $A^H
/// A$.
///
/// `etree` has length `A.ncols()`
#[inline]
pub fn col_etree<'out, I: Index>(
    A: SymbolicSparseColMatRef<'_, I>,
    col_perm: Option<PermRef<'_, I>>,
    etree: &'out mut [I],
    stack: PodStack<'_>,
) -> EliminationTreeRef<'out, I> {
    Size::with2(A.nrows(), A.ncols(), |M, N| {
        ghost_col_etree(
            ghost::SymbolicSparseColMatRef::new(A, M, N),
            col_perm.map(|perm| ghost::PermRef::new(perm, N)),
            Array::from_mut(bytemuck::cast_slice_mut(etree), N),
            stack,
        );

        EliminationTreeRef {
            inner: bytemuck::cast_
    
    fn test_numeric_qr_1_transpose() {
        type I = usize;
        type E = c64;

        let I = I::truncate;

        let mut gen = rand::rngs::StdRng::seed_from_u64(0);

        let (m, n, col_ptr, row_ind, values) =
            load_mtx::<usize>(MtxData::from_file("test_data/lp_share2b.mtx").unwrap());
        let values = values
            .iter()
            .map(|&x| c64::new(x, gen.gen()))
            .collect::<Vec<_>>();

        let nnz = row_ind.len();

        let A = SparseColMatRef::<'_, I, E>::new(
            SymbolicSparseColMatRef::new_checked(m, n, &col_ptr, None, &row_ind),
            &values,
        );
        let zero = I(0);
        Size::with2(m, n, |M, N| {
            let A = ghost::SparseColMatRef::new(A, M, N);
            let mut new_col_ptrs = vec![zero; m + 1];
            let mut new_row_ind = vec![zero; nnz];
            let mut new_values = vec![E::faer_zero(); nnz];

            let AT = crate::sparse::utils::ghost_transpose(
                &mut new_col_ptrs,
                &mut new_row_ind,
                SliceGroupMut::<'_, E>::new(&mut new_values),
                A,
                PodStack::new(&mut GlobalPodBuffer::new(StackReq::new::<I>(*M))),
            )
            .into_const();

            let (A, AT) = (AT, A);
            let (M, N) = (N, M);
            let (m, n) = (n, m);

            let mut etree = vec![zero.to_signed(); n];
            let mut post = vec![zero; n];
            let mut col_counts = vec![zero; n];
            let mut min_row = vec![zero; m];

            ghost_col_etree(
                *A,
                None,
                Array::from_mut(&mut etree, N),
                PodStack::new(&mut GlobalPodBuffer::new(StackReq::new::<I>(*M + *N))),
            );
            let etree_ = Array::from_ref(MaybeIdx::from_slice_ref_checked(&etree, N), N);
            ghost_postorder(
                Array::from_mut(&mut post, N),
                etree_,
                PodStack::new(&mut GlobalPodBuffer::new(StackReq::new::<I>(3 * *N))),
            );

            ghost_column_counts_aat(
                Array::from_mut(&mut col_counts, N),
                Array::from_mut(bytemuck::cast_slice_mut(&mut min_row), M),
                *AT,
                None,
                etree_,
                Array::from_ref(Idx::from_slice_ref_checked(&post, N), N),
                PodStack::new(&mut GlobalPodBuffer::new(StackReq::new::<I>(5 * *N + *M))),
            );

            let min_col = min_row;

            let symbolic = factorize_supernodal_symbolic_qr::<I>(
                A.symbolic().into_inner(),
                None,
                min_col,
                EliminationTreeRef::<'_, I> { inner: &etree },
                &col_counts,
                PodStack::new(&mut GlobalPodBuffer::new(
                    supernodal::factorize_supernodal_symbolic_qr_req::<usize>(*M, *N).unwrap(),
                )),
                Default::default(),
            )
            .unwrap();

            let mut householder_row_indices =
                vec![zero; symbolic.householder().len_householder_row_indices()];

            let mut L_values = vec![E::faer_zero(); symbolic.r_adjoint().len_values()];
            let mut householder_values =
                vec![E::faer_zero(); symbolic.householder().len_householder_values()];
            let mut tau_values = vec![E::faer_zero(); symbolic.householder().len_tau_values()];

            let mut tau_blocksize = vec![I(0); n];
            let mut householder_nrows = vec![I(0); n];
            let mut householder_ncols = vec![I(0); n];

            let qr = factorize_supernodal_numeric_qr::<I, E>(
                &mut householder_row_indices,
                &mut tau_blocksize,
                &mut householder_nrows,
                &mut householder_ncols,
                &mut L_values,
                &mut householder_values,
                &mut tau_values,
                AT.into_inner(),
                None,
                &symbolic,
                crate::Parallelism::None,
                PodStack::new(&mut GlobalPodBuffer::new(
                    factorize_supernodal_numeric_qr_req::<usize, E>(
                        &symbolic,
                        crate::Parallelism::None,
                    )
                    .unwrap(),
                )),
            );

            let a = sparse_to_dense(A.into_inner());

            let rhs = Mat::<E>::from_fn(m, 2, |_, _| c64::new(gen.gen(), gen.gen()));
            let mut x = rhs.clone();
            let mut work = rhs.clone();
            qr.solve_in_place_with_conj(
                crate::Conj::No,
                x.as_mut(),
                crate::Parallelism::None,
                work.as_mut(),
                PodStack::new(&mut GlobalPodBuffer::new(
                    symbolic
                        .solve_in_place_req::<E>(2, crate::Parallelism::None)
                        .unwrap(),
                )),
            );
            let x = x.as_ref().subrows(0, n);

            let linsolve_diff = a.adjoint() * (&a * &x - &rhs);

            let llt = reconstruct_from_supernodal_llt::<I, E>(symbolic.r_adjoint(), &L_values);
            let ata = a.adjoint() * &a;

            let llt_diff = &llt - &ata;
            assert!(llt_diff.norm_max() <= 1e-10);
            assert!(linsolve_diff.norm_max() <= 1e-10);
        });
    }