Merged latest changes from the parent

This commit is contained in:
Benoit Steiner 2014-03-18 12:58:08 -07:00
commit 8a0845ebd7
36 changed files with 373 additions and 175 deletions

View File

@ -4,10 +4,14 @@
## # The following are required to uses Dart and the Cdash dashboard ## # The following are required to uses Dart and the Cdash dashboard
## ENABLE_TESTING() ## ENABLE_TESTING()
## INCLUDE(CTest) ## INCLUDE(CTest)
set(CTEST_PROJECT_NAME "Eigen3.2") set(CTEST_PROJECT_NAME "Eigen")
set(CTEST_NIGHTLY_START_TIME "00:00:00 UTC") set(CTEST_NIGHTLY_START_TIME "00:00:00 UTC")
set(CTEST_DROP_METHOD "http") set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "manao.inria.fr") set(CTEST_DROP_SITE "manao.inria.fr")
set(CTEST_DROP_LOCATION "/CDash/submit.php?project=Eigen3.2") set(CTEST_DROP_LOCATION "/CDash/submit.php?project=Eigen")
set(CTEST_DROP_SITE_CDASH TRUE) set(CTEST_DROP_SITE_CDASH TRUE)
set(CTEST_PROJECT_SUBPROJECTS
Official
Unsupported
)

View File

@ -291,13 +291,6 @@ template<> struct ldlt_inplace<Lower>
cutoff = abs(NumTraits<Scalar>::epsilon() * biggest_in_corner); cutoff = abs(NumTraits<Scalar>::epsilon() * biggest_in_corner);
} }
// Finish early if the matrix is not full rank.
if(biggest_in_corner < cutoff)
{
for(Index i = k; i < size; i++) transpositions.coeffRef(i) = i;
break;
}
transpositions.coeffRef(k) = index_of_biggest_in_corner; transpositions.coeffRef(k) = index_of_biggest_in_corner;
if(k != index_of_biggest_in_corner) if(k != index_of_biggest_in_corner)
{ {
@ -333,6 +326,7 @@ template<> struct ldlt_inplace<Lower>
if(rs>0) if(rs>0)
A21.noalias() -= A20 * temp.head(k); A21.noalias() -= A20 * temp.head(k);
} }
if((rs>0) && (abs(mat.coeffRef(k,k)) > cutoff)) if((rs>0) && (abs(mat.coeffRef(k,k)) > cutoff))
A21 /= mat.coeffRef(k,k); A21 /= mat.coeffRef(k,k);
@ -518,12 +512,12 @@ struct solve_retval<LDLT<_MatrixType,_UpLo>, Rhs>
typedef typename LDLTType::RealScalar RealScalar; typedef typename LDLTType::RealScalar RealScalar;
const Diagonal<const MatrixType> vectorD = dec().vectorD(); const Diagonal<const MatrixType> vectorD = dec().vectorD();
RealScalar tolerance = (max)(vectorD.array().abs().maxCoeff() * NumTraits<Scalar>::epsilon(), RealScalar tolerance = (max)(vectorD.array().abs().maxCoeff() * NumTraits<Scalar>::epsilon(),
RealScalar(1) / NumTraits<RealScalar>::highest()); // motivated by LAPACK's xGELSS RealScalar(1) / NumTraits<RealScalar>::highest()); // motivated by LAPACK's xGELSS
for (Index i = 0; i < vectorD.size(); ++i) { for (Index i = 0; i < vectorD.size(); ++i) {
if(abs(vectorD(i)) > tolerance) if(abs(vectorD(i)) > tolerance)
dst.row(i) /= vectorD(i); dst.row(i) /= vectorD(i);
else else
dst.row(i).setZero(); dst.row(i).setZero();
} }
// dst = L^-T (D^-1 L^-1 P b) // dst = L^-T (D^-1 L^-1 P b)

View File

@ -49,7 +49,7 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
typedef typename internal::nested<ExpressionType>::type NestedExpressionType; typedef typename internal::nested<ExpressionType>::type NestedExpressionType;
EIGEN_DEVICE_FUNC EIGEN_DEVICE_FUNC
inline ArrayWrapper(ExpressionType& matrix) : m_expression(matrix) {} EIGEN_STRONG_INLINE ArrayWrapper(ExpressionType& matrix) : m_expression(matrix) {}
EIGEN_DEVICE_FUNC EIGEN_DEVICE_FUNC
inline Index rows() const { return m_expression.rows(); } inline Index rows() const { return m_expression.rows(); }

View File

@ -574,13 +574,13 @@ public:
template<int StoreMode, int LoadMode> template<int StoreMode, int LoadMode>
void assignPacket(Index row, Index col) void assignPacket(Index row, Index col)
{ {
m_functor.assignPacket<StoreMode>(&m_dst.coeffRef(row,col), m_src.template packet<LoadMode>(row,col)); m_functor.template assignPacket<StoreMode>(&m_dst.coeffRef(row,col), m_src.template packet<LoadMode>(row,col));
} }
template<int StoreMode, int LoadMode> template<int StoreMode, int LoadMode>
void assignPacket(Index index) void assignPacket(Index index)
{ {
m_functor.assignPacket<StoreMode>(&m_dst.coeffRef(index), m_src.template packet<LoadMode>(index)); m_functor.template assignPacket<StoreMode>(&m_dst.coeffRef(index), m_src.template packet<LoadMode>(index));
} }
template<int StoreMode, int LoadMode> template<int StoreMode, int LoadMode>

View File

@ -45,6 +45,18 @@ struct CommaInitializer
m_xpr.block(0, 0, other.rows(), other.cols()) = other; m_xpr.block(0, 0, other.rows(), other.cols()) = other;
} }
/* Copy/Move constructor which transfers ownership. This is crucial in
* absence of return value optimization to avoid assertions during destruction. */
// FIXME in C++11 mode this could be replaced by a proper RValue constructor
EIGEN_DEVICE_FUNC
inline CommaInitializer(const CommaInitializer& o)
: m_xpr(o.m_xpr), m_row(o.m_row), m_col(o.m_col), m_currentBlockRows(o.m_currentBlockRows) {
// Mark original object as finished. In absence of R-value references we need to const_cast:
const_cast<CommaInitializer&>(o).m_row = m_xpr.rows();
const_cast<CommaInitializer&>(o).m_col = m_xpr.cols();
const_cast<CommaInitializer&>(o).m_currentBlockRows = 0;
}
/* inserts a scalar value in the target matrix */ /* inserts a scalar value in the target matrix */
EIGEN_DEVICE_FUNC EIGEN_DEVICE_FUNC
CommaInitializer& operator,(const Scalar& s) CommaInitializer& operator,(const Scalar& s)
@ -110,7 +122,7 @@ struct CommaInitializer
EIGEN_DEVICE_FUNC EIGEN_DEVICE_FUNC
inline XprType& finished() { return m_xpr; } inline XprType& finished() { return m_xpr; }
XprType& m_xpr; // target expression XprType& m_xpr; // target expression
Index m_row; // current row id Index m_row; // current row id
Index m_col; // current col id Index m_col; // current col id
Index m_currentBlockRows; // current block height Index m_currentBlockRows; // current block height

View File

@ -356,8 +356,6 @@ template<typename Derived> class MatrixBase
Scalar trace() const; Scalar trace() const;
/////////// Array module ///////////
template<int p> EIGEN_DEVICE_FUNC RealScalar lpNorm() const; template<int p> EIGEN_DEVICE_FUNC RealScalar lpNorm() const;
EIGEN_DEVICE_FUNC MatrixBase<Derived>& matrix() { return *this; } EIGEN_DEVICE_FUNC MatrixBase<Derived>& matrix() { return *this; }
@ -365,8 +363,10 @@ template<typename Derived> class MatrixBase
/** \returns an \link Eigen::ArrayBase Array \endlink expression of this matrix /** \returns an \link Eigen::ArrayBase Array \endlink expression of this matrix
* \sa ArrayBase::matrix() */ * \sa ArrayBase::matrix() */
EIGEN_DEVICE_FUNC ArrayWrapper<Derived> array() { return derived(); } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ArrayWrapper<Derived> array() { return derived(); }
EIGEN_DEVICE_FUNC const ArrayWrapper<const Derived> array() const { return derived(); } /** \returns a const \link Eigen::ArrayBase Array \endlink expression of this matrix
* \sa ArrayBase::matrix() */
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const ArrayWrapper<const Derived> array() const { return derived(); }
/////////// LU module /////////// /////////// LU module ///////////

View File

@ -101,7 +101,7 @@ struct traits<Ref<_PlainObjectType, _Options, _StrideType> >
template<typename Derived> struct match { template<typename Derived> struct match {
enum { enum {
HasDirectAccess = internal::has_direct_access<Derived>::ret, HasDirectAccess = internal::has_direct_access<Derived>::ret,
StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)), StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)),
InnerStrideMatch = int(StrideType::InnerStrideAtCompileTime)==int(Dynamic) InnerStrideMatch = int(StrideType::InnerStrideAtCompileTime)==int(Dynamic)
|| int(StrideType::InnerStrideAtCompileTime)==int(Derived::InnerStrideAtCompileTime) || int(StrideType::InnerStrideAtCompileTime)==int(Derived::InnerStrideAtCompileTime)
|| (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1), || (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1),
@ -172,8 +172,12 @@ protected:
} }
else else
::new (static_cast<Base*>(this)) Base(expr.data(), expr.rows(), expr.cols()); ::new (static_cast<Base*>(this)) Base(expr.data(), expr.rows(), expr.cols());
::new (&m_stride) StrideBase(StrideType::OuterStrideAtCompileTime==0?0:expr.outerStride(),
StrideType::InnerStrideAtCompileTime==0?0:expr.innerStride()); if(Expression::IsVectorAtCompileTime && (!PlainObjectType::IsVectorAtCompileTime) && ((Expression::Flags&RowMajorBit)!=(PlainObjectType::Flags&RowMajorBit)))
::new (&m_stride) StrideBase(expr.innerStride(), StrideType::InnerStrideAtCompileTime==0?0:1);
else
::new (&m_stride) StrideBase(StrideType::OuterStrideAtCompileTime==0?0:expr.outerStride(),
StrideType::InnerStrideAtCompileTime==0?0:expr.innerStride());
} }
StrideBase m_stride; StrideBase m_stride;

View File

@ -1277,6 +1277,7 @@ EIGEN_DONT_INLINE void gemm_pack_rhs<Scalar, Index, nr, ColMajor, Conjugate, Pan
template<typename Scalar, typename Index, int nr, bool Conjugate, bool PanelMode> template<typename Scalar, typename Index, int nr, bool Conjugate, bool PanelMode>
struct gemm_pack_rhs<Scalar, Index, nr, RowMajor, Conjugate, PanelMode> struct gemm_pack_rhs<Scalar, Index, nr, RowMajor, Conjugate, PanelMode>
{ {
typedef typename packet_traits<Scalar>::type Packet;
enum { PacketSize = packet_traits<Scalar>::size }; enum { PacketSize = packet_traits<Scalar>::size };
EIGEN_DONT_INLINE void operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols, Index stride=0, Index offset=0); EIGEN_DONT_INLINE void operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols, Index stride=0, Index offset=0);
}; };
@ -1298,12 +1299,18 @@ EIGEN_DONT_INLINE void gemm_pack_rhs<Scalar, Index, nr, RowMajor, Conjugate, Pan
if(PanelMode) count += nr * offset; if(PanelMode) count += nr * offset;
for(Index k=0; k<depth; k++) for(Index k=0; k<depth; k++)
{ {
const Scalar* b0 = &rhs[k*rhsStride + j2]; if (nr == PacketSize) {
blockB[count+0] = cj(b0[0]); Packet A = ploadu<Packet>(&rhs[k*rhsStride + j2]);
blockB[count+1] = cj(b0[1]); pstoreu(blockB+count, cj.pconj(A));
if(nr==4) blockB[count+2] = cj(b0[2]); count += PacketSize;
if(nr==4) blockB[count+3] = cj(b0[3]); } else {
count += nr; const Scalar* b0 = &rhs[k*rhsStride + j2];
blockB[count+0] = cj(b0[0]);
blockB[count+1] = cj(b0[1]);
if(nr==4) blockB[count+2] = cj(b0[2]);
if(nr==4) blockB[count+3] = cj(b0[3]);
count += nr;
}
} }
// skip what we have after // skip what we have after
if(PanelMode) count += nr * (stride-offset-depth); if(PanelMode) count += nr * (stride-offset-depth);

View File

@ -113,9 +113,9 @@ EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product<Scalar,Index,StorageOrd
for (size_t i=starti; i<alignedStart; ++i) for (size_t i=starti; i<alignedStart; ++i)
{ {
res[i] += t0 * A0[i] + t1 * A1[i]; res[i] += cj0.pmul(A0[i], t0) + cj0.pmul(A1[i],t1);
t2 += numext::conj(A0[i]) * rhs[i]; t2 += cj1.pmul(A0[i], rhs[i]);
t3 += numext::conj(A1[i]) * rhs[i]; t3 += cj1.pmul(A1[i], rhs[i]);
} }
// Yes this an optimization for gcc 4.3 and 4.4 (=> huge speed up) // Yes this an optimization for gcc 4.3 and 4.4 (=> huge speed up)
// gcc 4.2 does this optimization automatically. // gcc 4.2 does this optimization automatically.

View File

@ -274,12 +274,12 @@ inline void* aligned_realloc(void *ptr, size_t new_size, size_t old_size)
// The defined(_mm_free) is just here to verify that this MSVC version // The defined(_mm_free) is just here to verify that this MSVC version
// implements _mm_malloc/_mm_free based on the corresponding _aligned_ // implements _mm_malloc/_mm_free based on the corresponding _aligned_
// functions. This may not always be the case and we just try to be safe. // functions. This may not always be the case and we just try to be safe.
#if defined(_MSC_VER) && defined(_mm_free) #if defined(_MSC_VER) && (!defined(_WIN32_WCE)) && defined(_mm_free)
result = _aligned_realloc(ptr,new_size,EIGEN_ALIGN_BYTES); result = _aligned_realloc(ptr,new_size,EIGEN_ALIGN_BYTES);
#else #else
result = generic_aligned_realloc(ptr,new_size,old_size); result = generic_aligned_realloc(ptr,new_size,old_size);
#endif #endif
#elif defined(_MSC_VER) #elif defined(_MSC_VER) && (!defined(_WIN32_WCE))
result = _aligned_realloc(ptr,new_size,EIGEN_ALIGN_BYTES); result = _aligned_realloc(ptr,new_size,EIGEN_ALIGN_BYTES);
#else #else
result = handmade_aligned_realloc(ptr,new_size,old_size); result = handmade_aligned_realloc(ptr,new_size,old_size);
@ -464,7 +464,7 @@ template<typename T, bool Align> inline void conditional_aligned_delete_auto(T *
* There is also the variant first_aligned(const MatrixBase&) defined in DenseCoeffsBase.h. * There is also the variant first_aligned(const MatrixBase&) defined in DenseCoeffsBase.h.
*/ */
template<typename Scalar, typename Index> template<typename Scalar, typename Index>
static inline Index first_aligned(const Scalar* array, Index size) inline Index first_aligned(const Scalar* array, Index size)
{ {
enum { PacketSize = packet_traits<Scalar>::size, enum { PacketSize = packet_traits<Scalar>::size,
PacketAlignedMask = PacketSize-1 PacketAlignedMask = PacketSize-1
@ -492,7 +492,7 @@ static inline Index first_aligned(const Scalar* array, Index size)
/** \internal Returns the smallest integer multiple of \a base and greater or equal to \a size /** \internal Returns the smallest integer multiple of \a base and greater or equal to \a size
*/ */
template<typename Index> template<typename Index>
inline static Index first_multiple(Index size, Index base) inline Index first_multiple(Index size, Index base)
{ {
return ((size+base-1)/base)*base; return ((size+base-1)/base)*base;
} }

View File

@ -34,8 +34,9 @@ struct quaternionbase_assign_impl;
template<class Derived> template<class Derived>
class QuaternionBase : public RotationBase<Derived, 3> class QuaternionBase : public RotationBase<Derived, 3>
{ {
public:
typedef RotationBase<Derived, 3> Base; typedef RotationBase<Derived, 3> Base;
public:
using Base::operator*; using Base::operator*;
using Base::derived; using Base::derived;
@ -203,6 +204,8 @@ public:
* \li \c Quaternionf for \c float * \li \c Quaternionf for \c float
* \li \c Quaterniond for \c double * \li \c Quaterniond for \c double
* *
* \warning Operations interpreting the quaternion as rotation have undefined behavior if the quaternion is not normalized.
*
* \sa class AngleAxis, class Transform * \sa class AngleAxis, class Transform
*/ */
@ -223,10 +226,10 @@ struct traits<Quaternion<_Scalar,_Options> >
template<typename _Scalar, int _Options> template<typename _Scalar, int _Options>
class Quaternion : public QuaternionBase<Quaternion<_Scalar,_Options> > class Quaternion : public QuaternionBase<Quaternion<_Scalar,_Options> >
{ {
public:
typedef QuaternionBase<Quaternion<_Scalar,_Options> > Base; typedef QuaternionBase<Quaternion<_Scalar,_Options> > Base;
enum { IsAligned = internal::traits<Quaternion>::IsAligned }; enum { IsAligned = internal::traits<Quaternion>::IsAligned };
public:
typedef _Scalar Scalar; typedef _Scalar Scalar;
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Quaternion) EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Quaternion)
@ -334,9 +337,9 @@ template<typename _Scalar, int _Options>
class Map<const Quaternion<_Scalar>, _Options > class Map<const Quaternion<_Scalar>, _Options >
: public QuaternionBase<Map<const Quaternion<_Scalar>, _Options> > : public QuaternionBase<Map<const Quaternion<_Scalar>, _Options> >
{ {
public:
typedef QuaternionBase<Map<const Quaternion<_Scalar>, _Options> > Base; typedef QuaternionBase<Map<const Quaternion<_Scalar>, _Options> > Base;
public:
typedef _Scalar Scalar; typedef _Scalar Scalar;
typedef typename internal::traits<Map>::Coefficients Coefficients; typedef typename internal::traits<Map>::Coefficients Coefficients;
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map) EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
@ -344,7 +347,7 @@ class Map<const Quaternion<_Scalar>, _Options >
/** Constructs a Mapped Quaternion object from the pointer \a coeffs /** Constructs a Mapped Quaternion object from the pointer \a coeffs
* *
* The pointer \a coeffs must reference the four coeffecients of Quaternion in the following order: * The pointer \a coeffs must reference the four coefficients of Quaternion in the following order:
* \code *coeffs == {x, y, z, w} \endcode * \code *coeffs == {x, y, z, w} \endcode
* *
* If the template parameter _Options is set to #Aligned, then the pointer coeffs must be aligned. */ * If the template parameter _Options is set to #Aligned, then the pointer coeffs must be aligned. */
@ -371,9 +374,9 @@ template<typename _Scalar, int _Options>
class Map<Quaternion<_Scalar>, _Options > class Map<Quaternion<_Scalar>, _Options >
: public QuaternionBase<Map<Quaternion<_Scalar>, _Options> > : public QuaternionBase<Map<Quaternion<_Scalar>, _Options> >
{ {
public:
typedef QuaternionBase<Map<Quaternion<_Scalar>, _Options> > Base; typedef QuaternionBase<Map<Quaternion<_Scalar>, _Options> > Base;
public:
typedef _Scalar Scalar; typedef _Scalar Scalar;
typedef typename internal::traits<Map>::Coefficients Coefficients; typedef typename internal::traits<Map>::Coefficients Coefficients;
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map) EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
@ -464,7 +467,7 @@ QuaternionBase<Derived>::_transformVector(Vector3 v) const
// Note that this algorithm comes from the optimization by hand // Note that this algorithm comes from the optimization by hand
// of the conversion to a Matrix followed by a Matrix/Vector product. // of the conversion to a Matrix followed by a Matrix/Vector product.
// It appears to be much faster than the common algorithm found // It appears to be much faster than the common algorithm found
// in the litterature (30 versus 39 flops). It also requires two // in the literature (30 versus 39 flops). It also requires two
// Vector3 as temporaries. // Vector3 as temporaries.
Vector3 uv = this->vec().cross(v); Vector3 uv = this->vec().cross(v);
uv += uv; uv += uv;
@ -667,10 +670,10 @@ QuaternionBase<Derived>::angularDistance(const QuaternionBase<OtherDerived>& oth
{ {
using std::acos; using std::acos;
using std::abs; using std::abs;
double d = abs(this->dot(other)); Scalar d = abs(this->dot(other));
if (d>=1.0) if (d>=Scalar(1))
return Scalar(0); return Scalar(0);
return static_cast<Scalar>(2 * acos(d)); return Scalar(2) * acos(d);
} }

View File

@ -62,10 +62,10 @@ public:
template<int Dim, int Mode, int Options> template<int Dim, int Mode, int Options>
inline Transform<Scalar,Dim,(int(Mode)==int(Isometry)?Affine:Mode)> operator* (const Transform<Scalar,Dim, Mode, Options>& t) const inline Transform<Scalar,Dim,(int(Mode)==int(Isometry)?Affine:Mode)> operator* (const Transform<Scalar,Dim, Mode, Options>& t) const
{ {
Transform<Scalar,Dim,(int(Mode)==int(Isometry)?Affine:Mode)> res = t; Transform<Scalar,Dim,(int(Mode)==int(Isometry)?Affine:Mode)> res = t;
res.prescale(factor()); res.prescale(factor());
return res; return res;
} }
/** Concatenates a uniform scaling and a linear transformation matrix */ /** Concatenates a uniform scaling and a linear transformation matrix */
// TODO returns an expression // TODO returns an expression

View File

@ -530,9 +530,9 @@ public:
inline Transform& operator=(const UniformScaling<Scalar>& t); inline Transform& operator=(const UniformScaling<Scalar>& t);
inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); } inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); }
inline Transform<Scalar,Dim,(int(Mode)==int(Isometry)?Affine:Mode)> operator*(const UniformScaling<Scalar>& s) const inline TransformTimeDiagonalReturnType operator*(const UniformScaling<Scalar>& s) const
{ {
Transform<Scalar,Dim,(int(Mode)==int(Isometry)?Affine:Mode),Options> res = *this; TransformTimeDiagonalReturnType res = *this;
res.scale(s.factor()); res.scale(s.factor());
return res; return res;
} }

View File

@ -12,6 +12,14 @@
namespace Eigen { namespace Eigen {
#if defined(DCOMPLEX)
#define PASTIX_COMPLEX COMPLEX
#define PASTIX_DCOMPLEX DCOMPLEX
#else
#define PASTIX_COMPLEX std::complex<float>
#define PASTIX_DCOMPLEX std::complex<double>
#endif
/** \ingroup PaStiXSupport_Module /** \ingroup PaStiXSupport_Module
* \brief Interface to the PaStix solver * \brief Interface to the PaStix solver
* *
@ -74,14 +82,14 @@ namespace internal
{ {
if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; }
if (nbrhs == 0) {x = NULL; nbrhs=1;} if (nbrhs == 0) {x = NULL; nbrhs=1;}
c_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast<COMPLEX*>(vals), perm, invp, reinterpret_cast<COMPLEX*>(x), nbrhs, iparm, dparm); c_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast<PASTIX_COMPLEX*>(vals), perm, invp, reinterpret_cast<PASTIX_COMPLEX*>(x), nbrhs, iparm, dparm);
} }
void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex<double> *vals, int *perm, int * invp, std::complex<double> *x, int nbrhs, int *iparm, double *dparm) void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex<double> *vals, int *perm, int * invp, std::complex<double> *x, int nbrhs, int *iparm, double *dparm)
{ {
if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; }
if (nbrhs == 0) {x = NULL; nbrhs=1;} if (nbrhs == 0) {x = NULL; nbrhs=1;}
z_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast<DCOMPLEX*>(vals), perm, invp, reinterpret_cast<DCOMPLEX*>(x), nbrhs, iparm, dparm); z_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast<PASTIX_DCOMPLEX*>(vals), perm, invp, reinterpret_cast<PASTIX_DCOMPLEX*>(x), nbrhs, iparm, dparm);
} }
// Convert the matrix to Fortran-style Numbering // Convert the matrix to Fortran-style Numbering

View File

@ -350,7 +350,7 @@ template<typename _MatrixType> class ColPivHouseholderQR
return m_usePrescribedThreshold ? m_prescribedThreshold return m_usePrescribedThreshold ? m_prescribedThreshold
// this formula comes from experimenting (see "LU precision tuning" thread on the list) // this formula comes from experimenting (see "LU precision tuning" thread on the list)
// and turns out to be identical to Higham's formula used already in LDLt. // and turns out to be identical to Higham's formula used already in LDLt.
: NumTraits<Scalar>::epsilon() * m_qr.diagonalSize(); : NumTraits<Scalar>::epsilon() * RealScalar(m_qr.diagonalSize());
} }
/** \returns the number of nonzero pivots in the QR decomposition. /** \returns the number of nonzero pivots in the QR decomposition.

View File

@ -346,7 +346,7 @@ template<typename _MatrixType> class FullPivHouseholderQR
return m_usePrescribedThreshold ? m_prescribedThreshold return m_usePrescribedThreshold ? m_prescribedThreshold
// this formula comes from experimenting (see "LU precision tuning" thread on the list) // this formula comes from experimenting (see "LU precision tuning" thread on the list)
// and turns out to be identical to Higham's formula used already in LDLt. // and turns out to be identical to Higham's formula used already in LDLt.
: NumTraits<Scalar>::epsilon() * m_qr.diagonalSize(); : NumTraits<Scalar>::epsilon() * RealScalar(m_qr.diagonalSize());
} }
/** \returns the number of nonzero pivots in the QR decomposition. /** \returns the number of nonzero pivots in the QR decomposition.
@ -417,7 +417,7 @@ FullPivHouseholderQR<MatrixType>& FullPivHouseholderQR<MatrixType>::compute(cons
m_temp.resize(cols); m_temp.resize(cols);
m_precision = NumTraits<Scalar>::epsilon() * size; m_precision = NumTraits<Scalar>::epsilon() * RealScalar(size);
m_rows_transpositions.resize(size); m_rows_transpositions.resize(size);
m_cols_transpositions.resize(size); m_cols_transpositions.resize(size);

View File

@ -338,7 +338,10 @@ const Block<const Derived,Dynamic,Dynamic,true> SparseMatrixBase<Derived>::inner
namespace internal { namespace internal {
template< typename XprType, int BlockRows, int BlockCols, bool InnerPanel, template< typename XprType, int BlockRows, int BlockCols, bool InnerPanel,
bool OuterVector = (BlockCols==1 && XprType::IsRowMajor) || (BlockRows==1 && !XprType::IsRowMajor)> bool OuterVector = (BlockCols==1 && XprType::IsRowMajor)
| // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&".
// revert to || as soon as not needed anymore.
(BlockRows==1 && !XprType::IsRowMajor)>
class GenericSparseBlockInnerIteratorImpl; class GenericSparseBlockInnerIteratorImpl;
} }

View File

@ -48,6 +48,12 @@ include_directories(
# set(DEFAULT_LIBRARIES ${MKL_LIBRARIES}) # set(DEFAULT_LIBRARIES ${MKL_LIBRARIES})
# endif (MKL_FOUND) # endif (MKL_FOUND)
find_library(EIGEN_BTL_RT_LIBRARY rt)
# if we cannot find it easily, then we don't need it!
if(NOT EIGEN_BTL_RT_LIBRARY)
set(EIGEN_BTL_RT_LIBRARY "")
endif()
MACRO(BTL_ADD_BENCH targetname) MACRO(BTL_ADD_BENCH targetname)
foreach(_current_var ${ARGN}) foreach(_current_var ${ARGN})
@ -70,7 +76,7 @@ MACRO(BTL_ADD_BENCH targetname)
IF(BUILD_${targetname}) IF(BUILD_${targetname})
ADD_EXECUTABLE(${targetname} ${_sources}) ADD_EXECUTABLE(${targetname} ${_sources})
ADD_TEST(${targetname} "${targetname}") ADD_TEST(${targetname} "${targetname}")
target_link_libraries(${targetname} ${DEFAULT_LIBRARIES} rt) target_link_libraries(${targetname} ${DEFAULT_LIBRARIES} ${EIGEN_BTL_RT_LIBRARY})
ENDIF(BUILD_${targetname}) ENDIF(BUILD_${targetname})
ENDMACRO(BTL_ADD_BENCH) ENDMACRO(BTL_ADD_BENCH)

View File

@ -102,8 +102,8 @@ BTL_DONT_INLINE void bench( int size_min, int size_max, int nb_point )
// merge the two data // merge the two data
std::vector<int> newSizes; std::vector<int> newSizes;
std::vector<double> newFlops; std::vector<double> newFlops;
int i=0; unsigned int i=0;
int j=0; unsigned int j=0;
while (i<tab_sizes.size() && j<oldSizes.size()) while (i<tab_sizes.size() && j<oldSizes.size())
{ {
if (tab_sizes[i] == oldSizes[j]) if (tab_sizes[i] == oldSizes[j])

View File

@ -46,7 +46,7 @@
#if (defined __GNUC__) && (!defined __INTEL_COMPILER) && !defined(__arm__) && !defined(__powerpc__) #if (defined __GNUC__) && (!defined __INTEL_COMPILER) && !defined(__arm__) && !defined(__powerpc__)
#define BTL_DISABLE_SSE_EXCEPTIONS() { \ #define BTL_DISABLE_SSE_EXCEPTIONS() { \
int aux; \ int aux = 0; \
asm( \ asm( \
"stmxcsr %[aux] \n\t" \ "stmxcsr %[aux] \n\t" \
"orl $32832, %[aux] \n\t" \ "orl $32832, %[aux] \n\t" \

View File

@ -29,7 +29,7 @@ BTL_DONT_INLINE void init_row(Vector & X, int size, int row){
X.resize(size); X.resize(size);
for (int j=0;j<X.size();j++){ for (unsigned int j=0;j<X.size();j++){
X[j]=typename Vector::value_type(init_function(row,j)); X[j]=typename Vector::value_type(init_function(row,j));
} }
} }
@ -42,7 +42,7 @@ BTL_DONT_INLINE void init_row(Vector & X, int size, int row){
template<double init_function(int,int),class Vector> template<double init_function(int,int),class Vector>
BTL_DONT_INLINE void init_matrix(Vector & A, int size){ BTL_DONT_INLINE void init_matrix(Vector & A, int size){
A.resize(size); A.resize(size);
for (int row=0; row<A.size() ; row++){ for (unsigned int row=0; row<A.size() ; row++){
init_row<init_function>(A[row],size,row); init_row<init_function>(A[row],size,row);
} }
} }
@ -50,11 +50,11 @@ BTL_DONT_INLINE void init_matrix(Vector & A, int size){
template<double init_function(int,int),class Matrix> template<double init_function(int,int),class Matrix>
BTL_DONT_INLINE void init_matrix_symm(Matrix& A, int size){ BTL_DONT_INLINE void init_matrix_symm(Matrix& A, int size){
A.resize(size); A.resize(size);
for (int row=0; row<A.size() ; row++) for (unsigned int row=0; row<A.size() ; row++)
A[row].resize(size); A[row].resize(size);
for (int row=0; row<A.size() ; row++){ for (unsigned int row=0; row<A.size() ; row++){
A[row][row] = init_function(row,row); A[row][row] = init_function(row,row);
for (int col=0; col<row ; col++){ for (unsigned int col=0; col<row ; col++){
double x = init_function(row,col); double x = init_function(row,col);
A[row][col] = A[col][row] = x; A[row][col] = A[col][row] = x;
} }

View File

@ -29,7 +29,7 @@ void init_vector(Vector & X, int size){
X.resize(size); X.resize(size);
for (int i=0;i<X.size();i++){ for (unsigned int i=0;i<X.size();i++){
X[i]=typename Vector::value_type(init_function(i)); X[i]=typename Vector::value_type(init_function(i));
} }
} }

View File

@ -78,7 +78,7 @@ public:
// time measurement // time measurement
action.calculate(); action.calculate();
_chronos.start(); _chronos.start();
for (int ii=0;ii<_nb_calc;ii++) for (unsigned int ii=0;ii<_nb_calc;ii++)
{ {
action.calculate(); action.calculate();
} }

View File

@ -34,7 +34,7 @@
// timer -------------------------------------------------------------------// // timer -------------------------------------------------------------------//
// A timer object measures CPU time. // A timer object measures CPU time.
#ifdef _MSC_VER #if defined(_MSC_VER)
#define NOMINMAX #define NOMINMAX
#include <windows.h> #include <windows.h>
@ -87,6 +87,48 @@
}; // Portable_Timer }; // Portable_Timer
#elif defined(__APPLE__)
#include <CoreServices/CoreServices.h>
#include <mach/mach_time.h>
class Portable_Timer
{
public:
Portable_Timer()
{
}
void start()
{
m_start_time = double(mach_absolute_time())*1e-9;;
}
void stop()
{
m_stop_time = double(mach_absolute_time())*1e-9;;
}
double elapsed()
{
return user_time();
}
double user_time()
{
return m_stop_time - m_start_time;
}
private:
double m_stop_time, m_start_time;
}; // Portable_Timer (Apple)
#else #else
#include <sys/time.h> #include <sys/time.h>
@ -138,7 +180,7 @@ private:
int m_clkid; int m_clkid;
double m_stop_time, m_start_time; double m_stop_time, m_start_time;
}; // Portable_Timer }; // Portable_Timer (Linux)
#endif #endif

View File

@ -52,8 +52,8 @@ public :
static BTL_DONT_INLINE void matrix_from_stl(gene_matrix & A, stl_matrix & A_stl){ static BTL_DONT_INLINE void matrix_from_stl(gene_matrix & A, stl_matrix & A_stl){
A.resize(A_stl[0].size(), A_stl.size()); A.resize(A_stl[0].size(), A_stl.size());
for (int j=0; j<A_stl.size() ; j++){ for (unsigned int j=0; j<A_stl.size() ; j++){
for (int i=0; i<A_stl[j].size() ; i++){ for (unsigned int i=0; i<A_stl[j].size() ; i++){
A.coeffRef(i,j) = A_stl[j][i]; A.coeffRef(i,j) = A_stl[j][i];
} }
} }
@ -62,13 +62,13 @@ public :
static BTL_DONT_INLINE void vector_from_stl(gene_vector & B, stl_vector & B_stl){ static BTL_DONT_INLINE void vector_from_stl(gene_vector & B, stl_vector & B_stl){
B.resize(B_stl.size(),1); B.resize(B_stl.size(),1);
for (int i=0; i<B_stl.size() ; i++){ for (unsigned int i=0; i<B_stl.size() ; i++){
B.coeffRef(i) = B_stl[i]; B.coeffRef(i) = B_stl[i];
} }
} }
static BTL_DONT_INLINE void vector_to_stl(gene_vector & B, stl_vector & B_stl){ static BTL_DONT_INLINE void vector_to_stl(gene_vector & B, stl_vector & B_stl){
for (int i=0; i<B_stl.size() ; i++){ for (unsigned int i=0; i<B_stl.size() ; i++){
B_stl[i] = B.coeff(i); B_stl[i] = B.coeff(i);
} }
} }

View File

@ -249,7 +249,7 @@ For an introduction on linear solvers and decompositions, check this \link Tutor
<dt><b>Implicit Multi Threading (MT)</b></dt> <dt><b>Implicit Multi Threading (MT)</b></dt>
<dd>Means the algorithm can take advantage of multicore processors via OpenMP. "Implicit" means the algortihm itself is not parallelized, but that it relies on parallelized matrix-matrix product rountines.</dd> <dd>Means the algorithm can take advantage of multicore processors via OpenMP. "Implicit" means the algortihm itself is not parallelized, but that it relies on parallelized matrix-matrix product rountines.</dd>
<dt><b>Explicit Multi Threading (MT)</b></dt> <dt><b>Explicit Multi Threading (MT)</b></dt>
<dd>Means the algorithm is explicitely parallelized to take advantage of multicore processors via OpenMP.</dd> <dd>Means the algorithm is explicitly parallelized to take advantage of multicore processors via OpenMP.</dd>
<dt><b>Meta-unroller</b></dt> <dt><b>Meta-unroller</b></dt>
<dd>Means the algorithm is automatically and explicitly unrolled for very small fixed size matrices.</dd> <dd>Means the algorithm is automatically and explicitly unrolled for very small fixed size matrices.</dd>
<dt><b></b></dt> <dt><b></b></dt>

View File

@ -39,7 +39,7 @@ int main(int argc, char** argv)
} }
\endcode \endcode
\warning note that all functions generating random matrices are \b not re-entrant nor thread-safe. Those include DenseBase::Random(), and DenseBase::setRandom() despite a call to Eigen::initParallel(). This is because these functions are based on std::rand which is not re-entrant. For thread-safe random generator, we recommend the use of boost::random of c++11 random feature. \warning note that all functions generating random matrices are \b not re-entrant nor thread-safe. Those include DenseBase::Random(), and DenseBase::setRandom() despite a call to Eigen::initParallel(). This is because these functions are based on std::rand which is not re-entrant. For thread-safe random generator, we recommend the use of boost::random or c++11 random feature.
In the case your application is parallelized with OpenMP, you might want to disable Eigen's own parallization as detailed in the previous section. In the case your application is parallelized with OpenMP, you might want to disable Eigen's own parallization as detailed in the previous section.

View File

@ -1,4 +1,4 @@
MatrixXd ones = MatrixXd::Ones(3,3); MatrixXd ones = MatrixXd::Ones(3,3);
EigenSolver<MatrixXd> es(ones); EigenSolver<MatrixXd> es(ones);
cout << "The first eigenvector of the 3x3 matrix of ones is:" cout << "The first eigenvector of the 3x3 matrix of ones is:"
<< endl << es.eigenvectors().col(1) << endl; << endl << es.eigenvectors().col(0) << endl;

View File

@ -13,11 +13,26 @@ if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/split_test_helper.h)
endforeach() endforeach()
endif() endif()
# check if we have a Fortran compiler
include("../cmake/language_support.cmake")
workaround_9220(Fortran EIGEN_Fortran_COMPILER_WORKS)
if(EIGEN_Fortran_COMPILER_WORKS)
enable_language(Fortran OPTIONAL)
if(NOT CMAKE_Fortran_COMPILER)
set(EIGEN_Fortran_COMPILER_WORKS OFF)
endif()
endif()
if(NOT EIGEN_Fortran_COMPILER_WORKS)
# search for a default Lapack library to complete Eigen's one
find_package(LAPACK)
endif()
# configure blas/lapack (use Eigen's ones) # configure blas/lapack (use Eigen's ones)
set(BLAS_FOUND TRUE) set(EIGEN_BLAS_LIBRARIES eigen_blas)
set(LAPACK_FOUND TRUE) set(EIGEN_LAPACK_LIBRARIES eigen_lapack)
set(BLAS_LIBRARIES eigen_blas)
set(LAPACK_LIBRARIES eigen_lapack)
set(EIGEN_TEST_MATRIX_DIR "" CACHE STRING "Enable testing of realword sparse matrices contained in the specified path") set(EIGEN_TEST_MATRIX_DIR "" CACHE STRING "Enable testing of realword sparse matrices contained in the specified path")
if(EIGEN_TEST_MATRIX_DIR) if(EIGEN_TEST_MATRIX_DIR)
@ -32,33 +47,33 @@ endif(EIGEN_TEST_MATRIX_DIR)
set(SPARSE_LIBS " ") set(SPARSE_LIBS " ")
find_package(Cholmod) find_package(Cholmod)
if(CHOLMOD_FOUND AND BLAS_FOUND AND LAPACK_FOUND) if(CHOLMOD_FOUND)
add_definitions("-DEIGEN_CHOLMOD_SUPPORT") add_definitions("-DEIGEN_CHOLMOD_SUPPORT")
include_directories(${CHOLMOD_INCLUDES}) include_directories(${CHOLMOD_INCLUDES})
set(SPARSE_LIBS ${SPARSE_LIBS} ${CHOLMOD_LIBRARIES} ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES}) set(SPARSE_LIBS ${SPARSE_LIBS} ${CHOLMOD_LIBRARIES} ${EIGEN_BLAS_LIBRARIES} ${EIGEN_LAPACK_LIBRARIES})
set(CHOLMOD_ALL_LIBS ${CHOLMOD_LIBRARIES} ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES}) set(CHOLMOD_ALL_LIBS ${CHOLMOD_LIBRARIES} ${EIGEN_BLAS_LIBRARIES} ${EIGEN_LAPACK_LIBRARIES})
ei_add_property(EIGEN_TESTED_BACKENDS "Cholmod, ") ei_add_property(EIGEN_TESTED_BACKENDS "Cholmod, ")
else() else()
ei_add_property(EIGEN_MISSING_BACKENDS "Cholmod, ") ei_add_property(EIGEN_MISSING_BACKENDS "Cholmod, ")
endif() endif()
find_package(Umfpack) find_package(Umfpack)
if(UMFPACK_FOUND AND BLAS_FOUND) if(UMFPACK_FOUND)
add_definitions("-DEIGEN_UMFPACK_SUPPORT") add_definitions("-DEIGEN_UMFPACK_SUPPORT")
include_directories(${UMFPACK_INCLUDES}) include_directories(${UMFPACK_INCLUDES})
set(SPARSE_LIBS ${SPARSE_LIBS} ${UMFPACK_LIBRARIES} ${BLAS_LIBRARIES}) set(SPARSE_LIBS ${SPARSE_LIBS} ${UMFPACK_LIBRARIES} ${EIGEN_BLAS_LIBRARIES})
set(UMFPACK_ALL_LIBS ${UMFPACK_LIBRARIES} ${BLAS_LIBRARIES}) set(UMFPACK_ALL_LIBS ${UMFPACK_LIBRARIES} ${EIGEN_BLAS_LIBRARIES})
ei_add_property(EIGEN_TESTED_BACKENDS "UmfPack, ") ei_add_property(EIGEN_TESTED_BACKENDS "UmfPack, ")
else() else()
ei_add_property(EIGEN_MISSING_BACKENDS "UmfPack, ") ei_add_property(EIGEN_MISSING_BACKENDS "UmfPack, ")
endif() endif()
find_package(SuperLU) find_package(SuperLU)
if(SUPERLU_FOUND AND BLAS_FOUND) if(SUPERLU_FOUND)
add_definitions("-DEIGEN_SUPERLU_SUPPORT") add_definitions("-DEIGEN_SUPERLU_SUPPORT")
include_directories(${SUPERLU_INCLUDES}) include_directories(${SUPERLU_INCLUDES})
set(SPARSE_LIBS ${SPARSE_LIBS} ${SUPERLU_LIBRARIES} ${BLAS_LIBRARIES}) set(SPARSE_LIBS ${SPARSE_LIBS} ${SUPERLU_LIBRARIES} ${EIGEN_BLAS_LIBRARIES})
set(SUPERLU_ALL_LIBS ${SUPERLU_LIBRARIES} ${BLAS_LIBRARIES}) set(SUPERLU_ALL_LIBS ${SUPERLU_LIBRARIES} ${EIGEN_BLAS_LIBRARIES})
ei_add_property(EIGEN_TESTED_BACKENDS "SuperLU, ") ei_add_property(EIGEN_TESTED_BACKENDS "SuperLU, ")
else() else()
ei_add_property(EIGEN_MISSING_BACKENDS "SuperLU, ") ei_add_property(EIGEN_MISSING_BACKENDS "SuperLU, ")
@ -68,7 +83,7 @@ endif()
find_package(Pastix) find_package(Pastix)
find_package(Scotch) find_package(Scotch)
find_package(Metis) find_package(Metis)
if(PASTIX_FOUND AND BLAS_FOUND) if(PASTIX_FOUND)
add_definitions("-DEIGEN_PASTIX_SUPPORT") add_definitions("-DEIGEN_PASTIX_SUPPORT")
include_directories(${PASTIX_INCLUDES}) include_directories(${PASTIX_INCLUDES})
if(SCOTCH_FOUND) if(SCOTCH_FOUND)
@ -80,8 +95,8 @@ if(PASTIX_FOUND AND BLAS_FOUND)
else(SCOTCH_FOUND) else(SCOTCH_FOUND)
ei_add_property(EIGEN_MISSING_BACKENDS "PaStiX, ") ei_add_property(EIGEN_MISSING_BACKENDS "PaStiX, ")
endif(SCOTCH_FOUND) endif(SCOTCH_FOUND)
set(SPARSE_LIBS ${SPARSE_LIBS} ${PASTIX_LIBRARIES} ${ORDERING_LIBRARIES} ${BLAS_LIBRARIES}) set(SPARSE_LIBS ${SPARSE_LIBS} ${PASTIX_LIBRARIES} ${ORDERING_LIBRARIES} ${EIGEN_BLAS_LIBRARIES})
set(PASTIX_ALL_LIBS ${PASTIX_LIBRARIES} ${BLAS_LIBRARIES}) set(PASTIX_ALL_LIBS ${PASTIX_LIBRARIES} ${EIGEN_BLAS_LIBRARIES})
ei_add_property(EIGEN_TESTED_BACKENDS "PaStiX, ") ei_add_property(EIGEN_TESTED_BACKENDS "PaStiX, ")
else() else()
ei_add_property(EIGEN_MISSING_BACKENDS "PaStiX, ") ei_add_property(EIGEN_MISSING_BACKENDS "PaStiX, ")
@ -96,16 +111,14 @@ else()
endif() endif()
find_package(SPQR) find_package(SPQR)
if(SPQR_FOUND AND BLAS_FOUND AND LAPACK_FOUND) if(SPQR_FOUND AND CHOLMOD_FOUND AND (EIGEN_Fortran_COMPILER_WORKS OR LAPACK_FOUND) )
if(CHOLMOD_FOUND) add_definitions("-DEIGEN_SPQR_SUPPORT")
add_definitions("-DEIGEN_SPQR_SUPPORT") include_directories(${SPQR_INCLUDES})
include_directories(${SPQR_INCLUDES}) set(SPQR_ALL_LIBS ${SPQR_LIBRARIES} ${CHOLMOD_LIBRARIES} ${EIGEN_LAPACK_LIBRARIES} ${EIGEN_BLAS_LIBRARIES} ${LAPACK_LIBRARIES})
set(SPQR_ALL_LIBS ${SPQR_LIBRARIES} ${CHOLMOD_LIBRARIES} ${LAPACK_LIBRARIES} ${BLAS_LIBRARIES}) set(SPARSE_LIBS ${SPARSE_LIBS} ${SPQR_ALL_LIBS})
set(SPARSE_LIBS ${SPARSE_LIBS} ${SPQR_ALL_LIBS}) ei_add_property(EIGEN_TESTED_BACKENDS "SPQR, ")
ei_add_property(EIGEN_TESTED_BACKENDS "SPQR, ") else()
else(CHOLMOD_FOUND) ei_add_property(EIGEN_MISSING_BACKENDS "SPQR, ")
ei_add_property(EIGEN_MISSING_BACKENDS "SPQR, ")
endif(CHOLMOD_FOUND)
endif() endif()
option(EIGEN_TEST_NOQT "Disable Qt support in unit tests" OFF) option(EIGEN_TEST_NOQT "Disable Qt support in unit tests" OFF)

View File

@ -10,6 +10,26 @@
#define EIGEN_NO_STATIC_ASSERT // otherwise we fail at compile time on unused paths #define EIGEN_NO_STATIC_ASSERT // otherwise we fail at compile time on unused paths
#include "main.h" #include "main.h"
template<typename MatrixType, typename Index, typename Scalar>
typename Eigen::internal::enable_if<!NumTraits<typename MatrixType::Scalar>::IsComplex,typename MatrixType::Scalar>::type
block_real_only(const MatrixType &m1, Index r1, Index r2, Index c1, Index c2, const Scalar& s1) {
// check cwise-Functions:
VERIFY_IS_APPROX(m1.row(r1).cwiseMax(s1), m1.cwiseMax(s1).row(r1));
VERIFY_IS_APPROX(m1.col(c1).cwiseMin(s1), m1.cwiseMin(s1).col(c1));
VERIFY_IS_APPROX(m1.block(r1,c1,r2-r1+1,c2-c1+1).cwiseMin(s1), m1.cwiseMin(s1).block(r1,c1,r2-r1+1,c2-c1+1));
VERIFY_IS_APPROX(m1.block(r1,c1,r2-r1+1,c2-c1+1).cwiseMax(s1), m1.cwiseMax(s1).block(r1,c1,r2-r1+1,c2-c1+1));
return Scalar(0);
}
template<typename MatrixType, typename Index, typename Scalar>
typename Eigen::internal::enable_if<NumTraits<typename MatrixType::Scalar>::IsComplex,typename MatrixType::Scalar>::type
block_real_only(const MatrixType &, Index, Index, Index, Index, const Scalar&) {
return Scalar(0);
}
template<typename MatrixType> void block(const MatrixType& m) template<typename MatrixType> void block(const MatrixType& m)
{ {
typedef typename MatrixType::Index Index; typedef typename MatrixType::Index Index;
@ -37,6 +57,8 @@ template<typename MatrixType> void block(const MatrixType& m)
Index c1 = internal::random<Index>(0,cols-1); Index c1 = internal::random<Index>(0,cols-1);
Index c2 = internal::random<Index>(c1,cols-1); Index c2 = internal::random<Index>(c1,cols-1);
block_real_only(m1, r1, r2, c1, c1, s1);
//check row() and col() //check row() and col()
VERIFY_IS_EQUAL(m1.col(c1).transpose(), m1.transpose().row(c1)); VERIFY_IS_EQUAL(m1.col(c1).transpose(), m1.transpose().row(c1));
//check operator(), both constant and non-constant, on row() and col() //check operator(), both constant and non-constant, on row() and col()
@ -51,7 +73,8 @@ template<typename MatrixType> void block(const MatrixType& m)
VERIFY_IS_APPROX(m1.col(c1), m1_copy.col(c1) + s1 * m1_copy.col(c2)); VERIFY_IS_APPROX(m1.col(c1), m1_copy.col(c1) + s1 * m1_copy.col(c2));
m1.col(c1).col(0) += s1 * m1_copy.col(c2); m1.col(c1).col(0) += s1 * m1_copy.col(c2);
VERIFY_IS_APPROX(m1.col(c1), m1_copy.col(c1) + Scalar(2) * s1 * m1_copy.col(c2)); VERIFY_IS_APPROX(m1.col(c1), m1_copy.col(c1) + Scalar(2) * s1 * m1_copy.col(c2));
//check block() //check block()
Matrix<Scalar,Dynamic,Dynamic> b1(1,1); b1(0,0) = m1(r1,c1); Matrix<Scalar,Dynamic,Dynamic> b1(1,1); b1(0,0) = m1(r1,c1);

View File

@ -179,6 +179,38 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
// restore // restore
if(sign == -1) if(sign == -1)
symm = -symm; symm = -symm;
// check matrices coming from linear constraints with Lagrange multipliers
if(rows>=3)
{
SquareMatrixType A = symm;
int c = internal::random<int>(0,rows-2);
A.bottomRightCorner(c,c).setZero();
// Make sure a solution exists:
vecX.setRandom();
vecB = A * vecX;
vecX.setZero();
ldltlo.compute(A);
VERIFY_IS_APPROX(A, ldltlo.reconstructedMatrix());
vecX = ldltlo.solve(vecB);
VERIFY_IS_APPROX(A * vecX, vecB);
}
// check non-full rank matrices
if(rows>=3)
{
int r = internal::random<int>(1,rows-1);
Matrix<Scalar,Dynamic,Dynamic> a = Matrix<Scalar,Dynamic,Dynamic>::Random(rows,r);
SquareMatrixType A = a * a.adjoint();
// Make sure a solution exists:
vecX.setRandom();
vecB = A * vecX;
vecX.setZero();
ldltlo.compute(A);
VERIFY_IS_APPROX(A, ldltlo.reconstructedMatrix());
vecX = ldltlo.solve(vecB);
VERIFY_IS_APPROX(A * vecX, vecB);
}
} }
// update/downdate // update/downdate

View File

@ -154,59 +154,79 @@ template<typename PlainObjectType> void check_const_correctness(const PlainObjec
VERIFY( !(Ref<ConstPlainObjectType, Aligned>::Flags & LvalueBit) ); VERIFY( !(Ref<ConstPlainObjectType, Aligned>::Flags & LvalueBit) );
} }
EIGEN_DONT_INLINE void call_ref_1(Ref<VectorXf> ) { } template<typename B>
EIGEN_DONT_INLINE void call_ref_2(const Ref<const VectorXf>& ) { } EIGEN_DONT_INLINE void call_ref_1(Ref<VectorXf> a, const B &b) { VERIFY_IS_EQUAL(a,b); }
EIGEN_DONT_INLINE void call_ref_3(Ref<VectorXf,0,InnerStride<> > ) { } template<typename B>
EIGEN_DONT_INLINE void call_ref_4(const Ref<const VectorXf,0,InnerStride<> >& ) { } EIGEN_DONT_INLINE void call_ref_2(const Ref<const VectorXf>& a, const B &b) { VERIFY_IS_EQUAL(a,b); }
EIGEN_DONT_INLINE void call_ref_5(Ref<MatrixXf,0,OuterStride<> > ) { } template<typename B>
EIGEN_DONT_INLINE void call_ref_6(const Ref<const MatrixXf,0,OuterStride<> >& ) { } EIGEN_DONT_INLINE void call_ref_3(Ref<VectorXf,0,InnerStride<> > a, const B &b) { VERIFY_IS_EQUAL(a,b); }
template<typename B>
EIGEN_DONT_INLINE void call_ref_4(const Ref<const VectorXf,0,InnerStride<> >& a, const B &b) { VERIFY_IS_EQUAL(a,b); }
template<typename B>
EIGEN_DONT_INLINE void call_ref_5(Ref<MatrixXf,0,OuterStride<> > a, const B &b) { VERIFY_IS_EQUAL(a,b); }
template<typename B>
EIGEN_DONT_INLINE void call_ref_6(const Ref<const MatrixXf,0,OuterStride<> >& a, const B &b) { VERIFY_IS_EQUAL(a,b); }
template<typename B>
EIGEN_DONT_INLINE void call_ref_7(Ref<Matrix<float,Dynamic,3> > a, const B &b) { VERIFY_IS_EQUAL(a,b); }
void call_ref() void call_ref()
{ {
VectorXcf ca(10); VectorXcf ca = VectorXcf::Random(10);
VectorXf a(10); VectorXf a = VectorXf::Random(10);
RowVectorXf b = RowVectorXf::Random(10);
MatrixXf A = MatrixXf::Random(10,10);
RowVector3f c = RowVector3f::Random();
const VectorXf& ac(a); const VectorXf& ac(a);
VectorBlock<VectorXf> ab(a,0,3); VectorBlock<VectorXf> ab(a,0,3);
MatrixXf A(10,10);
const VectorBlock<VectorXf> abc(a,0,3); const VectorBlock<VectorXf> abc(a,0,3);
VERIFY_EVALUATION_COUNT( call_ref_1(a), 0); VERIFY_EVALUATION_COUNT( call_ref_1(a,a), 0);
//call_ref_1(ac); // does not compile because ac is const VERIFY_EVALUATION_COUNT( call_ref_1(b,b.transpose()), 0);
VERIFY_EVALUATION_COUNT( call_ref_1(ab), 0); // call_ref_1(ac); // does not compile because ac is const
VERIFY_EVALUATION_COUNT( call_ref_1(a.head(4)), 0); VERIFY_EVALUATION_COUNT( call_ref_1(ab,ab), 0);
VERIFY_EVALUATION_COUNT( call_ref_1(abc), 0); VERIFY_EVALUATION_COUNT( call_ref_1(a.head(4),a.head(4)), 0);
VERIFY_EVALUATION_COUNT( call_ref_1(A.col(3)), 0); VERIFY_EVALUATION_COUNT( call_ref_1(abc,abc), 0);
// call_ref_1(A.row(3)); // does not compile because innerstride!=1 VERIFY_EVALUATION_COUNT( call_ref_1(A.col(3),A.col(3)), 0);
VERIFY_EVALUATION_COUNT( call_ref_3(A.row(3)), 0); // call_ref_1(A.row(3)); // does not compile because innerstride!=1
VERIFY_EVALUATION_COUNT( call_ref_4(A.row(3)), 0); VERIFY_EVALUATION_COUNT( call_ref_3(A.row(3),A.row(3).transpose()), 0);
//call_ref_1(a+a); // does not compile for obvious reason VERIFY_EVALUATION_COUNT( call_ref_4(A.row(3),A.row(3).transpose()), 0);
// call_ref_1(a+a); // does not compile for obvious reason
VERIFY_EVALUATION_COUNT( call_ref_2(A*A.col(1)), 1); // evaluated into a temp MatrixXf tmp = A*A.col(1);
VERIFY_EVALUATION_COUNT( call_ref_2(ac.head(5)), 0); VERIFY_EVALUATION_COUNT( call_ref_2(A*A.col(1), tmp), 1); // evaluated into a temp
VERIFY_EVALUATION_COUNT( call_ref_2(ac), 0); VERIFY_EVALUATION_COUNT( call_ref_2(ac.head(5),ac.head(5)), 0);
VERIFY_EVALUATION_COUNT( call_ref_2(a), 0); VERIFY_EVALUATION_COUNT( call_ref_2(ac,ac), 0);
VERIFY_EVALUATION_COUNT( call_ref_2(ab), 0); VERIFY_EVALUATION_COUNT( call_ref_2(a,a), 0);
VERIFY_EVALUATION_COUNT( call_ref_2(a.head(4)), 0); VERIFY_EVALUATION_COUNT( call_ref_2(ab,ab), 0);
VERIFY_EVALUATION_COUNT( call_ref_2(a+a), 1); // evaluated into a temp VERIFY_EVALUATION_COUNT( call_ref_2(a.head(4),a.head(4)), 0);
VERIFY_EVALUATION_COUNT( call_ref_2(ca.imag()), 1); // evaluated into a temp tmp = a+a;
VERIFY_EVALUATION_COUNT( call_ref_2(a+a,tmp), 1); // evaluated into a temp
VERIFY_EVALUATION_COUNT( call_ref_2(ca.imag(),ca.imag()), 1); // evaluated into a temp
VERIFY_EVALUATION_COUNT( call_ref_4(ac.head(5)), 0); VERIFY_EVALUATION_COUNT( call_ref_4(ac.head(5),ac.head(5)), 0);
VERIFY_EVALUATION_COUNT( call_ref_4(a+a), 1); // evaluated into a temp tmp = a+a;
VERIFY_EVALUATION_COUNT( call_ref_4(ca.imag()), 0); VERIFY_EVALUATION_COUNT( call_ref_4(a+a,tmp), 1); // evaluated into a temp
VERIFY_EVALUATION_COUNT( call_ref_4(ca.imag(),ca.imag()), 0);
VERIFY_EVALUATION_COUNT( call_ref_5(a), 0); VERIFY_EVALUATION_COUNT( call_ref_5(a,a), 0);
VERIFY_EVALUATION_COUNT( call_ref_5(a.head(3)), 0); VERIFY_EVALUATION_COUNT( call_ref_5(a.head(3),a.head(3)), 0);
VERIFY_EVALUATION_COUNT( call_ref_5(A), 0); VERIFY_EVALUATION_COUNT( call_ref_5(A,A), 0);
// call_ref_5(A.transpose()); // does not compile // call_ref_5(A.transpose()); // does not compile
VERIFY_EVALUATION_COUNT( call_ref_5(A.block(1,1,2,2)), 0); VERIFY_EVALUATION_COUNT( call_ref_5(A.block(1,1,2,2),A.block(1,1,2,2)), 0);
VERIFY_EVALUATION_COUNT( call_ref_5(b,b), 0); // storage order do not match, but this is a degenerate case that should work
VERIFY_EVALUATION_COUNT( call_ref_5(a.row(3),a.row(3)), 0);
VERIFY_EVALUATION_COUNT( call_ref_6(a), 0); VERIFY_EVALUATION_COUNT( call_ref_6(a,a), 0);
VERIFY_EVALUATION_COUNT( call_ref_6(a.head(3)), 0); VERIFY_EVALUATION_COUNT( call_ref_6(a.head(3),a.head(3)), 0);
VERIFY_EVALUATION_COUNT( call_ref_6(A.row(3)), 1); // evaluated into a temp thouth it could be avoided by viewing it as a 1xn matrix VERIFY_EVALUATION_COUNT( call_ref_6(A.row(3),A.row(3)), 1); // evaluated into a temp thouth it could be avoided by viewing it as a 1xn matrix
VERIFY_EVALUATION_COUNT( call_ref_6(A+A), 1); // evaluated into a temp tmp = A+A;
VERIFY_EVALUATION_COUNT( call_ref_6(A), 0); VERIFY_EVALUATION_COUNT( call_ref_6(A+A,tmp), 1); // evaluated into a temp
VERIFY_EVALUATION_COUNT( call_ref_6(A.transpose()), 1); // evaluated into a temp because the storage orders do not match VERIFY_EVALUATION_COUNT( call_ref_6(A,A), 0);
VERIFY_EVALUATION_COUNT( call_ref_6(A.block(1,1,2,2)), 0); VERIFY_EVALUATION_COUNT( call_ref_6(A.transpose(),A.transpose()), 1); // evaluated into a temp because the storage orders do not match
VERIFY_EVALUATION_COUNT( call_ref_6(A.block(1,1,2,2),A.block(1,1,2,2)), 0);
VERIFY_EVALUATION_COUNT( call_ref_7(c,c), 0);
} }
void test_ref() void test_ref()

View File

@ -21,6 +21,8 @@ template<typename MatrixType> void verifySizeOf(const MatrixType&)
void test_sizeof() void test_sizeof()
{ {
CALL_SUBTEST(verifySizeOf(Matrix<float, 1, 1>()) ); CALL_SUBTEST(verifySizeOf(Matrix<float, 1, 1>()) );
CALL_SUBTEST(verifySizeOf(Vector2d()) );
CALL_SUBTEST(verifySizeOf(Vector4f()) );
CALL_SUBTEST(verifySizeOf(Matrix4d()) ); CALL_SUBTEST(verifySizeOf(Matrix4d()) );
CALL_SUBTEST(verifySizeOf(Matrix<double, 4, 2>()) ); CALL_SUBTEST(verifySizeOf(Matrix<double, 4, 2>()) );
CALL_SUBTEST(verifySizeOf(Matrix<bool, 7, 5>()) ); CALL_SUBTEST(verifySizeOf(Matrix<bool, 7, 5>()) );

View File

@ -37,22 +37,31 @@ namespace Eigen {
typedef typename Dest::Scalar Scalar; typedef typename Dest::Scalar Scalar;
typedef Matrix<Scalar,Dynamic,1> VectorType; typedef Matrix<Scalar,Dynamic,1> VectorType;
// Check for zero rhs
const RealScalar rhsNorm2(rhs.squaredNorm());
if(rhsNorm2 == 0)
{
x.setZero();
iters = 0;
tol_error = 0;
return;
}
// initialize // initialize
const int maxIters(iters); // initialize maxIters to iters const int maxIters(iters); // initialize maxIters to iters
const int N(mat.cols()); // the size of the matrix const int N(mat.cols()); // the size of the matrix
const RealScalar rhsNorm2(rhs.squaredNorm());
const RealScalar threshold2(tol_error*tol_error*rhsNorm2); // convergence threshold (compared to residualNorm2) const RealScalar threshold2(tol_error*tol_error*rhsNorm2); // convergence threshold (compared to residualNorm2)
// Initialize preconditioned Lanczos // Initialize preconditioned Lanczos
// VectorType v_old(N); // will be initialized inside loop VectorType v_old(N); // will be initialized inside loop
VectorType v( VectorType::Zero(N) ); //initialize v VectorType v( VectorType::Zero(N) ); //initialize v
VectorType v_new(rhs-mat*x); //initialize v_new VectorType v_new(rhs-mat*x); //initialize v_new
RealScalar residualNorm2(v_new.squaredNorm()); RealScalar residualNorm2(v_new.squaredNorm());
// VectorType w(N); // will be initialized inside loop VectorType w(N); // will be initialized inside loop
VectorType w_new(precond.solve(v_new)); // initialize w_new VectorType w_new(precond.solve(v_new)); // initialize w_new
// RealScalar beta; // will be initialized inside loop // RealScalar beta; // will be initialized inside loop
RealScalar beta_new2(v_new.dot(w_new)); RealScalar beta_new2(v_new.dot(w_new));
eigen_assert(beta_new2 >= 0 && "PRECONDITIONER IS NOT POSITIVE DEFINITE"); eigen_assert(beta_new2 >= 0.0 && "PRECONDITIONER IS NOT POSITIVE DEFINITE");
RealScalar beta_new(sqrt(beta_new2)); RealScalar beta_new(sqrt(beta_new2));
const RealScalar beta_one(beta_new); const RealScalar beta_one(beta_new);
v_new /= beta_new; v_new /= beta_new;
@ -62,14 +71,14 @@ namespace Eigen {
RealScalar c_old(1.0); RealScalar c_old(1.0);
RealScalar s(0.0); // the sine of the Givens rotation RealScalar s(0.0); // the sine of the Givens rotation
RealScalar s_old(0.0); // the sine of the Givens rotation RealScalar s_old(0.0); // the sine of the Givens rotation
// VectorType p_oold(N); // will be initialized in loop VectorType p_oold(N); // will be initialized in loop
VectorType p_old(VectorType::Zero(N)); // initialize p_old=0 VectorType p_old(VectorType::Zero(N)); // initialize p_old=0
VectorType p(p_old); // initialize p=0 VectorType p(p_old); // initialize p=0
RealScalar eta(1.0); RealScalar eta(1.0);
iters = 0; // reset iters iters = 0; // reset iters
while ( iters < maxIters ){ while ( iters < maxIters )
{
// Preconditioned Lanczos // Preconditioned Lanczos
/* Note that there are 4 variants on the Lanczos algorithm. These are /* Note that there are 4 variants on the Lanczos algorithm. These are
* described in Paige, C. C. (1972). Computational variants of * described in Paige, C. C. (1972). Computational variants of
@ -81,17 +90,17 @@ namespace Eigen {
* A. Greenbaum, Iterative Methods for Solving Linear Systems, SIAM (1987). * A. Greenbaum, Iterative Methods for Solving Linear Systems, SIAM (1987).
*/ */
const RealScalar beta(beta_new); const RealScalar beta(beta_new);
// v_old = v; // update: at first time step, this makes v_old = 0 so value of beta doesn't matter v_old = v; // update: at first time step, this makes v_old = 0 so value of beta doesn't matter
const VectorType v_old(v); // NOT SURE IF CREATING v_old EVERY ITERATION IS EFFICIENT // const VectorType v_old(v); // NOT SURE IF CREATING v_old EVERY ITERATION IS EFFICIENT
v = v_new; // update v = v_new; // update
// w = w_new; // update w = w_new; // update
const VectorType w(w_new); // NOT SURE IF CREATING w EVERY ITERATION IS EFFICIENT // const VectorType w(w_new); // NOT SURE IF CREATING w EVERY ITERATION IS EFFICIENT
v_new.noalias() = mat*w - beta*v_old; // compute v_new v_new.noalias() = mat*w - beta*v_old; // compute v_new
const RealScalar alpha = v_new.dot(w); const RealScalar alpha = v_new.dot(w);
v_new -= alpha*v; // overwrite v_new v_new -= alpha*v; // overwrite v_new
w_new = precond.solve(v_new); // overwrite w_new w_new = precond.solve(v_new); // overwrite w_new
beta_new2 = v_new.dot(w_new); // compute beta_new beta_new2 = v_new.dot(w_new); // compute beta_new
eigen_assert(beta_new2 >= 0 && "PRECONDITIONER IS NOT POSITIVE DEFINITE"); eigen_assert(beta_new2 >= 0.0 && "PRECONDITIONER IS NOT POSITIVE DEFINITE");
beta_new = sqrt(beta_new2); // compute beta_new beta_new = sqrt(beta_new2); // compute beta_new
v_new /= beta_new; // overwrite v_new for next iteration v_new /= beta_new; // overwrite v_new for next iteration
w_new /= beta_new; // overwrite w_new for next iteration w_new /= beta_new; // overwrite w_new for next iteration
@ -107,28 +116,34 @@ namespace Eigen {
s=beta_new/r1; // new sine s=beta_new/r1; // new sine
// Update solution // Update solution
// p_oold = p_old; p_oold = p_old;
const VectorType p_oold(p_old); // NOT SURE IF CREATING p_oold EVERY ITERATION IS EFFICIENT // const VectorType p_oold(p_old); // NOT SURE IF CREATING p_oold EVERY ITERATION IS EFFICIENT
p_old = p; p_old = p;
p.noalias()=(w-r2*p_old-r3*p_oold) /r1; // IS NOALIAS REQUIRED? p.noalias()=(w-r2*p_old-r3*p_oold) /r1; // IS NOALIAS REQUIRED?
x += beta_one*c*eta*p; x += beta_one*c*eta*p;
/* Update the squared residual. Note that this is the estimated residual.
The real residual |Ax-b|^2 may be slightly larger */
residualNorm2 *= s*s; residualNorm2 *= s*s;
if ( residualNorm2 < threshold2){ if ( residualNorm2 < threshold2)
{
break; break;
} }
eta=-s*eta; // update eta eta=-s*eta; // update eta
iters++; // increment iteration number (for output purposes) iters++; // increment iteration number (for output purposes)
} }
tol_error = std::sqrt(residualNorm2 / rhsNorm2); // return error. Note that this is the estimated error. The real error |Ax-b|/|b| may be slightly larger
/* Compute error. Note that this is the estimated error. The real
error |Ax-b|/|b| may be slightly larger */
tol_error = std::sqrt(residualNorm2 / rhsNorm2);
} }
} }
template< typename _MatrixType, int _UpLo=Lower, template< typename _MatrixType, int _UpLo=Lower,
typename _Preconditioner = IdentityPreconditioner> typename _Preconditioner = IdentityPreconditioner>
// typename _Preconditioner = IdentityPreconditioner<typename _MatrixType::Scalar> > // preconditioner must be positive definite
class MINRES; class MINRES;
namespace internal { namespace internal {

View File

@ -57,7 +57,7 @@ namespace Eigen
**/ **/
Spline() Spline()
: m_knots(1, (Degree==Dynamic ? 2 : 2*Degree+2)) : m_knots(1, (Degree==Dynamic ? 2 : 2*Degree+2))
, m_ctrls(ControlPointVectorType::Zero(2,(Degree==Dynamic ? 1 : Degree+1))) , m_ctrls(ControlPointVectorType::Zero(Dimension,(Degree==Dynamic ? 1 : Degree+1)))
{ {
// in theory this code can go to the initializer list but it will get pretty // in theory this code can go to the initializer list but it will get pretty
// much unreadable ... // much unreadable ...

View File

@ -1,8 +1,8 @@
// This file is part of Eigen, a lightweight C++ template library // This file is part of Eigen, a lightweight C++ template library
// for linear algebra. // for linear algebra.
// //
// Copyright (C) 2011 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2012 Giacomo Po <gpo@ucla.edu> // Copyright (C) 2012 Giacomo Po <gpo@ucla.edu>
// Copyright (C) 2011 Gael Guennebaud <g.gael@free.fr>
// //
// This Source Code Form is subject to the terms of the Mozilla // This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed // Public License v. 2.0. If a copy of the MPL was not distributed
@ -14,19 +14,29 @@
template<typename T> void test_minres_T() template<typename T> void test_minres_T()
{ {
MINRES<SparseMatrix<T>, Lower, DiagonalPreconditioner<T> > minres_colmajor_diag; // Identity preconditioner
MINRES<SparseMatrix<T>, Lower, IdentityPreconditioner > minres_colmajor_I; MINRES<SparseMatrix<T>, Lower, IdentityPreconditioner > minres_colmajor_lower_I;
// MINRES<SparseMatrix<T>, Lower, IncompleteLUT<T> > minres_colmajor_ilut; MINRES<SparseMatrix<T>, Upper, IdentityPreconditioner > minres_colmajor_upper_I;
//minres<SparseMatrix<T>, SSORPreconditioner<T> > minres_colmajor_ssor;
// Diagonal preconditioner
MINRES<SparseMatrix<T>, Lower, DiagonalPreconditioner<T> > minres_colmajor_lower_diag;
MINRES<SparseMatrix<T>, Upper, DiagonalPreconditioner<T> > minres_colmajor_upper_diag;
// call tests for SPD matrix
CALL_SUBTEST( check_sparse_spd_solving(minres_colmajor_lower_I) );
CALL_SUBTEST( check_sparse_spd_solving(minres_colmajor_upper_I) );
CALL_SUBTEST( check_sparse_spd_solving(minres_colmajor_lower_diag) );
CALL_SUBTEST( check_sparse_spd_solving(minres_colmajor_upper_diag) );
// TO DO: symmetric semi-definite matrix
// TO DO: symmetric indefinite matrix
CALL_SUBTEST( check_sparse_square_solving(minres_colmajor_diag) );
CALL_SUBTEST( check_sparse_spd_solving(minres_colmajor_I) );
// CALL_SUBTEST( check_sparse_square_solving(minres_colmajor_ilut) );
//CALL_SUBTEST( check_sparse_square_solving(minres_colmajor_ssor) );
} }
void test_minres() void test_minres()
{ {
CALL_SUBTEST_1(test_minres_T<double>()); CALL_SUBTEST_1(test_minres_T<double>());
// CALL_SUBTEST_2(test_minres_T<std::complex<double> >()); // CALL_SUBTEST_2(test_minres_T<std::compex<double> >());
} }