bugfix of set_coef introduced by c84cc28d1c

The problem is that building the matrix from a set of triplets sums
the value provided in case several values at the same position are
provided. In order to overwrite a value, we have no other choice
than to build the matrix and set the value (with current Eigen API).
The following fix is as efficient if the matrix is assembled
in one pass. Using the boolean member of set_coef is very important now
as it can imply a premature building of the eigen matrix.
This commit is contained in:
Sébastien Loriot 2013-02-13 18:24:26 +01:00
parent c0fcf54002
commit d64f988b7d
1 changed files with 30 additions and 16 deletions

View File

@ -53,7 +53,7 @@ public:
/// Create a square matrix initialized with zeros. /// Create a square matrix initialized with zeros.
Eigen_sparse_matrix(int dim, ///< Matrix dimension. Eigen_sparse_matrix(int dim, ///< Matrix dimension.
bool is_symmetric = false) ///< Symmetric/hermitian? bool is_symmetric = false) ///< Symmetric/hermitian?
: m_is_uptodate(false), m_matrix(dim,dim) : m_is_already_built(false), m_matrix(dim,dim)
{ {
CGAL_precondition(dim > 0); CGAL_precondition(dim > 0);
@ -68,7 +68,7 @@ public:
Eigen_sparse_matrix(int rows, ///< Number of rows. Eigen_sparse_matrix(int rows, ///< Number of rows.
int columns, ///< Number of columns. int columns, ///< Number of columns.
bool is_symmetric = false) ///< Symmetric/hermitian? bool is_symmetric = false) ///< Symmetric/hermitian?
: m_is_uptodate(false), m_matrix(rows,columns) : m_is_already_built(false), m_matrix(rows,columns)
{ {
CGAL_precondition(rows > 0); CGAL_precondition(rows > 0);
CGAL_precondition(columns > 0); CGAL_precondition(columns > 0);
@ -103,7 +103,7 @@ public:
/// @commentheading Preconditions: /// @commentheading Preconditions:
/// - 0 <= i < row_dimension(). /// - 0 <= i < row_dimension().
/// - 0 <= j < column_dimension(). /// - 0 <= j < column_dimension().
void set_coef(int i, int j, T val, bool /* new_coef */ = false) void set_coef(int i, int j, T val, bool new_coef = false)
{ {
CGAL_precondition(i < row_dimension()); CGAL_precondition(i < row_dimension());
CGAL_precondition(j < column_dimension()); CGAL_precondition(j < column_dimension());
@ -111,8 +111,18 @@ public:
if (m_is_symmetric && (j > i)) if (m_is_symmetric && (j > i))
return; return;
if (m_is_already_built)
m_matrix.coeffRef(i,j)=val;
else
{
if ( new_coef == false )
{
assemble_matrix();
m_matrix.coeffRef(i,j)=val;
}
else
m_triplets.push_back(Triplet(i,j,val)); m_triplets.push_back(Triplet(i,j,val));
m_is_uptodate = false; }
} }
/// Write access to a matrix coefficient: a_ij <- a_ij+val. /// Write access to a matrix coefficient: a_ij <- a_ij+val.
@ -132,19 +142,23 @@ public:
if (m_is_symmetric && (j > i)) if (m_is_symmetric && (j > i))
return; return;
if (m_is_already_built)
m_matrix.coeffRef(i,j)+=val;
else
m_triplets.push_back(Triplet(i,j,val)); m_triplets.push_back(Triplet(i,j,val));
m_is_uptodate = false;
} }
void assemble_matrix() const
{
m_matrix.setFromTriplets(m_triplets.begin(), m_triplets.end());
m_is_already_built = true;
m_triplets.clear(); //the matrix is built and will not be rebuilt
}
const EigenType& eigen_object() const const EigenType& eigen_object() const
{ {
if(!m_is_uptodate) if(!m_is_already_built) assemble_matrix();
{
m_matrix.setFromTriplets(m_triplets.begin(), m_triplets.end());
m_is_uptodate = true;
}
// turns the matrix into compressed mode: // turns the matrix into compressed mode:
// -> release some memory // -> release some memory
// -> required for some external solvers // -> required for some external solvers
@ -162,7 +176,7 @@ private:
// Fields // Fields
private: private:
mutable bool m_is_uptodate; mutable bool m_is_already_built;
typedef Eigen::Triplet<T,int> Triplet; typedef Eigen::Triplet<T,int> Triplet;
mutable std::vector<Triplet> m_triplets; mutable std::vector<Triplet> m_triplets;