Pulled latest updates from trunk

This commit is contained in:
Benoit Steiner 2015-11-23 08:28:34 -08:00
commit 4286b2d494
7 changed files with 57 additions and 43 deletions

View File

@ -748,13 +748,13 @@ template<typename T> EIGEN_DEVICE_FUNC bool isinf_msvc_helper(T x)
} }
//MSVC defines a _isnan builtin function, but for double only //MSVC defines a _isnan builtin function, but for double only
template<> EIGEN_DEVICE_FUNC inline bool isnan_impl(const long double& x) { return _isnan(x); } EIGEN_DEVICE_FUNC inline bool isnan_impl(const long double& x) { return _isnan(x); }
template<> EIGEN_DEVICE_FUNC inline bool isnan_impl(const double& x) { return _isnan(x); } EIGEN_DEVICE_FUNC inline bool isnan_impl(const double& x) { return _isnan(x); }
template<> EIGEN_DEVICE_FUNC inline bool isnan_impl(const float& x) { return _isnan(x); } EIGEN_DEVICE_FUNC inline bool isnan_impl(const float& x) { return _isnan(x); }
template<> EIGEN_DEVICE_FUNC inline bool isinf_impl(const long double& x) { return isinf_msvc_helper(x); } EIGEN_DEVICE_FUNC inline bool isinf_impl(const long double& x) { return isinf_msvc_helper(x); }
template<> EIGEN_DEVICE_FUNC inline bool isinf_impl(const double& x) { return isinf_msvc_helper(x); } EIGEN_DEVICE_FUNC inline bool isinf_impl(const double& x) { return isinf_msvc_helper(x); }
template<> EIGEN_DEVICE_FUNC inline bool isinf_impl(const float& x) { return isinf_msvc_helper(x); } EIGEN_DEVICE_FUNC inline bool isinf_impl(const float& x) { return isinf_msvc_helper(x); }
#elif (defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ && EIGEN_COMP_GNUC) #elif (defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ && EIGEN_COMP_GNUC)

View File

@ -36,37 +36,40 @@ const std::ptrdiff_t defaultL3CacheSize = 512*1024;
#endif #endif
/** \internal */ /** \internal */
inline void manage_caching_sizes(Action action, std::ptrdiff_t* l1, std::ptrdiff_t* l2, std::ptrdiff_t* l3) struct CacheSizes {
{ CacheSizes(): m_l1(-1),m_l2(-1),m_l3(-1) {
static bool m_cache_sizes_initialized = false;
static std::ptrdiff_t m_l1CacheSize = 0;
static std::ptrdiff_t m_l2CacheSize = 0;
static std::ptrdiff_t m_l3CacheSize = 0;
if(!m_cache_sizes_initialized)
{
int l1CacheSize, l2CacheSize, l3CacheSize; int l1CacheSize, l2CacheSize, l3CacheSize;
queryCacheSizes(l1CacheSize, l2CacheSize, l3CacheSize); queryCacheSizes(l1CacheSize, l2CacheSize, l3CacheSize);
m_l1CacheSize = manage_caching_sizes_helper(l1CacheSize, defaultL1CacheSize); m_l1 = manage_caching_sizes_helper(l1CacheSize, defaultL1CacheSize);
m_l2CacheSize = manage_caching_sizes_helper(l2CacheSize, defaultL2CacheSize); m_l2 = manage_caching_sizes_helper(l2CacheSize, defaultL2CacheSize);
m_l3CacheSize = manage_caching_sizes_helper(l3CacheSize, defaultL3CacheSize); m_l3 = manage_caching_sizes_helper(l3CacheSize, defaultL3CacheSize);
m_cache_sizes_initialized = true;
} }
std::ptrdiff_t m_l1;
std::ptrdiff_t m_l2;
std::ptrdiff_t m_l3;
};
/** \internal */
inline void manage_caching_sizes(Action action, std::ptrdiff_t* l1, std::ptrdiff_t* l2, std::ptrdiff_t* l3)
{
static CacheSizes m_cacheSizes;
if(action==SetAction) if(action==SetAction)
{ {
// set the cpu cache size and cache all block sizes from a global cache size in byte // set the cpu cache size and cache all block sizes from a global cache size in byte
eigen_internal_assert(l1!=0 && l2!=0); eigen_internal_assert(l1!=0 && l2!=0);
m_l1CacheSize = *l1; m_cacheSizes.m_l1 = *l1;
m_l2CacheSize = *l2; m_cacheSizes.m_l2 = *l2;
m_l3CacheSize = *l3; m_cacheSizes.m_l3 = *l3;
} }
else if(action==GetAction) else if(action==GetAction)
{ {
eigen_internal_assert(l1!=0 && l2!=0); eigen_internal_assert(l1!=0 && l2!=0);
*l1 = m_l1CacheSize; *l1 = m_cacheSizes.m_l1;
*l2 = m_l2CacheSize; *l2 = m_cacheSizes.m_l2;
*l3 = m_l3CacheSize; *l3 = m_cacheSizes.m_l3;
} }
else else
{ {

View File

@ -10,6 +10,7 @@
// 4244 - 'argument' : conversion from 'type1' to 'type2', possible loss of data // 4244 - 'argument' : conversion from 'type1' to 'type2', possible loss of data
// 4273 - QtAlignedMalloc, inconsistent DLL linkage // 4273 - QtAlignedMalloc, inconsistent DLL linkage
// 4324 - structure was padded due to declspec(align()) // 4324 - structure was padded due to declspec(align())
// 4503 - decorated name length exceeded, name was truncated
// 4512 - assignment operator could not be generated // 4512 - assignment operator could not be generated
// 4522 - 'class' : multiple assignment operators specified // 4522 - 'class' : multiple assignment operators specified
// 4700 - uninitialized local variable 'xyz' used // 4700 - uninitialized local variable 'xyz' used
@ -17,7 +18,7 @@
#ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS #ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS
#pragma warning( push ) #pragma warning( push )
#endif #endif
#pragma warning( disable : 4100 4101 4127 4181 4211 4244 4273 4324 4512 4522 4700 4717 ) #pragma warning( disable : 4100 4101 4127 4181 4211 4244 4273 4324 4503 4512 4522 4700 4717 )
#elif defined __INTEL_COMPILER #elif defined __INTEL_COMPILER
// 2196 - routine is both "inline" and "noinline" ("noinline" assumed) // 2196 - routine is both "inline" and "noinline" ("noinline" assumed)
// ICC 12 generates this warning even without any inline keyword, when defining class methods 'inline' i.e. inside of class body // ICC 12 generates this warning even without any inline keyword, when defining class methods 'inline' i.e. inside of class body

View File

@ -720,7 +720,7 @@ void FullPivLU<_MatrixType>::_solve_impl(const RhsType &rhs, DstType &dst) const
const Index rows = this->rows(), const Index rows = this->rows(),
cols = this->cols(), cols = this->cols(),
nonzero_pivots = this->nonzeroPivots(); nonzero_pivots = this->rank();
eigen_assert(rhs.rows() == rows); eigen_assert(rhs.rows() == rows);
const Index smalldim = (std::min)(rows, cols); const Index smalldim = (std::min)(rows, cols);

View File

@ -39,10 +39,9 @@ class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Sparse>
EIGEN_SPARSE_PUBLIC_INTERFACE(Derived) EIGEN_SPARSE_PUBLIC_INTERFACE(Derived)
CwiseBinaryOpImpl() CwiseBinaryOpImpl()
{ {
typedef typename internal::traits<Lhs>::StorageKind LhsStorageKind;
typedef typename internal::traits<Rhs>::StorageKind RhsStorageKind;
EIGEN_STATIC_ASSERT(( EIGEN_STATIC_ASSERT((
(!internal::is_same<LhsStorageKind,RhsStorageKind>::value) (!internal::is_same<typename internal::traits<Lhs>::StorageKind,
typename internal::traits<Rhs>::StorageKind>::value)
|| ((Lhs::Flags&RowMajorBit) == (Rhs::Flags&RowMajorBit))), || ((Lhs::Flags&RowMajorBit) == (Rhs::Flags&RowMajorBit))),
THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH); THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH);
} }

View File

@ -43,6 +43,8 @@ int main(int argc, char** argv)
} }
\endcode \endcode
\note With Eigen 3.3, and a fully C++11 compliant compiler (i.e., <a href="http://en.cppreference.com/w/cpp/language/storage_duration#Static_local_variables">thread-safe static local variable initialization</a>), then calling \c initParallel() is optional.
\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. \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

@ -12,6 +12,12 @@
#include <Eigen/LU> #include <Eigen/LU>
#include <Eigen/SVD> #include <Eigen/SVD>
template<typename T>
Matrix<T,2,1> angleToVec(T a)
{
return Matrix<T,2,1>(std::cos(a), std::sin(a));
}
template<typename Scalar, int Mode, int Options> void non_projective_only() template<typename Scalar, int Mode, int Options> void non_projective_only()
{ {
/* this test covers the following files: /* this test covers the following files:
@ -130,14 +136,16 @@ template<typename Scalar, int Mode, int Options> void transformations()
AngleAxisx aa = AngleAxisx(q1); AngleAxisx aa = AngleAxisx(q1);
VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1); VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
if(abs(aa.angle()) > NumTraits<Scalar>::dummy_precision()) // The following test is stable only if 2*angle != angle and v1 is not colinear with axis
if( (abs(aa.angle()) > test_precision<Scalar>()) && (abs(aa.axis().dot(v1.normalized()))<(Scalar(1)-Scalar(4)*test_precision<Scalar>())) )
{ {
VERIFY( !(q1 * v1).isApprox(Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1) ); VERIFY( !(q1 * v1).isApprox(Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1) );
} }
aa.fromRotationMatrix(aa.toRotationMatrix()); aa.fromRotationMatrix(aa.toRotationMatrix());
VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1); VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
if(abs(aa.angle()) > NumTraits<Scalar>::dummy_precision()) // The following test is stable only if 2*angle != angle and v1 is not colinear with axis
if( (abs(aa.angle()) > test_precision<Scalar>()) && (abs(aa.axis().dot(v1.normalized()))<(Scalar(1)-Scalar(4)*test_precision<Scalar>())) )
{ {
VERIFY( !(q1 * v1).isApprox(Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1) ); VERIFY( !(q1 * v1).isApprox(Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1) );
} }
@ -214,7 +222,9 @@ template<typename Scalar, int Mode, int Options> void transformations()
t4 *= aa3; t4 *= aa3;
VERIFY_IS_APPROX(t3.matrix(), t4.matrix()); VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
v3 = Vector3::Random(); do {
v3 = Vector3::Random();
} while (v3.cwiseAbs().minCoeff()<NumTraits<Scalar>::epsilon());
Translation3 tv3(v3); Translation3 tv3(v3);
Transform3 t5(tv3); Transform3 t5(tv3);
t4 = tv3; t4 = tv3;
@ -414,14 +424,12 @@ template<typename Scalar, int Mode, int Options> void transformations()
Scalar angle = internal::random<Scalar>(-100,100); Scalar angle = internal::random<Scalar>(-100,100);
Rotation2D<Scalar> rot2(angle); Rotation2D<Scalar> rot2(angle);
VERIFY( rot2.smallestPositiveAngle() >= 0 ); VERIFY( rot2.smallestPositiveAngle() >= 0 );
VERIFY( rot2.smallestPositiveAngle() < Scalar(2)*Scalar(EIGEN_PI) ); VERIFY( rot2.smallestPositiveAngle() <= Scalar(2)*Scalar(EIGEN_PI) );
VERIFY_IS_APPROX( std::cos(rot2.smallestPositiveAngle()), std::cos(rot2.angle()) ); VERIFY_IS_APPROX( angleToVec(rot2.smallestPositiveAngle()), angleToVec(rot2.angle()) );
VERIFY_IS_APPROX( std::sin(rot2.smallestPositiveAngle()), std::sin(rot2.angle()) );
VERIFY( rot2.smallestAngle() >= -Scalar(EIGEN_PI) ); VERIFY( rot2.smallestAngle() >= -Scalar(EIGEN_PI) );
VERIFY( rot2.smallestAngle() <= Scalar(EIGEN_PI) ); VERIFY( rot2.smallestAngle() <= Scalar(EIGEN_PI) );
VERIFY_IS_APPROX( std::cos(rot2.smallestAngle()), std::cos(rot2.angle()) ); VERIFY_IS_APPROX( angleToVec(rot2.smallestAngle()), angleToVec(rot2.angle()) );
VERIFY_IS_APPROX( std::sin(rot2.smallestAngle()), std::sin(rot2.angle()) );
} }
s0 = internal::random<Scalar>(-100,100); s0 = internal::random<Scalar>(-100,100);
@ -437,7 +445,7 @@ template<typename Scalar, int Mode, int Options> void transformations()
VERIFY_IS_APPROX(t20,t21); VERIFY_IS_APPROX(t20,t21);
VERIFY_IS_APPROX(s0, (R0.slerp(0, R1)).angle()); VERIFY_IS_APPROX(s0, (R0.slerp(0, R1)).angle());
VERIFY_IS_APPROX(R1.smallestPositiveAngle(), (R0.slerp(1, R1)).smallestPositiveAngle()); VERIFY_IS_APPROX( angleToVec(R1.smallestPositiveAngle()), angleToVec((R0.slerp(1, R1)).smallestPositiveAngle()) );
VERIFY_IS_APPROX(R0.smallestPositiveAngle(), (R0.slerp(0.5, R0)).smallestPositiveAngle()); VERIFY_IS_APPROX(R0.smallestPositiveAngle(), (R0.slerp(0.5, R0)).smallestPositiveAngle());
if(std::cos(s0)>0) if(std::cos(s0)>0)
@ -447,13 +455,14 @@ template<typename Scalar, int Mode, int Options> void transformations()
// Check path length // Check path length
Scalar l = 0; Scalar l = 0;
for(int k=0; k<100; ++k) int path_steps = 100;
for(int k=0; k<path_steps; ++k)
{ {
Scalar a1 = R0.slerp(Scalar(k)/Scalar(100), R1).angle(); Scalar a1 = R0.slerp(Scalar(k)/Scalar(path_steps), R1).angle();
Scalar a2 = R0.slerp(Scalar(k+1)/Scalar(100), R1).angle(); Scalar a2 = R0.slerp(Scalar(k+1)/Scalar(path_steps), R1).angle();
l += std::abs(a2-a1); l += std::abs(a2-a1);
} }
VERIFY(l<=EIGEN_PI); VERIFY(l<=EIGEN_PI*(Scalar(1)+NumTraits<Scalar>::epsilon()*Scalar(path_steps/2)));
// check basic features // check basic features
{ {