various compilation and bug fixes in selfadjoint stuff

This commit is contained in:
Gael Guennebaud 2009-07-27 13:17:39 +02:00
parent b5e4064289
commit 0590c18555
10 changed files with 95 additions and 97 deletions

View File

@ -125,9 +125,11 @@ template<typename MatrixType, unsigned int UpLo> class SelfAdjointView
* The vectors \a u and \c v \b must be column vectors, however they can be * The vectors \a u and \c v \b must be column vectors, however they can be
* a adjoint expression without any overhead. Only the meaningful triangular * a adjoint expression without any overhead. Only the meaningful triangular
* part of the matrix is updated, the rest is left unchanged. * part of the matrix is updated, the rest is left unchanged.
*
* \sa rankUpdate(const MatrixBase<DerivedU>&, Scalar)
*/ */
template<typename DerivedU, typename DerivedV> template<typename DerivedU, typename DerivedV>
SelfAdjointView& rank2update(const MatrixBase<DerivedU>& u, const MatrixBase<DerivedV>& v, Scalar alpha = Scalar(1)); SelfAdjointView& rankUpdate(const MatrixBase<DerivedU>& u, const MatrixBase<DerivedV>& v, Scalar alpha = Scalar(1));
/** Perform a symmetric rank K update of the selfadjoint matrix \c *this: /** 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. * \f$ this = this + \alpha ( u u^* ) \f$ where \a u is a vector or matrix.
@ -136,9 +138,11 @@ template<typename MatrixType, unsigned int UpLo> class SelfAdjointView
* *
* Note that to perform \f$ this = this + \alpha ( u^* u ) \f$ you can simply * Note that to perform \f$ this = this + \alpha ( u^* u ) \f$ you can simply
* call this function with u.adjoint(). * call this function with u.adjoint().
*
* \sa rankUpdate(const MatrixBase<DerivedU>&, const MatrixBase<DerivedV>&, Scalar)
*/ */
template<typename DerivedU> template<typename DerivedU>
SelfAdjointView& rankKupdate(const MatrixBase<DerivedU>& u, Scalar alpha = Scalar(1)); SelfAdjointView& rankUpdate(const MatrixBase<DerivedU>& u, Scalar alpha = Scalar(1));
/////////// Cholesky module /////////// /////////// Cholesky module ///////////
@ -231,13 +235,14 @@ struct ei_selfadjoint_product_returntype<Lhs,LhsMode,false,Rhs,0,true>
template<typename Dest> void evalTo(Dest& dst) const template<typename Dest> void evalTo(Dest& dst) const
{ {
dst.resize(m_lhs.rows(), m_rhs.cols());
dst.setZero(); dst.setZero();
evalTo(dst,1); evalTo(dst,1);
} }
template<typename Dest> void evalTo(Dest& dst, Scalar alpha) const template<typename Dest> void evalTo(Dest& dst, Scalar alpha) const
{ {
ei_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols());
const ActualLhsType lhs = LhsBlasTraits::extract(m_lhs); const ActualLhsType lhs = LhsBlasTraits::extract(m_lhs);
const ActualRhsType rhs = RhsBlasTraits::extract(m_rhs); const ActualRhsType rhs = RhsBlasTraits::extract(m_rhs);

View File

@ -63,9 +63,6 @@ static EIGEN_DONT_INLINE void ei_product_selfadjoint_vector(
rhs = r; rhs = r;
} }
for (int i=0;i<size;i++)
res[i] = 0;
int bound = std::max(0,size-8) & 0xfffffffE; int bound = std::max(0,size-8) & 0xfffffffE;
if (FirstTriangular) if (FirstTriangular)
bound = size - bound; bound = size - bound;

View File

@ -126,7 +126,7 @@ struct ei_selfadjoint_product<Scalar,MatStorageOrder, ColMajor, AAT, UpLo>
template<typename MatrixType, unsigned int UpLo> template<typename MatrixType, unsigned int UpLo>
template<typename DerivedU> template<typename DerivedU>
SelfAdjointView<MatrixType,UpLo>& SelfAdjointView<MatrixType,UpLo> SelfAdjointView<MatrixType,UpLo>& SelfAdjointView<MatrixType,UpLo>
::rankKupdate(const MatrixBase<DerivedU>& u, Scalar alpha) ::rankUpdate(const MatrixBase<DerivedU>& u, Scalar alpha)
{ {
typedef ei_blas_traits<DerivedU> UBlasTraits; typedef ei_blas_traits<DerivedU> UBlasTraits;
typedef typename UBlasTraits::DirectLinearAccessType ActualUType; typedef typename UBlasTraits::DirectLinearAccessType ActualUType;

View File

@ -70,7 +70,7 @@ template<bool Cond, typename T> struct ei_conj_expr_if
template<typename MatrixType, unsigned int UpLo> template<typename MatrixType, unsigned int UpLo>
template<typename DerivedU, typename DerivedV> template<typename DerivedU, typename DerivedV>
SelfAdjointView<MatrixType,UpLo>& SelfAdjointView<MatrixType,UpLo> SelfAdjointView<MatrixType,UpLo>& SelfAdjointView<MatrixType,UpLo>
::rank2update(const MatrixBase<DerivedU>& u, const MatrixBase<DerivedV>& v, Scalar alpha) ::rankUpdate(const MatrixBase<DerivedU>& u, const MatrixBase<DerivedV>& v, Scalar alpha)
{ {
typedef ei_blas_traits<DerivedU> UBlasTraits; typedef ei_blas_traits<DerivedU> UBlasTraits;
typedef typename UBlasTraits::DirectLinearAccessType ActualUType; typedef typename UBlasTraits::DirectLinearAccessType ActualUType;
@ -87,8 +87,8 @@ SelfAdjointView<MatrixType,UpLo>& SelfAdjointView<MatrixType,UpLo>
enum { IsRowMajor = (ei_traits<MatrixType>::Flags&RowMajorBit)?1:0 }; enum { IsRowMajor = (ei_traits<MatrixType>::Flags&RowMajorBit)?1:0 };
ei_selfadjoint_rank2_update_selector<Scalar, ei_selfadjoint_rank2_update_selector<Scalar,
typename ei_conj_expr_if<IsRowMajor ^ UBlasTraits::NeedToConjugate,_ActualUType>::ret, typename ei_cleantype<typename ei_conj_expr_if<IsRowMajor ^ UBlasTraits::NeedToConjugate,_ActualUType>::ret>::type,
typename ei_conj_expr_if<IsRowMajor ^ VBlasTraits::NeedToConjugate,_ActualVType>::ret, typename ei_cleantype<typename ei_conj_expr_if<IsRowMajor ^ VBlasTraits::NeedToConjugate,_ActualVType>::ret>::type,
(IsRowMajor ? (UpLo==UpperTriangular ? LowerTriangular : UpperTriangular) : UpLo)> (IsRowMajor ? (UpLo==UpperTriangular ? LowerTriangular : UpperTriangular) : UpLo)>
::run(const_cast<Scalar*>(_expression().data()),_expression().stride(),actualU,actualV,actualAlpha); ::run(const_cast<Scalar*>(_expression().data()),_expression().stride(),actualU,actualV,actualAlpha);

View File

@ -224,21 +224,19 @@ void Tridiagonalization<MatrixType>::_compute(MatrixType& matA, CoeffVectorType&
// Apply similarity transformation to remaining columns, // Apply similarity transformation to remaining columns,
// i.e., A = H' A H where H = I - h v v' and v = matA.col(i).end(n-i-1) // i.e., A = H' A H where H = I - h v v' and v = matA.col(i).end(n-i-1)
matA.col(i).coeffRef(i+1) = 1; matA.col(i).coeffRef(i+1) = 1;
// hCoeffs.end(n-i-1) = (matA.corner(BottomRight,n-i-1,n-i-1).template part<LowerTriangular|SelfAdjoint>() // hCoeffs.end(n-i-1) = (matA.corner(BottomRight,n-i-1,n-i-1).template selfadjointView<LowerTriangular>()
// * matA.col(i).end(n-i-1)).lazy(); // * (h * matA.col(i).end(n-i-1)));
// TODO map the above code to the function call below:
ei_product_selfadjoint_vector<Scalar,MatrixType::Flags&RowMajorBit,LowerTriangularBit>
(n-i-1,matA.corner(BottomRight,n-i-1,n-i-1).data(), matA.stride(), matA.col(i).end(n-i-1).data(), const_cast<Scalar*>(hCoeffs.end(n-i-1).data()));
hCoeffs.end(n-i-1) = hCoeffs.end(n-i-1)*h hCoeffs.end(n-i-1).setZero();
+ (h*ei_conj(h)*Scalar(-0.5)*(matA.col(i).end(n-i-1).dot(hCoeffs.end(n-i-1)))) * ei_product_selfadjoint_vector<Scalar,MatrixType::Flags&RowMajorBit,LowerTriangular,false,false>
matA.col(i).end(n-i-1); (n-i-1,matA.corner(BottomRight,n-i-1,n-i-1).data(), matA.stride(), matA.col(i).end(n-i-1).data(), 1, const_cast<Scalar*>(hCoeffs.end(n-i-1).data()), h);
hCoeffs.end(n-i-1) += (h*Scalar(-0.5)*(matA.col(i).end(n-i-1).dot(hCoeffs.end(n-i-1)))) * matA.col(i).end(n-i-1);
matA.corner(BottomRight, n-i-1, n-i-1).template selfadjointView<LowerTriangular>() matA.corner(BottomRight, n-i-1, n-i-1).template selfadjointView<LowerTriangular>()
.rank2update(matA.col(i).end(n-i-1), hCoeffs.end(n-i-1), -1); .rankUpdate(matA.col(i).end(n-i-1), hCoeffs.end(n-i-1), -1);
// note: at that point matA(i+1,i+1) is the (i+1)-th element of the final diagonal // note: at that point matA(i+1,i+1) is the (i+1)-th element of the final diagonal
// note: the sequence of the beta values leads to the subdiagonal entries // note: the sequence of the beta values leads to the subdiagonal entries

View File

@ -119,8 +119,8 @@ void test_eigensolver_selfadjoint()
// very important to test a 3x3 matrix since we provide a special path for it // very important to test a 3x3 matrix since we provide a special path for it
CALL_SUBTEST( selfadjointeigensolver(Matrix3f()) ); CALL_SUBTEST( selfadjointeigensolver(Matrix3f()) );
CALL_SUBTEST( selfadjointeigensolver(Matrix4d()) ); CALL_SUBTEST( selfadjointeigensolver(Matrix4d()) );
CALL_SUBTEST( selfadjointeigensolver(MatrixXf(4,4)) ); CALL_SUBTEST( selfadjointeigensolver(MatrixXf(10,10)) );
CALL_SUBTEST( selfadjointeigensolver(MatrixXcd(7,7)) ); CALL_SUBTEST( selfadjointeigensolver(MatrixXcd(17,17)) );
CALL_SUBTEST( selfadjointeigensolver(MatrixXd(19,19)) ); CALL_SUBTEST( selfadjointeigensolver(MatrixXd(19,19)) );
// some trivial but implementation-wise tricky cases // some trivial but implementation-wise tricky cases

View File

@ -62,13 +62,14 @@ template<typename MatrixType> void product_extra(const MatrixType& m)
// all the expressions in this test should be compiled as a single matrix product // all the expressions in this test should be compiled as a single matrix product
// TODO: add internal checks to verify that // TODO: add internal checks to verify that
VERIFY_IS_APPROX(m1 * m2.adjoint(), m1 * m2.adjoint().eval()); VERIFY_IS_APPROX(m3 = (m1 * m2.adjoint()).lazy(), m1 * m2.adjoint().eval());
VERIFY_IS_APPROX(m1.adjoint() * square.adjoint(), m1.adjoint().eval() * square.adjoint().eval()); VERIFY_IS_APPROX(m3 = (m1.adjoint() * square.adjoint()).lazy(), m1.adjoint().eval() * square.adjoint().eval());
VERIFY_IS_APPROX(m1.adjoint() * m2, m1.adjoint().eval() * m2); VERIFY_IS_APPROX(m3 = (m1.adjoint() * m2).lazy(), m1.adjoint().eval() * m2);
VERIFY_IS_APPROX( (s1 * m1.adjoint()) * m2, (s1 * m1.adjoint()).eval() * m2); VERIFY_IS_APPROX(m3 = ((s1 * m1.adjoint()) * m2).lazy(), (s1 * m1.adjoint()).eval() * m2);
VERIFY_IS_APPROX( (- m1.adjoint() * s1) * (s3 * m2), (- m1.adjoint() * s1).eval() * (s3 * m2).eval()); VERIFY_IS_APPROX(m3 = ((- m1.adjoint() * s1) * (s3 * m2)).lazy(), (- m1.adjoint() * s1).eval() * (s3 * m2).eval());
VERIFY_IS_APPROX( (s2 * m1.adjoint() * s1) * m2, (s2 * m1.adjoint() * s1).eval() * m2); VERIFY_IS_APPROX(m3 = ((s2 * m1.adjoint() * s1) * m2).lazy(), (s2 * m1.adjoint() * s1).eval() * m2);
VERIFY_IS_APPROX( (-m1*s2) * s1*m2.adjoint(), (-m1*s2).eval() * (s1*m2.adjoint()).eval()); VERIFY_IS_APPROX(m3 = ((-m1*s2) * s1*m2.adjoint()).lazy(), (-m1*s2).eval() * (s1*m2.adjoint()).eval());
// a very tricky case where a scale factor has to be automatically conjugated: // a very tricky case where a scale factor has to be automatically conjugated:
VERIFY_IS_APPROX( m1.adjoint() * (s1*m2).conjugate(), (m1.adjoint()).eval() * ((s1*m2).conjugate()).eval()); VERIFY_IS_APPROX( m1.adjoint() * (s1*m2).conjugate(), (m1.adjoint()).eval() * ((s1*m2).conjugate()).eval());

View File

@ -52,42 +52,23 @@ template<typename MatrixType> void product_selfadjoint(const MatrixType& m)
m1 = (m1.adjoint() + m1).eval(); m1 = (m1.adjoint() + m1).eval();
// lower
m2 = m1.template triangularView<LowerTriangular>();
VERIFY_IS_APPROX(v3 = (s1*m2).template selfadjointView<LowerTriangular>() * (s2*v1), (s1*m1) * (s2*v1));
VERIFY_IS_APPROX(v3 = (s1*m2.conjugate()).template selfadjointView<LowerTriangular>() * (s2*v1), (s1*m1.conjugate()) * (s2*v1));
VERIFY_IS_APPROX(v3 = (s1*m2).template selfadjointView<LowerTriangular>() * (s2*m4.col(1)), (s1*m1) * (s2*m4.col(1)));
VERIFY_IS_APPROX(v3 = (s1*m2).template selfadjointView<LowerTriangular>() * (s2*v1.conjugate()), (s1*m1) * (s2*v1.conjugate()));
VERIFY_IS_APPROX(v3 = (s1*m2.conjugate()).template selfadjointView<LowerTriangular>() * (s2*v1.conjugate()), (s1*m1.conjugate()) * (s2*v1.conjugate()));
// upper
m2 = m1.template triangularView<UpperTriangular>();
VERIFY_IS_APPROX(v3 = (s1*m2).template selfadjointView<UpperTriangular>() * (s2*v1), (s1*m1) * (s2*v1));
VERIFY_IS_APPROX(v3 = (s1*m2.conjugate()).template selfadjointView<UpperTriangular>() * (s2*v1), (s1*m1.conjugate()) * (s2*v1));
VERIFY_IS_APPROX(v3 = (s1*m2.adjoint()).template selfadjointView<LowerTriangular>() * (s2*v1), (s1*m1.adjoint()) * (s2*v1));
VERIFY_IS_APPROX(v3 = (s1*m2.transpose()).template selfadjointView<LowerTriangular>() * (s2*v1), (s1*m1.transpose()) * (s2*v1));
VERIFY_IS_APPROX(v3 = (s1*m2).template selfadjointView<UpperTriangular>() * (s2*v1.conjugate()), (s1*m1) * (s2*v1.conjugate()));
VERIFY_IS_APPROX(v3 = (s1*m2.conjugate()).template selfadjointView<UpperTriangular>() * (s2*v1.conjugate()), (s1*m1.conjugate()) * (s2*v1.conjugate()));
// rank2 update // rank2 update
m2 = m1.template triangularView<LowerTriangular>(); m2 = m1.template triangularView<LowerTriangular>();
m2.template selfadjointView<LowerTriangular>().rank2update(v1,v2); m2.template selfadjointView<LowerTriangular>().rankUpdate(v1,v2);
VERIFY_IS_APPROX(m2, (m1 + v1 * v2.adjoint()+ v2 * v1.adjoint()).template triangularView<LowerTriangular>().toDense()); VERIFY_IS_APPROX(m2, (m1 + v1 * v2.adjoint()+ v2 * v1.adjoint()).template triangularView<LowerTriangular>().toDense());
m2 = m1.template triangularView<UpperTriangular>(); m2 = m1.template triangularView<UpperTriangular>();
m2.template selfadjointView<UpperTriangular>().rank2update(-v1,s2*v2,s3); m2.template selfadjointView<UpperTriangular>().rankUpdate(-v1,s2*v2,s3);
VERIFY_IS_APPROX(m2, (m1 + (-s2*s3) * (v1 * v2.adjoint()+ v2 * v1.adjoint())).template triangularView<UpperTriangular>().toDense()); VERIFY_IS_APPROX(m2, (m1 + (-s2*s3) * (v1 * v2.adjoint()+ v2 * v1.adjoint())).template triangularView<UpperTriangular>().toDense());
m2 = m1.template triangularView<UpperTriangular>(); m2 = m1.template triangularView<UpperTriangular>();
m2.template selfadjointView<UpperTriangular>().rank2update(-r1.adjoint(),r2.adjoint()*s3,s1); m2.template selfadjointView<UpperTriangular>().rankUpdate(-r1.adjoint(),r2.adjoint()*s3,s1);
VERIFY_IS_APPROX(m2, (m1 + (-s3*s1) * (r1.adjoint() * r2 + r2.adjoint() * r1)).template triangularView<UpperTriangular>().toDense()); VERIFY_IS_APPROX(m2, (m1 + (-s3*s1) * (r1.adjoint() * r2 + r2.adjoint() * r1)).template triangularView<UpperTriangular>().toDense());
if (rows>1) if (rows>1)
{ {
m2 = m1.template triangularView<LowerTriangular>(); m2 = m1.template triangularView<LowerTriangular>();
m2.block(1,1,rows-1,cols-1).template selfadjointView<LowerTriangular>().rank2update(v1.end(rows-1),v2.start(cols-1)); m2.block(1,1,rows-1,cols-1).template selfadjointView<LowerTriangular>().rankUpdate(v1.end(rows-1),v2.start(cols-1));
m3 = m1; m3 = m1;
m3.block(1,1,rows-1,cols-1) += v1.end(rows-1) * v2.start(cols-1).adjoint()+ v2.start(cols-1) * v1.end(rows-1).adjoint(); m3.block(1,1,rows-1,cols-1) += v1.end(rows-1) * v2.start(cols-1).adjoint()+ v2.start(cols-1) * v1.end(rows-1).adjoint();
VERIFY_IS_APPROX(m2, m3.template triangularView<LowerTriangular>().toDense()); VERIFY_IS_APPROX(m2, m3.template triangularView<LowerTriangular>().toDense());

View File

@ -24,25 +24,43 @@
#include "main.h" #include "main.h"
template<typename MatrixType> void symm(const MatrixType& m) template<int OtherSize> struct symm_extra {
{ template<typename M1, typename M2, typename Scalar>
typedef typename MatrixType::Scalar Scalar; static void run(M1& m1, M1& m2, M2& rhs2, M2& rhs22, M2& rhs23, Scalar s1, Scalar s2)
typedef typename NumTraits<Scalar>::Real RealScalar; {
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, Dynamic> Rhs1; m2 = m1.template triangularView<LowerTriangular>();
typedef Matrix<Scalar, Dynamic, MatrixType::RowsAtCompileTime> Rhs2; VERIFY_IS_APPROX(rhs22 = (rhs2) * (m2).template selfadjointView<LowerTriangular>(),
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, Dynamic,RowMajor> Rhs3; rhs23 = (rhs2) * (m1));
VERIFY_IS_APPROX(rhs22 = (s2*rhs2) * (s1*m2).template selfadjointView<LowerTriangular>(),
rhs23 = (s2*rhs2) * (s1*m1));
}
};
int rows = m.rows(); template<> struct symm_extra<1> {
int cols = m.cols(); template<typename M1, typename M2, typename Scalar>
static void run(M1& m1, M1& m2, M2& rhs2, M2& rhs22, M2& rhs23, Scalar s1, Scalar s2) {}
};
template<typename Scalar, int Size, int OtherSize> void symm(int size = Size, int othersize = OtherSize)
{
typedef typename NumTraits<Scalar>::Real RealScalar;
typedef Matrix<Scalar, Size, Size> MatrixType;
typedef Matrix<Scalar, Size, OtherSize> Rhs1;
typedef Matrix<Scalar, OtherSize, Size> Rhs2;
typedef Matrix<Scalar, Size, OtherSize,RowMajor> Rhs3;
int rows = size;
int cols = size;
MatrixType m1 = MatrixType::Random(rows, cols), MatrixType m1 = MatrixType::Random(rows, cols),
m2 = MatrixType::Random(rows, cols); m2 = MatrixType::Random(rows, cols);
m1 = (m1+m1.adjoint()).eval(); m1 = (m1+m1.adjoint()).eval();
Rhs1 rhs1 = Rhs1::Random(cols, ei_random<int>(1,320)), rhs12, rhs13; Rhs1 rhs1 = Rhs1::Random(cols, othersize), rhs12(cols, othersize), rhs13(cols, othersize);
Rhs2 rhs2 = Rhs2::Random(ei_random<int>(1,320), rows), rhs22, rhs23; Rhs2 rhs2 = Rhs2::Random(othersize, rows), rhs22(othersize, rows), rhs23(othersize, rows);
Rhs3 rhs3 = Rhs3::Random(cols, ei_random<int>(1,320)), rhs32, rhs33; Rhs3 rhs3 = Rhs3::Random(cols, othersize), rhs32(cols, othersize), rhs33(cols, othersize);
Scalar s1 = ei_random<Scalar>(), Scalar s1 = ei_random<Scalar>(),
s2 = ei_random<Scalar>(); s2 = ei_random<Scalar>();
@ -51,46 +69,44 @@ template<typename MatrixType> void symm(const MatrixType& m)
VERIFY_IS_APPROX(rhs12 = (s1*m2).template selfadjointView<LowerTriangular>() * (s2*rhs1), VERIFY_IS_APPROX(rhs12 = (s1*m2).template selfadjointView<LowerTriangular>() * (s2*rhs1),
rhs13 = (s1*m1) * (s2*rhs1)); rhs13 = (s1*m1) * (s2*rhs1));
m2 = m1.template triangularView<UpperTriangular>(); m2 = m1.template triangularView<UpperTriangular>(); rhs12.setRandom(); rhs13 = rhs12;
VERIFY_IS_APPROX(rhs12 = (s1*m2).template selfadjointView<UpperTriangular>() * (s2*rhs1), VERIFY_IS_APPROX(rhs12 += (s1*m2).template selfadjointView<UpperTriangular>() * (s2*rhs1),
rhs13 = (s1*m1) * (s2*rhs1)); rhs13 += (s1*m1) * (s2*rhs1));
m2 = m1.template triangularView<LowerTriangular>(); m2 = m1.template triangularView<LowerTriangular>();
VERIFY_IS_APPROX(rhs22 = (s1*m2).template selfadjointView<LowerTriangular>() * (s2*rhs2.adjoint()), VERIFY_IS_APPROX(rhs12 = (s1*m2).template selfadjointView<LowerTriangular>() * (s2*rhs2.adjoint()),
rhs23 = (s1*m1) * (s2*rhs2.adjoint())); rhs13 = (s1*m1) * (s2*rhs2.adjoint()));
m2 = m1.template triangularView<UpperTriangular>(); m2 = m1.template triangularView<UpperTriangular>();
VERIFY_IS_APPROX(rhs22 = (s1*m2).template selfadjointView<UpperTriangular>() * (s2*rhs2.adjoint()), VERIFY_IS_APPROX(rhs12 = (s1*m2).template selfadjointView<UpperTriangular>() * (s2*rhs2.adjoint()),
rhs23 = (s1*m1) * (s2*rhs2.adjoint())); rhs13 = (s1*m1) * (s2*rhs2.adjoint()));
m2 = m1.template triangularView<UpperTriangular>(); m2 = m1.template triangularView<UpperTriangular>();
VERIFY_IS_APPROX(rhs22 = (s1*m2.adjoint()).template selfadjointView<LowerTriangular>() * (s2*rhs2.adjoint()), VERIFY_IS_APPROX(rhs12 = (s1*m2.adjoint()).template selfadjointView<LowerTriangular>() * (s2*rhs2.adjoint()),
rhs23 = (s1*m1.adjoint()) * (s2*rhs2.adjoint())); rhs13 = (s1*m1.adjoint()) * (s2*rhs2.adjoint()));
// test row major = <...> // test row major = <...>
m2 = m1.template triangularView<LowerTriangular>(); m2 = m1.template triangularView<LowerTriangular>(); rhs12.setRandom(); rhs13 = rhs12;
VERIFY_IS_APPROX(rhs32 = (s1*m2).template selfadjointView<LowerTriangular>() * (s2*rhs3), VERIFY_IS_APPROX(rhs12 -= (s1*m2).template selfadjointView<LowerTriangular>() * (s2*rhs3),
rhs33 = (s1*m1) * (s2 * rhs3)); rhs13 -= (s1*m1) * (s2 * rhs3));
m2 = m1.template triangularView<UpperTriangular>(); m2 = m1.template triangularView<UpperTriangular>();
VERIFY_IS_APPROX(rhs32 = (s1*m2.adjoint()).template selfadjointView<LowerTriangular>() * (s2*rhs3).conjugate(), VERIFY_IS_APPROX(rhs12 = (s1*m2.adjoint()).template selfadjointView<LowerTriangular>() * (s2*rhs3).conjugate(),
rhs33 = (s1*m1.adjoint()) * (s2*rhs3).conjugate()); rhs13 = (s1*m1.adjoint()) * (s2*rhs3).conjugate());
// test matrix * selfadjoint // test matrix * selfadjoint
m2 = m1.template triangularView<LowerTriangular>(); symm_extra<OtherSize>::run(m1,m2,rhs2,rhs22,rhs23,s1,s2);
VERIFY_IS_APPROX(rhs22 = (rhs2) * (m2).template selfadjointView<LowerTriangular>(),
rhs23 = (rhs2) * (m1));
VERIFY_IS_APPROX(rhs22 = (s2*rhs2) * (s1*m2).template selfadjointView<LowerTriangular>(),
rhs23 = (s2*rhs2) * (s1*m1));
} }
void test_product_symm() void test_product_symm()
{ {
for(int i = 0; i < g_repeat ; i++) for(int i = 0; i < g_repeat ; i++)
{ {
int s; CALL_SUBTEST(( symm<float,Dynamic,Dynamic>(ei_random<int>(10,320),ei_random<int>(10,320)) ));
s = ei_random<int>(10,320); CALL_SUBTEST(( symm<std::complex<double>,Dynamic,Dynamic>(ei_random<int>(10,320),ei_random<int>(10,320)) ));
CALL_SUBTEST( symm(MatrixXf(s, s)) );
s = ei_random<int>(10,320); CALL_SUBTEST(( symm<float,Dynamic,1>(ei_random<int>(10,320)) ));
CALL_SUBTEST( symm(MatrixXcd(s, s)) ); CALL_SUBTEST(( symm<std::complex<double>,Dynamic,1>(ei_random<int>(10,320)) ));
} }
} }

View File

@ -46,27 +46,27 @@ template<typename MatrixType> void syrk(const MatrixType& m)
s2 = ei_random<Scalar>(); s2 = ei_random<Scalar>();
m2.setZero(); m2.setZero();
VERIFY_IS_APPROX((m2.template selfadjointView<LowerTriangular>().rankKupdate(rhs2,s1)._expression()), VERIFY_IS_APPROX((m2.template selfadjointView<LowerTriangular>().rankUpdate(rhs2,s1)._expression()),
((s1 * rhs2 * rhs2.adjoint()).eval().template triangularView<LowerTriangular>().toDense())); ((s1 * rhs2 * rhs2.adjoint()).eval().template triangularView<LowerTriangular>().toDense()));
m2.setZero(); m2.setZero();
VERIFY_IS_APPROX(m2.template selfadjointView<UpperTriangular>().rankKupdate(rhs2,s1)._expression(), VERIFY_IS_APPROX(m2.template selfadjointView<UpperTriangular>().rankUpdate(rhs2,s1)._expression(),
(s1 * rhs2 * rhs2.adjoint()).eval().template triangularView<UpperTriangular>().toDense()); (s1 * rhs2 * rhs2.adjoint()).eval().template triangularView<UpperTriangular>().toDense());
m2.setZero(); m2.setZero();
VERIFY_IS_APPROX(m2.template selfadjointView<LowerTriangular>().rankKupdate(rhs1.adjoint(),s1)._expression(), VERIFY_IS_APPROX(m2.template selfadjointView<LowerTriangular>().rankUpdate(rhs1.adjoint(),s1)._expression(),
(s1 * rhs1.adjoint() * rhs1).eval().template triangularView<LowerTriangular>().toDense()); (s1 * rhs1.adjoint() * rhs1).eval().template triangularView<LowerTriangular>().toDense());
m2.setZero(); m2.setZero();
VERIFY_IS_APPROX(m2.template selfadjointView<UpperTriangular>().rankKupdate(rhs1.adjoint(),s1)._expression(), VERIFY_IS_APPROX(m2.template selfadjointView<UpperTriangular>().rankUpdate(rhs1.adjoint(),s1)._expression(),
(s1 * rhs1.adjoint() * rhs1).eval().template triangularView<UpperTriangular>().toDense()); (s1 * rhs1.adjoint() * rhs1).eval().template triangularView<UpperTriangular>().toDense());
m2.setZero(); m2.setZero();
VERIFY_IS_APPROX(m2.template selfadjointView<LowerTriangular>().rankKupdate(rhs3.adjoint(),s1)._expression(), VERIFY_IS_APPROX(m2.template selfadjointView<LowerTriangular>().rankUpdate(rhs3.adjoint(),s1)._expression(),
(s1 * rhs3.adjoint() * rhs3).eval().template triangularView<LowerTriangular>().toDense()); (s1 * rhs3.adjoint() * rhs3).eval().template triangularView<LowerTriangular>().toDense());
m2.setZero(); m2.setZero();
VERIFY_IS_APPROX(m2.template selfadjointView<UpperTriangular>().rankKupdate(rhs3.adjoint(),s1)._expression(), VERIFY_IS_APPROX(m2.template selfadjointView<UpperTriangular>().rankUpdate(rhs3.adjoint(),s1)._expression(),
(s1 * rhs3.adjoint() * rhs3).eval().template triangularView<UpperTriangular>().toDense()); (s1 * rhs3.adjoint() * rhs3).eval().template triangularView<UpperTriangular>().toDense());
} }