17faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// This file is part of Eigen, a lightweight C++ template library
27faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// for linear algebra.
37faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez//
47faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
57faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez//
67faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// This Source Code Form is subject to the terms of the Mozilla
77faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// Public License v. 2.0. If a copy of the MPL was not distributed
87faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
97faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#ifndef EIGEN_INCOMPLETE_CHOlESKY_H
117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#define EIGEN_INCOMPLETE_CHOlESKY_H
127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include "Eigen/src/IterativeLinearSolvers/IncompleteLUT.h"
137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include <Eigen/OrderingMethods>
147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include <list>
157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeznamespace Eigen {
177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez/**
187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \brief Modified Incomplete Cholesky with dual threshold
197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez *
207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * References : C-J. Lin and J. J. Moré, Incomplete Cholesky Factorizations with
217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez *              Limited memory, SIAM J. Sci. Comput.  21(1), pp. 24-45, 1999
227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez *
237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \tparam _MatrixType The type of the sparse matrix. It should be a symmetric
247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez *                     matrix. It is advised to give  a row-oriented sparse matrix
257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \tparam _UpLo The triangular part of the matrix to reference.
267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \tparam _OrderingType
277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */
287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate <typename Scalar, int _UpLo = Lower, typename _OrderingType = NaturalOrdering<int> >
307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezclass IncompleteCholesky : internal::noncopyable
317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{
327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  public:
337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef SparseMatrix<Scalar,ColMajor> MatrixType;
347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef _OrderingType OrderingType;
357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef typename MatrixType::RealScalar RealScalar;
367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef typename MatrixType::Index Index;
377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef PermutationMatrix<Dynamic, Dynamic, Index> PermutationType;
387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef Matrix<Scalar,Dynamic,1> ScalarType;
397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef Matrix<Index,Dynamic, 1> IndexType;
407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef std::vector<std::list<Index> > VectorList;
417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    enum { UpLo = _UpLo };
427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  public:
437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    IncompleteCholesky() : m_shift(1),m_factorizationIsOk(false) {}
447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    IncompleteCholesky(const MatrixType& matrix) : m_shift(1),m_factorizationIsOk(false)
457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      compute(matrix);
477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Index rows() const { return m_L.rows(); }
507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Index cols() const { return m_L.cols(); }
527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /** \brief Reports whether previous computation was successful.
557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      *
567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      * \returns \c Success if computation was succesful,
577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      *          \c NumericalIssue if the matrix appears to be negative.
587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      */
597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    ComputationInfo info() const
607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      eigen_assert(m_isInitialized && "IncompleteLLT is not initialized.");
627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      return m_info;
637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /**
667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez     * \brief Set the initial shift parameter
677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez     */
687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    void setShift( Scalar shift) { m_shift = shift; }
697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /**
717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    * \brief Computes the fill reducing permutation vector.
727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    */
737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    template<typename MatrixType>
747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    void analyzePattern(const MatrixType& mat)
757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      OrderingType ord;
777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      ord(mat.template selfadjointView<UpLo>(), m_perm);
787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      m_analysisIsOk = true;
797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    template<typename MatrixType>
827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    void factorize(const MatrixType& amat);
837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    template<typename MatrixType>
857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    void compute (const MatrixType& matrix)
867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      analyzePattern(matrix);
887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      factorize(matrix);
897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    template<typename Rhs, typename Dest>
927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    void _solve(const Rhs& b, Dest& x) const
937faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      eigen_assert(m_factorizationIsOk && "factorize() should be called first");
957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      if (m_perm.rows() == b.rows())
967faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        x = m_perm.inverse() * b;
977faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      else
987faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        x = b;
997faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      x = m_scal.asDiagonal() * x;
1007faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      x = m_L.template triangularView<UnitLower>().solve(x);
1017faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      x = m_L.adjoint().template triangularView<Upper>().solve(x);
1027faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      if (m_perm.rows() == b.rows())
1037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        x = m_perm * x;
1047faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      x = m_scal.asDiagonal() * x;
1057faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
1067faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    template<typename Rhs> inline const internal::solve_retval<IncompleteCholesky, Rhs>
1077faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    solve(const MatrixBase<Rhs>& b) const
1087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
1097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      eigen_assert(m_factorizationIsOk && "IncompleteLLT did not succeed");
1107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      eigen_assert(m_isInitialized && "IncompleteLLT is not initialized.");
1117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      eigen_assert(cols()==b.rows()
1127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez                && "IncompleteLLT::solve(): invalid number of rows of the right hand side matrix b");
1137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      return internal::solve_retval<IncompleteCholesky, Rhs>(*this, b.derived());
1147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
1157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  protected:
1167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    SparseMatrix<Scalar,ColMajor> m_L;  // The lower part stored in CSC
1177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    ScalarType m_scal; // The vector for scaling the matrix
1187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Scalar m_shift; //The initial shift parameter
1197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    bool m_analysisIsOk;
1207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    bool m_factorizationIsOk;
1217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    bool m_isInitialized;
1227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    ComputationInfo m_info;
1237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    PermutationType m_perm;
1247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  private:
1267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    template <typename IdxType, typename SclType>
1277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    inline void updateList(const IdxType& colPtr, IdxType& rowIdx, SclType& vals, const Index& col, const Index& jk, IndexType& firstElt, VectorList& listCol);
1287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez};
1297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename Scalar, int _UpLo, typename OrderingType>
1317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename _MatrixType>
1327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezvoid IncompleteCholesky<Scalar,_UpLo, OrderingType>::factorize(const _MatrixType& mat)
1337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{
1347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  using std::sqrt;
1357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  using std::min;
1367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  eigen_assert(m_analysisIsOk && "analyzePattern() should be called first");
1377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  // Dropping strategies : Keep only the p largest elements per column, where p is the number of elements in the column of the original matrix. Other strategies will be added
1397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  // Apply the fill-reducing permutation computed in analyzePattern()
1417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  if (m_perm.rows() == mat.rows() ) // To detect the null permutation
1427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    m_L.template selfadjointView<Lower>() = mat.template selfadjointView<_UpLo>().twistedBy(m_perm);
1437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  else
1447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    m_L.template selfadjointView<Lower>() = mat.template selfadjointView<_UpLo>();
1457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Index n = m_L.cols();
1477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Index nnz = m_L.nonZeros();
1487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Map<ScalarType> vals(m_L.valuePtr(), nnz); //values
1497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Map<IndexType> rowIdx(m_L.innerIndexPtr(), nnz);  //Row indices
1507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Map<IndexType> colPtr( m_L.outerIndexPtr(), n+1); // Pointer to the beginning of each row
1517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  IndexType firstElt(n-1); // for each j, points to the next entry in vals that will be used in the factorization
1527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  VectorList listCol(n); // listCol(j) is a linked list of columns to update column j
1537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  ScalarType curCol(n); // Store a  nonzero values in each column
1547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  IndexType irow(n); // Row indices of nonzero elements in each column
1557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  // Computes the scaling factors
1587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  m_scal.resize(n);
1597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  for (int j = 0; j < n; j++)
1607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  {
1617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    m_scal(j) = m_L.col(j).norm();
1627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    m_scal(j) = sqrt(m_scal(j));
1637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
1647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  // Scale and compute the shift for the matrix
1657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Scalar mindiag = vals[0];
1667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  for (int j = 0; j < n; j++){
1677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    for (int k = colPtr[j]; k < colPtr[j+1]; k++)
1687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez     vals[k] /= (m_scal(j) * m_scal(rowIdx[k]));
1697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    mindiag = (min)(vals[colPtr[j]], mindiag);
1707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
1717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  if(mindiag < Scalar(0.)) m_shift = m_shift - mindiag;
1737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  // Apply the shift to the diagonal elements of the matrix
1747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  for (int j = 0; j < n; j++)
1757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    vals[colPtr[j]] += m_shift;
1767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  // jki version of the Cholesky factorization
1777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  for (int j=0; j < n; ++j)
1787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  {
1797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    //Left-looking factorize the column j
1807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // First, load the jth column into curCol
1817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Scalar diag = vals[colPtr[j]];  // It is assumed that only the lower part is stored
1827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    curCol.setZero();
1837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    irow.setLinSpaced(n,0,n-1);
1847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    for (int i = colPtr[j] + 1; i < colPtr[j+1]; i++)
1857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
1867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      curCol(rowIdx[i]) = vals[i];
1877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      irow(rowIdx[i]) = rowIdx[i];
1887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
1897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    std::list<int>::iterator k;
1907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // Browse all previous columns that will update column j
1917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    for(k = listCol[j].begin(); k != listCol[j].end(); k++)
1927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
1937faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      int jk = firstElt(*k); // First element to use in the column
1947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      jk += 1;
1957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      for (int i = jk; i < colPtr[*k+1]; i++)
1967faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      {
1977faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        curCol(rowIdx[i]) -= vals[i] * vals[jk] ;
1987faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      }
1997faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      updateList(colPtr,rowIdx,vals, *k, jk, firstElt, listCol);
2007faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
2017faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
2027faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // Scale the current column
2037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    if(RealScalar(diag) <= 0)
2047faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
2057faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      std::cerr << "\nNegative diagonal during Incomplete factorization... "<< j << "\n";
2067faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      m_info = NumericalIssue;
2077faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      return;
2087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
2097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    RealScalar rdiag = sqrt(RealScalar(diag));
2107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    vals[colPtr[j]] = rdiag;
2117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    for (int i = j+1; i < n; i++)
2127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
2137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      //Scale
2147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      curCol(i) /= rdiag;
2157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      //Update the remaining diagonals with curCol
2167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      vals[colPtr[i]] -= curCol(i) * curCol(i);
2177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
2187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // Select the largest p elements
2197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    //  p is the original number of elements in the column (without the diagonal)
2207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    int p = colPtr[j+1] - colPtr[j] - 1 ;
2217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    internal::QuickSplit(curCol, irow, p);
2227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // Insert the largest p elements in the matrix
2237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    int cpt = 0;
2247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    for (int i = colPtr[j]+1; i < colPtr[j+1]; i++)
2257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
2267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      vals[i] = curCol(cpt);
2277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      rowIdx[i] = irow(cpt);
2287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      cpt ++;
2297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
2307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // Get the first smallest row index and put it after the diagonal element
2317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Index jk = colPtr(j)+1;
2327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    updateList(colPtr,rowIdx,vals,j,jk,firstElt,listCol);
2337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
2347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  m_factorizationIsOk = true;
2357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  m_isInitialized = true;
2367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  m_info = Success;
2377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez}
2387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
2397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename Scalar, int _UpLo, typename OrderingType>
2407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate <typename IdxType, typename SclType>
2417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezinline void IncompleteCholesky<Scalar,_UpLo, OrderingType>::updateList(const IdxType& colPtr, IdxType& rowIdx, SclType& vals, const Index& col, const Index& jk, IndexType& firstElt, VectorList& listCol)
2427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{
2437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  if (jk < colPtr(col+1) )
2447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  {
2457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Index p = colPtr(col+1) - jk;
2467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Index minpos;
2477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    rowIdx.segment(jk,p).minCoeff(&minpos);
2487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    minpos += jk;
2497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    if (rowIdx(minpos) != rowIdx(jk))
2507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
2517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      //Swap
2527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      std::swap(rowIdx(jk),rowIdx(minpos));
2537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      std::swap(vals(jk),vals(minpos));
2547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
2557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    firstElt(col) = jk;
2567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    listCol[rowIdx(jk)].push_back(col);
2577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
2587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez}
2597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeznamespace internal {
2607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
2617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename _Scalar, int _UpLo, typename OrderingType, typename Rhs>
2627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezstruct solve_retval<IncompleteCholesky<_Scalar,  _UpLo, OrderingType>, Rhs>
2637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  : solve_retval_base<IncompleteCholesky<_Scalar, _UpLo, OrderingType>, Rhs>
2647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{
2657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  typedef IncompleteCholesky<_Scalar, _UpLo, OrderingType> Dec;
2667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs)
2677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
2687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  template<typename Dest> void evalTo(Dest& dst) const
2697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  {
2707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    dec()._solve(rhs(),dst);
2717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
2727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez};
2737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
2747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} // end namespace internal
2757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
2767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} // end namespace Eigen
2777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
2787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#endif
279