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: lu.rs
    path of file: ./repos/faer-rs/src/sparse/linalg
    
    the code of the file until where you have to start completion: //! Computes the LU decomposition of a given sparse matrix. See
//! [`faer::linalg::lu`](crate::linalg::lu) for more info.
//!
//! The entry point in this module is [`SymbolicLu`] and [`factorize_symbolic_lu`].
//!
//! # Warning
//! The functions in this module accept unsorted input, and always produce unsorted decomposition
//! factors.

use super::{
    cholesky::simplicial::EliminationTreeRef,
    colamd::Control,
    ghost,
    ghost::{Array, Idx, MaybeIdx},
    mem::{
        NONE, {self},
    },
    nomem, try_zeroed, FaerError, Index, LuError, SupernodalThreshold, SymbolicSparseColMatRef,
    SymbolicSupernodalParams,
};
use crate::{
    assert,
    linalg::{matmul, temp_mat_req, temp_mat_uninit, triangular_solve as solve},
    perm::PermRef,
    sparse::SparseColMatRef,
    utils::{constrained::Size, slice::*, vec::*},
    Conj, MatMut, Parallelism, SignedIndex,
};
use core::{iter::zip, mem::MaybeUninit};
use dyn_stack::{PodStack, SizeOverflow, StackReq};
use faer_entity::*;
use reborrow::*;

#[inline(never)]
fn resize_scalar<E: Entity>(
    v: &mut VecGroup<E>,
    n: usize,
    exact: bool,
    reserve_only: bool,
) -> Result<(), FaerError> {
    let reserve = if exact {
        VecGroup::try_reserve_exact
    } else {
        VecGroup::try_reserve
    };
    reserve(v, n.saturating_sub(v.len())).map_err(|_| FaerError::OutOfMemory)?;
    if !reserve
    
    fn test_solver_lu_simplicial() {
        type E = crate::complex_native::c64;

        let (m, n, col_ptr, row_ind, val) =
            load_mtx::<usize>(MtxData::from_file("test_data/YAO.mtx").unwrap());

        let mut rng = StdRng::seed_from_u64(0);
        let mut gen = || E::new(rng.gen::<f64>(), rng.gen::<f64>());

        let val = val.iter().map(|_| gen()).collect::<alloc::vec::Vec<_>>();
        let A = SparseColMatRef::<'_, usize, E>::new(
            SymbolicSparseColMatRef::new_checked(m, n, &col_ptr, None, &row_ind),
            &val,
        );

        let rhs = Mat::<E>::from_fn(m, 6, |_, _| gen());

        for supernodal_flop_ratio_threshold in [
            SupernodalThreshold::AUTO,
            SupernodalThreshold::FORCE_SUPERNODAL,
            SupernodalThreshold::FORCE_SIMPLICIAL,
        ] {
            let symbolic = factorize_symbolic_lu(
                A.symbolic(),
                LuSymbolicParams {
                    supernodal_flop_ratio_threshold,
                    ..Default::default()
                },
            )
            .unwrap();
            let mut numeric = NumericLu::<usize, E>::new();
            let lu = symbolic
                .factorize_numeric_lu(
                    &mut numeric,
                    A,
                    Parallelism::None,
                    PodStack::new(&mut GlobalPodBuffer::new(
                        symbolic
                            .factorize_numeric_lu_req::<E>(Parallelism::None)
                            .unwrap(),
                    )),
                )
                .unwrap();

            {
                let mut x = rhs.clone();
                lu.solve_in_place_with_conj(
                    crate::Conj::No,
                    x.as_mut(),
                    Parallelism::None,
                    PodStack::new(&mut GlobalPodBuffer::new(
                        symbolic
                            .solve_in_place_req::<E>(rhs.ncols(), Parallelism::None)
                            .unwrap(),
                    )),
                );

                let linsolve_diff = A * &x - &rhs;
                assert!(linsolve_diff.norm_max() <= 1e-10);
            }
            {
                let mut x = rhs.clone();
                lu.solve_in_place_with_conj(
                    crate::Conj::Yes,
                    x.as_mut(),
                    Parallelism::None,
                    PodStack::new(&mut GlobalPodBuffer::new(
                        symbolic
                            .solve_in_place_req::<E>(rhs.ncols(), Parallelism::None)
                            .unwrap(),
                    )),
                );

                let linsolve_diff = A.conjugate() * &x - &rhs;
                assert!(linsolve_diff.norm_max() <= 1e-10);
            }

            {
                let mut x = rhs.clone();
                lu.solve_transpose_in_place_with_conj(
                    crate::Conj::No,
                    x.as_mut(),
                    Parallelism::None,
                    PodStack::new(&mut GlobalPodBuffer::new(
                        symbolic
                            .solve_transpose_in_place_req::<E>(rhs.ncols(), Parallelism::None)
                            .unwrap(),
                    )),
                );

                let linsolve_diff = A.transpose() * &x - &rhs;
                assert!(linsolve_diff.norm_max() <= 1e-10);
            }
            {
                let mut x = rhs.clone();
                lu.solve_transpose_in_place_with_conj(
                    crate::Conj::Yes,
                    x.as_mut(),
                    Parallelism::None,
                    PodStack::new(&mut GlobalPodBuffer::new(
                        symbolic
                            .solve_transpose_in_place_req::<E>(rhs.ncols(), Parallelism::None)
                            .unwrap(),
                    )),
                );

                let linsolve_diff = A.adjoint() * &x - &rhs;
                assert!(linsolve_diff.norm_max() <= 1e-10);
            }
        }
    }