mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7abf6d02db | ||
|
|
73cb54835c | ||
|
|
cfe315476f | ||
|
|
f1583e86f6 | ||
|
|
4bd69750ed | ||
|
|
d40e32c94e | ||
|
|
a0bf1b4242 | ||
|
|
cf645db95b | ||
|
|
13135a82bd | ||
|
|
769cb99845 | ||
|
|
ba9add3c59 | ||
|
|
ddfb72a92f | ||
|
|
8c7e281c9e | ||
|
|
66c092e44e | ||
|
|
3ec6d38f35 | ||
|
|
96f64441f7 | ||
|
|
5af4d77511 | ||
|
|
88ac8ffad5 | ||
|
|
edb0183e0c | ||
|
|
befa141699 | ||
|
|
5c70b43abd | ||
|
|
6a3797f46f | ||
|
|
c4432aad15 | ||
|
|
ea0168c5a5 | ||
|
|
05fad4959a | ||
|
|
98eedb0c9a | ||
|
|
71424c4bf8 | ||
|
|
e59b246b08 | ||
|
|
4aa7038074 |
@@ -464,7 +464,7 @@ LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const MatrixType& a)
|
|||||||
*/
|
*/
|
||||||
template<typename MatrixType, int _UpLo>
|
template<typename MatrixType, int _UpLo>
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Derived>& w, const typename NumTraits<typename MatrixType::Scalar>::Real& sigma)
|
LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Derived>& w, const typename LDLT<MatrixType,_UpLo>::RealScalar& sigma)
|
||||||
{
|
{
|
||||||
const Index size = w.rows();
|
const Index size = w.rows();
|
||||||
if (m_isInitialized)
|
if (m_isInitialized)
|
||||||
|
|||||||
@@ -449,7 +449,7 @@ struct assign_impl<Derived1, Derived2, SliceVectorizedTraversal, NoUnrolling, Ve
|
|||||||
srcAlignment = assign_traits<Derived1,Derived2>::JointAlignment
|
srcAlignment = assign_traits<Derived1,Derived2>::JointAlignment
|
||||||
};
|
};
|
||||||
const Scalar *dst_ptr = &dst.coeffRef(0,0);
|
const Scalar *dst_ptr = &dst.coeffRef(0,0);
|
||||||
if((!bool(dstIsAligned)) && (Index(dst_ptr) % sizeof(Scalar))>0)
|
if((!bool(dstIsAligned)) && (size_t(dst_ptr) % sizeof(Scalar))>0)
|
||||||
{
|
{
|
||||||
// the pointer is not aligend-on scalar, so alignment is not possible
|
// the pointer is not aligend-on scalar, so alignment is not possible
|
||||||
return assign_impl<Derived1,Derived2,DefaultTraversal,NoUnrolling>::run(dst, src);
|
return assign_impl<Derived1,Derived2,DefaultTraversal,NoUnrolling>::run(dst, src);
|
||||||
|
|||||||
@@ -183,10 +183,6 @@ template<typename Derived> class DenseBase
|
|||||||
/** \returns the number of nonzero coefficients which is in practice the number
|
/** \returns the number of nonzero coefficients which is in practice the number
|
||||||
* of stored coefficients. */
|
* of stored coefficients. */
|
||||||
inline Index nonZeros() const { return size(); }
|
inline Index nonZeros() const { return size(); }
|
||||||
/** \returns true if either the number of rows or the number of columns is equal to 1.
|
|
||||||
* In other words, this function returns
|
|
||||||
* \code rows()==1 || cols()==1 \endcode
|
|
||||||
* \sa rows(), cols(), IsVectorAtCompileTime. */
|
|
||||||
|
|
||||||
/** \returns the outer size.
|
/** \returns the outer size.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ template<typename Lhs, typename Rhs>
|
|||||||
class GeneralProduct<Lhs, Rhs, OuterProduct>
|
class GeneralProduct<Lhs, Rhs, OuterProduct>
|
||||||
: public ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs>
|
: public ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs>
|
||||||
{
|
{
|
||||||
template<typename T> struct IsRowMajor : internal::conditional<(int(T::Flags)&RowMajorBit), internal::true_type, internal::false_type>::type {};
|
template<typename T> struct is_row_major : internal::conditional<(int(T::Flags)&RowMajorBit), internal::true_type, internal::false_type>::type {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
|
EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
|
||||||
@@ -281,22 +281,22 @@ class GeneralProduct<Lhs, Rhs, OuterProduct>
|
|||||||
|
|
||||||
template<typename Dest>
|
template<typename Dest>
|
||||||
inline void evalTo(Dest& dest) const {
|
inline void evalTo(Dest& dest) const {
|
||||||
internal::outer_product_selector_run(*this, dest, set(), IsRowMajor<Dest>());
|
internal::outer_product_selector_run(*this, dest, set(), is_row_major<Dest>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Dest>
|
template<typename Dest>
|
||||||
inline void addTo(Dest& dest) const {
|
inline void addTo(Dest& dest) const {
|
||||||
internal::outer_product_selector_run(*this, dest, add(), IsRowMajor<Dest>());
|
internal::outer_product_selector_run(*this, dest, add(), is_row_major<Dest>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Dest>
|
template<typename Dest>
|
||||||
inline void subTo(Dest& dest) const {
|
inline void subTo(Dest& dest) const {
|
||||||
internal::outer_product_selector_run(*this, dest, sub(), IsRowMajor<Dest>());
|
internal::outer_product_selector_run(*this, dest, sub(), is_row_major<Dest>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Dest> void scaleAndAddTo(Dest& dest, const Scalar& alpha) const
|
template<typename Dest> void scaleAndAddTo(Dest& dest, const Scalar& alpha) const
|
||||||
{
|
{
|
||||||
internal::outer_product_selector_run(*this, dest, adds(alpha), IsRowMajor<Dest>());
|
internal::outer_product_selector_run(*this, dest, adds(alpha), is_row_major<Dest>());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
|
|||||||
return internal::ploadt<PacketScalar, LoadMode>(m_data + index * innerStride());
|
return internal::ploadt<PacketScalar, LoadMode>(m_data + index * innerStride());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline MapBase(PointerType dataPtr) : m_data(dataPtr), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime)
|
explicit inline MapBase(PointerType dataPtr) : m_data(dataPtr), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
|
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
|
||||||
checkSanity();
|
checkSanity();
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ struct hypot_impl
|
|||||||
RealScalar _x = abs(x);
|
RealScalar _x = abs(x);
|
||||||
RealScalar _y = abs(y);
|
RealScalar _y = abs(y);
|
||||||
RealScalar p = (max)(_x, _y);
|
RealScalar p = (max)(_x, _y);
|
||||||
if(p==RealScalar(0)) return 0;
|
if(p==RealScalar(0)) return RealScalar(0);
|
||||||
RealScalar q = (min)(_x, _y);
|
RealScalar q = (min)(_x, _y);
|
||||||
RealScalar qp = q/p;
|
RealScalar qp = q/p;
|
||||||
return p * sqrt(RealScalar(1) + qp*qp);
|
return p * sqrt(RealScalar(1) + qp*qp);
|
||||||
|
|||||||
@@ -437,6 +437,22 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** Copy constructor */
|
||||||
|
EIGEN_STRONG_INLINE PlainObjectBase(const PlainObjectBase& other)
|
||||||
|
: m_storage()
|
||||||
|
{
|
||||||
|
_check_template_params();
|
||||||
|
lazyAssign(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherDerived>
|
||||||
|
EIGEN_STRONG_INLINE PlainObjectBase(const DenseBase<OtherDerived> &other)
|
||||||
|
: m_storage()
|
||||||
|
{
|
||||||
|
_check_template_params();
|
||||||
|
lazyAssign(other);
|
||||||
|
}
|
||||||
|
|
||||||
EIGEN_STRONG_INLINE PlainObjectBase(Index a_size, Index nbRows, Index nbCols)
|
EIGEN_STRONG_INLINE PlainObjectBase(Index a_size, Index nbRows, Index nbCols)
|
||||||
: m_storage(a_size, nbRows, nbCols)
|
: m_storage(a_size, nbRows, nbCols)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -245,6 +245,15 @@ template<typename TPlainObjectType, int Options, typename StrideType> class Ref<
|
|||||||
construct(expr.derived(), typename Traits::template match<Derived>::type());
|
construct(expr.derived(), typename Traits::template match<Derived>::type());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Ref(const Ref& other) : Base(other) {
|
||||||
|
// copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherRef>
|
||||||
|
inline Ref(const RefBase<OtherRef>& other) {
|
||||||
|
construct(other.derived(), typename Traits::template match<OtherRef>::type());
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
template<typename Expression>
|
template<typename Expression>
|
||||||
|
|||||||
@@ -384,6 +384,7 @@ template<> EIGEN_STRONG_INLINE int predux_max<Packet4i>(const Packet4i& a)
|
|||||||
a_lo = vget_low_s32(a);
|
a_lo = vget_low_s32(a);
|
||||||
a_hi = vget_high_s32(a);
|
a_hi = vget_high_s32(a);
|
||||||
max = vpmax_s32(a_lo, a_hi);
|
max = vpmax_s32(a_lo, a_hi);
|
||||||
|
max = vpmax_s32(max, max);
|
||||||
|
|
||||||
return vget_lane_s32(max, 0);
|
return vget_lane_s32(max, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ struct product_triangular_matrix_matrix_trmm<EIGTYPE,Index,Mode,true, \
|
|||||||
/* Non-square case - doesn't fit to MKL ?TRMM. Fall to default triangular product or call MKL ?GEMM*/ \
|
/* Non-square case - doesn't fit to MKL ?TRMM. Fall to default triangular product or call MKL ?GEMM*/ \
|
||||||
if (rows != depth) { \
|
if (rows != depth) { \
|
||||||
\
|
\
|
||||||
int nthr = mkl_domain_get_max_threads(MKL_BLAS); \
|
int nthr = mkl_domain_get_max_threads(EIGEN_MKL_DOMAIN_BLAS); \
|
||||||
\
|
\
|
||||||
if (((nthr==1) && (((std::max)(rows,depth)-diagSize)/(double)diagSize < 0.5))) { \
|
if (((nthr==1) && (((std::max)(rows,depth)-diagSize)/(double)diagSize < 0.5))) { \
|
||||||
/* Most likely no benefit to call TRMM or GEMM from MKL*/ \
|
/* Most likely no benefit to call TRMM or GEMM from MKL*/ \
|
||||||
@@ -223,7 +223,7 @@ struct product_triangular_matrix_matrix_trmm<EIGTYPE,Index,Mode,false, \
|
|||||||
/* Non-square case - doesn't fit to MKL ?TRMM. Fall to default triangular product or call MKL ?GEMM*/ \
|
/* Non-square case - doesn't fit to MKL ?TRMM. Fall to default triangular product or call MKL ?GEMM*/ \
|
||||||
if (cols != depth) { \
|
if (cols != depth) { \
|
||||||
\
|
\
|
||||||
int nthr = mkl_domain_get_max_threads(MKL_BLAS); \
|
int nthr = mkl_domain_get_max_threads(EIGEN_MKL_DOMAIN_BLAS); \
|
||||||
\
|
\
|
||||||
if ((nthr==1) && (((std::max)(cols,depth)-diagSize)/(double)diagSize < 0.5)) { \
|
if ((nthr==1) && (((std::max)(cols,depth)-diagSize)/(double)diagSize < 0.5)) { \
|
||||||
/* Most likely no benefit to call TRMM or GEMM from MKL*/ \
|
/* Most likely no benefit to call TRMM or GEMM from MKL*/ \
|
||||||
|
|||||||
@@ -76,6 +76,38 @@
|
|||||||
#include <mkl_lapacke.h>
|
#include <mkl_lapacke.h>
|
||||||
#define EIGEN_MKL_VML_THRESHOLD 128
|
#define EIGEN_MKL_VML_THRESHOLD 128
|
||||||
|
|
||||||
|
/* MKL_DOMAIN_BLAS, etc are defined only in 10.3 update 7 */
|
||||||
|
/* MKL_BLAS, etc are not defined in 11.2 */
|
||||||
|
#ifdef MKL_DOMAIN_ALL
|
||||||
|
#define EIGEN_MKL_DOMAIN_ALL MKL_DOMAIN_ALL
|
||||||
|
#else
|
||||||
|
#define EIGEN_MKL_DOMAIN_ALL MKL_ALL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MKL_DOMAIN_BLAS
|
||||||
|
#define EIGEN_MKL_DOMAIN_BLAS MKL_DOMAIN_BLAS
|
||||||
|
#else
|
||||||
|
#define EIGEN_MKL_DOMAIN_BLAS MKL_BLAS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MKL_DOMAIN_FFT
|
||||||
|
#define EIGEN_MKL_DOMAIN_FFT MKL_DOMAIN_FFT
|
||||||
|
#else
|
||||||
|
#define EIGEN_MKL_DOMAIN_FFT MKL_FFT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MKL_DOMAIN_VML
|
||||||
|
#define EIGEN_MKL_DOMAIN_VML MKL_DOMAIN_VML
|
||||||
|
#else
|
||||||
|
#define EIGEN_MKL_DOMAIN_VML MKL_VML
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MKL_DOMAIN_PARDISO
|
||||||
|
#define EIGEN_MKL_DOMAIN_PARDISO MKL_DOMAIN_PARDISO
|
||||||
|
#else
|
||||||
|
#define EIGEN_MKL_DOMAIN_PARDISO MKL_PARDISO
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Eigen {
|
namespace Eigen {
|
||||||
|
|
||||||
typedef std::complex<double> dcomplex;
|
typedef std::complex<double> dcomplex;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#define EIGEN_WORLD_VERSION 3
|
#define EIGEN_WORLD_VERSION 3
|
||||||
#define EIGEN_MAJOR_VERSION 2
|
#define EIGEN_MAJOR_VERSION 2
|
||||||
#define EIGEN_MINOR_VERSION 5
|
#define EIGEN_MINOR_VERSION 6
|
||||||
|
|
||||||
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
|
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
|
||||||
(EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
|
(EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
|
||||||
@@ -314,7 +314,7 @@ namespace Eigen {
|
|||||||
// just an empty macro !
|
// just an empty macro !
|
||||||
#define EIGEN_EMPTY
|
#define EIGEN_EMPTY
|
||||||
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER < 1800) && (!defined(__INTEL_COMPILER))
|
#if defined(_MSC_VER) && (_MSC_VER < 1900) && (!defined(__INTEL_COMPILER))
|
||||||
#define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \
|
#define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \
|
||||||
using Base::operator =;
|
using Base::operator =;
|
||||||
#elif defined(__clang__) // workaround clang bug (see http://forum.kde.org/viewtopic.php?f=74&t=102653)
|
#elif defined(__clang__) // workaround clang bug (see http://forum.kde.org/viewtopic.php?f=74&t=102653)
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
|||||||
typedef typename MatrixType::Scalar Scalar;
|
typedef typename MatrixType::Scalar Scalar;
|
||||||
typedef typename MatrixType::Index Index;
|
typedef typename MatrixType::Index Index;
|
||||||
|
|
||||||
|
typedef Matrix<Scalar,Size,Size,ColMajor,MaxColsAtCompileTime,MaxColsAtCompileTime> EigenvectorsType;
|
||||||
|
|
||||||
/** \brief Real scalar type for \p _MatrixType.
|
/** \brief Real scalar type for \p _MatrixType.
|
||||||
*
|
*
|
||||||
* This is just \c Scalar if #Scalar is real (e.g., \c float or
|
* This is just \c Scalar if #Scalar is real (e.g., \c float or
|
||||||
@@ -225,7 +227,7 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
|||||||
*
|
*
|
||||||
* \sa eigenvalues()
|
* \sa eigenvalues()
|
||||||
*/
|
*/
|
||||||
const MatrixType& eigenvectors() const
|
const EigenvectorsType& eigenvectors() const
|
||||||
{
|
{
|
||||||
eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
|
eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
|
||||||
eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
|
eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
|
||||||
@@ -356,7 +358,7 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
|||||||
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
|
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
|
||||||
}
|
}
|
||||||
|
|
||||||
MatrixType m_eivec;
|
EigenvectorsType m_eivec;
|
||||||
RealVectorType m_eivalues;
|
RealVectorType m_eivalues;
|
||||||
typename TridiagonalizationType::SubDiagonalType m_subdiag;
|
typename TridiagonalizationType::SubDiagonalType m_subdiag;
|
||||||
ComputationInfo m_info;
|
ComputationInfo m_info;
|
||||||
@@ -381,7 +383,7 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
|||||||
* "implicit symmetric QR step with Wilkinson shift"
|
* "implicit symmetric QR step with Wilkinson shift"
|
||||||
*/
|
*/
|
||||||
namespace internal {
|
namespace internal {
|
||||||
template<int StorageOrder,typename RealScalar, typename Scalar, typename Index>
|
template<typename RealScalar, typename Scalar, typename Index>
|
||||||
static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end, Scalar* matrixQ, Index n);
|
static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end, Scalar* matrixQ, Index n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,7 +415,7 @@ SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
|
|||||||
|
|
||||||
// declare some aliases
|
// declare some aliases
|
||||||
RealVectorType& diag = m_eivalues;
|
RealVectorType& diag = m_eivalues;
|
||||||
MatrixType& mat = m_eivec;
|
EigenvectorsType& mat = m_eivec;
|
||||||
|
|
||||||
// map the matrix coefficients to [-1:1] to avoid over- and underflow.
|
// map the matrix coefficients to [-1:1] to avoid over- and underflow.
|
||||||
mat = matrix.template triangularView<Lower>();
|
mat = matrix.template triangularView<Lower>();
|
||||||
@@ -449,7 +451,7 @@ SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
|
|||||||
while (start>0 && m_subdiag[start-1]!=0)
|
while (start>0 && m_subdiag[start-1]!=0)
|
||||||
start--;
|
start--;
|
||||||
|
|
||||||
internal::tridiagonal_qr_step<MatrixType::Flags&RowMajorBit ? RowMajor : ColMajor>(diag.data(), m_subdiag.data(), start, end, computeEigenvectors ? m_eivec.data() : (Scalar*)0, n);
|
internal::tridiagonal_qr_step(diag.data(), m_subdiag.data(), start, end, computeEigenvectors ? m_eivec.data() : (Scalar*)0, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iter <= m_maxIterations * n)
|
if (iter <= m_maxIterations * n)
|
||||||
@@ -498,6 +500,7 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,3
|
|||||||
typedef typename SolverType::RealVectorType VectorType;
|
typedef typename SolverType::RealVectorType VectorType;
|
||||||
typedef typename SolverType::Scalar Scalar;
|
typedef typename SolverType::Scalar Scalar;
|
||||||
typedef typename MatrixType::Index Index;
|
typedef typename MatrixType::Index Index;
|
||||||
|
typedef typename SolverType::EigenvectorsType EigenvectorsType;
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
* Computes the roots of the characteristic polynomial of \a m.
|
* Computes the roots of the characteristic polynomial of \a m.
|
||||||
@@ -570,7 +573,7 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,3
|
|||||||
&& "invalid option parameter");
|
&& "invalid option parameter");
|
||||||
bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors;
|
bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors;
|
||||||
|
|
||||||
MatrixType& eivecs = solver.m_eivec;
|
EigenvectorsType& eivecs = solver.m_eivec;
|
||||||
VectorType& eivals = solver.m_eivalues;
|
VectorType& eivals = solver.m_eivalues;
|
||||||
|
|
||||||
// Shift the matrix to the mean eigenvalue and map the matrix coefficients to [-1:1] to avoid over- and underflow.
|
// Shift the matrix to the mean eigenvalue and map the matrix coefficients to [-1:1] to avoid over- and underflow.
|
||||||
@@ -652,6 +655,7 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,2
|
|||||||
typedef typename SolverType::MatrixType MatrixType;
|
typedef typename SolverType::MatrixType MatrixType;
|
||||||
typedef typename SolverType::RealVectorType VectorType;
|
typedef typename SolverType::RealVectorType VectorType;
|
||||||
typedef typename SolverType::Scalar Scalar;
|
typedef typename SolverType::Scalar Scalar;
|
||||||
|
typedef typename SolverType::EigenvectorsType EigenvectorsType;
|
||||||
|
|
||||||
static inline void computeRoots(const MatrixType& m, VectorType& roots)
|
static inline void computeRoots(const MatrixType& m, VectorType& roots)
|
||||||
{
|
{
|
||||||
@@ -673,7 +677,7 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,2
|
|||||||
&& "invalid option parameter");
|
&& "invalid option parameter");
|
||||||
bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors;
|
bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors;
|
||||||
|
|
||||||
MatrixType& eivecs = solver.m_eivec;
|
EigenvectorsType& eivecs = solver.m_eivec;
|
||||||
VectorType& eivals = solver.m_eivalues;
|
VectorType& eivals = solver.m_eivalues;
|
||||||
|
|
||||||
// map the matrix coefficients to [-1:1] to avoid over- and underflow.
|
// map the matrix coefficients to [-1:1] to avoid over- and underflow.
|
||||||
@@ -732,7 +736,7 @@ SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
template<int StorageOrder,typename RealScalar, typename Scalar, typename Index>
|
template<typename RealScalar, typename Scalar, typename Index>
|
||||||
static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end, Scalar* matrixQ, Index n)
|
static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end, Scalar* matrixQ, Index n)
|
||||||
{
|
{
|
||||||
using std::abs;
|
using std::abs;
|
||||||
@@ -784,8 +788,7 @@ static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index sta
|
|||||||
// apply the givens rotation to the unit matrix Q = Q * G
|
// apply the givens rotation to the unit matrix Q = Q * G
|
||||||
if (matrixQ)
|
if (matrixQ)
|
||||||
{
|
{
|
||||||
// FIXME if StorageOrder == RowMajor this operation is not very efficient
|
Map<Matrix<Scalar,Dynamic,Dynamic,ColMajor> > q(matrixQ,n,n);
|
||||||
Map<Matrix<Scalar,Dynamic,Dynamic,StorageOrder> > q(matrixQ,n,n);
|
|
||||||
q.applyOnTheRight(k,k+1,rot);
|
q.applyOnTheRight(k,k+1,rot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
|||||||
* a uniform distribution */
|
* a uniform distribution */
|
||||||
inline VectorType sample() const
|
inline VectorType sample() const
|
||||||
{
|
{
|
||||||
VectorType r;
|
VectorType r(dim());
|
||||||
for(Index d=0; d<dim(); ++d)
|
for(Index d=0; d<dim(); ++d)
|
||||||
{
|
{
|
||||||
if(!ScalarTraits::IsInteger)
|
if(!ScalarTraits::IsInteger)
|
||||||
|
|||||||
@@ -102,11 +102,11 @@ public:
|
|||||||
/** \returns a quaternion representing an identity rotation
|
/** \returns a quaternion representing an identity rotation
|
||||||
* \sa MatrixBase::Identity()
|
* \sa MatrixBase::Identity()
|
||||||
*/
|
*/
|
||||||
static inline Quaternion<Scalar> Identity() { return Quaternion<Scalar>(1, 0, 0, 0); }
|
static inline Quaternion<Scalar> Identity() { return Quaternion<Scalar>(Scalar(1), Scalar(0), Scalar(0), Scalar(0)); }
|
||||||
|
|
||||||
/** \sa QuaternionBase::Identity(), MatrixBase::setIdentity()
|
/** \sa QuaternionBase::Identity(), MatrixBase::setIdentity()
|
||||||
*/
|
*/
|
||||||
inline QuaternionBase& setIdentity() { coeffs() << 0, 0, 0, 1; return *this; }
|
inline QuaternionBase& setIdentity() { coeffs() << Scalar(0), Scalar(0), Scalar(0), Scalar(1); return *this; }
|
||||||
|
|
||||||
/** \returns the squared norm of the quaternion's coefficients
|
/** \returns the squared norm of the quaternion's coefficients
|
||||||
* \sa QuaternionBase::norm(), MatrixBase::squaredNorm()
|
* \sa QuaternionBase::norm(), MatrixBase::squaredNorm()
|
||||||
|
|||||||
@@ -65,10 +65,10 @@ class DiagonalPreconditioner
|
|||||||
{
|
{
|
||||||
typename MatType::InnerIterator it(mat,j);
|
typename MatType::InnerIterator it(mat,j);
|
||||||
while(it && it.index()!=j) ++it;
|
while(it && it.index()!=j) ++it;
|
||||||
if(it && it.index()==j)
|
if(it && it.index()==j && it.value()!=Scalar(0))
|
||||||
m_invdiag(j) = Scalar(1)/it.value();
|
m_invdiag(j) = Scalar(1)/it.value();
|
||||||
else
|
else
|
||||||
m_invdiag(j) = 0;
|
m_invdiag(j) = Scalar(1);
|
||||||
}
|
}
|
||||||
m_isInitialized = true;
|
m_isInitialized = true;
|
||||||
return *this;
|
return *this;
|
||||||
|
|||||||
@@ -137,9 +137,6 @@ void minimum_degree_ordering(SparseMatrix<Scalar,ColMajor,Index>& C, Permutation
|
|||||||
degree[i] = len[i]; // degree of node i
|
degree[i] = len[i]; // degree of node i
|
||||||
}
|
}
|
||||||
mark = internal::cs_wclear<Index>(0, 0, w, n); /* clear w */
|
mark = internal::cs_wclear<Index>(0, 0, w, n); /* clear w */
|
||||||
elen[n] = -2; /* n is a dead element */
|
|
||||||
Cp[n] = -1; /* n is a root of assembly tree */
|
|
||||||
w[n] = 0; /* n is a dead element */
|
|
||||||
|
|
||||||
/* --- Initialize degree lists ------------------------------------------ */
|
/* --- Initialize degree lists ------------------------------------------ */
|
||||||
for(i = 0; i < n; i++)
|
for(i = 0; i < n; i++)
|
||||||
@@ -153,7 +150,7 @@ void minimum_degree_ordering(SparseMatrix<Scalar,ColMajor,Index>& C, Permutation
|
|||||||
}
|
}
|
||||||
|
|
||||||
d = degree[i];
|
d = degree[i];
|
||||||
if(d == 1) /* node i is empty */
|
if(d == 1 && has_diag) /* node i is empty */
|
||||||
{
|
{
|
||||||
elen[i] = -2; /* element i is dead */
|
elen[i] = -2; /* element i is dead */
|
||||||
nel++;
|
nel++;
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ class SparseVector
|
|||||||
|
|
||||||
Index inner = IsColVector ? row : col;
|
Index inner = IsColVector ? row : col;
|
||||||
Index outer = IsColVector ? col : row;
|
Index outer = IsColVector ? col : row;
|
||||||
|
EIGEN_ONLY_USED_FOR_DEBUG(outer);
|
||||||
eigen_assert(outer==0);
|
eigen_assert(outer==0);
|
||||||
return insert(inner);
|
return insert(inner);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -749,8 +749,8 @@ struct SparseLUMatrixUReturnType : internal::no_assignment_operator
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Map<const Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > A( &(m_mapL.valuePtr()[luptr]), nsupc, nsupc, OuterStride<>(lda) );
|
Map<const Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > A( &(m_mapL.valuePtr()[luptr]), nsupc, nsupc, OuterStride<>(lda) );
|
||||||
Map< Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > U (&(X(fsupc,0)), nsupc, nrhs, OuterStride<>(n) );
|
Map< Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > U (&(X(fsupc,0)), nsupc, nrhs, OuterStride<>(n) );
|
||||||
U = A.template triangularView<Upper>().solve(U);
|
U = A.template triangularView<Upper>().solve(U);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ class SparseLUImpl
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Matrix<Scalar,Dynamic,1> ScalarVector;
|
typedef Matrix<Scalar,Dynamic,1> ScalarVector;
|
||||||
|
typedef Matrix<Scalar,Dynamic,Dynamic,ColMajor> ScalarMatrix;
|
||||||
|
typedef Map<ScalarMatrix, 0, OuterStride<> > MappedMatrixBlock;
|
||||||
typedef Matrix<Index,Dynamic,1> IndexVector;
|
typedef Matrix<Index,Dynamic,1> IndexVector;
|
||||||
typedef typename ScalarVector::RealScalar RealScalar;
|
typedef typename ScalarVector::RealScalar RealScalar;
|
||||||
typedef Ref<Matrix<Scalar,Dynamic,1> > BlockScalarVector;
|
typedef Ref<Matrix<Scalar,Dynamic,1> > BlockScalarVector;
|
||||||
|
|||||||
@@ -153,8 +153,8 @@ Index SparseLUImpl<Scalar,Index>::memInit(Index m, Index n, Index annz, Index lw
|
|||||||
{
|
{
|
||||||
Index& num_expansions = glu.num_expansions; //No memory expansions so far
|
Index& num_expansions = glu.num_expansions; //No memory expansions so far
|
||||||
num_expansions = 0;
|
num_expansions = 0;
|
||||||
glu.nzumax = glu.nzlumax = (std::min)(fillratio * annz / n, m) * n; // estimated number of nonzeros in U
|
glu.nzumax = glu.nzlumax = (std::min)(fillratio * (annz+1) / n, m) * n; // estimated number of nonzeros in U
|
||||||
glu.nzlmax = (std::max)(Index(4), fillratio) * annz / 4; // estimated nnz in L factor
|
glu.nzlmax = (std::max)(Index(4), fillratio) * (annz+1) / 4; // estimated nnz in L factor
|
||||||
// Return the estimated size to the user if necessary
|
// Return the estimated size to the user if necessary
|
||||||
Index tempSpace;
|
Index tempSpace;
|
||||||
tempSpace = (2*panel_size + 4 + LUNoMarker) * m * sizeof(Index) + (panel_size + 1) * m * sizeof(Scalar);
|
tempSpace = (2*panel_size + 4 + LUNoMarker) * m * sizeof(Index) + (panel_size + 1) * m * sizeof(Scalar);
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ void MappedSuperNodalMatrix<Scalar,Index>::solveInPlace( MatrixBase<Dest>&X) con
|
|||||||
Index n = X.rows();
|
Index n = X.rows();
|
||||||
Index nrhs = X.cols();
|
Index nrhs = X.cols();
|
||||||
const Scalar * Lval = valuePtr(); // Nonzero values
|
const Scalar * Lval = valuePtr(); // Nonzero values
|
||||||
Matrix<Scalar,Dynamic,Dynamic> work(n, nrhs); // working vector
|
Matrix<Scalar,Dynamic,Dynamic, ColMajor> work(n, nrhs); // working vector
|
||||||
work.setZero();
|
work.setZero();
|
||||||
for (Index k = 0; k <= nsuper(); k ++)
|
for (Index k = 0; k <= nsuper(); k ++)
|
||||||
{
|
{
|
||||||
@@ -267,12 +267,12 @@ void MappedSuperNodalMatrix<Scalar,Index>::solveInPlace( MatrixBase<Dest>&X) con
|
|||||||
Index lda = colIndexPtr()[fsupc+1] - luptr;
|
Index lda = colIndexPtr()[fsupc+1] - luptr;
|
||||||
|
|
||||||
// Triangular solve
|
// Triangular solve
|
||||||
Map<const Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > A( &(Lval[luptr]), nsupc, nsupc, OuterStride<>(lda) );
|
Map<const Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > A( &(Lval[luptr]), nsupc, nsupc, OuterStride<>(lda) );
|
||||||
Map< Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > U (&(X(fsupc,0)), nsupc, nrhs, OuterStride<>(n) );
|
Map< Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > U (&(X(fsupc,0)), nsupc, nrhs, OuterStride<>(n) );
|
||||||
U = A.template triangularView<UnitLower>().solve(U);
|
U = A.template triangularView<UnitLower>().solve(U);
|
||||||
|
|
||||||
// Matrix-vector product
|
// Matrix-vector product
|
||||||
new (&A) Map<const Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > ( &(Lval[luptr+nsupc]), nrow, nsupc, OuterStride<>(lda) );
|
new (&A) Map<const Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > ( &(Lval[luptr+nsupc]), nrow, nsupc, OuterStride<>(lda) );
|
||||||
work.block(0, 0, nrow, nrhs) = A * U;
|
work.block(0, 0, nrow, nrhs) = A * U;
|
||||||
|
|
||||||
//Begin Scatter
|
//Begin Scatter
|
||||||
|
|||||||
@@ -162,11 +162,11 @@ Index SparseLUImpl<Scalar,Index>::column_bmod(const Index jcol, const Index nseg
|
|||||||
// points to the beginning of jcol in snode L\U(jsupno)
|
// points to the beginning of jcol in snode L\U(jsupno)
|
||||||
ufirst = glu.xlusup(jcol) + d_fsupc;
|
ufirst = glu.xlusup(jcol) + d_fsupc;
|
||||||
Index lda = glu.xlusup(jcol+1) - glu.xlusup(jcol);
|
Index lda = glu.xlusup(jcol+1) - glu.xlusup(jcol);
|
||||||
Map<Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > A( &(glu.lusup.data()[luptr]), nsupc, nsupc, OuterStride<>(lda) );
|
MappedMatrixBlock A( &(glu.lusup.data()[luptr]), nsupc, nsupc, OuterStride<>(lda) );
|
||||||
VectorBlock<ScalarVector> u(glu.lusup, ufirst, nsupc);
|
VectorBlock<ScalarVector> u(glu.lusup, ufirst, nsupc);
|
||||||
u = A.template triangularView<UnitLower>().solve(u);
|
u = A.template triangularView<UnitLower>().solve(u);
|
||||||
|
|
||||||
new (&A) Map<Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > ( &(glu.lusup.data()[luptr+nsupc]), nrow, nsupc, OuterStride<>(lda) );
|
new (&A) MappedMatrixBlock ( &(glu.lusup.data()[luptr+nsupc]), nrow, nsupc, OuterStride<>(lda) );
|
||||||
VectorBlock<ScalarVector> l(glu.lusup, ufirst+nsupc, nrow);
|
VectorBlock<ScalarVector> l(glu.lusup, ufirst+nsupc, nrow);
|
||||||
l.noalias() -= A * u;
|
l.noalias() -= A * u;
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ EIGEN_DONT_INLINE void LU_kernel_bmod<SegSizeAtCompileTime>::run(const int segsi
|
|||||||
// Dense triangular solve -- start effective triangle
|
// Dense triangular solve -- start effective triangle
|
||||||
luptr += lda * no_zeros + no_zeros;
|
luptr += lda * no_zeros + no_zeros;
|
||||||
// Form Eigen matrix and vector
|
// Form Eigen matrix and vector
|
||||||
Map<Matrix<Scalar,SegSizeAtCompileTime,SegSizeAtCompileTime>, 0, OuterStride<> > A( &(lusup.data()[luptr]), segsize, segsize, OuterStride<>(lda) );
|
Map<Matrix<Scalar,SegSizeAtCompileTime,SegSizeAtCompileTime, ColMajor>, 0, OuterStride<> > A( &(lusup.data()[luptr]), segsize, segsize, OuterStride<>(lda) );
|
||||||
Map<Matrix<Scalar,SegSizeAtCompileTime,1> > u(tempv.data(), segsize);
|
Map<Matrix<Scalar,SegSizeAtCompileTime,1> > u(tempv.data(), segsize);
|
||||||
|
|
||||||
u = A.template triangularView<UnitLower>().solve(u);
|
u = A.template triangularView<UnitLower>().solve(u);
|
||||||
@@ -65,7 +65,7 @@ EIGEN_DONT_INLINE void LU_kernel_bmod<SegSizeAtCompileTime>::run(const int segsi
|
|||||||
luptr += segsize;
|
luptr += segsize;
|
||||||
const Index PacketSize = internal::packet_traits<Scalar>::size;
|
const Index PacketSize = internal::packet_traits<Scalar>::size;
|
||||||
Index ldl = internal::first_multiple(nrow, PacketSize);
|
Index ldl = internal::first_multiple(nrow, PacketSize);
|
||||||
Map<Matrix<Scalar,Dynamic,SegSizeAtCompileTime>, 0, OuterStride<> > B( &(lusup.data()[luptr]), nrow, segsize, OuterStride<>(lda) );
|
Map<Matrix<Scalar,Dynamic,SegSizeAtCompileTime, ColMajor>, 0, OuterStride<> > B( &(lusup.data()[luptr]), nrow, segsize, OuterStride<>(lda) );
|
||||||
Index aligned_offset = internal::first_aligned(tempv.data()+segsize, PacketSize);
|
Index aligned_offset = internal::first_aligned(tempv.data()+segsize, PacketSize);
|
||||||
Index aligned_with_B_offset = (PacketSize-internal::first_aligned(B.data(), PacketSize))%PacketSize;
|
Index aligned_with_B_offset = (PacketSize-internal::first_aligned(B.data(), PacketSize))%PacketSize;
|
||||||
Map<Matrix<Scalar,Dynamic,1>, 0, OuterStride<> > l(tempv.data()+segsize+aligned_offset+aligned_with_B_offset, nrow, OuterStride<>(ldl) );
|
Map<Matrix<Scalar,Dynamic,1>, 0, OuterStride<> > l(tempv.data()+segsize+aligned_offset+aligned_with_B_offset, nrow, OuterStride<>(ldl) );
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ void SparseLUImpl<Scalar,Index>::panel_bmod(const Index m, const Index w, const
|
|||||||
if(nsupc >= 2)
|
if(nsupc >= 2)
|
||||||
{
|
{
|
||||||
Index ldu = internal::first_multiple<Index>(u_rows, PacketSize);
|
Index ldu = internal::first_multiple<Index>(u_rows, PacketSize);
|
||||||
Map<Matrix<Scalar,Dynamic,Dynamic>, Aligned, OuterStride<> > U(tempv.data(), u_rows, u_cols, OuterStride<>(ldu));
|
Map<ScalarMatrix, Aligned, OuterStride<> > U(tempv.data(), u_rows, u_cols, OuterStride<>(ldu));
|
||||||
|
|
||||||
// gather U
|
// gather U
|
||||||
Index u_col = 0;
|
Index u_col = 0;
|
||||||
@@ -136,17 +136,17 @@ void SparseLUImpl<Scalar,Index>::panel_bmod(const Index m, const Index w, const
|
|||||||
Index lda = glu.xlusup(fsupc+1) - glu.xlusup(fsupc);
|
Index lda = glu.xlusup(fsupc+1) - glu.xlusup(fsupc);
|
||||||
no_zeros = (krep - u_rows + 1) - fsupc;
|
no_zeros = (krep - u_rows + 1) - fsupc;
|
||||||
luptr += lda * no_zeros + no_zeros;
|
luptr += lda * no_zeros + no_zeros;
|
||||||
Map<Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > A(glu.lusup.data()+luptr, u_rows, u_rows, OuterStride<>(lda) );
|
MappedMatrixBlock A(glu.lusup.data()+luptr, u_rows, u_rows, OuterStride<>(lda) );
|
||||||
U = A.template triangularView<UnitLower>().solve(U);
|
U = A.template triangularView<UnitLower>().solve(U);
|
||||||
|
|
||||||
// update
|
// update
|
||||||
luptr += u_rows;
|
luptr += u_rows;
|
||||||
Map<Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > B(glu.lusup.data()+luptr, nrow, u_rows, OuterStride<>(lda) );
|
MappedMatrixBlock B(glu.lusup.data()+luptr, nrow, u_rows, OuterStride<>(lda) );
|
||||||
eigen_assert(tempv.size()>w*ldu + nrow*w + 1);
|
eigen_assert(tempv.size()>w*ldu + nrow*w + 1);
|
||||||
|
|
||||||
Index ldl = internal::first_multiple<Index>(nrow, PacketSize);
|
Index ldl = internal::first_multiple<Index>(nrow, PacketSize);
|
||||||
Index offset = (PacketSize-internal::first_aligned(B.data(), PacketSize)) % PacketSize;
|
Index offset = (PacketSize-internal::first_aligned(B.data(), PacketSize)) % PacketSize;
|
||||||
Map<Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > L(tempv.data()+w*ldu+offset, nrow, u_cols, OuterStride<>(ldl));
|
MappedMatrixBlock L(tempv.data()+w*ldu+offset, nrow, u_cols, OuterStride<>(ldl));
|
||||||
|
|
||||||
L.setZero();
|
L.setZero();
|
||||||
internal::sparselu_gemm<Scalar>(L.rows(), L.cols(), B.cols(), B.data(), B.outerStride(), U.data(), U.outerStride(), L.data(), L.outerStride());
|
internal::sparselu_gemm<Scalar>(L.rows(), L.cols(), B.cols(), B.data(), B.outerStride(), U.data(), U.outerStride(), L.data(), L.outerStride());
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ Index SparseLUImpl<Scalar,Index>::pivotL(const Index jcol, const RealScalar& dia
|
|||||||
|
|
||||||
// Determine the largest abs numerical value for partial pivoting
|
// Determine the largest abs numerical value for partial pivoting
|
||||||
Index diagind = iperm_c(jcol); // diagonal index
|
Index diagind = iperm_c(jcol); // diagonal index
|
||||||
RealScalar pivmax = 0.0;
|
RealScalar pivmax(-1.0);
|
||||||
Index pivptr = nsupc;
|
Index pivptr = nsupc;
|
||||||
Index diag = emptyIdxLU;
|
Index diag = emptyIdxLU;
|
||||||
RealScalar rtemp;
|
RealScalar rtemp;
|
||||||
@@ -87,8 +87,9 @@ Index SparseLUImpl<Scalar,Index>::pivotL(const Index jcol, const RealScalar& dia
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test for singularity
|
// Test for singularity
|
||||||
if ( pivmax == 0.0 ) {
|
if ( pivmax <= RealScalar(0.0) ) {
|
||||||
pivrow = lsub_ptr[pivptr];
|
// if pivmax == -1, the column is structurally empty, otherwise it is only numerically zero
|
||||||
|
pivrow = pivmax < RealScalar(0.0) ? diagind : lsub_ptr[pivptr];
|
||||||
perm_r(pivrow) = jcol;
|
perm_r(pivrow) = jcol;
|
||||||
return (jcol+1);
|
return (jcol+1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -324,23 +324,15 @@ macro(ei_get_compilerver VAR)
|
|||||||
# on all other system we rely on ${CMAKE_CXX_COMPILER}
|
# on all other system we rely on ${CMAKE_CXX_COMPILER}
|
||||||
# supporting a "--version" or "/version" flag
|
# supporting a "--version" or "/version" flag
|
||||||
|
|
||||||
if(WIN32 AND NOT CYGWIN)
|
if(WIN32 AND ${CMAKE_CXX_COMPILER_ID} EQUAL "Intel")
|
||||||
set(EIGEN_CXX_FLAG_VERSION "/version")
|
set(EIGEN_CXX_FLAG_VERSION "/version")
|
||||||
else()
|
else()
|
||||||
set(EIGEN_CXX_FLAG_VERSION "--version")
|
set(EIGEN_CXX_FLAG_VERSION "--version")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# check whether the head command exists
|
execute_process(COMMAND ${CMAKE_CXX_COMPILER} ${EIGEN_CXX_FLAG_VERSION}
|
||||||
find_program(HEAD_EXE head NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH)
|
OUTPUT_VARIABLE eigen_cxx_compiler_version_string OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
if(HEAD_EXE)
|
string(REGEX REPLACE "[\n\r].*" "" eigen_cxx_compiler_version_string ${eigen_cxx_compiler_version_string})
|
||||||
execute_process(COMMAND ${CMAKE_CXX_COMPILER} ${EIGEN_CXX_FLAG_VERSION}
|
|
||||||
COMMAND head -n 1
|
|
||||||
OUTPUT_VARIABLE eigen_cxx_compiler_version_string OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
else()
|
|
||||||
execute_process(COMMAND ${CMAKE_CXX_COMPILER} ${EIGEN_CXX_FLAG_VERSION}
|
|
||||||
OUTPUT_VARIABLE eigen_cxx_compiler_version_string OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
string(REGEX REPLACE "[\n\r].*" "" eigen_cxx_compiler_version_string ${eigen_cxx_compiler_version_string})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
ei_get_compilerver_from_cxx_version_string("${eigen_cxx_compiler_version_string}" CNAME CVER)
|
ei_get_compilerver_from_cxx_version_string("${eigen_cxx_compiler_version_string}" CNAME CVER)
|
||||||
set(${VAR} "${CNAME}-${CVER}")
|
set(${VAR} "${CNAME}-${CVER}")
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace Eigen {
|
|||||||
- \subpage TopicCustomizingEigen
|
- \subpage TopicCustomizingEigen
|
||||||
- \subpage TopicMultiThreading
|
- \subpage TopicMultiThreading
|
||||||
- \subpage TopicUsingIntelMKL
|
- \subpage TopicUsingIntelMKL
|
||||||
|
- \subpage TopicPitfalls
|
||||||
- \subpage TopicTemplateKeyword
|
- \subpage TopicTemplateKeyword
|
||||||
- \subpage UserManual_UnderstandingEigen
|
- \subpage UserManual_UnderstandingEigen
|
||||||
*/
|
*/
|
||||||
|
|||||||
38
doc/Pitfalls.dox
Normal file
38
doc/Pitfalls.dox
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
namespace Eigen {
|
||||||
|
|
||||||
|
/** \page TopicPitfalls Common pitfalls
|
||||||
|
|
||||||
|
\section TopicPitfalls_template_keyword Compilation error with template methods
|
||||||
|
|
||||||
|
See this \link TopicTemplateKeyword page \endlink.
|
||||||
|
|
||||||
|
\section TopicPitfalls_auto_keyword C++11 and the auto keyword
|
||||||
|
|
||||||
|
In short: do not use the auto keywords with Eigen's expressions, unless you are 100% sure about what you are doing. In particular, do not use the auto keyword as a replacement for a Matrix<> type. Here is an example:
|
||||||
|
|
||||||
|
\code
|
||||||
|
MatrixXd A, B;
|
||||||
|
auto C = A*B;
|
||||||
|
for(...) { ... w = C * v; ...}
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
In this example, the type of C is not a MatrixXd but an abstract expression representing a matrix product and storing references to A and B. Therefore, the product of A*B will be carried out multiple times, once per iteration of the for loop. Moreover, if the coefficients of A or B change during the iteration, then C will evaluate to different values.
|
||||||
|
|
||||||
|
Here is another example leading to a segfault:
|
||||||
|
\code
|
||||||
|
auto C = ((A+B).eval()).transpose();
|
||||||
|
// do something with C
|
||||||
|
\endcode
|
||||||
|
The problem is that eval() returns a temporary object (in this case a MatrixXd) which is then referenced by the Transpose<> expression. However, this temporary is deleted right after the first line, and there the C expression reference a dead object. The same issue might occur when sub expressions are automatically evaluated by Eigen as in the following example:
|
||||||
|
\code
|
||||||
|
VectorXd u, v;
|
||||||
|
auto C = u + (A*v).normalized();
|
||||||
|
// do something with C
|
||||||
|
\endcode
|
||||||
|
where the normalized() method has to evaluate the expensive product A*v to avoid evaluating it twice. On the other hand, the following example is perfectly fine:
|
||||||
|
\code
|
||||||
|
auto C = (u + (A*v).normalized()).eval();
|
||||||
|
\endcode
|
||||||
|
In this case, C will be a regular VectorXd object.
|
||||||
|
*/
|
||||||
|
}
|
||||||
@@ -40,7 +40,8 @@ Since Eigen version 3.1 and later, users can benefit from built-in Intel MKL opt
|
|||||||
<a href="http://eigen.tuxfamily.org/Counter/redirect_to_mkl.php"> Intel MKL </a> provides highly optimized multi-threaded mathematical routines for x86-compatible architectures.
|
<a href="http://eigen.tuxfamily.org/Counter/redirect_to_mkl.php"> Intel MKL </a> provides highly optimized multi-threaded mathematical routines for x86-compatible architectures.
|
||||||
Intel MKL is available on Linux, Mac and Windows for both Intel64 and IA32 architectures.
|
Intel MKL is available on Linux, Mac and Windows for both Intel64 and IA32 architectures.
|
||||||
|
|
||||||
\warning Be aware that Intel® MKL is a proprietary software. It is the responsibility of the users to buy MKL licenses for their products. Moreover, the license of the user product has to allow linking to proprietary software that excludes any unmodified versions of the GPL.
|
\note
|
||||||
|
Intel® MKL is a proprietary software and it is the responsibility of users to buy or register for community (free) Intel MKL licenses for their products. Moreover, the license of the user product has to allow linking to proprietary software that excludes any unmodified versions of the GPL.
|
||||||
|
|
||||||
Using Intel MKL through Eigen is easy:
|
Using Intel MKL through Eigen is easy:
|
||||||
-# define the \c EIGEN_USE_MKL_ALL macro before including any Eigen's header
|
-# define the \c EIGEN_USE_MKL_ALL macro before including any Eigen's header
|
||||||
|
|||||||
@@ -172,6 +172,8 @@ void test_geo_alignedbox()
|
|||||||
CALL_SUBTEST_9( alignedbox(AlignedBox1i()) );
|
CALL_SUBTEST_9( alignedbox(AlignedBox1i()) );
|
||||||
CALL_SUBTEST_10( alignedbox(AlignedBox2i()) );
|
CALL_SUBTEST_10( alignedbox(AlignedBox2i()) );
|
||||||
CALL_SUBTEST_11( alignedbox(AlignedBox3i()) );
|
CALL_SUBTEST_11( alignedbox(AlignedBox3i()) );
|
||||||
|
|
||||||
|
CALL_SUBTEST_14( alignedbox(AlignedBox<double,Dynamic>(4)) );
|
||||||
}
|
}
|
||||||
CALL_SUBTEST_12( specificTest1() );
|
CALL_SUBTEST_12( specificTest1() );
|
||||||
CALL_SUBTEST_13( specificTest2() );
|
CALL_SUBTEST_13( specificTest2() );
|
||||||
|
|||||||
@@ -277,7 +277,17 @@ int generate_sparse_square_problem(Solver&, typename Solver::MatrixType& A, Dens
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Solver> void check_sparse_square_solving(Solver& solver)
|
|
||||||
|
struct prune_column {
|
||||||
|
int m_col;
|
||||||
|
prune_column(int col) : m_col(col) {}
|
||||||
|
template<class Scalar>
|
||||||
|
bool operator()(int, int col, const Scalar&) const {
|
||||||
|
return col != m_col;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Solver> void check_sparse_square_solving(Solver& solver, bool checkDeficient = false)
|
||||||
{
|
{
|
||||||
typedef typename Solver::MatrixType Mat;
|
typedef typename Solver::MatrixType Mat;
|
||||||
typedef typename Mat::Scalar Scalar;
|
typedef typename Mat::Scalar Scalar;
|
||||||
@@ -309,6 +319,13 @@ template<typename Solver> void check_sparse_square_solving(Solver& solver)
|
|||||||
b = DenseVector::Zero(size);
|
b = DenseVector::Zero(size);
|
||||||
check_sparse_solving(solver, A, b, dA, b);
|
check_sparse_solving(solver, A, b, dA, b);
|
||||||
}
|
}
|
||||||
|
// regression test for Bug 792 (structurally rank deficient matrices):
|
||||||
|
if(checkDeficient && size>1) {
|
||||||
|
int col = internal::random<int>(0,size-1);
|
||||||
|
A.prune(prune_column(col));
|
||||||
|
solver.compute(A);
|
||||||
|
VERIFY_IS_EQUAL(solver.info(), NumericalIssue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, get the folder
|
// First, get the folder
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ template<typename T> void test_sparselu_T()
|
|||||||
SparseLU<SparseMatrix<T, ColMajor>, AMDOrdering<int> > sparselu_amd;
|
SparseLU<SparseMatrix<T, ColMajor>, AMDOrdering<int> > sparselu_amd;
|
||||||
SparseLU<SparseMatrix<T, ColMajor, long int>, NaturalOrdering<long int> > sparselu_natural;
|
SparseLU<SparseMatrix<T, ColMajor, long int>, NaturalOrdering<long int> > sparselu_natural;
|
||||||
|
|
||||||
check_sparse_square_solving(sparselu_colamd);
|
check_sparse_square_solving(sparselu_colamd, true);
|
||||||
check_sparse_square_solving(sparselu_amd);
|
check_sparse_square_solving(sparselu_amd, true);
|
||||||
check_sparse_square_solving(sparselu_natural);
|
check_sparse_square_solving(sparselu_natural,true);
|
||||||
|
|
||||||
check_sparse_square_abs_determinant(sparselu_colamd);
|
check_sparse_square_abs_determinant(sparselu_colamd);
|
||||||
check_sparse_square_abs_determinant(sparselu_amd);
|
check_sparse_square_abs_determinant(sparselu_amd);
|
||||||
|
|||||||
@@ -111,6 +111,18 @@ template<typename ArrayType> void vectorwiseop_array(const ArrayType& m)
|
|||||||
m2.rowwise() /= m2.colwise().sum();
|
m2.rowwise() /= m2.colwise().sum();
|
||||||
VERIFY_IS_APPROX(m2, m1.rowwise() / m1.colwise().sum());
|
VERIFY_IS_APPROX(m2, m1.rowwise() / m1.colwise().sum());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// all/any
|
||||||
|
Array<bool,Dynamic,Dynamic> mb(rows,cols);
|
||||||
|
mb = (m1.real()<=0.7).colwise().all();
|
||||||
|
VERIFY( (mb.col(c) == (m1.real().col(c)<=0.7).all()).all() );
|
||||||
|
mb = (m1.real()<=0.7).rowwise().all();
|
||||||
|
VERIFY( (mb.row(r) == (m1.real().row(r)<=0.7).all()).all() );
|
||||||
|
|
||||||
|
mb = (m1.real()>=0.7).colwise().any();
|
||||||
|
VERIFY( (mb.col(c) == (m1.real().col(c)>=0.7).any()).all() );
|
||||||
|
mb = (m1.real()>=0.7).rowwise().any();
|
||||||
|
VERIFY( (mb.row(r) == (m1.real().row(r)>=0.7).any()).all() );
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m)
|
template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m)
|
||||||
|
|||||||
Reference in New Issue
Block a user