// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
// Copyright (C) 2012-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// SPDX-License-Identifier: MPL-2.0

#ifndef EIGEN_SPARSE_LU_H
#define EIGEN_SPARSE_LU_H

// IWYU pragma: private
#include "./InternalHeaderCheck.h"

namespace Eigen {

template <typename MatrixType_, typename OrderingType_ = COLAMDOrdering<typename MatrixType_::StorageIndex>>
class SparseLU;
template <typename MappedSparseMatrixType>
struct SparseLUMatrixLReturnType;
template <typename MatrixLType, typename MatrixUType>
struct SparseLUMatrixUReturnType;

template <bool Conjugate, class SparseLUType>
class SparseLUTransposeView : public SparseSolverBase<SparseLUTransposeView<Conjugate, SparseLUType>> {
 protected:
  using APIBase = SparseSolverBase<SparseLUTransposeView<Conjugate, SparseLUType>>;
  using APIBase::m_isInitialized;

 public:
  using Scalar = typename SparseLUType::Scalar;
  using StorageIndex = typename SparseLUType::StorageIndex;
  using MatrixType = typename SparseLUType::MatrixType;
  using OrderingType = typename SparseLUType::OrderingType;

  enum { ColsAtCompileTime = MatrixType::ColsAtCompileTime, MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime };

  SparseLUTransposeView() = default;
  SparseLUTransposeView(const SparseLUTransposeView& view) : APIBase() {
    this->m_sparseLU = view.m_sparseLU;
    this->m_isInitialized = view.m_isInitialized;
  }
  void setIsInitialized(const bool isInitialized) { this->m_isInitialized = isInitialized; }
  void setSparseLU(SparseLUType* sparseLU) { m_sparseLU = sparseLU; }
  using APIBase::_solve_impl;
  template <typename Rhs, typename Dest>
  bool _solve_impl(const MatrixBase<Rhs>& B, MatrixBase<Dest>& X_base) const {
    Dest& X(X_base.derived());
    eigen_assert(m_sparseLU->info() == Success && "The matrix should be factorized first");
    EIGEN_STATIC_ASSERT((Dest::Flags & RowMajorBit) == 0, THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);

    // const_cast_derived() is needed to enable aliasing detection when applying the permutations.
    for (Index j = 0; j < B.cols(); ++j) {
      X.col(j) = m_sparseLU->colsPermutation() * B.const_cast_derived().col(j);
    }
    // Forward substitution with transposed or adjoint of U
    m_sparseLU->matrixU().template solveTransposedInPlace<Conjugate>(X);

    // Backward substitution with transposed or adjoint of L
    m_sparseLU->matrixL().template solveTransposedInPlace<Conjugate>(X);

    // Permute back the solution
    for (Index j = 0; j < B.cols(); ++j) X.col(j) = m_sparseLU->rowsPermutation().transpose() * X.col(j);
    return true;
  }
  inline Index rows() const { return m_sparseLU->rows(); }
  inline Index cols() const { return m_sparseLU->cols(); }

 private:
  SparseLUType* m_sparseLU = nullptr;
  SparseLUTransposeView& operator=(const SparseLUTransposeView&) = delete;
};

/** \ingroup SparseLU_Module
 * \class SparseLU
 *
 * \brief Sparse supernodal LU factorization for general matrices
 *
 * This class implements the supernodal LU factorization for general matrices.
 * It uses the main techniques from the sequential SuperLU package
 * (http://crd-legacy.lbl.gov/~xiaoye/SuperLU/). It handles transparently real
 * and complex arithmetic with single and double precision, depending on the
 * scalar type of your input matrix.
 * The code has been optimized to provide BLAS-3 operations during supernode-panel updates.
 * It benefits directly from the built-in high-performant Eigen BLAS routines.
 * Moreover, when the size of a supernode is very small, the BLAS calls are avoided to
 * enable a better optimization from the compiler. For best performance,
 * you should compile it with NDEBUG flag to avoid the numerous bounds checking on vectors.
 *
 * An important parameter of this class is the ordering method. It is used to reorder the columns
 * (and eventually the rows) of the matrix to reduce the number of new elements that are created during
 * numerical factorization. The cheapest method available is COLAMD.
 * See  \link OrderingMethods_Module the OrderingMethods module \endlink for the list of
 * built-in and external ordering methods.
 *
 * Simple example with key steps
 * \code
 * VectorXd x(n), b(n);
 * SparseMatrix<double> A;
 * SparseLU<SparseMatrix<double>, COLAMDOrdering<int> > solver;
 * // Fill A and b.
 * // Compute the ordering permutation vector from the structural pattern of A.
 * solver.analyzePattern(A);
 * // Compute the numerical factorization.
 * solver.factorize(A);
 * // Use the factors to solve the linear system.
 * x = solver.solve(b);
 * \endcode
 *
 * We can directly call compute() instead of analyzePattern() and factorize()
 * \code
 * VectorXd x(n), b(n);
 * SparseMatrix<double> A;
 * SparseLU<SparseMatrix<double>, COLAMDOrdering<int> > solver;
 * // Fill A and b.
 * solver.compute(A);
 * // Use the factors to solve the linear system.
 * x = solver.solve(b);
 * \endcode
 *
 * Or give the matrix to the constructor SparseLU(const MatrixType& matrix)
 * \code
 * VectorXd x(n), b(n);
 * SparseMatrix<double> A;
 * // Fill A and b.
 * SparseLU<SparseMatrix<double>, COLAMDOrdering<int> > solver(A);
 * // Use the factors to solve the linear system.
 * x = solver.solve(b);
 * \endcode
 *
 * \warning The input matrix A should be in a \b compressed and \b column-major form.
 * Otherwise an expensive copy will be made. You can call the inexpensive makeCompressed() to get a compressed matrix.
 *
 * \note Unlike the initial SuperLU implementation, there is no step to equilibrate the matrix.
 * For badly scaled matrices, this step can be useful to reduce the pivoting during factorization.
 * If this is the case for your matrices, you can try the basic scaling method at
 *  "Eigen/src/IterativeLinearSolvers/Scaling.h"
 *
 * \tparam MatrixType_ The type of the sparse matrix. It must be a column-major SparseMatrix<>
 * \tparam OrderingType_ The ordering method to use, either AMD, COLAMD or METIS. Default is COLAMD
 *
 * \implsparsesolverconcept
 *
 * \sa \ref TutorialSparseSolverConcept
 * \sa \ref OrderingMethods_Module
 */
template <typename MatrixType_, typename OrderingType_>
class SparseLU : public SparseSolverBase<SparseLU<MatrixType_, OrderingType_>>,
                 public internal::SparseLUImpl<typename MatrixType_::Scalar, typename MatrixType_::StorageIndex> {
 protected:
  using APIBase = SparseSolverBase<SparseLU<MatrixType_, OrderingType_>>;
  using APIBase::m_isInitialized;

 public:
  using APIBase::_solve_impl;

  using MatrixType = MatrixType_;
  using OrderingType = OrderingType_;
  using Scalar = typename MatrixType::Scalar;
  using RealScalar = typename MatrixType::RealScalar;
  using StorageIndex = typename MatrixType::StorageIndex;
  using NCMatrix = SparseMatrix<Scalar, ColMajor, StorageIndex>;
  using SCMatrix = internal::MappedSuperNodalMatrix<Scalar, StorageIndex>;
  using ScalarVector = Matrix<Scalar, Dynamic, 1>;
  using IndexVector = Matrix<StorageIndex, Dynamic, 1>;
  using PermutationType = PermutationMatrix<Dynamic, Dynamic, StorageIndex>;
  using Base = internal::SparseLUImpl<Scalar, StorageIndex>;

  enum { ColsAtCompileTime = MatrixType::ColsAtCompileTime, MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime };

 public:
  /** \brief Basic constructor of the solver.
   *
   * Construct a SparseLU. As no matrix is given as argument, compute() should be called afterward with a matrix.
   */
  SparseLU()
      : m_lastError(""), m_Ustore(0, 0, 0, 0, 0, 0), m_symmetricmode(false), m_diagpivotthresh(1.0), m_detPermR(1) {
    initperfvalues();
  }
  /** \brief Constructor of the solver already based on a specific matrix.
   *
   * Construct a SparseLU. compute() is already called with the given matrix.
   */
  explicit SparseLU(const MatrixType& matrix)
      : m_lastError(""), m_Ustore(0, 0, 0, 0, 0, 0), m_symmetricmode(false), m_diagpivotthresh(1.0), m_detPermR(1) {
    initperfvalues();
    compute(matrix);
  }

  ~SparseLU() {
    // Free all explicit dynamic pointers
  }

  void analyzePattern(const MatrixType& matrix);
  void factorize(const MatrixType& matrix);
  void simplicialfactorize(const MatrixType& matrix);

  /** \brief Analyze and factorize the matrix so the solver is ready to solve.
   *
   * Compute the symbolic and numeric factorization of the input sparse matrix.
   * The input matrix should be in column-major storage, otherwise analyzePattern()
   * will do a heavy copy.
   *
   * Call analyzePattern() followed by factorize()
   *
   * \sa analyzePattern(), factorize()
   */
  void compute(const MatrixType& matrix) {
    // Analyze
    analyzePattern(matrix);
    // Factorize
    factorize(matrix);
  }

  /** \brief Return a solver for the transposed matrix.
   *
   * \returns an expression of the transposed of the factored matrix.
   *
   * A typical usage is to solve for the transposed problem A^T x = b:
   * \code
   * solver.compute(A);
   * x = solver.transpose().solve(b);
   * \endcode
   *
   * \sa adjoint(), solve()
   */
  const SparseLUTransposeView<false, SparseLU<MatrixType_, OrderingType_>> transpose() {
    SparseLUTransposeView<false, SparseLU<MatrixType_, OrderingType_>> transposeView;
    transposeView.setSparseLU(this);
    transposeView.setIsInitialized(this->m_isInitialized);
    return transposeView;
  }

  /** \brief Return a solver for the adjointed matrix.
   *
   * \returns an expression of the adjoint of the factored matrix
   *
   * A typical usage is to solve for the adjoint problem A' x = b:
   * \code
   * solver.compute(A);
   * x = solver.adjoint().solve(b);
   * \endcode
   *
   * For real scalar types, this function is equivalent to transpose().
   *
   * \sa transpose(), solve()
   */
  const SparseLUTransposeView<true, SparseLU<MatrixType_, OrderingType_>> adjoint() {
    SparseLUTransposeView<true, SparseLU<MatrixType_, OrderingType_>> adjointView;
    adjointView.setSparseLU(this);
    adjointView.setIsInitialized(this->m_isInitialized);
    return adjointView;
  }

  /** \brief Give the number of rows.
   */
  inline Index rows() const { return m_mat.rows(); }
  /** \brief Give the number of columns.
   */
  inline Index cols() const { return m_mat.cols(); }
  /** \brief Let you set that the pattern of the input matrix is symmetric
   */
  void isSymmetric(bool sym) { m_symmetricmode = sym; }

  /** \brief Give the matrixL
   *
   * \returns an expression of the matrix L, internally stored as supernodes
   * The only operation available with this expression is the triangular solve
   * \code
   * y = b; matrixL().solveInPlace(y);
   * \endcode
   */
  SparseLUMatrixLReturnType<SCMatrix> matrixL() const { return SparseLUMatrixLReturnType<SCMatrix>(m_Lstore); }
  /** \brief Give the MatrixU
   *
   * \returns an expression of the matrix U,
   * The only operation available with this expression is the triangular solve
   * \code
   * y = b; matrixU().solveInPlace(y);
   * \endcode
   */
  SparseLUMatrixUReturnType<SCMatrix, Map<SparseMatrix<Scalar, ColMajor, StorageIndex>>> matrixU() const {
    return SparseLUMatrixUReturnType<SCMatrix, Map<SparseMatrix<Scalar, ColMajor, StorageIndex>>>(m_Lstore, m_Ustore);
  }

  /** \brief Give the row matrix permutation.
   *
   * \returns a reference to the row matrix permutation \f$ P_r \f$ such that \f$P_r A P_c^T = L U\f$
   * \sa colsPermutation()
   */
  inline const PermutationType& rowsPermutation() const { return m_perm_r; }
  /** \brief Give the column matrix permutation.
   *
   * \returns a reference to the column matrix permutation \f$ P_c \f$ such that \f$P_r A P_c^T = L U\f$
   * \sa rowsPermutation()
   */
  inline const PermutationType& colsPermutation() const { return m_perm_c; }
  /** Set the threshold used for a diagonal entry to be an acceptable pivot. */
  void setPivotThreshold(const RealScalar& thresh) { m_diagpivotthresh = thresh; }

#ifdef EIGEN_PARSED_BY_DOXYGEN
  /** \brief Solve a system \f$ A X = B \f$
   *
   * \returns the solution X of \f$ A X = B \f$ using the current decomposition of A.
   *
   * \warning the destination matrix X in X = this->solve(B) must be column-major.
   *
   * \sa compute()
   */
  template <typename Rhs>
  inline Solve<SparseLU, Rhs> solve(const MatrixBase<Rhs>& B) const;
#endif  // EIGEN_PARSED_BY_DOXYGEN

  /** \brief Reports whether previous computation was successful.
   *
   * \returns \c Success if computation was successful,
   *          \c NumericalIssue if the LU factorization reports a problem, zero diagonal for instance
   *          \c InvalidInput if the input matrix is invalid
   *
   * You can get a readable error message with lastErrorMessage().
   *
   * \sa lastErrorMessage()
   */
  ComputationInfo info() const {
    eigen_assert(m_isInitialized && "Decomposition is not initialized.");
    return m_info;
  }

  /** \brief Give a human readable error
   *
   * \returns A string describing the type of error
   */
  std::string lastErrorMessage() const { return m_lastError; }

  template <typename Rhs, typename Dest>
  bool _solve_impl(const MatrixBase<Rhs>& B, MatrixBase<Dest>& X_base) const {
    Dest& X(X_base.derived());
    eigen_assert(m_factorizationIsOk && "The matrix should be factorized first");
    EIGEN_STATIC_ASSERT((Dest::Flags & RowMajorBit) == 0, THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);

    // Permute the right hand side to form X = Pr*B
    // on return, X is overwritten by the computed solution
    X.resize(B.rows(), B.cols());

    // const_cast_derived() is needed to enable aliasing detection when applying the permutations.
    for (Index j = 0; j < B.cols(); ++j) X.col(j) = rowsPermutation() * B.const_cast_derived().col(j);

    // Forward substitution with L
    this->matrixL().solveInPlace(X);
    this->matrixU().solveInPlace(X);

    // Permute back the solution
    for (Index j = 0; j < B.cols(); ++j) X.col(j) = colsPermutation().inverse() * X.col(j);

    return true;
  }

  /** \brief Give the absolute value of the determinant.
   *
   * \returns the absolute value of the determinant of the matrix of which
   * *this is the LU factorization.
   *
   * \warning a determinant can be very big or small, so for matrices
   * of large enough dimension, there is a risk of overflow/underflow.
   * One way to work around that is to use logAbsDeterminant() instead.
   *
   * \sa logAbsDeterminant(), signDeterminant()
   */
  Scalar absDeterminant() const {
    using std::abs;
    eigen_assert(m_factorizationIsOk && "The matrix should be factorized first.");
    // Initialize with the determinant of the row matrix
    Scalar det = Scalar(1.);
    // Note that the diagonal blocks of U are stored in supernodes,
    // which are available in the  L part :)
    for (Index j = 0; j < this->cols(); ++j) {
      for (typename SCMatrix::InnerIterator it(m_Lstore, j); it; ++it) {
        if (it.index() == j) {
          det *= abs(it.value());
          break;
        }
      }
    }
    return det;
  }

  /** \brief Give the natural log of the absolute determinant.
   *
   * \returns the natural log of the absolute value of the determinant of the matrix
   * of which *this is the LU factorization
   *
   * \note This method is useful to work around the risk of overflow/underflow that's
   * inherent to the determinant computation.
   *
   * \sa absDeterminant(), signDeterminant()
   */
  Scalar logAbsDeterminant() const {
    using std::abs;
    using std::log;

    eigen_assert(m_factorizationIsOk && "The matrix should be factorized first.");
    Scalar det = Scalar(0.);
    for (Index j = 0; j < this->cols(); ++j) {
      for (typename SCMatrix::InnerIterator it(m_Lstore, j); it; ++it) {
        if (it.row() < j) continue;
        if (it.row() == j) {
          det += log(abs(it.value()));
          break;
        }
      }
    }
    return det;
  }

  /** \brief Give the sign of the determinant.
   *
   * \returns A number representing the sign of the determinant
   *
   * \sa absDeterminant(), logAbsDeterminant()
   */
  Scalar signDeterminant() const {
    eigen_assert(m_factorizationIsOk && "The matrix should be factorized first.");
    // Initialize with the determinant of the row matrix
    Index det = 1;
    // Note that the diagonal blocks of U are stored in supernodes,
    // which are available in the  L part :)
    for (Index j = 0; j < this->cols(); ++j) {
      for (typename SCMatrix::InnerIterator it(m_Lstore, j); it; ++it) {
        if (it.index() == j) {
          if (it.value() < 0)
            det = -det;
          else if (it.value() == 0)
            return 0;
          break;
        }
      }
    }
    return det * m_detPermR * m_detPermC;
  }

  /** \brief Give the determinant.
   *
   * \returns The determinant of the matrix.
   *
   * \sa absDeterminant(), logAbsDeterminant()
   */
  Scalar determinant() const {
    eigen_assert(m_factorizationIsOk && "The matrix should be factorized first.");
    // Initialize with the determinant of the row matrix
    Scalar det = Scalar(1.);
    // Note that the diagonal blocks of U are stored in supernodes,
    // which are available in the  L part :)
    for (Index j = 0; j < this->cols(); ++j) {
      for (typename SCMatrix::InnerIterator it(m_Lstore, j); it; ++it) {
        if (it.index() == j) {
          det *= it.value();
          break;
        }
      }
    }
    return (m_detPermR * m_detPermC) > 0 ? det : -det;
  }

  /** \brief Give the number of non zero in matrix L.
   */
  Index nnzL() const { return m_nnzL; }
  /** \brief Give the number of non zero in matrix U.
   */
  Index nnzU() const { return m_nnzU; }

 protected:
  // Functions
  void initperfvalues() {
    m_perfv.panel_size = 16;
    m_perfv.relax = 1;
    m_perfv.maxsuper = 128;
    m_perfv.rowblk = 16;
    m_perfv.colblk = 8;
    m_perfv.fillfactor = 20;
  }

  // Variables
  mutable ComputationInfo m_info;
  bool m_factorizationIsOk;
  bool m_analysisIsOk;
  std::string m_lastError;
  NCMatrix m_mat;                                              // The input (permuted ) matrix
  SCMatrix m_Lstore;                                           // The lower triangular matrix (supernodal)
  Map<SparseMatrix<Scalar, ColMajor, StorageIndex>> m_Ustore;  // The upper triangular matrix
  PermutationType m_perm_c;                                    // Column permutation
  PermutationType m_perm_r;                                    // Row permutation
  IndexVector m_etree;                                         // Column elimination tree

  typename Base::GlobalLU_t m_glu;

  // SparseLU options
  bool m_symmetricmode;
  // values for performance
  internal::perfvalues m_perfv;
  RealScalar m_diagpivotthresh;  // Specifies the threshold used for a diagonal entry to be an acceptable pivot
  Index m_nnzL, m_nnzU;          // Nonzeros in L and U factors
  Index m_detPermR, m_detPermC;  // Determinants of the permutation matrices
 private:
  SparseLU(const SparseLU&) = delete;
};  // End class SparseLU

// Functions needed by the analysis phase
/** \brief Compute the column permutation.
 *
 * Compute the column permutation to minimize the fill-in
 *
 *  - Apply this permutation to the input matrix -
 *
 *  - Compute the column elimination tree on the permuted matrix
 *
 *  - Postorder the elimination tree and the column permutation
 *
 * It is possible to call compute() instead of analyzePattern() + factorize().
 *
 * If the matrix is row-major this function will do a heavy copy.
 *
 * \sa factorize(), compute()
 */
template <typename MatrixType, typename OrderingType>
void SparseLU<MatrixType, OrderingType>::analyzePattern(const MatrixType& mat) {
  // TODO  It is possible as in SuperLU to compute row and column scaling vectors to equilibrate the matrix mat.

  // Firstly, copy the whole input matrix.
  m_mat = mat;

  // Compute fill-in ordering
  OrderingType ord;
  ord(m_mat, m_perm_c);

  // Apply the permutation to the column of the input matrix
  if (m_perm_c.size()) {
    // Switch to uncompressed mode so innerNonZeroPtr() exists and can be
    // permuted consistently with outerIndexPtr().
    // Downstream sparse traversals may also rely on these per-column counts
    // while m_mat remains uncompressed.
    m_mat.uncompress();
    // A compressed column-major input already exposes valid column pointers.
    // Otherwise snapshot the internal column-major structure before permuting in place.
    const bool useInputOuterIndex = !MatrixType::IsRowMajor && mat.isCompressed();
    ei_declare_aligned_stack_constructed_variable(
        StorageIndex, outerIndexPtr, m_mat.cols() + 1,
        useInputOuterIndex ? const_cast<StorageIndex*>(mat.outerIndexPtr()) : 0);
    if (!useInputOuterIndex)
      IndexVector::Map(outerIndexPtr, m_mat.cols() + 1) = IndexVector::Map(m_mat.outerIndexPtr(), m_mat.cols() + 1);

    // Apply the permutation and compute the nnz per column.
    for (Index i = 0; i < mat.cols(); i++) {
      m_mat.outerIndexPtr()[m_perm_c.indices()(i)] = outerIndexPtr[i];
      m_mat.innerNonZeroPtr()[m_perm_c.indices()(i)] = outerIndexPtr[i + 1] - outerIndexPtr[i];
    }
  }

  // Compute the column elimination tree of the permuted matrix
  IndexVector firstRowElt;
  internal::coletree(m_mat, m_etree, firstRowElt);

  // In symmetric mode, do not do postorder here
  if (!m_symmetricmode) {
    IndexVector post, iwork;
    // Post order etree
    internal::treePostorder(StorageIndex(m_mat.cols()), m_etree, post);

    // Renumber etree in postorder
    Index m = m_mat.cols();
    iwork.resize(m + 1);
    for (Index i = 0; i < m; ++i) iwork(post(i)) = post(m_etree(i));
    m_etree = iwork;

    // Postmultiply A*Pc by post, i.e reorder the matrix according to the postorder of the etree
    PermutationType post_perm(m);
    for (Index i = 0; i < m; i++) post_perm.indices()(i) = post(i);

    // Combine the two permutations : postorder the permutation for future use
    if (m_perm_c.size()) {
      m_perm_c = post_perm * m_perm_c;
    }

  }  // end postordering

  m_analysisIsOk = true;
}

// Functions needed by the numerical factorization phase

/** \brief Factorize the matrix to get the solver ready.
 *
 *  - Numerical factorization
 *  - Interleaved with the symbolic factorization
 *
 * To get error of this function you should check info(), you can get more info of
 * errors with lastErrorMessage().
 *
 * In the past (before 2012 (git history is not older)), this function was returning an integer.
 * This exit was 0 if successful factorization.
 * > 0 if info = i, and i is been completed, but the factor U is exactly singular,
 * and division by zero will occur if it is used to solve a system of equation.
 * > A->ncol: number of bytes allocated when memory allocation failure occurred, plus A->ncol.
 * If lwork = -1, it is the estimated amount of space needed, plus A->ncol.
 *
 * Note: 'A' in the above description refers to the factored matrix (historical naming from SuperLU).
 *
 * \sa analyzePattern(), compute(), SparseLU(), info(), lastErrorMessage()
 */
template <typename MatrixType, typename OrderingType>
void SparseLU<MatrixType, OrderingType>::factorize(const MatrixType& matrix) {
  using internal::emptyIdxLU;
  eigen_assert(m_analysisIsOk && "analyzePattern() should be called first");
  eigen_assert((matrix.rows() == matrix.cols()) && "Only for squared matrices");

  m_isInitialized = true;

  // Reset state from any prior factorize() so info() and lastErrorMessage()
  // describe this call's outcome, not the previous matrix's.
  m_info = Success;
  m_lastError.clear();

  // Apply the column permutation computed in analyzepattern()
  m_mat = matrix;
  if (m_perm_c.size()) {
    // Switch to uncompressed mode so innerNonZeroPtr() exists and can be
    // permuted consistently with outerIndexPtr().
    m_mat.uncompress();
    const bool useInputOuterIndex = !MatrixType::IsRowMajor && matrix.isCompressed();
    ei_declare_aligned_stack_constructed_variable(
        StorageIndex, outerIndexPtr, m_mat.cols() + 1,
        useInputOuterIndex ? const_cast<StorageIndex*>(matrix.outerIndexPtr()) : 0);
    if (!useInputOuterIndex)
      IndexVector::Map(outerIndexPtr, m_mat.cols() + 1) = IndexVector::Map(m_mat.outerIndexPtr(), m_mat.cols() + 1);
    for (Index i = 0; i < matrix.cols(); i++) {
      m_mat.outerIndexPtr()[m_perm_c.indices()(i)] = outerIndexPtr[i];
      m_mat.innerNonZeroPtr()[m_perm_c.indices()(i)] = outerIndexPtr[i + 1] - outerIndexPtr[i];
    }
  } else {  // FIXME This should not be needed if the empty permutation is handled transparently
    m_perm_c.resize(matrix.cols());
    for (StorageIndex i = 0; i < matrix.cols(); ++i) m_perm_c.indices()(i) = i;
  }

  Index m = m_mat.rows();
  Index n = m_mat.cols();
  Index nnz = m_mat.nonZeros();
  Index maxpanel = m_perfv.panel_size * m;
  // Allocate working storage common to the factor routines
  Index lwork = 0;
  // Return the size of actually allocated memory when allocation failed,
  // and 0 on success.
  Index info = Base::memInit(m, n, nnz, lwork, m_perfv.fillfactor, m_perfv.panel_size, m_glu);
  if (info) {
    m_lastError = "UNABLE TO ALLOCATE WORKING MEMORY\n\n";
    m_factorizationIsOk = false;
    return;
  }

  // Set up pointers for integer working arrays
  IndexVector segrep(m);
  segrep.setZero();
  IndexVector parent(m);
  parent.setZero();
  IndexVector xplore(m);
  xplore.setZero();
  IndexVector repfnz(maxpanel);
  IndexVector panel_lsub(maxpanel);
  IndexVector xprune(n);
  xprune.setZero();
  IndexVector marker(m * internal::LUNoMarker);
  marker.setZero();

  repfnz.setConstant(-1);
  panel_lsub.setConstant(-1);

  // Set up pointers for scalar working arrays
  ScalarVector dense;
  dense.setZero(maxpanel);
  ScalarVector tempv;
  tempv.setZero(internal::LUnumTempV(m, m_perfv.panel_size, m_perfv.maxsuper, /*m_perfv.rowblk*/ m));

  // Compute the inverse of perm_c
  PermutationType iperm_c(m_perm_c.inverse());

  // Identify initial relaxed snodes
  IndexVector relax_end(n);
  if (m_symmetricmode == true)
    Base::heap_relax_snode(n, m_etree, m_perfv.relax, marker, relax_end);
  else
    Base::relax_snode(n, m_etree, m_perfv.relax, marker, relax_end);

  m_perm_r.resize(m);
  m_perm_r.indices().setConstant(-1);
  marker.setConstant(-1);
  m_detPermR = 1;  // Record the determinant of the row permutation

  m_glu.supno(0) = emptyIdxLU;
  m_glu.xsup.setConstant(0);
  m_glu.xsup(0) = m_glu.xlsub(0) = m_glu.xusub(0) = m_glu.xlusup(0) = Index(0);

  // Work on one 'panel' at a time. A panel is one of the following :
  //  (a) a relaxed supernode at the bottom of the etree, or
  //  (b) panel_size contiguous columns, <panel_size> defined by the user
  Index jcol;
  Index pivrow;  // Pivotal row number in the original row matrix
  Index nseg1;   // Number of segments in U-column above panel row jcol
  Index nseg;    // Number of segments in each U-column
  Index irep;
  Index i, k, jj;
  for (jcol = 0; jcol < n;) {
    // Adjust panel size so that a panel won't overlap with the next relaxed snode.
    Index panel_size = m_perfv.panel_size;  // upper bound on panel width
    for (k = jcol + 1; k < (std::min)(jcol + panel_size, n); k++) {
      if (relax_end(k) != emptyIdxLU) {
        panel_size = k - jcol;
        break;
      }
    }
    if (k == n) panel_size = n - jcol;

    // Symbolic outer factorization on a panel of columns
    Base::panel_dfs(m, panel_size, jcol, m_mat, m_perm_r.indices(), nseg1, dense, panel_lsub, segrep, repfnz, xprune,
                    marker, parent, xplore, m_glu);

    // Numeric sup-panel updates in topological order
    Base::panel_bmod(m, panel_size, jcol, nseg1, dense, tempv, segrep, repfnz, m_glu);

    // Sparse LU within the panel, and below the panel diagonal
    for (jj = jcol; jj < jcol + panel_size; jj++) {
      k = (jj - jcol) * m;  // Column index for w-wide arrays

      nseg = nseg1;  // begin after all the panel segments
      // Depth-first-search for the current column
      VectorBlock<IndexVector> panel_lsubk(panel_lsub, k, m);
      VectorBlock<IndexVector> repfnz_k(repfnz, k, m);
      // Return 0 on success and > 0 number of bytes allocated when run out of space.
      info = Base::column_dfs(m, jj, m_perm_r.indices(), m_perfv.maxsuper, nseg, panel_lsubk, segrep, repfnz_k, xprune,
                              marker, parent, xplore, m_glu);
      if (info) {
        m_lastError = "UNABLE TO EXPAND MEMORY IN COLUMN_DFS() ";
        m_info = NumericalIssue;
        m_factorizationIsOk = false;
        return;
      }
      // Numeric updates to this column
      VectorBlock<ScalarVector> dense_k(dense, k, m);
      VectorBlock<IndexVector> segrep_k(segrep, nseg1, m - nseg1);
      // Return 0 on success and > 0 number of bytes allocated when run out of space.
      info = Base::column_bmod(jj, (nseg - nseg1), dense_k, tempv, segrep_k, repfnz_k, jcol, m_glu);
      if (info) {
        m_lastError = "UNABLE TO EXPAND MEMORY IN COLUMN_BMOD() ";
        m_info = NumericalIssue;
        m_factorizationIsOk = false;
        return;
      }

      // Copy the U-segments to ucol(*)
      // Return 0 on success and > 0 number of bytes allocated when run out of space.
      info = Base::copy_to_ucol(jj, nseg, segrep, repfnz_k, m_perm_r.indices(), dense_k, m_glu);
      if (info) {
        m_lastError = "UNABLE TO EXPAND MEMORY IN COPY_TO_UCOL() ";
        m_info = NumericalIssue;
        m_factorizationIsOk = false;
        return;
      }

      // Form the L-segment
      // Return 0 if success, i > 0 if U(i, i) is exactly zero.
      info = Base::pivotL(jj, m_diagpivotthresh, m_perm_r.indices(), iperm_c.indices(), pivrow, m_glu);
      if (info) {
        m_lastError = "THE MATRIX IS STRUCTURALLY SINGULAR";
#ifndef EIGEN_NO_IO
        std::ostringstream returnInfo;
        returnInfo << " ... ZERO COLUMN AT ";
        returnInfo << info;
        m_lastError += returnInfo.str();
#endif
        m_info = NumericalIssue;
        m_factorizationIsOk = false;
        return;
      }

      // Prune columns (0:jj-1) using column jj
      Base::pruneL(jj, m_perm_r.indices(), pivrow, nseg, segrep, repfnz_k, xprune, m_glu);

      // Reset repfnz for this column
      for (i = 0; i < nseg; i++) {
        irep = segrep(i);
        repfnz_k(irep) = emptyIdxLU;
      }
    }                    // end SparseLU within the panel
    jcol += panel_size;  // Move to the next panel
  }                      // end for -- end elimination

  m_detPermR = m_perm_r.determinant();
  m_detPermC = m_perm_c.determinant();

  // Count the number of nonzeros in factors
  Base::countnz(n, m_nnzL, m_nnzU, m_glu);
  // Apply permutation  to the L subscripts
  Base::fixupL(n, m_perm_r.indices(), m_glu);

  // Create supernode matrix L
  m_Lstore.setInfos(m, n, m_glu.lusup, m_glu.xlusup, m_glu.lsub, m_glu.xlsub, m_glu.supno, m_glu.xsup);
  // Create the column major upper sparse matrix  U;
  new (&m_Ustore) Map<SparseMatrix<Scalar, ColMajor, StorageIndex>>(m, n, m_nnzU, m_glu.xusub.data(), m_glu.usub.data(),
                                                                    m_glu.ucol.data());

  m_info = Success;
  m_factorizationIsOk = true;
}

template <typename MappedSupernodalType>
struct SparseLUMatrixLReturnType : internal::no_assignment_operator {
  using Scalar = typename MappedSupernodalType::Scalar;
  explicit SparseLUMatrixLReturnType(const MappedSupernodalType& mapL) : m_mapL(mapL) {}
  Index rows() const { return m_mapL.rows(); }
  Index cols() const { return m_mapL.cols(); }
  template <typename Dest>
  void solveInPlace(MatrixBase<Dest>& X) const {
    m_mapL.solveInPlace(X);
  }
  template <bool Conjugate, typename Dest>
  void solveTransposedInPlace(MatrixBase<Dest>& X) const {
    m_mapL.template solveTransposedInPlace<Conjugate>(X);
  }

  SparseMatrix<Scalar, ColMajor, Index> toSparse() const {
    ArrayXi colCount = ArrayXi::Ones(cols());
    for (Index i = 0; i < cols(); i++) {
      typename MappedSupernodalType::InnerIterator iter(m_mapL, i);
      for (; iter; ++iter) {
        if (iter.row() > iter.col()) {
          colCount(iter.col())++;
        }
      }
    }
    SparseMatrix<Scalar, ColMajor, Index> sL(rows(), cols());
    sL.reserve(colCount);
    for (Index i = 0; i < cols(); i++) {
      sL.insert(i, i) = 1.0;
      typename MappedSupernodalType::InnerIterator iter(m_mapL, i);
      for (; iter; ++iter) {
        if (iter.row() > iter.col()) {
          sL.insert(iter.row(), iter.col()) = iter.value();
        }
      }
    }
    sL.makeCompressed();
    return sL;
  }

  const MappedSupernodalType& m_mapL;
};

template <typename MatrixLType, typename MatrixUType>
struct SparseLUMatrixUReturnType : internal::no_assignment_operator {
  using Scalar = typename MatrixLType::Scalar;
  SparseLUMatrixUReturnType(const MatrixLType& mapL, const MatrixUType& mapU) : m_mapL(mapL), m_mapU(mapU) {}
  Index rows() const { return m_mapL.rows(); }
  Index cols() const { return m_mapL.cols(); }

  template <typename Dest>
  void solveInPlace(MatrixBase<Dest>& X) const {
    Index nrhs = X.cols();
    // Backward solve with U
    for (Index k = m_mapL.nsuper(); k >= 0; k--) {
      Index fsupc = m_mapL.supToCol()[k];
      Index lda = m_mapL.colIndexPtr()[fsupc + 1] - m_mapL.colIndexPtr()[fsupc];  // leading dimension
      Index nsupc = m_mapL.supToCol()[k + 1] - fsupc;
      Index luptr = m_mapL.colIndexPtr()[fsupc];

      if (nsupc == 1) {
        for (Index j = 0; j < nrhs; j++) {
          X(fsupc, j) /= m_mapL.valuePtr()[luptr];
        }
      } else {
        // FIXME: the following lines should use Block expressions and not Map!
        Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<>> A(&(m_mapL.valuePtr()[luptr]), nsupc,
                                                                                  nsupc, OuterStride<>(lda));
        typename Dest::RowsBlockXpr U = X.derived().middleRows(fsupc, nsupc);
        U = A.template triangularView<Upper>().solve(U);
      }

      for (Index j = 0; j < nrhs; ++j) {
        for (Index jcol = fsupc; jcol < fsupc + nsupc; jcol++) {
          typename MatrixUType::InnerIterator it(m_mapU, jcol);
          for (; it; ++it) {
            Index irow = it.index();
            X(irow, j) -= X(jcol, j) * it.value();
          }
        }
      }
    }  // End For U-solve
  }

  template <bool Conjugate, typename Dest>
  void solveTransposedInPlace(MatrixBase<Dest>& X) const {
    using numext::conj;
    Index nrhs = X.cols();
    // Forward solve with U
    for (Index k = 0; k <= m_mapL.nsuper(); k++) {
      Index fsupc = m_mapL.supToCol()[k];
      Index lda = m_mapL.colIndexPtr()[fsupc + 1] - m_mapL.colIndexPtr()[fsupc];  // leading dimension
      Index nsupc = m_mapL.supToCol()[k + 1] - fsupc;
      Index luptr = m_mapL.colIndexPtr()[fsupc];

      for (Index j = 0; j < nrhs; ++j) {
        for (Index jcol = fsupc; jcol < fsupc + nsupc; jcol++) {
          typename MatrixUType::InnerIterator it(m_mapU, jcol);
          for (; it; ++it) {
            Index irow = it.index();
            X(jcol, j) -= X(irow, j) * (Conjugate ? conj(it.value()) : it.value());
          }
        }
      }
      if (nsupc == 1) {
        for (Index j = 0; j < nrhs; j++) {
          X(fsupc, j) /= (Conjugate ? conj(m_mapL.valuePtr()[luptr]) : m_mapL.valuePtr()[luptr]);
        }
      } else {
        Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<>> A(&(m_mapL.valuePtr()[luptr]), nsupc,
                                                                                  nsupc, OuterStride<>(lda));
        typename Dest::RowsBlockXpr U = X.derived().middleRows(fsupc, nsupc);
        EIGEN_IF_CONSTEXPR (Conjugate)
          U = A.adjoint().template triangularView<Lower>().solve(U);
        else
          U = A.transpose().template triangularView<Lower>().solve(U);
      }
    }  // End For U-solve
  }

  SparseMatrix<Scalar, RowMajor, Index> toSparse() {
    ArrayXi rowCount = ArrayXi::Zero(rows());
    for (Index i = 0; i < cols(); i++) {
      typename MatrixLType::InnerIterator iter(m_mapL, i);
      for (; iter; ++iter) {
        if (iter.row() <= iter.col()) {
          rowCount(iter.row())++;
        }
      }
    }

    SparseMatrix<Scalar, RowMajor, Index> sU(rows(), cols());
    sU.reserve(rowCount);
    for (Index i = 0; i < cols(); i++) {
      typename MatrixLType::InnerIterator iter(m_mapL, i);
      for (; iter; ++iter) {
        if (iter.row() <= iter.col()) {
          sU.insert(iter.row(), iter.col()) = iter.value();
        }
      }
    }
    sU.makeCompressed();
    const SparseMatrix<Scalar, RowMajor, Index> u = m_mapU;  // convert to RowMajor
    sU += u;
    return sU;
  }

  const MatrixLType& m_mapL;
  const MatrixUType& m_mapU;
};

}  // End namespace Eigen

#endif
