// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// 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_TRIDIAGONALIZATION_H
#define EIGEN_TRIDIAGONALIZATION_H

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

namespace Eigen {

namespace internal {

template <typename MatrixType>
struct TridiagonalizationMatrixTReturnType;
template <typename MatrixType>
struct traits<TridiagonalizationMatrixTReturnType<MatrixType>> : public traits<typename MatrixType::PlainObject> {
  // matrixT() returns a dense n x n matrix. A band-stored alternative (e.g. a
  // future matrixTBand() returning BandMatrix<Scalar, Dynamic, Dynamic, 1, 1>)
  // would be ~3n storage instead of n^2, but changing this ReturnType in place
  // would be API-breaking for callers that assume a dense matrix.
  using ReturnType = typename MatrixType::PlainObject;
  enum { Flags = 0 };
};

template <typename MatrixType, typename CoeffVectorType>
EIGEN_DEVICE_FUNC void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs);
}  // namespace internal

/** \eigenvalues_module \ingroup Eigenvalues_Module
 *
 *
 * \class Tridiagonalization
 *
 * \brief Tridiagonal decomposition of a selfadjoint matrix
 *
 * \tparam MatrixType_ the type of the matrix of which we are computing the
 * tridiagonal decomposition; this is expected to be an instantiation of the
 * Matrix class template.
 *
 * This class performs a tridiagonal decomposition of a selfadjoint matrix \f$ A \f$ such that:
 * \f$ A = Q T Q^* \f$ where \f$ Q \f$ is unitary and \f$ T \f$ a real symmetric tridiagonal matrix.
 *
 * A tridiagonal matrix is a matrix which has nonzero elements only on the
 * main diagonal and the first diagonal below and above it. The Hessenberg
 * decomposition of a selfadjoint matrix is in fact a tridiagonal
 * decomposition. This class is used in SelfAdjointEigenSolver to compute the
 * eigenvalues and eigenvectors of a selfadjoint matrix.
 *
 * Call the function compute() to compute the tridiagonal decomposition of a
 * given matrix. Alternatively, you can use the Tridiagonalization(const MatrixType&)
 * constructor which computes the tridiagonal Schur decomposition at
 * construction time. Once the decomposition is computed, you can use the
 * matrixQ() and matrixT() functions to retrieve the matrices Q and T in the
 * decomposition.
 *
 * The documentation of Tridiagonalization(const MatrixType&) contains an
 * example of the typical use of this class.
 *
 * \sa class HessenbergDecomposition, class SelfAdjointEigenSolver
 */
template <typename MatrixType_>
class Tridiagonalization {
 public:
  /** \brief Synonym for the template parameter \p MatrixType_. */
  using MatrixType = MatrixType_;

  using Scalar = typename MatrixType::Scalar;
  using RealScalar = typename NumTraits<Scalar>::Real;
  using Index = Eigen::Index;  ///< \deprecated since Eigen 3.3

  enum {
    Size = MatrixType::RowsAtCompileTime,
    SizeMinusOne = Size == Dynamic ? Dynamic : (Size > 1 ? Size - 1 : 1),
    Options = internal::traits<MatrixType>::Options,
    MaxSize = MatrixType::MaxRowsAtCompileTime,
    MaxSizeMinusOne = MaxSize == Dynamic ? Dynamic : (MaxSize > 1 ? MaxSize - 1 : 1)
  };

  using CoeffVectorType = Matrix<Scalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1>;
  using DiagonalType = typename internal::plain_col_type<MatrixType, RealScalar>::type;
  using SubDiagonalType = Matrix<RealScalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1>;
  using MatrixTypeRealView = internal::remove_all_t<typename MatrixType::RealReturnType>;
  using MatrixTReturnType = internal::TridiagonalizationMatrixTReturnType<MatrixTypeRealView>;

  using DiagonalReturnType =
      std::conditional_t<NumTraits<Scalar>::IsComplex,
                         internal::add_const_on_value_type_t<typename Diagonal<const MatrixType>::RealReturnType>,
                         const Diagonal<const MatrixType>>;

  using SubDiagonalReturnType =
      std::conditional_t<NumTraits<Scalar>::IsComplex,
                         internal::add_const_on_value_type_t<typename Diagonal<const MatrixType, -1>::RealReturnType>,
                         const Diagonal<const MatrixType, -1>>;

  /** \brief Return type of matrixQ() */
  using HouseholderSequenceType =
      HouseholderSequence<MatrixType, internal::remove_all_t<typename CoeffVectorType::ConjugateReturnType>>;

  /** \brief Default constructor.
   *
   * \param [in]  size  Positive integer, size of the matrix whose tridiagonal
   * decomposition will be computed.
   *
   * The default constructor is useful in cases in which the user intends to
   * perform decompositions via compute().  The \p size parameter is only
   * used as a hint. It is not an error to give a wrong \p size, but it may
   * impair performance.
   *
   * \sa compute() for an example.
   */
  explicit Tridiagonalization(Index size = Size == Dynamic ? 2 : Size)
      : m_matrix(size, size), m_hCoeffs(size > 1 ? size - 1 : 1), m_isInitialized(false) {}

  /** \brief Constructor; computes tridiagonal decomposition of given matrix.
   *
   * \param[in]  matrix  Selfadjoint matrix whose tridiagonal decomposition
   * is to be computed.
   *
   * This constructor calls compute() to compute the tridiagonal decomposition.
   *
   * Example: \include Tridiagonalization_Tridiagonalization_MatrixType.cpp
   * Output: \verbinclude Tridiagonalization_Tridiagonalization_MatrixType.out
   */
  template <typename InputType>
  explicit Tridiagonalization(const EigenBase<InputType>& matrix)
      : m_matrix(matrix.derived()), m_hCoeffs(matrix.cols() > 1 ? matrix.cols() - 1 : 1), m_isInitialized(false) {
    internal::tridiagonalization_inplace(m_matrix, m_hCoeffs);
    m_isInitialized = true;
  }

  /** \brief Computes tridiagonal decomposition of given matrix.
   *
   * \param[in]  matrix  Selfadjoint matrix whose tridiagonal decomposition
   * is to be computed.
   * \returns    Reference to \c *this
   *
   * The tridiagonal decomposition is computed by bringing the columns of
   * the matrix successively in the required form using Householder
   * reflections. The cost is \f$ 4n^3/3 \f$ flops, where \f$ n \f$ denotes
   * the size of the given matrix.
   *
   * This method reuses the allocated data in the Tridiagonalization
   * object, if the size of the matrix does not change.
   *
   * Example: \include Tridiagonalization_compute.cpp
   * Output: \verbinclude Tridiagonalization_compute.out
   */
  template <typename InputType>
  Tridiagonalization& compute(const EigenBase<InputType>& matrix) {
    m_matrix = matrix.derived();
    m_hCoeffs.resize(matrix.rows() - 1, 1);
    internal::tridiagonalization_inplace(m_matrix, m_hCoeffs);
    m_isInitialized = true;
    return *this;
  }

  /** \brief Returns the Householder coefficients.
   *
   * \returns a const reference to the vector of Householder coefficients
   *
   * \pre Either the constructor Tridiagonalization(const MatrixType&) or
   * the member function compute(const MatrixType&) has been called before
   * to compute the tridiagonal decomposition of a matrix.
   *
   * The Householder coefficients allow the reconstruction of the matrix
   * \f$ Q \f$ in the tridiagonal decomposition from the packed data.
   *
   * Example: \include Tridiagonalization_householderCoefficients.cpp
   * Output: \verbinclude Tridiagonalization_householderCoefficients.out
   *
   * \sa packedMatrix(), \ref Householder_Module "Householder module"
   */
  inline CoeffVectorType householderCoefficients() const {
    eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
    return m_hCoeffs;
  }

  /** \brief Returns the internal representation of the decomposition
   *
   *	\returns a const reference to a matrix with the internal representation
   *	         of the decomposition.
   *
   * \pre Either the constructor Tridiagonalization(const MatrixType&) or
   * the member function compute(const MatrixType&) has been called before
   * to compute the tridiagonal decomposition of a matrix.
   *
   * The returned matrix contains the following information:
   *  - the strict upper triangular part is equal to the input matrix A.
   *  - the diagonal and lower sub-diagonal represent the real tridiagonal
   *    symmetric matrix T.
   *  - the rest of the lower part contains the Householder vectors that,
   *    combined with Householder coefficients returned by
   *    householderCoefficients(), allows to reconstruct the matrix Q as
   *       \f$ Q = H_{N-1} \ldots H_1 H_0 \f$.
   *    Here, the matrices \f$ H_i \f$ are the Householder transformations
   *       \f$ H_i = (I - h_i v_i v_i^T) \f$
   *    where \f$ h_i \f$ is the \f$ i \f$th Householder coefficient and
   *    \f$ v_i \f$ is the Householder vector defined by
   *       \f$ v_i = [ 0, \ldots, 0, 1, M(i+2,i), \ldots, M(N-1,i) ]^T \f$
   *    with M the matrix returned by this function.
   *
   * See LAPACK for further details on this packed storage.
   *
   * Example: \include Tridiagonalization_packedMatrix.cpp
   * Output: \verbinclude Tridiagonalization_packedMatrix.out
   *
   * \sa householderCoefficients()
   */
  inline const MatrixType& packedMatrix() const {
    eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
    return m_matrix;
  }

  /** \brief Returns the unitary matrix Q in the decomposition
   *
   * \returns object representing the matrix Q
   *
   * \pre Either the constructor Tridiagonalization(const MatrixType&) or
   * the member function compute(const MatrixType&) has been called before
   * to compute the tridiagonal decomposition of a matrix.
   *
   * This function returns a light-weight object of template class
   * HouseholderSequence. You can either apply it directly to a matrix or
   * you can convert it to a matrix of type #MatrixType.
   *
   * \sa Tridiagonalization(const MatrixType&) for an example,
   *     matrixT(), class HouseholderSequence
   */
  HouseholderSequenceType matrixQ() const {
    eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
    return HouseholderSequenceType(m_matrix, m_hCoeffs.conjugate()).setLength(m_matrix.rows() - 1).setShift(1);
  }

  /** \brief Returns an expression of the tridiagonal matrix T in the decomposition
   *
   * \returns expression object representing the matrix T
   *
   * \pre Either the constructor Tridiagonalization(const MatrixType&) or
   * the member function compute(const MatrixType&) has been called before
   * to compute the tridiagonal decomposition of a matrix.
   *
   * Currently, this function can be used to extract the matrix T from internal
   * data and copy it to a dense matrix object. In most cases, it may be
   * sufficient to directly use the packed matrix or the vector expressions
   * returned by diagonal() and subDiagonal() instead of creating a new
   * dense copy matrix with this function.
   *
   * \sa Tridiagonalization(const MatrixType&) for an example,
   * matrixQ(), packedMatrix(), diagonal(), subDiagonal()
   */
  MatrixTReturnType matrixT() const {
    eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
    return MatrixTReturnType(m_matrix.real());
  }

  /** \brief Returns the diagonal of the tridiagonal matrix T in the decomposition.
   *
   * \returns expression representing the diagonal of T
   *
   * \pre Either the constructor Tridiagonalization(const MatrixType&) or
   * the member function compute(const MatrixType&) has been called before
   * to compute the tridiagonal decomposition of a matrix.
   *
   * Example: \include Tridiagonalization_diagonal.cpp
   * Output: \verbinclude Tridiagonalization_diagonal.out
   *
   * \sa matrixT(), subDiagonal()
   */
  DiagonalReturnType diagonal() const;

  /** \brief Returns the subdiagonal of the tridiagonal matrix T in the decomposition.
   *
   * \returns expression representing the subdiagonal of T
   *
   * \pre Either the constructor Tridiagonalization(const MatrixType&) or
   * the member function compute(const MatrixType&) has been called before
   * to compute the tridiagonal decomposition of a matrix.
   *
   * \sa diagonal() for an example, matrixT()
   */
  SubDiagonalReturnType subDiagonal() const;

 protected:
  MatrixType m_matrix;
  CoeffVectorType m_hCoeffs;
  bool m_isInitialized;
};

template <typename MatrixType>
typename Tridiagonalization<MatrixType>::DiagonalReturnType Tridiagonalization<MatrixType>::diagonal() const {
  eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
  return m_matrix.diagonal().real();
}

template <typename MatrixType>
typename Tridiagonalization<MatrixType>::SubDiagonalReturnType Tridiagonalization<MatrixType>::subDiagonal() const {
  eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
  return m_matrix.template diagonal<-1>().real();
}

namespace internal {

/** \internal
 * Unblocked tridiagonal decomposition of the selfadjoint matrix \a matA in-place.
 * Processes one column at a time using Level 2 BLAS operations (SYMV, SYR2).
 *
 * \param[in,out] matA On input the selfadjoint matrix. Only the \b lower triangular part is referenced.
 *                     On output, the strict upper part is left unchanged, and the lower triangular part
 *                     represents the T and Q matrices in packed format as detailed below.
 * \param[out]    hCoeffs returned Householder coefficients (see below)
 *
 * On output, the tridiagonal selfadjoint matrix T is stored in the diagonal
 * and lower sub-diagonal of the matrix \a matA.
 * The unitary matrix Q is represented in a compact way as a product of
 * Householder reflectors \f$ H_i \f$ such that:
 *       \f$ Q = H_{N-1} \ldots H_1 H_0 \f$.
 * The Householder reflectors are defined as
 *       \f$ H_i = (I - h_i v_i v_i^T) \f$
 * where \f$ h_i = hCoeffs[i]\f$ is the \f$ i \f$th Householder coefficient and
 * \f$ v_i \f$ is the Householder vector defined by
 *       \f$ v_i = [ 0, \ldots, 0, 1, matA(i+2,i), \ldots, matA(N-1,i) ]^T \f$.
 *
 * Implemented from Golub's "Matrix Computations", algorithm 8.3.1.
 *
 * \sa Tridiagonalization::packedMatrix()
 */
template <typename MatrixType, typename CoeffVectorType>
EIGEN_DEVICE_FUNC void tridiagonalization_inplace_unblocked(MatrixType& matA, CoeffVectorType& hCoeffs) {
  using numext::conj;
  using Scalar = typename MatrixType::Scalar;
  using RealScalar = typename MatrixType::RealScalar;
  Index n = matA.rows();
  eigen_assert(n == matA.cols());
  eigen_assert(n == hCoeffs.size() + 1 || n == 1);

  for (Index i = 0; i < n - 1; ++i) {
    Index remainingSize = n - i - 1;
    RealScalar beta;
    Scalar h;
    matA.col(i).tail(remainingSize).makeHouseholderInPlace(h, beta);

    // Apply similarity transformation to remaining columns,
    // i.e., A = H A H' where H = I - h v v' and v = matA.col(i).tail(n-i-1)
    matA.col(i).coeffRef(i + 1) = Scalar(1);

    hCoeffs.tail(n - i - 1).noalias() =
        (matA.bottomRightCorner(remainingSize, remainingSize).template selfadjointView<Lower>() *
         (conj(h) * matA.col(i).tail(remainingSize)));

    hCoeffs.tail(n - i - 1) +=
        (conj(h) * RealScalar(-0.5) * (hCoeffs.tail(remainingSize).dot(matA.col(i).tail(remainingSize)))) *
        matA.col(i).tail(n - i - 1);

    matA.bottomRightCorner(remainingSize, remainingSize)
        .template selfadjointView<Lower>()
        .rankUpdate(matA.col(i).tail(remainingSize), hCoeffs.tail(remainingSize), Scalar(-1));

    matA.col(i).coeffRef(i + 1) = beta;
    hCoeffs.coeffRef(i) = h;
  }
}

#if !defined(EIGEN_GPU_COMPILE_PHASE)
/** \internal
 * Blocked tridiagonal decomposition (analogous to LAPACK's dsytrd/dlatrd).
 * Processes columns in panels of BlockSize, accumulating Householder reflectors
 * and deferring the symmetric rank-2k update to use Level 3 BLAS (triangular GEMM).
 * Falls back to the unblocked algorithm for the last (partial) panel.
 */
template <typename MatrixType, typename CoeffVectorType>
void tridiagonalization_inplace_blocked(MatrixType& matA, CoeffVectorType& hCoeffs, Index nb = 16) {
  using numext::conj;
  using Scalar = typename MatrixType::Scalar;
  using RealScalar = typename MatrixType::RealScalar;
  const Index n = matA.rows();
  eigen_assert(n == matA.cols());
  eigen_assert(n == hCoeffs.size() + 1);
  eigen_assert(nb >= 2 && nb < n);

  enum {
    StorageOrder = (traits<MatrixType>::Flags & RowMajorBit) ? RowMajor : ColMajor,
    RhsStorageOrder = (StorageOrder == ColMajor) ? RowMajor : ColMajor
  };

  // Workspace: W matrix (n x nb) for deferred update vectors, temp vector (nb) for GEMV, betas (nb).
  using WorkMatrixType = Matrix<Scalar, Dynamic, Dynamic, StorageOrder>;
  WorkMatrixType W(n, nb);
  Matrix<Scalar, Dynamic, 1> temp(nb);
  Matrix<RealScalar, Dynamic, 1> betas(nb);

  // Pre-allocate GEMM blocking workspace for the largest trailing matrix (first panel).
  // Reused across all panels to avoid repeated heap allocations.
  using BlockingType = gemm_blocking_space<StorageOrder, Scalar, Scalar, Dynamic, Dynamic, Dynamic>;
  const Index maxTrailingSize = n - nb;
  BlockingType blocking(maxTrailingSize, maxTrailingSize, nb, 1, false);

  Index j0 = 0;
  for (; j0 + nb < n - 1; j0 += nb) {
    const Index j_end = j0 + nb;

    // ---- Panel factorization (dlatrd) ----
    // Process columns j0..j_end-1, computing Householder vectors (stored in matA)
    // and update vectors (stored in W). The rank-2k update to the trailing
    // submatrix is deferred until after the panel.
    for (Index j = j0; j < j_end; ++j) {
      const Index local_j = j - j0;
      const Index remainingSize = n - j - 1;

      // Step 1: Update column j for deferred rank-2 updates from columns j0..j-1.
      // A(j:n-1, j) -= V * W(j,:)^H + W * V(j,:)^H
      // where V = matA(j:n-1, j0:j-1) holds Householder vectors,
      // and W(j:n-1, 0:lj-1) holds the corresponding update vectors.
      if (local_j > 0) {
        auto col_j = matA.col(j).segment(j, n - j);
        col_j.noalias() -= matA.block(j, j0, n - j, local_j) * W.row(j).head(local_j).adjoint();
        col_j.noalias() -= W.block(j, 0, n - j, local_j) * matA.row(j).segment(j0, local_j).adjoint();
        // Keep diagonal real (for complex scalars; no-op for real).
        matA.coeffRef(j, j) = numext::real(matA.coeff(j, j));
      }

      // Step 2: Compute Householder reflector for column j.
      RealScalar beta;
      Scalar h;
      matA.col(j).tail(remainingSize).makeHouseholderInPlace(h, beta);
      betas(local_j) = beta;
      matA.col(j).coeffRef(j + 1) = Scalar(1);

      auto v = matA.col(j).tail(remainingSize);
      auto w = W.col(local_j).tail(remainingSize);

      // Step 3: Compute w = conj(h) * A_eff * v where A_eff accounts for deferred updates.
      // Start with SYMV on the stored (not yet updated) trailing submatrix.
      w.noalias() =
          matA.bottomRightCorner(remainingSize, remainingSize).template selfadjointView<Lower>() * (conj(h) * v);

      // GEMV corrections for deferred rank-2 updates within this panel.
      if (local_j > 0) {
        auto V_prev = matA.block(j + 1, j0, remainingSize, local_j);
        auto W_prev = W.block(j + 1, 0, remainingSize, local_j);

        // w -= conj(h) * V_prev * (W_prev^H * v)
        temp.head(local_j).noalias() = W_prev.adjoint() * v;
        w.noalias() -= conj(h) * (V_prev * temp.head(local_j));

        // w -= conj(h) * W_prev * (V_prev^H * v)
        temp.head(local_j).noalias() = V_prev.adjoint() * v;
        w.noalias() -= conj(h) * (W_prev * temp.head(local_j));
      }

      // Step 4: Half-dot correction: w -= 0.5 * conj(h) * (w^H * v) * v
      w += (conj(h) * RealScalar(-0.5) * w.dot(v)) * v;

      hCoeffs.coeffRef(j) = h;
    }

    // ---- Apply rank-2k update to trailing submatrix ----
    // A(j_end:n-1, j_end:n-1) -= V_trail * W_trail^H + W_trail * V_trail^H
    // using Level 3 BLAS (triangular GEMM).
    const Index trailingSize = n - j_end;
    if (trailingSize > 0) {
      const Scalar* V_data = &matA.coeffRef(j_end, j0);
      const Scalar* W_data = &W.coeffRef(j_end, 0);
      Scalar* C_data = &matA.coeffRef(j_end, j_end);
      const Index V_stride = matA.outerStride();
      const Index W_stride = W.outerStride();
      const Index C_stride = matA.outerStride();

      // C -= V * W^H
      general_matrix_matrix_triangular_product<Index, Scalar, StorageOrder, false, Scalar, RhsStorageOrder,
                                               NumTraits<Scalar>::IsComplex, StorageOrder, 1,
                                               Lower>::run(trailingSize, nb, V_data, V_stride, W_data, W_stride, C_data,
                                                           1, C_stride, Scalar(-1), blocking);

      // C -= W * V^H
      general_matrix_matrix_triangular_product<Index, Scalar, StorageOrder, false, Scalar, RhsStorageOrder,
                                               NumTraits<Scalar>::IsComplex, StorageOrder, 1,
                                               Lower>::run(trailingSize, nb, W_data, W_stride, V_data, V_stride, C_data,
                                                           1, C_stride, Scalar(-1), blocking);
    }

    // Restore subdiagonal entries (overwritten with 1 for Householder vectors).
    for (Index j = j0; j < j_end; ++j) {
      matA.coeffRef(j + 1, j) = betas(j - j0);
    }
  }

  // ---- Process remaining columns with unblocked algorithm ----
  if (j0 < n - 1) {
    const Index remaining = n - j0;
    auto trailing = matA.bottomRightCorner(remaining, remaining);
    auto hCoeffs_tail = hCoeffs.segment(j0, remaining - 1);
    tridiagonalization_inplace_unblocked(trailing, hCoeffs_tail);
  }
}
#endif  // !EIGEN_GPU_COMPILE_PHASE

/** \internal
 * Dispatches to blocked or unblocked tridiagonalization based on matrix size.
 * On GPU, always uses the unblocked algorithm.
 */
template <typename MatrixType, typename CoeffVectorType>
EIGEN_DEVICE_FUNC void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs) {
  eigen_assert(matA.rows() == matA.cols());
  eigen_assert(matA.rows() == hCoeffs.size() + 1 || matA.rows() == 1);

#if !defined(EIGEN_GPU_COMPILE_PHASE)
  EIGEN_IF_CONSTEXPR (MatrixType::RowsAtCompileTime == Dynamic || MatrixType::ColsAtCompileTime == Dynamic) {
    if (matA.rows() >= 96) {
      tridiagonalization_inplace_blocked(matA, hCoeffs);
      return;
    }
  }
#endif
  tridiagonalization_inplace_unblocked(matA, hCoeffs);
}

// forward declaration, implementation at the end of this file
template <typename MatrixType, int Size = MatrixType::ColsAtCompileTime,
          bool IsComplex = NumTraits<typename MatrixType::Scalar>::IsComplex>
struct tridiagonalization_inplace_selector;

/** \brief Performs a full tridiagonalization in place
 *
 * \param[in,out]  mat  On input, the selfadjoint matrix whose tridiagonal
 *    decomposition is to be computed. Only the lower triangular part referenced.
 *    The rest is left unchanged. On output, the orthogonal matrix Q
 *    in the decomposition if \p extractQ is true.
 * \param[out]  diag  The diagonal of the tridiagonal matrix T in the
 *    decomposition.
 * \param[out]  subdiag  The subdiagonal of the tridiagonal matrix T in
 *    the decomposition.
 * \param[out]  hcoeffs
 * \param[out]  workspace
 * \param[in]  extractQ  If true, the orthogonal matrix Q in the
 *    decomposition is computed and stored in \p mat.
 *
 * Computes the tridiagonal decomposition of the selfadjoint matrix \p mat in place
 * such that \f$ mat = Q T Q^* \f$ where \f$ Q \f$ is unitary and \f$ T \f$ a real
 * symmetric tridiagonal matrix.
 *
 * The tridiagonal matrix T is passed to the output parameters \p diag and \p subdiag. If
 * \p extractQ is true, then the orthogonal matrix Q is passed to \p mat. Otherwise the lower
 * part of the matrix \p mat is destroyed.
 *
 * The vectors \p diag and \p subdiag are not resized. The function
 * assumes that they are already of the correct size. The length of the
 * vector \p diag should equal the number of rows in \p mat, and the
 * length of the vector \p subdiag should be one less.
 *
 * This implementation contains an optimized path for 3-by-3 matrices
 * which is especially useful for plane fitting.
 *
 * \note Currently, it requires two temporary vectors to hold the intermediate
 * Householder coefficients, and to reconstruct the matrix Q from the Householder
 * reflectors.
 *
 * Example (this uses the same matrix as the example in
 *    Tridiagonalization::Tridiagonalization(const MatrixType&)):
 *    \include Tridiagonalization_decomposeInPlace.cpp
 * Output: \verbinclude Tridiagonalization_decomposeInPlace.out
 *
 * \sa class Tridiagonalization
 */
template <typename MatrixType, typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType,
          typename WorkSpaceType>
EIGEN_DEVICE_FUNC void tridiagonalization_inplace(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag,
                                                  CoeffVectorType& hcoeffs, WorkSpaceType& workspace, bool extractQ) {
  eigen_assert(mat.cols() == mat.rows() && diag.size() == mat.rows() && subdiag.size() == mat.rows() - 1);
  tridiagonalization_inplace_selector<MatrixType>::run(mat, diag, subdiag, hcoeffs, workspace, extractQ);
}

/** \internal
 * General full tridiagonalization
 */
template <typename MatrixType, int Size, bool IsComplex>
struct tridiagonalization_inplace_selector {
  using HouseholderSequenceType = typename Tridiagonalization<MatrixType>::HouseholderSequenceType;
  template <typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType, typename WorkSpaceType>
  static EIGEN_DEVICE_FUNC void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag,
                                    CoeffVectorType& hCoeffs, WorkSpaceType& workspace, bool extractQ) {
    tridiagonalization_inplace(mat, hCoeffs);
    diag = mat.diagonal().real();
    subdiag = mat.template diagonal<-1>().real();
    if (extractQ) {
      HouseholderSequenceType(mat, hCoeffs.conjugate()).setLength(mat.rows() - 1).setShift(1).evalTo(mat, workspace);
    }
  }
};

/** \internal
 * Specialization for 3x3 real matrices.
 * Especially useful for plane fitting.
 */
template <typename MatrixType>
struct tridiagonalization_inplace_selector<MatrixType, 3, false> {
  using Scalar = typename MatrixType::Scalar;
  using RealScalar = typename MatrixType::RealScalar;

  template <typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType, typename WorkSpaceType>
  static EIGEN_DEVICE_FUNC void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, CoeffVectorType&,
                                    WorkSpaceType&, bool extractQ) {
    using std::sqrt;
    const RealScalar tol = (std::numeric_limits<RealScalar>::min)();
    diag[0] = mat(0, 0);
    RealScalar v1norm2 = numext::abs2(mat(2, 0));
    if (v1norm2 <= tol) {
      diag[1] = mat(1, 1);
      diag[2] = mat(2, 2);
      subdiag[0] = mat(1, 0);
      subdiag[1] = mat(2, 1);
      if (extractQ) mat.setIdentity();
    } else {
      RealScalar beta = sqrt(numext::abs2(mat(1, 0)) + v1norm2);
      RealScalar invBeta = RealScalar(1) / beta;
      Scalar m01 = mat(1, 0) * invBeta;
      Scalar m02 = mat(2, 0) * invBeta;
      Scalar q = RealScalar(2) * m01 * mat(2, 1) + m02 * (mat(2, 2) - mat(1, 1));
      diag[1] = mat(1, 1) + m02 * q;
      diag[2] = mat(2, 2) - m02 * q;
      subdiag[0] = beta;
      subdiag[1] = mat(2, 1) - m01 * q;
      if (extractQ) {
        mat << 1, 0, 0, 0, m01, m02, 0, m02, -m01;
      }
    }
  }
};

/** \internal
 * Trivial specialization for 1x1 matrices
 */
template <typename MatrixType, bool IsComplex>
struct tridiagonalization_inplace_selector<MatrixType, 1, IsComplex> {
  using Scalar = typename MatrixType::Scalar;

  template <typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType, typename WorkSpaceType>
  static EIGEN_DEVICE_FUNC void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType&, CoeffVectorType&,
                                    WorkSpaceType&, bool extractQ) {
    diag(0, 0) = numext::real(mat(0, 0));
    if (extractQ) mat(0, 0) = Scalar(1);
  }
};

/** \internal
 * \eigenvalues_module \ingroup Eigenvalues_Module
 *
 * \brief Expression type for return value of Tridiagonalization::matrixT()
 *
 * \tparam MatrixType type of underlying dense matrix
 */
template <typename MatrixType>
struct TridiagonalizationMatrixTReturnType : public ReturnByValue<TridiagonalizationMatrixTReturnType<MatrixType>> {
 public:
  /** \brief Constructor.
   *
   * \param[in] mat The underlying dense matrix
   */
  TridiagonalizationMatrixTReturnType(const MatrixType& mat) : m_matrix(mat) {}

  template <typename ResultType>
  inline void evalTo(ResultType& result) const {
    result.setZero();
    result.template diagonal<1>() = m_matrix.template diagonal<-1>().conjugate();
    result.diagonal() = m_matrix.diagonal();
    result.template diagonal<-1>() = m_matrix.template diagonal<-1>();
  }

  constexpr Index rows() const noexcept { return m_matrix.rows(); }
  constexpr Index cols() const noexcept { return m_matrix.cols(); }

 protected:
  typename MatrixType::Nested m_matrix;
};

}  // end namespace internal

}  // end namespace Eigen

#endif  // EIGEN_TRIDIAGONALIZATION_H
