mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-06-02 17:31:08 +08:00
bug #1381: fix sparse.diagonal() used as a rvalue.
The problem was that is "sparse" is not const, then sparse.diagonal() must have the LValueBit flag meaning that sparse.diagonal().coeff(i) must returns a const reference, const Scalar&. However, sparse::coeff() cannot returns a reference for a non-existing zero coefficient. The trick is to return a reference to a local member of evaluator<SparseMatrix>.
This commit is contained in:
parent
d06a48959a
commit
296d24be4d
@ -1613,9 +1613,7 @@ struct evaluator<Diagonal<ArgType, DiagIndex> >
|
|||||||
{ }
|
{ }
|
||||||
|
|
||||||
typedef typename XprType::Scalar Scalar;
|
typedef typename XprType::Scalar Scalar;
|
||||||
// FIXME having to check whether ArgType is sparse here i not very nice.
|
typedef typename XprType::CoeffReturnType CoeffReturnType;
|
||||||
typedef typename internal::conditional<!internal::is_same<typename ArgType::StorageKind,Sparse>::value,
|
|
||||||
typename XprType::CoeffReturnType,Scalar>::type CoeffReturnType;
|
|
||||||
|
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
CoeffReturnType coeff(Index row, Index) const
|
CoeffReturnType coeff(Index row, Index) const
|
||||||
|
@ -638,7 +638,7 @@ struct plain_constant_type
|
|||||||
template<typename ExpressionType>
|
template<typename ExpressionType>
|
||||||
struct is_lvalue
|
struct is_lvalue
|
||||||
{
|
{
|
||||||
enum { value = !bool(is_const<ExpressionType>::value) &&
|
enum { value = (!bool(is_const<ExpressionType>::value)) &&
|
||||||
bool(traits<ExpressionType>::Flags & LvalueBit) };
|
bool(traits<ExpressionType>::Flags & LvalueBit) };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -295,11 +295,11 @@ struct evaluator<SparseCompressedBase<Derived> >
|
|||||||
Flags = Derived::Flags
|
Flags = Derived::Flags
|
||||||
};
|
};
|
||||||
|
|
||||||
evaluator() : m_matrix(0)
|
evaluator() : m_matrix(0), m_zero(0)
|
||||||
{
|
{
|
||||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||||
}
|
}
|
||||||
explicit evaluator(const Derived &mat) : m_matrix(&mat)
|
explicit evaluator(const Derived &mat) : m_matrix(&mat), m_zero(0)
|
||||||
{
|
{
|
||||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||||
}
|
}
|
||||||
@ -312,26 +312,42 @@ struct evaluator<SparseCompressedBase<Derived> >
|
|||||||
operator const Derived&() const { return *m_matrix; }
|
operator const Derived&() const { return *m_matrix; }
|
||||||
|
|
||||||
typedef typename DenseCoeffsBase<Derived,ReadOnlyAccessors>::CoeffReturnType CoeffReturnType;
|
typedef typename DenseCoeffsBase<Derived,ReadOnlyAccessors>::CoeffReturnType CoeffReturnType;
|
||||||
Scalar coeff(Index row, Index col) const
|
const Scalar& coeff(Index row, Index col) const
|
||||||
{ return m_matrix->coeff(row,col); }
|
{
|
||||||
|
Index p = find(row,col);
|
||||||
|
|
||||||
|
if(p==Dynamic)
|
||||||
|
return m_zero;
|
||||||
|
else
|
||||||
|
return m_matrix->const_cast_derived().valuePtr()[p];
|
||||||
|
}
|
||||||
|
|
||||||
Scalar& coeffRef(Index row, Index col)
|
Scalar& coeffRef(Index row, Index col)
|
||||||
|
{
|
||||||
|
Index p = find(row,col);
|
||||||
|
eigen_assert(p!=Dynamic && "written coefficient does not exist");
|
||||||
|
return m_matrix->const_cast_derived().valuePtr()[p];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
Index find(Index row, Index col) const
|
||||||
{
|
{
|
||||||
eigen_internal_assert(row>=0 && row<m_matrix->rows() && col>=0 && col<m_matrix->cols());
|
eigen_internal_assert(row>=0 && row<m_matrix->rows() && col>=0 && col<m_matrix->cols());
|
||||||
|
|
||||||
const Index outer = Derived::IsRowMajor ? row : col;
|
const Index outer = Derived::IsRowMajor ? row : col;
|
||||||
const Index inner = Derived::IsRowMajor ? col : row;
|
const Index inner = Derived::IsRowMajor ? col : row;
|
||||||
|
|
||||||
Index start = m_matrix->outerIndexPtr()[outer];
|
Index start = m_matrix->outerIndexPtr()[outer];
|
||||||
Index end = m_matrix->isCompressed() ? m_matrix->outerIndexPtr()[outer+1] : m_matrix->outerIndexPtr()[outer] + m_matrix->innerNonZeroPtr()[outer];
|
Index end = m_matrix->isCompressed() ? m_matrix->outerIndexPtr()[outer+1] : m_matrix->outerIndexPtr()[outer] + m_matrix->innerNonZeroPtr()[outer];
|
||||||
eigen_assert(end>start && "you are using a non finalized sparse matrix or written coefficient does not exist");
|
eigen_assert(end>=start && "you are using a non finalized sparse matrix or written coefficient does not exist");
|
||||||
const Index p = std::lower_bound(m_matrix->innerIndexPtr()+start, m_matrix->innerIndexPtr()+end,inner)
|
const Index p = std::lower_bound(m_matrix->innerIndexPtr()+start, m_matrix->innerIndexPtr()+end,inner) - m_matrix->innerIndexPtr();
|
||||||
- m_matrix->innerIndexPtr();
|
|
||||||
eigen_assert((p<end) && (m_matrix->innerIndexPtr()[p]==inner) && "written coefficient does not exist");
|
return ((p<end) && (m_matrix->innerIndexPtr()[p]==inner)) ? p : Dynamic;
|
||||||
return m_matrix->const_cast_derived().valuePtr()[p];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Derived *m_matrix;
|
const Derived *m_matrix;
|
||||||
|
const Scalar m_zero;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -485,6 +485,10 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
|
|||||||
SparseMatrixType m2(rows, cols);
|
SparseMatrixType m2(rows, cols);
|
||||||
initSparse<Scalar>(density, refMat2, m2);
|
initSparse<Scalar>(density, refMat2, m2);
|
||||||
VERIFY_IS_APPROX(m2.diagonal(), refMat2.diagonal().eval());
|
VERIFY_IS_APPROX(m2.diagonal(), refMat2.diagonal().eval());
|
||||||
|
DenseVector d = m2.diagonal();
|
||||||
|
VERIFY_IS_APPROX(d, refMat2.diagonal().eval());
|
||||||
|
d = m2.diagonal().array();
|
||||||
|
VERIFY_IS_APPROX(d, refMat2.diagonal().eval());
|
||||||
VERIFY_IS_APPROX(const_cast<const SparseMatrixType&>(m2).diagonal(), refMat2.diagonal().eval());
|
VERIFY_IS_APPROX(const_cast<const SparseMatrixType&>(m2).diagonal(), refMat2.diagonal().eval());
|
||||||
|
|
||||||
initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag);
|
initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user