// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009-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/.

#ifndef EIGEN_SPARSE_SELFADJOINTVIEW_H
#define EIGEN_SPARSE_SELFADJOINTVIEW_H

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

namespace Eigen {

/** \ingroup SparseCore_Module
 * \class SparseSelfAdjointView
 *
 * \brief Pseudo expression to manipulate a triangular sparse matrix as a selfadjoint matrix.
 *
 * \param MatrixType the type of the dense matrix storing the coefficients
 * \param Mode can be either \c #Lower or \c #Upper
 *
 * This class is an expression of a sefladjoint matrix from a triangular part of a matrix
 * with given dense storage of the coefficients. It is the return type of MatrixBase::selfadjointView()
 * and most of the time this is the only way that it is used.
 *
 * \sa SparseMatrixBase::selfadjointView()
 */
namespace internal {

template <typename MatrixType, unsigned int Mode>
struct traits<SparseSelfAdjointView<MatrixType, Mode> > : traits<MatrixType> {};

template <int SrcMode, int DstMode, bool NonHermitian, typename MatrixType, int DestOrder>
void permute_symm_to_symm(
    const MatrixType& mat,
    SparseMatrix<typename MatrixType::Scalar, DestOrder, typename MatrixType::StorageIndex>& _dest,
    const typename MatrixType::StorageIndex* perm = 0);

template <int Mode, bool NonHermitian, typename MatrixType, int DestOrder>
void permute_symm_to_fullsymm(
    const MatrixType& mat,
    SparseMatrix<typename MatrixType::Scalar, DestOrder, typename MatrixType::StorageIndex>& _dest,
    const typename MatrixType::StorageIndex* perm = 0);

}  // namespace internal

template <typename MatrixType, unsigned int Mode_>
class SparseSelfAdjointView : public EigenBase<SparseSelfAdjointView<MatrixType, Mode_> > {
 public:
  enum {
    Mode = Mode_,
    TransposeMode = ((int(Mode) & int(Upper)) ? Lower : 0) | ((int(Mode) & int(Lower)) ? Upper : 0),
    RowsAtCompileTime = internal::traits<SparseSelfAdjointView>::RowsAtCompileTime,
    ColsAtCompileTime = internal::traits<SparseSelfAdjointView>::ColsAtCompileTime
  };

  typedef EigenBase<SparseSelfAdjointView> Base;
  typedef typename MatrixType::Scalar Scalar;
  typedef typename MatrixType::StorageIndex StorageIndex;
  typedef Matrix<StorageIndex, Dynamic, 1> VectorI;
  typedef typename internal::ref_selector<MatrixType>::non_const_type MatrixTypeNested;
  typedef internal::remove_all_t<MatrixTypeNested> MatrixTypeNested_;

  explicit inline SparseSelfAdjointView(MatrixType& matrix) : m_matrix(matrix) {
    eigen_assert(rows() == cols() && "SelfAdjointView is only for squared matrices");
  }

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

  /** \internal \returns a reference to the nested matrix */
  const MatrixTypeNested_& matrix() const { return m_matrix; }
  std::remove_reference_t<MatrixTypeNested>& matrix() { return m_matrix; }

  /** \returns an expression of the matrix product between a sparse self-adjoint matrix \c *this and a sparse matrix \a
   * rhs.
   *
   * Note that there is no algorithmic advantage of performing such a product compared to a general sparse-sparse matrix
   * product. Indeed, the SparseSelfadjointView operand is first copied into a temporary SparseMatrix before computing
   * the product.
   */
  template <typename OtherDerived>
  Product<SparseSelfAdjointView, OtherDerived> operator*(const SparseMatrixBase<OtherDerived>& rhs) const {
    return Product<SparseSelfAdjointView, OtherDerived>(*this, rhs.derived());
  }

  /** \returns an expression of the matrix product between a sparse matrix \a lhs and a sparse self-adjoint matrix \a
   * rhs.
   *
   * Note that there is no algorithmic advantage of performing such a product compared to a general sparse-sparse matrix
   * product. Indeed, the SparseSelfadjointView operand is first copied into a temporary SparseMatrix before computing
   * the product.
   */
  template <typename OtherDerived>
  friend Product<OtherDerived, SparseSelfAdjointView> operator*(const SparseMatrixBase<OtherDerived>& lhs,
                                                                const SparseSelfAdjointView& rhs) {
    return Product<OtherDerived, SparseSelfAdjointView>(lhs.derived(), rhs);
  }

  /** Efficient sparse self-adjoint matrix times dense vector/matrix product */
  template <typename OtherDerived>
  Product<SparseSelfAdjointView, OtherDerived> operator*(const MatrixBase<OtherDerived>& rhs) const {
    return Product<SparseSelfAdjointView, OtherDerived>(*this, rhs.derived());
  }

  /** Efficient dense vector/matrix times sparse self-adjoint matrix product */
  template <typename OtherDerived>
  friend Product<OtherDerived, SparseSelfAdjointView> operator*(const MatrixBase<OtherDerived>& lhs,
                                                                const SparseSelfAdjointView& rhs) {
    return Product<OtherDerived, SparseSelfAdjointView>(lhs.derived(), rhs);
  }

  /** Perform a symmetric rank K update of the selfadjoint matrix \c *this:
   * \f$ this = this + \alpha ( u u^* ) \f$ where \a u is a vector or matrix.
   *
   * \returns a reference to \c *this
   *
   * To perform \f$ this = this + \alpha ( u^* u ) \f$ you can simply
   * call this function with u.adjoint().
   */
  template <typename DerivedU>
  SparseSelfAdjointView& rankUpdate(const SparseMatrixBase<DerivedU>& u, const Scalar& alpha = Scalar(1));

  /** \returns an expression of P H P^-1 */
  // TODO implement twists in a more evaluator friendly fashion
  SparseSymmetricPermutationProduct<MatrixTypeNested_, Mode> twistedBy(
      const PermutationMatrix<Dynamic, Dynamic, StorageIndex>& perm) const {
    return SparseSymmetricPermutationProduct<MatrixTypeNested_, Mode>(m_matrix, perm);
  }

  template <typename SrcMatrixType, int SrcMode>
  SparseSelfAdjointView& operator=(const SparseSymmetricPermutationProduct<SrcMatrixType, SrcMode>& permutedMatrix) {
    internal::call_assignment_no_alias_no_transpose(*this, permutedMatrix);
    return *this;
  }

  SparseSelfAdjointView& operator=(const SparseSelfAdjointView& src) {
    PermutationMatrix<Dynamic, Dynamic, StorageIndex> pnull;
    return *this = src.twistedBy(pnull);
  }

  // Since we override the copy-assignment operator, we need to explicitly redeclare the copy-constructor
  EIGEN_DEFAULT_COPY_CONSTRUCTOR(SparseSelfAdjointView)

  template <typename SrcMatrixType, unsigned int SrcMode>
  SparseSelfAdjointView& operator=(const SparseSelfAdjointView<SrcMatrixType, SrcMode>& src) {
    PermutationMatrix<Dynamic, Dynamic, StorageIndex> pnull;
    return *this = src.twistedBy(pnull);
  }

  void resize(Index rows, Index cols) {
    EIGEN_ONLY_USED_FOR_DEBUG(rows);
    EIGEN_ONLY_USED_FOR_DEBUG(cols);
    eigen_assert(rows == this->rows() && cols == this->cols() &&
                 "SparseSelfadjointView::resize() does not actually allow to resize.");
  }

 protected:
  MatrixTypeNested m_matrix;
  // mutable VectorI m_countPerRow;
  // mutable VectorI m_countPerCol;
 private:
  template <typename Dest>
  void evalTo(Dest&) const;
};

/***************************************************************************
 * Implementation of SparseMatrixBase methods
 ***************************************************************************/

template <typename Derived>
template <unsigned int UpLo>
typename SparseMatrixBase<Derived>::template ConstSelfAdjointViewReturnType<UpLo>::Type
SparseMatrixBase<Derived>::selfadjointView() const {
  return SparseSelfAdjointView<const Derived, UpLo>(derived());
}

template <typename Derived>
template <unsigned int UpLo>
typename SparseMatrixBase<Derived>::template SelfAdjointViewReturnType<UpLo>::Type
SparseMatrixBase<Derived>::selfadjointView() {
  return SparseSelfAdjointView<Derived, UpLo>(derived());
}

/***************************************************************************
 * Implementation of SparseSelfAdjointView methods
 ***************************************************************************/

template <typename MatrixType, unsigned int Mode>
template <typename DerivedU>
SparseSelfAdjointView<MatrixType, Mode>& SparseSelfAdjointView<MatrixType, Mode>::rankUpdate(
    const SparseMatrixBase<DerivedU>& u, const Scalar& alpha) {
  SparseMatrix<Scalar, (MatrixType::Flags & RowMajorBit) ? RowMajor : ColMajor> tmp = u * u.adjoint();
  if (alpha == Scalar(0))
    m_matrix = tmp.template triangularView<Mode>();
  else
    m_matrix += alpha * tmp.template triangularView<Mode>();

  return *this;
}

namespace internal {

// TODO currently a selfadjoint expression has the form SelfAdjointView<.,.>
//      in the future selfadjoint-ness should be defined by the expression traits
//      such that Transpose<SelfAdjointView<.,.> > is valid. (currently TriangularBase::transpose() is overloaded to
//      make it work)
template <typename MatrixType, unsigned int Mode>
struct evaluator_traits<SparseSelfAdjointView<MatrixType, Mode> > {
  typedef typename storage_kind_to_evaluator_kind<typename MatrixType::StorageKind>::Kind Kind;
  typedef SparseSelfAdjointShape Shape;
};

struct SparseSelfAdjoint2Sparse {};

template <>
struct AssignmentKind<SparseShape, SparseSelfAdjointShape> {
  typedef SparseSelfAdjoint2Sparse Kind;
};
template <>
struct AssignmentKind<SparseSelfAdjointShape, SparseShape> {
  typedef Sparse2Sparse Kind;
};

template <typename DstXprType, typename SrcXprType, typename Functor>
struct Assignment<DstXprType, SrcXprType, Functor, SparseSelfAdjoint2Sparse> {
  typedef typename DstXprType::StorageIndex StorageIndex;
  typedef internal::assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar> AssignOpType;

  template <typename DestScalar, int StorageOrder>
  static void run(SparseMatrix<DestScalar, StorageOrder, StorageIndex>& dst, const SrcXprType& src,
                  const AssignOpType& /*func*/) {
    internal::permute_symm_to_fullsymm<SrcXprType::Mode, false>(src.matrix(), dst);
  }

  // FIXME: the handling of += and -= in sparse matrices should be cleanup so that next two overloads could be reduced
  // to:
  template <typename DestScalar, int StorageOrder, typename AssignFunc>
  static void run(SparseMatrix<DestScalar, StorageOrder, StorageIndex>& dst, const SrcXprType& src,
                  const AssignFunc& func) {
    SparseMatrix<DestScalar, StorageOrder, StorageIndex> tmp(src.rows(), src.cols());
    run(tmp, src, AssignOpType());
    call_assignment_no_alias_no_transpose(dst, tmp, func);
  }

  template <typename DestScalar, int StorageOrder>
  static void run(SparseMatrix<DestScalar, StorageOrder, StorageIndex>& dst, const SrcXprType& src,
                  const internal::add_assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>& /* func */) {
    SparseMatrix<DestScalar, StorageOrder, StorageIndex> tmp(src.rows(), src.cols());
    run(tmp, src, AssignOpType());
    dst += tmp;
  }

  template <typename DestScalar, int StorageOrder>
  static void run(SparseMatrix<DestScalar, StorageOrder, StorageIndex>& dst, const SrcXprType& src,
                  const internal::sub_assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>& /* func */) {
    SparseMatrix<DestScalar, StorageOrder, StorageIndex> tmp(src.rows(), src.cols());
    run(tmp, src, AssignOpType());
    dst -= tmp;
  }
};

}  // end namespace internal

/***************************************************************************
 * Implementation of sparse self-adjoint time dense matrix
 ***************************************************************************/

namespace internal {

template <int Mode, typename SparseLhsType, typename DenseRhsType, typename DenseResType, typename AlphaType>
inline void sparse_selfadjoint_time_dense_product(const SparseLhsType& lhs, const DenseRhsType& rhs, DenseResType& res,
                                                  const AlphaType& alpha) {
  EIGEN_ONLY_USED_FOR_DEBUG(alpha);

  typedef typename internal::nested_eval<SparseLhsType, DenseRhsType::MaxColsAtCompileTime>::type SparseLhsTypeNested;
  typedef internal::remove_all_t<SparseLhsTypeNested> SparseLhsTypeNestedCleaned;
  typedef evaluator<SparseLhsTypeNestedCleaned> LhsEval;
  typedef typename LhsEval::InnerIterator LhsIterator;
  typedef typename SparseLhsType::Scalar LhsScalar;

  enum {
    LhsIsRowMajor = (LhsEval::Flags & RowMajorBit) == RowMajorBit,
    ProcessFirstHalf = ((Mode & (Upper | Lower)) == (Upper | Lower)) || ((Mode & Upper) && !LhsIsRowMajor) ||
                       ((Mode & Lower) && LhsIsRowMajor),
    ProcessSecondHalf = !ProcessFirstHalf
  };

  SparseLhsTypeNested lhs_nested(lhs);
  LhsEval lhsEval(lhs_nested);

  // work on one column at once
  for (Index k = 0; k < rhs.cols(); ++k) {
    for (Index j = 0; j < lhs.outerSize(); ++j) {
      LhsIterator i(lhsEval, j);
      // handle diagonal coeff
      if (ProcessSecondHalf) {
        while (i && i.index() < j) ++i;
        if (i && i.index() == j) {
          res.coeffRef(j, k) += alpha * i.value() * rhs.coeff(j, k);
          ++i;
        }
      }

      // premultiplied rhs for scatters
      typename ScalarBinaryOpTraits<AlphaType, typename DenseRhsType::Scalar>::ReturnType rhs_j(alpha * rhs(j, k));
      // accumulator for partial scalar product
      typename DenseResType::Scalar res_j(0);
      for (; (ProcessFirstHalf ? i && i.index() < j : i); ++i) {
        LhsScalar lhs_ij = i.value();
        if (!LhsIsRowMajor) lhs_ij = numext::conj(lhs_ij);
        res_j += lhs_ij * rhs.coeff(i.index(), k);
        res(i.index(), k) += numext::conj(lhs_ij) * rhs_j;
      }
      res.coeffRef(j, k) += alpha * res_j;

      // handle diagonal coeff
      if (ProcessFirstHalf && i && (i.index() == j)) res.coeffRef(j, k) += alpha * i.value() * rhs.coeff(j, k);
    }
  }
}

template <typename LhsView, typename Rhs, int ProductType>
struct generic_product_impl<LhsView, Rhs, SparseSelfAdjointShape, DenseShape, ProductType>
    : generic_product_impl_base<LhsView, Rhs,
                                generic_product_impl<LhsView, Rhs, SparseSelfAdjointShape, DenseShape, ProductType> > {
  template <typename Dest>
  static void scaleAndAddTo(Dest& dst, const LhsView& lhsView, const Rhs& rhs, const typename Dest::Scalar& alpha) {
    typedef typename LhsView::MatrixTypeNested_ Lhs;
    typedef typename nested_eval<Lhs, Dynamic>::type LhsNested;
    typedef typename nested_eval<Rhs, Dynamic>::type RhsNested;
    LhsNested lhsNested(lhsView.matrix());
    RhsNested rhsNested(rhs);

    internal::sparse_selfadjoint_time_dense_product<LhsView::Mode>(lhsNested, rhsNested, dst, alpha);
  }
};

template <typename Lhs, typename RhsView, int ProductType>
struct generic_product_impl<Lhs, RhsView, DenseShape, SparseSelfAdjointShape, ProductType>
    : generic_product_impl_base<Lhs, RhsView,
                                generic_product_impl<Lhs, RhsView, DenseShape, SparseSelfAdjointShape, ProductType> > {
  template <typename Dest>
  static void scaleAndAddTo(Dest& dst, const Lhs& lhs, const RhsView& rhsView, const typename Dest::Scalar& alpha) {
    typedef typename RhsView::MatrixTypeNested_ Rhs;
    typedef typename nested_eval<Lhs, Dynamic>::type LhsNested;
    typedef typename nested_eval<Rhs, Dynamic>::type RhsNested;
    LhsNested lhsNested(lhs);
    RhsNested rhsNested(rhsView.matrix());

    // transpose everything
    Transpose<Dest> dstT(dst);
    internal::sparse_selfadjoint_time_dense_product<RhsView::TransposeMode>(rhsNested.transpose(),
                                                                            lhsNested.transpose(), dstT, alpha);
  }
};

// NOTE: these two overloads are needed to evaluate the sparse selfadjoint view into a full sparse matrix
// TODO: maybe the copy could be handled by generic_product_impl so that these overloads would not be needed anymore

template <typename LhsView, typename Rhs, int ProductTag>
struct product_evaluator<Product<LhsView, Rhs, DefaultProduct>, ProductTag, SparseSelfAdjointShape, SparseShape>
    : public evaluator<typename Product<typename Rhs::PlainObject, Rhs, DefaultProduct>::PlainObject> {
  typedef Product<LhsView, Rhs, DefaultProduct> XprType;
  typedef typename XprType::PlainObject PlainObject;
  typedef evaluator<PlainObject> Base;

  product_evaluator(const XprType& xpr) : m_lhs(xpr.lhs()), m_result(xpr.rows(), xpr.cols()) {
    internal::construct_at<Base>(this, m_result);
    generic_product_impl<typename Rhs::PlainObject, Rhs, SparseShape, SparseShape, ProductTag>::evalTo(m_result, m_lhs,
                                                                                                       xpr.rhs());
  }

 protected:
  typename Rhs::PlainObject m_lhs;
  PlainObject m_result;
};

template <typename Lhs, typename RhsView, int ProductTag>
struct product_evaluator<Product<Lhs, RhsView, DefaultProduct>, ProductTag, SparseShape, SparseSelfAdjointShape>
    : public evaluator<typename Product<Lhs, typename Lhs::PlainObject, DefaultProduct>::PlainObject> {
  typedef Product<Lhs, RhsView, DefaultProduct> XprType;
  typedef typename XprType::PlainObject PlainObject;
  typedef evaluator<PlainObject> Base;

  product_evaluator(const XprType& xpr) : m_rhs(xpr.rhs()), m_result(xpr.rows(), xpr.cols()) {
    ::new (static_cast<Base*>(this)) Base(m_result);
    generic_product_impl<Lhs, typename Lhs::PlainObject, SparseShape, SparseShape, ProductTag>::evalTo(
        m_result, xpr.lhs(), m_rhs);
  }

 protected:
  typename Lhs::PlainObject m_rhs;
  PlainObject m_result;
};

}  // namespace internal

/***************************************************************************
 * Implementation of symmetric copies and permutations
 ***************************************************************************/
namespace internal {

template <int Mode, bool NonHermitian, typename MatrixType, int DestOrder>
void permute_symm_to_fullsymm(
    const MatrixType& mat,
    SparseMatrix<typename MatrixType::Scalar, DestOrder, typename MatrixType::StorageIndex>& _dest,
    const typename MatrixType::StorageIndex* perm) {
  typedef typename MatrixType::StorageIndex StorageIndex;
  typedef typename MatrixType::Scalar Scalar;
  typedef SparseMatrix<Scalar, DestOrder, StorageIndex> Dest;
  typedef Matrix<StorageIndex, Dynamic, 1> VectorI;
  typedef evaluator<MatrixType> MatEval;
  typedef typename evaluator<MatrixType>::InnerIterator MatIterator;

  MatEval matEval(mat);
  Dest& dest(_dest.derived());
  enum { StorageOrderMatch = int(Dest::IsRowMajor) == int(MatrixType::IsRowMajor) };

  Index size = mat.rows();
  VectorI count;
  count.resize(size);
  count.setZero();
  dest.resize(size, size);
  for (Index j = 0; j < size; ++j) {
    Index jp = perm ? perm[j] : j;
    for (MatIterator it(matEval, j); it; ++it) {
      Index i = it.index();
      Index r = it.row();
      Index c = it.col();
      Index ip = perm ? perm[i] : i;
      if (Mode == int(Upper | Lower))
        count[StorageOrderMatch ? jp : ip]++;
      else if (r == c)
        count[ip]++;
      else if ((Mode == Lower && r > c) || (Mode == Upper && r < c)) {
        count[ip]++;
        count[jp]++;
      }
    }
  }
  Index nnz = count.sum();

  // reserve space
  dest.resizeNonZeros(nnz);
  dest.outerIndexPtr()[0] = 0;
  for (Index j = 0; j < size; ++j) dest.outerIndexPtr()[j + 1] = dest.outerIndexPtr()[j] + count[j];
  for (Index j = 0; j < size; ++j) count[j] = dest.outerIndexPtr()[j];

  // copy data
  for (StorageIndex j = 0; j < size; ++j) {
    for (MatIterator it(matEval, j); it; ++it) {
      StorageIndex i = internal::convert_index<StorageIndex>(it.index());
      Index r = it.row();
      Index c = it.col();

      StorageIndex jp = perm ? perm[j] : j;
      StorageIndex ip = perm ? perm[i] : i;

      if (Mode == int(Upper | Lower)) {
        Index k = count[StorageOrderMatch ? jp : ip]++;
        dest.innerIndexPtr()[k] = StorageOrderMatch ? ip : jp;
        dest.valuePtr()[k] = it.value();
      } else if (r == c) {
        Index k = count[ip]++;
        dest.innerIndexPtr()[k] = ip;
        dest.valuePtr()[k] = it.value();
      } else if (((Mode & Lower) == Lower && r > c) || ((Mode & Upper) == Upper && r < c)) {
        if (!StorageOrderMatch) std::swap(ip, jp);
        Index k = count[jp]++;
        dest.innerIndexPtr()[k] = ip;
        dest.valuePtr()[k] = it.value();
        k = count[ip]++;
        dest.innerIndexPtr()[k] = jp;
        dest.valuePtr()[k] = (NonHermitian ? it.value() : numext::conj(it.value()));
      }
    }
  }
}

template <int SrcMode_, int DstMode_, bool NonHermitian, typename MatrixType, int DstOrder>
void permute_symm_to_symm(const MatrixType& mat,
                          SparseMatrix<typename MatrixType::Scalar, DstOrder, typename MatrixType::StorageIndex>& _dest,
                          const typename MatrixType::StorageIndex* perm) {
  typedef typename MatrixType::StorageIndex StorageIndex;
  typedef typename MatrixType::Scalar Scalar;
  SparseMatrix<Scalar, DstOrder, StorageIndex>& dest(_dest.derived());
  typedef Matrix<StorageIndex, Dynamic, 1> VectorI;
  typedef evaluator<MatrixType> MatEval;
  typedef typename evaluator<MatrixType>::InnerIterator MatIterator;

  enum {
    SrcOrder = MatrixType::IsRowMajor ? RowMajor : ColMajor,
    StorageOrderMatch = int(SrcOrder) == int(DstOrder),
    DstMode = DstOrder == RowMajor ? (DstMode_ == Upper ? Lower : Upper) : DstMode_,
    SrcMode = SrcOrder == RowMajor ? (SrcMode_ == Upper ? Lower : Upper) : SrcMode_
  };

  MatEval matEval(mat);

  Index size = mat.rows();
  VectorI count(size);
  count.setZero();
  dest.resize(size, size);
  for (StorageIndex j = 0; j < size; ++j) {
    StorageIndex jp = perm ? perm[j] : j;
    for (MatIterator it(matEval, j); it; ++it) {
      StorageIndex i = it.index();
      if ((int(SrcMode) == int(Lower) && i < j) || (int(SrcMode) == int(Upper) && i > j)) continue;

      StorageIndex ip = perm ? perm[i] : i;
      count[int(DstMode) == int(Lower) ? (std::min)(ip, jp) : (std::max)(ip, jp)]++;
    }
  }
  dest.outerIndexPtr()[0] = 0;
  for (Index j = 0; j < size; ++j) dest.outerIndexPtr()[j + 1] = dest.outerIndexPtr()[j] + count[j];
  dest.resizeNonZeros(dest.outerIndexPtr()[size]);
  for (Index j = 0; j < size; ++j) count[j] = dest.outerIndexPtr()[j];

  for (StorageIndex j = 0; j < size; ++j) {
    for (MatIterator it(matEval, j); it; ++it) {
      StorageIndex i = it.index();
      if ((int(SrcMode) == int(Lower) && i < j) || (int(SrcMode) == int(Upper) && i > j)) continue;

      StorageIndex jp = perm ? perm[j] : j;
      StorageIndex ip = perm ? perm[i] : i;

      Index k = count[int(DstMode) == int(Lower) ? (std::min)(ip, jp) : (std::max)(ip, jp)]++;
      dest.innerIndexPtr()[k] = int(DstMode) == int(Lower) ? (std::max)(ip, jp) : (std::min)(ip, jp);

      if (!StorageOrderMatch) std::swap(ip, jp);
      if (((int(DstMode) == int(Lower) && ip < jp) || (int(DstMode) == int(Upper) && ip > jp)))
        dest.valuePtr()[k] = (NonHermitian ? it.value() : numext::conj(it.value()));
      else
        dest.valuePtr()[k] = it.value();
    }
  }
}

}  // namespace internal

// TODO implement twists in a more evaluator friendly fashion

namespace internal {

template <typename MatrixType, int Mode>
struct traits<SparseSymmetricPermutationProduct<MatrixType, Mode> > : traits<MatrixType> {};

}  // namespace internal

template <typename MatrixType, int Mode>
class SparseSymmetricPermutationProduct : public EigenBase<SparseSymmetricPermutationProduct<MatrixType, Mode> > {
 public:
  typedef typename MatrixType::Scalar Scalar;
  typedef typename MatrixType::StorageIndex StorageIndex;
  enum {
    RowsAtCompileTime = internal::traits<SparseSymmetricPermutationProduct>::RowsAtCompileTime,
    ColsAtCompileTime = internal::traits<SparseSymmetricPermutationProduct>::ColsAtCompileTime
  };

 protected:
  typedef PermutationMatrix<Dynamic, Dynamic, StorageIndex> Perm;

 public:
  typedef Matrix<StorageIndex, Dynamic, 1> VectorI;
  typedef typename MatrixType::Nested MatrixTypeNested;
  typedef internal::remove_all_t<MatrixTypeNested> NestedExpression;

  SparseSymmetricPermutationProduct(const MatrixType& mat, const Perm& perm) : m_matrix(mat), m_perm(perm) {}

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

  const NestedExpression& matrix() const { return m_matrix; }
  const Perm& perm() const { return m_perm; }

 protected:
  MatrixTypeNested m_matrix;
  const Perm& m_perm;
};

namespace internal {

template <typename DstXprType, typename MatrixType, int Mode, typename Scalar>
struct Assignment<DstXprType, SparseSymmetricPermutationProduct<MatrixType, Mode>,
                  internal::assign_op<Scalar, typename MatrixType::Scalar>, Sparse2Sparse> {
  typedef SparseSymmetricPermutationProduct<MatrixType, Mode> SrcXprType;
  typedef typename DstXprType::StorageIndex DstIndex;
  template <int Options>
  static void run(SparseMatrix<Scalar, Options, DstIndex>& dst, const SrcXprType& src,
                  const internal::assign_op<Scalar, typename MatrixType::Scalar>&) {
    // internal::permute_symm_to_fullsymm<Mode>(m_matrix,_dest,m_perm.indices().data());
    SparseMatrix<Scalar, (Options & RowMajor) == RowMajor ? ColMajor : RowMajor, DstIndex> tmp;
    internal::permute_symm_to_fullsymm<Mode, false>(src.matrix(), tmp, src.perm().indices().data());
    dst = tmp;
  }

  template <typename DestType, unsigned int DestMode>
  static void run(SparseSelfAdjointView<DestType, DestMode>& dst, const SrcXprType& src,
                  const internal::assign_op<Scalar, typename MatrixType::Scalar>&) {
    internal::permute_symm_to_symm<Mode, DestMode, false>(src.matrix(), dst.matrix(), src.perm().indices().data());
  }
};

}  // end namespace internal

}  // end namespace Eigen

#endif  // EIGEN_SPARSE_SELFADJOINTVIEW_H
