Fix bug #607: handle implicit transposition from sparse vector to dense vector

This commit is contained in:
Gael Guennebaud 2013-06-10 00:06:40 +02:00
parent 4811b4526c
commit e392948548
3 changed files with 24 additions and 17 deletions

View File

@ -520,18 +520,22 @@ struct assign_selector;
template<typename Derived, typename OtherDerived> template<typename Derived, typename OtherDerived>
struct assign_selector<Derived,OtherDerived,false,false> { struct assign_selector<Derived,OtherDerived,false,false> {
static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.derived()); } static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.derived()); }
static EIGEN_STRONG_INLINE Derived& evalTo(Derived& dst, const OtherDerived& other) { other.evalTo(dst); return dst; }
}; };
template<typename Derived, typename OtherDerived> template<typename Derived, typename OtherDerived>
struct assign_selector<Derived,OtherDerived,true,false> { struct assign_selector<Derived,OtherDerived,true,false> {
static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.eval()); } static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.eval()); }
static EIGEN_STRONG_INLINE Derived& evalTo(Derived& dst, const OtherDerived& other) { other.evalTo(dst); return dst; }
}; };
template<typename Derived, typename OtherDerived> template<typename Derived, typename OtherDerived>
struct assign_selector<Derived,OtherDerived,false,true> { struct assign_selector<Derived,OtherDerived,false,true> {
static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose()); } static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose()); }
static EIGEN_STRONG_INLINE Derived& evalTo(Derived& dst, const OtherDerived& other) { Transpose<Derived> dstTrans(dst); other.evalTo(dstTrans); return dst; }
}; };
template<typename Derived, typename OtherDerived> template<typename Derived, typename OtherDerived>
struct assign_selector<Derived,OtherDerived,true,true> { struct assign_selector<Derived,OtherDerived,true,true> {
static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose().eval()); } static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose().eval()); }
static EIGEN_STRONG_INLINE Derived& evalTo(Derived& dst, const OtherDerived& other) { Transpose<Derived> dstTrans(dst); other.evalTo(dstTrans); return dst; }
}; };
} // end namespace internal } // end namespace internal
@ -566,16 +570,14 @@ template<typename Derived>
template <typename OtherDerived> template <typename OtherDerived>
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const EigenBase<OtherDerived>& other) EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const EigenBase<OtherDerived>& other)
{ {
other.derived().evalTo(derived()); return internal::assign_selector<Derived,OtherDerived>::evalTo(derived(), other.derived());
return derived();
} }
template<typename Derived> template<typename Derived>
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other) EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other)
{ {
other.evalTo(derived()); return internal::assign_selector<Derived,OtherDerived>::evalTo(derived(), other.derived());
return derived();
} }
} // end namespace Eigen } // end namespace Eigen

View File

@ -403,20 +403,20 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
Block<Derived,Dynamic,Dynamic,true> innerVectors(Index outerStart, Index outerSize); Block<Derived,Dynamic,Dynamic,true> innerVectors(Index outerStart, Index outerSize);
const Block<const Derived,Dynamic,Dynamic,true> innerVectors(Index outerStart, Index outerSize) const; const Block<const Derived,Dynamic,Dynamic,true> innerVectors(Index outerStart, Index outerSize) const;
/** \internal use operator= */ /** \internal use operator= */
template<typename DenseDerived> template<typename DenseDerived>
void evalTo(MatrixBase<DenseDerived>& dst) const void evalTo(MatrixBase<DenseDerived>& dst) const
{ {
dst.setZero(); dst.setZero();
for (Index j=0; j<outerSize(); ++j) for (Index j=0; j<outerSize(); ++j)
for (typename Derived::InnerIterator i(derived(),j); i; ++i) for (typename Derived::InnerIterator i(derived(),j); i; ++i)
dst.coeffRef(i.row(),i.col()) = i.value(); dst.coeffRef(i.row(),i.col()) = i.value();
} }
Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime> toDense() const Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime> toDense() const
{ {
return derived(); return derived();
} }
template<typename OtherDerived> template<typename OtherDerived>
bool isApprox(const SparseMatrixBase<OtherDerived>& other, bool isApprox(const SparseMatrixBase<OtherDerived>& other,

View File

@ -90,6 +90,11 @@ template<typename Scalar> void sparse_vector(int rows, int cols)
VERIFY_IS_APPROX((mv1=v1),v1); VERIFY_IS_APPROX((mv1=v1),v1);
VERIFY_IS_APPROX(mv1,(v1=mv1)); VERIFY_IS_APPROX(mv1,(v1=mv1));
VERIFY_IS_APPROX(mv1,(v1=mv1.transpose())); VERIFY_IS_APPROX(mv1,(v1=mv1.transpose()));
// check copy to dense vector with transpose
refV3.resize(0);
VERIFY_IS_APPROX(refV3 = v1.transpose(),v1.toDense());
VERIFY_IS_APPROX(DenseVector(v1),v1.toDense());
} }