mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-01-06 14:14:46 +08:00
Refactor triangular assignment
This commit is contained in:
parent
fef534f52e
commit
5fa7262e4c
@ -140,6 +140,7 @@ public:
|
||||
template<typename Kernel, int Index, int Stop>
|
||||
struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling
|
||||
{
|
||||
// FIXME: this is not very clean, perhaps this information should be provided by the kernel?
|
||||
typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
|
||||
typedef typename DstEvaluatorType::XprType DstXprType;
|
||||
|
||||
@ -204,9 +205,10 @@ struct copy_using_evaluator_LinearTraversal_CompleteUnrolling<Kernel, Stop, Stop
|
||||
template<typename Kernel, int Index, int Stop>
|
||||
struct copy_using_evaluator_innervec_CompleteUnrolling
|
||||
{
|
||||
// FIXME: this is not very clean, perhaps this information should be provided by the kernel?
|
||||
typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
|
||||
typedef typename DstEvaluatorType::XprType DstXprType;
|
||||
|
||||
|
||||
enum {
|
||||
outer = Index / DstXprType::InnerSizeAtCompileTime,
|
||||
inner = Index % DstXprType::InnerSizeAtCompileTime,
|
||||
@ -233,8 +235,7 @@ struct copy_using_evaluator_innervec_InnerUnrolling
|
||||
static EIGEN_STRONG_INLINE void run(Kernel &kernel, int outer)
|
||||
{
|
||||
kernel.template assignPacketByOuterInner<Aligned, Aligned>(outer, Index);
|
||||
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
|
||||
enum { NextIndex = Index + packet_traits<typename DstXprType::Scalar>::size };
|
||||
enum { NextIndex = Index + packet_traits<typename Kernel::Scalar>::size };
|
||||
copy_using_evaluator_innervec_InnerUnrolling<Kernel, NextIndex, Stop>::run(kernel, outer);
|
||||
}
|
||||
};
|
||||
@ -542,12 +543,6 @@ public:
|
||||
m_functor.assignCoeff(m_dst.coeffRef(row,col), m_src.coeff(row,col));
|
||||
}
|
||||
|
||||
/// This overload by-passes the source expression, i.e., dst(row,col) ?= value
|
||||
void assignCoeff(Index row, Index col, const Scalar &value)
|
||||
{
|
||||
m_functor.assignCoeff(m_dst.coeffRef(row,col), value);
|
||||
}
|
||||
|
||||
/// \sa assignCoeff(Index,Index)
|
||||
void assignCoeff(Index index)
|
||||
{
|
||||
|
@ -244,6 +244,8 @@ template<typename _MatrixType, unsigned int UpLo> class SelfAdjointView
|
||||
|
||||
namespace internal {
|
||||
|
||||
#ifndef EIGEN_TEST_EVALUATORS
|
||||
|
||||
template<typename Derived1, typename Derived2, int UnrollCount, bool ClearOpposite>
|
||||
struct triangular_assignment_selector<Derived1, Derived2, (SelfAdjoint|Upper), UnrollCount, ClearOpposite>
|
||||
{
|
||||
@ -336,6 +338,8 @@ struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Lower, Dyn
|
||||
}
|
||||
};
|
||||
|
||||
#endif // EIGEN_TEST_EVALUATORS
|
||||
|
||||
#ifdef EIGEN_ENABLE_EVALUATORS
|
||||
// TODO currently a selfadjoint expression has the form SelfAdjointView<.,.>
|
||||
// in the future selfadjoint-ness should be defined by the expression traits
|
||||
@ -348,6 +352,7 @@ struct evaluator_traits<SelfAdjointView<MatrixType,Mode> >
|
||||
|
||||
static const int AssumeAliasing = 0;
|
||||
};
|
||||
|
||||
#endif // EIGEN_ENABLE_EVALUATORS
|
||||
|
||||
} // end namespace internal
|
||||
|
@ -148,6 +148,7 @@ template<typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT>
|
||||
class generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, swap_assign_op<typename DstEvaluatorTypeT::Scalar>, Specialized>
|
||||
: public generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, swap_assign_op<typename DstEvaluatorTypeT::Scalar>, BuiltIn>
|
||||
{
|
||||
protected:
|
||||
typedef generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, swap_assign_op<typename DstEvaluatorTypeT::Scalar>, BuiltIn> Base;
|
||||
typedef typename DstEvaluatorTypeT::PacketScalar PacketScalar;
|
||||
using Base::m_dst;
|
||||
|
@ -298,8 +298,8 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
|
||||
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
void lazyAssign(const MatrixBase<OtherDerived>& other);
|
||||
|
||||
void lazyAssign(const MatrixBase<OtherDerived>& other);
|
||||
|
||||
/** \sa MatrixBase::conjugate() */
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline TriangularView<MatrixConjugateReturnType,Mode> conjugate()
|
||||
@ -469,6 +469,8 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
|
||||
return m_matrix.diagonal().prod();
|
||||
}
|
||||
|
||||
#ifndef EIGEN_TEST_EVALUATORS
|
||||
|
||||
// TODO simplify the following:
|
||||
template<typename ProductDerived, typename Lhs, typename Rhs>
|
||||
EIGEN_DEVICE_FUNC
|
||||
@ -514,7 +516,9 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
|
||||
{
|
||||
return assignProduct(other,-other.alpha());
|
||||
}
|
||||
|
||||
|
||||
#endif // EIGEN_TEST_EVALUATORS
|
||||
|
||||
protected:
|
||||
|
||||
template<typename ProductDerived, typename Lhs, typename Rhs>
|
||||
@ -530,6 +534,8 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
|
||||
|
||||
namespace internal {
|
||||
|
||||
#ifndef EIGEN_TEST_EVALUATORS
|
||||
|
||||
template<typename Derived1, typename Derived2, unsigned int Mode, int UnrollCount, bool ClearOpposite>
|
||||
struct triangular_assignment_selector
|
||||
{
|
||||
@ -694,8 +700,52 @@ struct triangular_assignment_selector<Derived1, Derived2, UnitLower, Dynamic, Cl
|
||||
}
|
||||
};
|
||||
|
||||
#endif // EIGEN_TEST_EVALUATORS
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
#ifdef EIGEN_TEST_EVALUATORS
|
||||
|
||||
// FIXME should we keep that possibility
|
||||
template<typename MatrixType, unsigned int Mode>
|
||||
template<typename OtherDerived>
|
||||
inline TriangularView<MatrixType, Mode>&
|
||||
TriangularView<MatrixType, Mode>::operator=(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
internal::call_assignment(*this, other.template triangularView<Mode>(), internal::assign_op<Scalar>());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FIXME should we keep that possibility
|
||||
template<typename MatrixType, unsigned int Mode>
|
||||
template<typename OtherDerived>
|
||||
void TriangularView<MatrixType, Mode>::lazyAssign(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
internal::call_assignment(this->noalias(), other.template triangularView<Mode>());
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename MatrixType, unsigned int Mode>
|
||||
template<typename OtherDerived>
|
||||
inline TriangularView<MatrixType, Mode>&
|
||||
TriangularView<MatrixType, Mode>::operator=(const TriangularBase<OtherDerived>& other)
|
||||
{
|
||||
eigen_assert(Mode == int(OtherDerived::Mode));
|
||||
internal::call_assignment(*this, other.derived());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename MatrixType, unsigned int Mode>
|
||||
template<typename OtherDerived>
|
||||
void TriangularView<MatrixType, Mode>::lazyAssign(const TriangularBase<OtherDerived>& other)
|
||||
{
|
||||
eigen_assert(Mode == int(OtherDerived::Mode));
|
||||
internal::call_assignment(this->noalias(), other.derived());
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// FIXME should we keep that possibility
|
||||
template<typename MatrixType, unsigned int Mode>
|
||||
template<typename OtherDerived>
|
||||
@ -770,6 +820,8 @@ void TriangularView<MatrixType, Mode>::lazyAssign(const TriangularBase<OtherDeri
|
||||
>::run(m_matrix.const_cast_derived(), other.derived().nestedExpression());
|
||||
}
|
||||
|
||||
#endif // EIGEN_TEST_EVALUATORS
|
||||
|
||||
/***************************************************************************
|
||||
* Implementation of TriangularBase methods
|
||||
***************************************************************************/
|
||||
@ -790,6 +842,8 @@ void TriangularBase<Derived>::evalTo(MatrixBase<DenseDerived> &other) const
|
||||
evalToLazy(other.derived());
|
||||
}
|
||||
|
||||
#ifndef EIGEN_TEST_EVALUATORS
|
||||
|
||||
/** Assigns a triangular or selfadjoint matrix to a dense matrix.
|
||||
* If the matrix is triangular, the opposite part is set to zero. */
|
||||
template<typename Derived>
|
||||
@ -811,6 +865,8 @@ void TriangularBase<Derived>::evalToLazy(MatrixBase<DenseDerived> &other) const
|
||||
>::run(other.derived(), derived().nestedExpression());
|
||||
}
|
||||
|
||||
#endif // EIGEN_TEST_EVALUATORS
|
||||
|
||||
/***************************************************************************
|
||||
* Implementation of TriangularView methods
|
||||
***************************************************************************/
|
||||
@ -962,15 +1018,15 @@ struct evaluator_traits<TriangularView<MatrixType,Mode> >
|
||||
|
||||
template<typename MatrixType, unsigned int Mode, typename Kind>
|
||||
struct evaluator<TriangularView<MatrixType,Mode>, Kind, typename MatrixType::Scalar>
|
||||
: evaluator<MatrixType>
|
||||
: evaluator<typename internal::remove_all<MatrixType>::type>
|
||||
{
|
||||
typedef TriangularView<MatrixType,Mode> XprType;
|
||||
typedef evaluator<MatrixType> Base;
|
||||
typedef evaluator<typename internal::remove_all<MatrixType>::type> Base;
|
||||
typedef evaluator type;
|
||||
evaluator(const XprType &xpr) : Base(xpr.nestedExpression()) {}
|
||||
};
|
||||
|
||||
// Additional assignement kinds:
|
||||
// Additional assignment kinds:
|
||||
struct Triangular2Triangular {};
|
||||
struct Triangular2Dense {};
|
||||
struct Dense2Triangular {};
|
||||
@ -978,6 +1034,59 @@ struct Dense2Triangular {};
|
||||
|
||||
template<typename Kernel, unsigned int Mode, int UnrollCount, bool ClearOpposite> struct triangular_assignment_loop;
|
||||
|
||||
|
||||
// Specialization of the dense assignment kernel for triangular matrices.
|
||||
// The main additions are:
|
||||
// - An overload of assignCoeff(i, j, val) that by-passes the source expression. Needed to set the opposite triangular part to 0.
|
||||
// - When calling assignCoeff(i,j...), we guarantee that i!=j
|
||||
// - New assignDiagonalCoeff(i), and assignDiagonalCoeff(i, val) for assigning coefficients on the diagonal.
|
||||
template<int Mode, int ClearOpposite, typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT, typename Functor, int Version = Specialized>
|
||||
class triangular_dense_assignment_kernel : public generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, Version>
|
||||
{
|
||||
protected:
|
||||
typedef generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, Version> Base;
|
||||
typedef typename Base::DstXprType DstXprType;
|
||||
typedef typename Base::SrcXprType SrcXprType;
|
||||
using Base::m_dst;
|
||||
using Base::m_src;
|
||||
using Base::m_functor;
|
||||
public:
|
||||
|
||||
typedef typename Base::DstEvaluatorType DstEvaluatorType;
|
||||
typedef typename Base::SrcEvaluatorType SrcEvaluatorType;
|
||||
typedef typename Base::Scalar Scalar;
|
||||
typedef typename Base::Index Index;
|
||||
typedef typename Base::AssignmentTraits AssignmentTraits;
|
||||
|
||||
|
||||
triangular_dense_assignment_kernel(DstEvaluatorType &dst, const SrcEvaluatorType &src, const Functor &func, DstXprType& dstExpr)
|
||||
: Base(dst, src, func, dstExpr)
|
||||
{}
|
||||
|
||||
#ifdef EIGEN_INTERNAL_DEBUGGING
|
||||
void assignCoeff(Index row, Index col)
|
||||
{
|
||||
eigen_internal_assert(row!=col);
|
||||
Base::assignCoeff(row,col);
|
||||
}
|
||||
#else
|
||||
using Base::assignCoeff;
|
||||
#endif
|
||||
|
||||
void assignDiagonalCoeff(Index id)
|
||||
{
|
||||
if((Mode&UnitDiag) && ClearOpposite) m_functor.assignCoeff(m_dst.coeffRef(id,id), Scalar(1));
|
||||
else if((Mode&ZeroDiag) && ClearOpposite) m_functor.assignCoeff(m_dst.coeffRef(id,id), Scalar(0));
|
||||
else if((Mode&(UnitDiag|ZeroDiag))==0) Base::assignCoeff(id,id);
|
||||
}
|
||||
|
||||
void assignOppositeCoeff(Index row, Index col)
|
||||
{
|
||||
eigen_internal_assert(row!=col);
|
||||
if(ClearOpposite)
|
||||
m_functor.assignCoeff(m_dst.coeffRef(row,col), Scalar(0));
|
||||
}
|
||||
};
|
||||
|
||||
template<int Mode, bool ClearOpposite, typename DstXprType, typename SrcXprType, typename Functor>
|
||||
void call_triangular_assignment_loop(const DstXprType& dst, const SrcXprType& src, const Functor &func)
|
||||
@ -994,13 +1103,13 @@ void call_triangular_assignment_loop(const DstXprType& dst, const SrcXprType& sr
|
||||
DstEvaluatorType dstEvaluator(dst);
|
||||
SrcEvaluatorType srcEvaluator(src);
|
||||
|
||||
typedef generic_dense_assignment_kernel<DstEvaluatorType,SrcEvaluatorType,Functor> Kernel;
|
||||
typedef triangular_dense_assignment_kernel<Mode,ClearOpposite,DstEvaluatorType,SrcEvaluatorType,Functor> Kernel;
|
||||
Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
|
||||
|
||||
enum {
|
||||
unroll = DstXprType::SizeAtCompileTime != Dynamic
|
||||
&& internal::traits<SrcXprType>::CoeffReadCost != Dynamic
|
||||
&& DstXprType::SizeAtCompileTime * internal::traits<SrcXprType>::CoeffReadCost / 2 <= EIGEN_UNROLLING_LIMIT
|
||||
// && internal::traits<SrcXprType>::CoeffReadCost != Dynamic
|
||||
// && DstXprType::SizeAtCompileTime * internal::traits<SrcXprType>::CoeffReadCost / 2 <= EIGEN_UNROLLING_LIMIT
|
||||
};
|
||||
|
||||
triangular_assignment_loop<Kernel, Mode, unroll ? int(DstXprType::SizeAtCompileTime) : Dynamic, ClearOpposite>::run(kernel);
|
||||
@ -1050,9 +1159,13 @@ struct Assignment<DstXprType, SrcXprType, Functor, Dense2Triangular, Scalar>
|
||||
template<typename Kernel, unsigned int Mode, int UnrollCount, bool ClearOpposite>
|
||||
struct triangular_assignment_loop
|
||||
{
|
||||
// FIXME: this is not very clean, perhaps this information should be provided by the kernel?
|
||||
typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
|
||||
typedef typename DstEvaluatorType::XprType DstXprType;
|
||||
|
||||
enum {
|
||||
col = (UnrollCount-1) / Kernel::DstEvaluatorType::RowsAtCompileTime,
|
||||
row = (UnrollCount-1) % Kernel::DstEvaluatorType::RowsAtCompileTime
|
||||
col = (UnrollCount-1) / DstXprType::RowsAtCompileTime,
|
||||
row = (UnrollCount-1) % DstXprType::RowsAtCompileTime
|
||||
};
|
||||
|
||||
typedef typename Kernel::Scalar Scalar;
|
||||
@ -1061,24 +1174,13 @@ struct triangular_assignment_loop
|
||||
static inline void run(Kernel &kernel)
|
||||
{
|
||||
triangular_assignment_loop<Kernel, Mode, UnrollCount-1, ClearOpposite>::run(kernel);
|
||||
|
||||
// TODO should be a static assert
|
||||
eigen_assert( Mode == Upper || Mode == Lower
|
||||
|| Mode == StrictlyUpper || Mode == StrictlyLower
|
||||
|| Mode == UnitUpper || Mode == UnitLower);
|
||||
|
||||
if((Mode == Upper && row <= col)
|
||||
|| (Mode == Lower && row >= col)
|
||||
|| (Mode == StrictlyUpper && row < col)
|
||||
|| (Mode == StrictlyLower && row > col)
|
||||
|| (Mode == UnitUpper && row < col)
|
||||
|| (Mode == UnitLower && row > col))
|
||||
kernel.assignCoeff(row, col);
|
||||
else if(ClearOpposite)
|
||||
{
|
||||
if((Mode&UnitDiag) && row==col) kernel.assignCoeff(row, col, Scalar(1));
|
||||
else kernel.assignCoeff(row, col, Scalar(0));
|
||||
}
|
||||
if(row==col)
|
||||
kernel.assignDiagonalCoeff(row);
|
||||
else if( ((Mode&Lower) && row>col) || ((Mode&Upper) && row<col) )
|
||||
kernel.assignCoeff(row,col);
|
||||
else
|
||||
kernel.assignOppositeCoeff(row,col);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1090,94 +1192,14 @@ struct triangular_assignment_loop<Kernel, Mode, 0, ClearOpposite>
|
||||
static inline void run(Kernel &) {}
|
||||
};
|
||||
|
||||
// TODO: merge the following 6 variants into a single one (or max two),
|
||||
// and perhaps write them using sub-expressions
|
||||
|
||||
// TODO: expreiment with a recursive assignment procedure splitting the current
|
||||
|
||||
// TODO: experiment with a recursive assignment procedure splitting the current
|
||||
// triangular part into one rectangular and two triangular parts.
|
||||
|
||||
template<typename Kernel, bool ClearOpposite>
|
||||
struct triangular_assignment_loop<Kernel, Upper, Dynamic, ClearOpposite>
|
||||
{
|
||||
typedef typename Kernel::Index Index;
|
||||
typedef typename Kernel::Scalar Scalar;
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline void run(Kernel &kernel)
|
||||
{
|
||||
for(Index j = 0; j < kernel.cols(); ++j)
|
||||
{
|
||||
Index maxi = (std::min)(j, kernel.rows()-1);
|
||||
for(Index i = 0; i <= maxi; ++i)
|
||||
kernel.assignCoeff(i, j);
|
||||
if (ClearOpposite)
|
||||
for(Index i = maxi+1; i < kernel.rows(); ++i)
|
||||
kernel.assignCoeff(i, j, Scalar(0));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Kernel, bool ClearOpposite>
|
||||
struct triangular_assignment_loop<Kernel, Lower, Dynamic, ClearOpposite>
|
||||
{
|
||||
typedef typename Kernel::Index Index;
|
||||
typedef typename Kernel::Scalar Scalar;
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline void run(Kernel &kernel)
|
||||
{
|
||||
for(Index j = 0; j < kernel.cols(); ++j)
|
||||
{
|
||||
for(Index i = j; i < kernel.rows(); ++i)
|
||||
kernel.assignCoeff(i, j);
|
||||
Index maxi = (std::min)(j, kernel.rows());
|
||||
if (ClearOpposite)
|
||||
for(Index i = 0; i < maxi; ++i)
|
||||
kernel.assignCoeff(i, j, Scalar(0));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Kernel, bool ClearOpposite>
|
||||
struct triangular_assignment_loop<Kernel, StrictlyUpper, Dynamic, ClearOpposite>
|
||||
{
|
||||
typedef typename Kernel::Index Index;
|
||||
typedef typename Kernel::Scalar Scalar;
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline void run(Kernel &kernel)
|
||||
{
|
||||
for(Index j = 0; j < kernel.cols(); ++j)
|
||||
{
|
||||
Index maxi = (std::min)(j, kernel.rows());
|
||||
for(Index i = 0; i < maxi; ++i)
|
||||
kernel.assignCoeff(i, j);
|
||||
if (ClearOpposite)
|
||||
for(Index i = maxi; i < kernel.rows(); ++i)
|
||||
kernel.assignCoeff(i, j, Scalar(0));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Kernel, bool ClearOpposite>
|
||||
struct triangular_assignment_loop<Kernel, StrictlyLower, Dynamic, ClearOpposite>
|
||||
{
|
||||
typedef typename Kernel::Index Index;
|
||||
typedef typename Kernel::Scalar Scalar;
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline void run(Kernel &kernel)
|
||||
{
|
||||
for(Index j = 0; j < kernel.cols(); ++j)
|
||||
{
|
||||
for(Index i = j+1; i < kernel.rows(); ++i)
|
||||
kernel.assignCoeff(i, j);
|
||||
Index maxi = (std::min)(j, kernel.rows()-1);
|
||||
if (ClearOpposite)
|
||||
for(Index i = 0; i <= maxi; ++i)
|
||||
kernel.assignCoeff(i, j, Scalar(0));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Kernel, bool ClearOpposite>
|
||||
struct triangular_assignment_loop<Kernel, UnitUpper, Dynamic, ClearOpposite>
|
||||
template<typename Kernel, unsigned int Mode, bool ClearOpposite>
|
||||
struct triangular_assignment_loop<Kernel, Mode, Dynamic, ClearOpposite>
|
||||
{
|
||||
typedef typename Kernel::Index Index;
|
||||
typedef typename Kernel::Scalar Scalar;
|
||||
@ -1188,50 +1210,41 @@ struct triangular_assignment_loop<Kernel, UnitUpper, Dynamic, ClearOpposite>
|
||||
{
|
||||
Index maxi = (std::min)(j, kernel.rows());
|
||||
Index i = 0;
|
||||
for(; i < maxi; ++i)
|
||||
kernel.assignCoeff(i, j);
|
||||
|
||||
if(i<kernel.rows()) // then i==j
|
||||
kernel.assignCoeff(i++, j, Scalar(1));
|
||||
|
||||
if (ClearOpposite)
|
||||
{
|
||||
for(; i < kernel.rows(); ++i)
|
||||
kernel.assignCoeff(i, j, Scalar(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
template<typename Kernel, bool ClearOpposite>
|
||||
struct triangular_assignment_loop<Kernel, UnitLower, Dynamic, ClearOpposite>
|
||||
{
|
||||
typedef typename Kernel::Index Index;
|
||||
typedef typename Kernel::Scalar Scalar;
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline void run(Kernel &kernel)
|
||||
{
|
||||
for(Index j = 0; j < kernel.cols(); ++j)
|
||||
{
|
||||
Index maxi = (std::min)(j, kernel.rows());
|
||||
Index i = 0;
|
||||
if (ClearOpposite)
|
||||
if (((Mode&Lower) && ClearOpposite) || (Mode&Upper))
|
||||
{
|
||||
for(; i < maxi; ++i)
|
||||
kernel.assignCoeff(i, j, Scalar(0));
|
||||
if(Mode&Upper) kernel.assignCoeff(i, j);
|
||||
else kernel.assignOppositeCoeff(i, j);
|
||||
}
|
||||
else
|
||||
i = maxi;
|
||||
|
||||
if(i<kernel.rows()) // then i==j
|
||||
kernel.assignCoeff(i++, j, Scalar(1));
|
||||
kernel.assignDiagonalCoeff(i++);
|
||||
|
||||
for(; i < kernel.rows(); ++i)
|
||||
kernel.assignCoeff(i, j);
|
||||
if (((Mode&Upper) && ClearOpposite) || (Mode&Lower))
|
||||
{
|
||||
for(; i < kernel.rows(); ++i)
|
||||
if(Mode&Lower) kernel.assignCoeff(i, j);
|
||||
else kernel.assignOppositeCoeff(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
#endif
|
||||
/** Assigns a triangular or selfadjoint matrix to a dense matrix.
|
||||
* If the matrix is triangular, the opposite part is set to zero. */
|
||||
template<typename Derived>
|
||||
template<typename DenseDerived>
|
||||
void TriangularBase<Derived>::evalToLazy(MatrixBase<DenseDerived> &other) const
|
||||
{
|
||||
other.derived().resize(this->rows(), this->cols());
|
||||
internal::call_triangular_assignment_loop<Derived::Mode,true /* ClearOpposite */>(other.derived(), derived().nestedExpression());
|
||||
}
|
||||
|
||||
#endif // EIGEN_ENABLE_EVALUATORS
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user