mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-08-13 04:09:10 +08:00
detect and implement inplace permutations
This commit is contained in:
parent
d9ca0c0d36
commit
959a1b5d63
@ -326,21 +326,46 @@ struct ei_permut_matrix_product_retval
|
|||||||
template<typename Dest> inline void evalTo(Dest& dst) const
|
template<typename Dest> inline void evalTo(Dest& dst) const
|
||||||
{
|
{
|
||||||
const int n = Side==OnTheLeft ? rows() : cols();
|
const int n = Side==OnTheLeft ? rows() : cols();
|
||||||
for(int i = 0; i < n; ++i)
|
|
||||||
|
if(ei_is_same_type<MatrixTypeNestedCleaned,Dest>::ret && ei_extract_data(dst) == ei_extract_data(m_matrix))
|
||||||
{
|
{
|
||||||
Block<
|
// apply the permutation inplace
|
||||||
Dest,
|
Matrix<bool,PermutationType::RowsAtCompileTime,1,0,PermutationType::MaxRowsAtCompileTime> mask(m_permutation.size());
|
||||||
Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime,
|
mask.fill(false);
|
||||||
Side==OnTheRight ? 1 : Dest::ColsAtCompileTime
|
int r = 0;
|
||||||
>(dst, ((Side==OnTheLeft) ^ Transposed) ? m_permutation.indices().coeff(i) : i)
|
while(r < m_permutation.size())
|
||||||
|
{
|
||||||
|
// search for the next seed
|
||||||
|
while(r<m_permutation.size() && mask[r]) r++;
|
||||||
|
if(r>=m_permutation.size())
|
||||||
|
break;
|
||||||
|
// we got one, let's follow it until we are back to the seed
|
||||||
|
int k0 = r++;
|
||||||
|
int kPrev = k0;
|
||||||
|
mask.coeffRef(k0) = true;
|
||||||
|
for(int k=m_permutation.indices().coeff(k0); k!=k0; k=m_permutation.indices().coeff(k))
|
||||||
|
{
|
||||||
|
Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime>(dst, k)
|
||||||
|
.swap(Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime>
|
||||||
|
(dst,((Side==OnTheLeft) ^ Transposed) ? k0 : kPrev));
|
||||||
|
|
||||||
=
|
mask.coeffRef(k) = true;
|
||||||
|
kPrev = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(int i = 0; i < n; ++i)
|
||||||
|
{
|
||||||
|
Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime>
|
||||||
|
(dst, ((Side==OnTheLeft) ^ Transposed) ? m_permutation.indices().coeff(i) : i)
|
||||||
|
|
||||||
Block<
|
=
|
||||||
MatrixTypeNestedCleaned,
|
|
||||||
Side==OnTheLeft ? 1 : MatrixType::RowsAtCompileTime,
|
Block<MatrixTypeNestedCleaned,Side==OnTheLeft ? 1 : MatrixType::RowsAtCompileTime,Side==OnTheRight ? 1 : MatrixType::ColsAtCompileTime>
|
||||||
Side==OnTheRight ? 1 : MatrixType::ColsAtCompileTime
|
(m_matrix, ((Side==OnTheRight) ^ Transposed) ? m_permutation.indices().coeff(i) : i);
|
||||||
>(m_matrix, ((Side==OnTheRight) ^ Transposed) ? m_permutation.indices().coeff(i) : i);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,25 +295,6 @@ struct ei_blas_traits<SelfCwiseBinaryOp<BinOp,NestedXpr> >
|
|||||||
static inline const XprType extract(const XprType& x) { return x; }
|
static inline const XprType extract(const XprType& x) { return x; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template<typename T, int Access=ei_blas_traits<T>::ActualAccess>
|
|
||||||
struct ei_extract_data_selector {
|
|
||||||
static typename T::Scalar* run(const T& m)
|
|
||||||
{
|
|
||||||
return &ei_blas_traits<T>::extract(m).const_cast_derived().coeffRef(0,0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct ei_extract_data_selector<T,NoDirectAccess> {
|
|
||||||
static typename T::Scalar* run(const T&) { return 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T> typename T::Scalar* ei_extract_data(const T& m)
|
|
||||||
{
|
|
||||||
return ei_extract_data_selector<T>::run(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Scalar, bool DestIsTranposed, typename OtherDerived>
|
template<typename Scalar, bool DestIsTranposed, typename OtherDerived>
|
||||||
struct ei_check_transpose_aliasing_selector
|
struct ei_check_transpose_aliasing_selector
|
||||||
{
|
{
|
||||||
|
@ -236,4 +236,22 @@ struct ei_blas_traits<Transpose<NestedXpr> >
|
|||||||
static inline Scalar extractScalarFactor(const XprType& x) { return Base::extractScalarFactor(x.nestedExpression()); }
|
static inline Scalar extractScalarFactor(const XprType& x) { return Base::extractScalarFactor(x.nestedExpression()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T, int Access=ei_blas_traits<T>::ActualAccess>
|
||||||
|
struct ei_extract_data_selector {
|
||||||
|
static const typename T::Scalar* run(const T& m)
|
||||||
|
{
|
||||||
|
return &ei_blas_traits<T>::extract(m).const_cast_derived().coeffRef(0,0); // FIXME this should be .data()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct ei_extract_data_selector<T,NoDirectAccess> {
|
||||||
|
static typename T::Scalar* run(const T&) { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> const typename T::Scalar* ei_extract_data(const T& m)
|
||||||
|
{
|
||||||
|
return ei_extract_data_selector<T>::run(m);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // EIGEN_BLASUTIL_H
|
#endif // EIGEN_BLASUTIL_H
|
||||||
|
@ -119,7 +119,7 @@ template<typename _MatrixType> class FullPivLU
|
|||||||
* diagonal coefficient of U.
|
* diagonal coefficient of U.
|
||||||
*/
|
*/
|
||||||
RealScalar maxPivot() const { return m_maxpivot; }
|
RealScalar maxPivot() const { return m_maxpivot; }
|
||||||
|
|
||||||
/** \returns the permutation matrix P
|
/** \returns the permutation matrix P
|
||||||
*
|
*
|
||||||
* \sa permutationQ()
|
* \sa permutationQ()
|
||||||
@ -506,12 +506,10 @@ MatrixType FullPivLU<MatrixType>::reconstructedMatrix() const
|
|||||||
.template triangularView<Upper>().toDenseMatrix();
|
.template triangularView<Upper>().toDenseMatrix();
|
||||||
|
|
||||||
// P^{-1}(LU)
|
// P^{-1}(LU)
|
||||||
// FIXME implement inplace permutation
|
res = m_p.inverse() * res;
|
||||||
res = (m_p.inverse() * res).eval();
|
|
||||||
|
|
||||||
// (P^{-1}LU)Q^{-1}
|
// (P^{-1}LU)Q^{-1}
|
||||||
// FIXME implement inplace permutation
|
res = res * m_q.inverse();
|
||||||
res = (res * m_q.inverse()).eval();
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -412,10 +412,9 @@ MatrixType PartialPivLU<MatrixType>::reconstructedMatrix() const
|
|||||||
// LU
|
// LU
|
||||||
MatrixType res = m_lu.template triangularView<UnitLower>().toDenseMatrix()
|
MatrixType res = m_lu.template triangularView<UnitLower>().toDenseMatrix()
|
||||||
* m_lu.template triangularView<Upper>();
|
* m_lu.template triangularView<Upper>();
|
||||||
|
|
||||||
// P^{-1}(LU)
|
// P^{-1}(LU)
|
||||||
// FIXME implement inplace permutation
|
res = m_p.inverse() * res;
|
||||||
res = (m_p.inverse() * res).eval();
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,23 @@ template<typename MatrixType> void permutationmatrices(const MatrixType& m)
|
|||||||
identityp.setIdentity(rows);
|
identityp.setIdentity(rows);
|
||||||
VERIFY_IS_APPROX(m_original, identityp*m_original);
|
VERIFY_IS_APPROX(m_original, identityp*m_original);
|
||||||
|
|
||||||
|
// check inplace permutations
|
||||||
|
m_permuted = m_original;
|
||||||
|
m_permuted = lp.inverse() * m_permuted;
|
||||||
|
VERIFY_IS_APPROX(m_permuted, lp.inverse()*m_original);
|
||||||
|
|
||||||
|
m_permuted = m_original;
|
||||||
|
m_permuted = m_permuted * rp.inverse();
|
||||||
|
VERIFY_IS_APPROX(m_permuted, m_original*rp.inverse());
|
||||||
|
|
||||||
|
m_permuted = m_original;
|
||||||
|
m_permuted = lp * m_permuted;
|
||||||
|
VERIFY_IS_APPROX(m_permuted, lp*m_original);
|
||||||
|
|
||||||
|
m_permuted = m_original;
|
||||||
|
m_permuted = m_permuted * rp;
|
||||||
|
VERIFY_IS_APPROX(m_permuted, m_original*rp);
|
||||||
|
|
||||||
if(rows>1 && cols>1)
|
if(rows>1 && cols>1)
|
||||||
{
|
{
|
||||||
lp2 = lp;
|
lp2 = lp;
|
||||||
@ -114,7 +131,7 @@ void test_permutationmatrices()
|
|||||||
CALL_SUBTEST_2( permutationmatrices(Matrix3f()) );
|
CALL_SUBTEST_2( permutationmatrices(Matrix3f()) );
|
||||||
CALL_SUBTEST_3( permutationmatrices(Matrix<double,3,3,RowMajor>()) );
|
CALL_SUBTEST_3( permutationmatrices(Matrix<double,3,3,RowMajor>()) );
|
||||||
CALL_SUBTEST_4( permutationmatrices(Matrix4d()) );
|
CALL_SUBTEST_4( permutationmatrices(Matrix4d()) );
|
||||||
CALL_SUBTEST_5( permutationmatrices(Matrix<double,4,6>()) );
|
CALL_SUBTEST_5( permutationmatrices(Matrix<double,40,60>()) );
|
||||||
CALL_SUBTEST_6( permutationmatrices(Matrix<double,Dynamic,Dynamic,RowMajor>(20, 30)) );
|
CALL_SUBTEST_6( permutationmatrices(Matrix<double,Dynamic,Dynamic,RowMajor>(20, 30)) );
|
||||||
CALL_SUBTEST_7( permutationmatrices(MatrixXcf(15, 10)) );
|
CALL_SUBTEST_7( permutationmatrices(MatrixXcf(15, 10)) );
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user