Pulled latest updates from trunk

This commit is contained in:
Benoit Steiner 2015-11-20 11:10:37 -08:00
commit 86486eee2d
8 changed files with 165 additions and 115 deletions

View File

@ -53,6 +53,7 @@ template<typename Derived> class ArrayBase
typedef DenseBase<Derived> Base;
using Base::operator*;
using Base::operator/;
using Base::RowsAtCompileTime;
using Base::ColsAtCompileTime;
using Base::SizeAtCompileTime;

View File

@ -675,6 +675,115 @@ inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random()
return EIGEN_MATHFUNC_IMPL(random, Scalar)::run();
}
// Implementatin of is* functions
// std::is* do not work with fast-math and gcc, std::is* are available on MSVC 2013 and newer, as well as in clang.
#if (EIGEN_HAS_CXX11_MATH && !(EIGEN_COMP_GNUC_STRICT && __FINITE_MATH_ONLY__)) || (EIGEN_COMP_MSVC>=1800) || (EIGEN_COMP_CLANG)
#define EIGEN_USE_STD_FPCLASSIFY 1
#else
#define EIGEN_USE_STD_FPCLASSIFY 0
#endif
template<typename T>
EIGEN_DEVICE_FUNC
typename internal::enable_if<internal::is_integral<T>::value,bool>::type
isnan_impl(const T&) { return false; }
template<typename T>
EIGEN_DEVICE_FUNC
typename internal::enable_if<internal::is_integral<T>::value,bool>::type
isinf_impl(const T&) { return false; }
template<typename T>
EIGEN_DEVICE_FUNC
typename internal::enable_if<internal::is_integral<T>::value,bool>::type
isfinite_impl(const T&) { return true; }
template<typename T>
EIGEN_DEVICE_FUNC
typename internal::enable_if<(!internal::is_integral<T>::value)&&(!NumTraits<T>::IsComplex),bool>::type
isfinite_impl(const T& x)
{
#if EIGEN_USE_STD_FPCLASSIFY
using std::isfinite;
return isfinite EIGEN_NOT_A_MACRO (x);
#else
return x<NumTraits<T>::highest() && x>NumTraits<T>::lowest();
#endif
}
template<typename T>
EIGEN_DEVICE_FUNC
typename internal::enable_if<(!internal::is_integral<T>::value)&&(!NumTraits<T>::IsComplex),bool>::type
isinf_impl(const T& x)
{
#if EIGEN_USE_STD_FPCLASSIFY
using std::isinf;
return isinf EIGEN_NOT_A_MACRO (x);
#else
return x>NumTraits<T>::highest() || x<NumTraits<T>::lowest();
#endif
}
template<typename T>
EIGEN_DEVICE_FUNC
typename internal::enable_if<(!internal::is_integral<T>::value)&&(!NumTraits<T>::IsComplex),bool>::type
isnan_impl(const T& x)
{
#if EIGEN_USE_STD_FPCLASSIFY
using std::isnan;
return isnan EIGEN_NOT_A_MACRO (x);
#else
return x != x;
#endif
}
#if (!EIGEN_USE_STD_FPCLASSIFY)
#if EIGEN_COMP_MSVC
template<typename T> EIGEN_DEVICE_FUNC bool isinf_msvc_helper(T x)
{
return _fpclass(x)==_FPCLASS_NINF || _fpclass(x)==_FPCLASS_PINF;
}
//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); }
template<> 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); }
template<> 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); }
template<> 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)
#if EIGEN_GNUC_AT_LEAST(5,0)
#define EIGEN_TMP_NOOPT_ATTRIB EIGEN_DEVICE_FUNC inline __attribute__((optimize("no-finite-math-only")))
#else
// NOTE the inline qualifier and noinline attribute are both needed: the former is to avoid linking issue (duplicate symbol),
// while the second prevent too aggressive optimizations in fast-math mode:
#define EIGEN_TMP_NOOPT_ATTRIB EIGEN_DEVICE_FUNC inline __attribute__((noinline,optimize("no-finite-math-only")))
#endif
template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const long double& x) { return __builtin_isnan(x); }
template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const double& x) { return __builtin_isnan(x); }
template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const float& x) { return __builtin_isnan(x); }
template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const double& x) { return __builtin_isinf(x); }
template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const float& x) { return __builtin_isinf(x); }
template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const long double& x) { return __builtin_isinf(x); }
#undef EIGEN_TMP_NOOPT_ATTRIB
#endif
#endif
// The following overload are defined at the end of this file
template<typename T> bool isfinite_impl(const std::complex<T>& x);
template<typename T> bool isnan_impl(const std::complex<T>& x);
template<typename T> bool isinf_impl(const std::complex<T>& x);
} // end namespace internal
/****************************************************************************
@ -818,107 +927,9 @@ inline EIGEN_MATHFUNC_RETVAL(pow, Scalar) pow(const Scalar& x, const Scalar& y)
return EIGEN_MATHFUNC_IMPL(pow, Scalar)::run(x, y);
}
// std::is* do not work with fast-math and gcc, std::is* are available on MSVC 2013 and newer, as well as in clang.
#if (EIGEN_HAS_CXX11_MATH && !(EIGEN_COMP_GNUC_STRICT && __FINITE_MATH_ONLY__)) || (EIGEN_COMP_MSVC>=1800) || (EIGEN_COMP_CLANG)
#define EIGEN_USE_STD_FPCLASSIFY 1
#else
#define EIGEN_USE_STD_FPCLASSIFY 0
#endif
template<typename T>
EIGEN_DEVICE_FUNC
bool (isfinite)(const T& x)
{
#if EIGEN_USE_STD_FPCLASSIFY
using std::isfinite;
return isfinite EIGEN_NOT_A_MACRO (x);
#else
return x<NumTraits<T>::highest() && x>NumTraits<T>::lowest();
#endif
}
template<typename T>
EIGEN_DEVICE_FUNC
bool (isinf)(const T& x)
{
#if EIGEN_USE_STD_FPCLASSIFY
using std::isinf;
return isinf EIGEN_NOT_A_MACRO (x);
#else
return x>NumTraits<T>::highest() || x<NumTraits<T>::lowest();
#endif
}
template<typename T>
EIGEN_DEVICE_FUNC
bool (isnan)(const T& x)
{
#if EIGEN_USE_STD_FPCLASSIFY
using std::isnan;
return isnan EIGEN_NOT_A_MACRO (x);
#else
return x != x;
#endif
}
#if (!EIGEN_USE_STD_FPCLASSIFY)
#if EIGEN_COMP_MSVC
template<typename T> EIGEN_DEVICE_FUNC bool isinf_msvc_helper(T x)
{
return _fpclass(x)==_FPCLASS_NINF || _fpclass(x)==_FPCLASS_PINF;
}
//MSVC defines a _isnan builtin function, but for double only
template<> EIGEN_DEVICE_FUNC inline bool (isnan)(const long double& x) { return _isnan(x); }
template<> EIGEN_DEVICE_FUNC inline bool (isnan)(const double& x) { return _isnan(x); }
template<> EIGEN_DEVICE_FUNC inline bool (isnan)(const float& x) { return _isnan(x); }
template<> EIGEN_DEVICE_FUNC inline bool (isinf)(const long double& x) { return isinf_msvc_helper(x); }
template<> EIGEN_DEVICE_FUNC inline bool (isinf)(const double& x) { return isinf_msvc_helper(x); }
template<> EIGEN_DEVICE_FUNC inline bool (isinf)(const float& x) { return isinf_msvc_helper(x); }
#elif (defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ && EIGEN_COMP_GNUC)
#if EIGEN_GNUC_AT_LEAST(5,0)
#define EIGEN_TMP_NOOPT_ATTRIB EIGEN_DEVICE_FUNC inline __attribute__((optimize("no-finite-math-only")))
#else
// NOTE the inline qualifier and noinline attribute are both needed: the former is to avoid linking issue (duplicate symbol),
// while the second prevent too aggressive optimizations in fast-math mode:
#define EIGEN_TMP_NOOPT_ATTRIB EIGEN_DEVICE_FUNC inline __attribute__((noinline,optimize("no-finite-math-only")))
#endif
template<> EIGEN_TMP_NOOPT_ATTRIB bool (isnan)(const long double& x) { return __builtin_isnan(x); }
template<> EIGEN_TMP_NOOPT_ATTRIB bool (isnan)(const double& x) { return __builtin_isnan(x); }
template<> EIGEN_TMP_NOOPT_ATTRIB bool (isnan)(const float& x) { return __builtin_isnan(x); }
template<> EIGEN_TMP_NOOPT_ATTRIB bool (isinf)(const double& x) { return __builtin_isinf(x); }
template<> EIGEN_TMP_NOOPT_ATTRIB bool (isinf)(const float& x) { return __builtin_isinf(x); }
template<> EIGEN_TMP_NOOPT_ATTRIB bool (isinf)(const long double& x) { return __builtin_isinf(x); }
#undef EIGEN_TMP_NOOPT_ATTRIB
#endif
#endif
template<typename T>
bool (isfinite)(const std::complex<T>& x)
{
return (numext::isfinite)(numext::real(x)) && (numext::isfinite)(numext::imag(x));
}
template<typename T>
bool (isnan)(const std::complex<T>& x)
{
return (numext::isnan)(numext::real(x)) || (numext::isnan)(numext::imag(x));
}
template<typename T>
bool (isinf)(const std::complex<T>& x)
{
return ((numext::isinf)(numext::real(x)) || (numext::isinf)(numext::imag(x))) && (!(numext::isnan)(x));
}
template<typename T> EIGEN_DEVICE_FUNC bool (isnan) (const T &x) { return internal::isnan_impl(x); }
template<typename T> EIGEN_DEVICE_FUNC bool (isinf) (const T &x) { return internal::isinf_impl(x); }
template<typename T> EIGEN_DEVICE_FUNC bool (isfinite)(const T &x) { return internal::isfinite_impl(x); }
template<typename Scalar>
EIGEN_DEVICE_FUNC
@ -962,6 +973,24 @@ inline int log2(int x)
namespace internal {
template<typename T>
bool isfinite_impl(const std::complex<T>& x)
{
return (numext::isfinite)(numext::real(x)) && (numext::isfinite)(numext::imag(x));
}
template<typename T>
bool isnan_impl(const std::complex<T>& x)
{
return (numext::isnan)(numext::real(x)) || (numext::isnan)(numext::imag(x));
}
template<typename T>
bool isinf_impl(const std::complex<T>& x)
{
return ((numext::isinf)(numext::real(x)) || (numext::isinf)(numext::imag(x))) && (!(numext::isnan)(x));
}
/****************************************************************************
* Implementation of fuzzy comparisons *
****************************************************************************/

View File

@ -73,6 +73,18 @@ template<> struct is_arithmetic<unsigned int> { enum { value = true }; };
template<> struct is_arithmetic<signed long> { enum { value = true }; };
template<> struct is_arithmetic<unsigned long> { enum { value = true }; };
template<typename T> struct is_integral { enum { value = false }; };
template<> struct is_integral<bool> { enum { value = true }; };
template<> struct is_integral<char> { enum { value = true }; };
template<> struct is_integral<signed char> { enum { value = true }; };
template<> struct is_integral<unsigned char> { enum { value = true }; };
template<> struct is_integral<signed short> { enum { value = true }; };
template<> struct is_integral<unsigned short> { enum { value = true }; };
template<> struct is_integral<signed int> { enum { value = true }; };
template<> struct is_integral<unsigned int> { enum { value = true }; };
template<> struct is_integral<signed long> { enum { value = true }; };
template<> struct is_integral<unsigned long> { enum { value = true }; };
template <typename T> struct add_const { typedef const T type; };
template <typename T> struct add_const<T&> { typedef T& type; };

View File

@ -659,7 +659,7 @@ void SuperLU<MatrixType>::_solve_impl(const MatrixBase<Rhs> &b, MatrixBase<Dest>
&m_sluStat, &info, Scalar());
StatFree(&m_sluStat);
if(&x.coeffRef(0) != x_ref.data())
if(x.derived().data() != x_ref.data())
x = x_ref;
m_info = info==0 ? Success : NumericalIssue;

View File

@ -365,11 +365,15 @@ template<typename ArrayType> void array_complex(const ArrayType& m)
std::complex<RealScalar> zero(0.0,0.0);
VERIFY((Eigen::isnan)(m1*zero/zero).all());
#if EIGEN_COMP_MSVC
// msvc complex division is not robust
VERIFY((Eigen::isinf)(m4/RealScalar(0)).all());
#else
#if EIGEN_COMP_CLANG
// clang's complex division is notoriously broken
// clang's complex division is notoriously broken too
if((numext::isinf)(m4(0,0)/RealScalar(0))) {
#endif
VERIFY((Eigen::isinf)(m4/zero).all());
VERIFY((Eigen::isinf)(m4/zero).all());
#if EIGEN_COMP_CLANG
}
else
@ -377,6 +381,8 @@ template<typename ArrayType> void array_complex(const ArrayType& m)
VERIFY((Eigen::isinf)(m4.real()/zero.real()).all());
}
#endif
#endif // MSVC
VERIFY(((Eigen::isfinite)(m1) && (!(Eigen::isfinite)(m1*zero/zero)) && (!(Eigen::isfinite)(m1/zero))).all());
VERIFY_IS_APPROX(inverse(inverse(m1)),m1);

View File

@ -108,9 +108,11 @@ void test_linearstructure()
CALL_SUBTEST_7( linearStructure(MatrixXi (internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
CALL_SUBTEST_8( linearStructure(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
CALL_SUBTEST_9( linearStructure(ArrayXXf (internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
CALL_SUBTEST_10( linearStructure(ArrayXXcf (internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
CALL_SUBTEST_10( real_complex<Matrix4cd>() );
CALL_SUBTEST_10( real_complex<MatrixXcf>(10,10) );
CALL_SUBTEST_11( real_complex<Matrix4cd>() );
CALL_SUBTEST_11( real_complex<MatrixXcf>(10,10) );
CALL_SUBTEST_11( real_complex<ArrayXXcf>(10,10) );
}
#ifdef EIGEN_TEST_PART_4

View File

@ -15,10 +15,10 @@
void test_signed_32bit()
{
// Divide by one
const Eigen::internal::TensorIntDivisor<int32_t, false> div(1);
const Eigen::internal::TensorIntDivisor<int32_t, false> div_by_one(1);
for (int32_t j = 0; j < 25000; ++j) {
const int32_t fast_div = j / div;
const int32_t fast_div = j / div_by_one;
const int32_t slow_div = j / 1;
VERIFY_IS_EQUAL(fast_div, slow_div);
}

View File

@ -14,7 +14,7 @@
using Eigen::internal::TensorUInt128;
using Eigen::internal::static_val;
static void VERIFY_EQUAL(TensorUInt128<uint64_t, uint64_t> actual, __uint128_t expected) {
void VERIFY_EQUAL(TensorUInt128<uint64_t, uint64_t> actual, __uint128_t expected) {
bool matchl = actual.lower() == static_cast<uint64_t>(expected);
bool matchh = actual.upper() == static_cast<uint64_t>(expected >> 64);
if (!matchl || !matchh) {
@ -27,7 +27,7 @@ static void VERIFY_EQUAL(TensorUInt128<uint64_t, uint64_t> actual, __uint128_t e
}
static void test_add() {
void test_add() {
uint64_t incr = internal::random<uint64_t>(1, 9999999999);
for (uint64_t i1 = 0; i1 < 100; ++i1) {
for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
@ -46,7 +46,7 @@ static void test_add() {
}
}
static void test_sub() {
void test_sub() {
uint64_t incr = internal::random<uint64_t>(1, 9999999999);
for (uint64_t i1 = 0; i1 < 100; ++i1) {
for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
@ -65,7 +65,7 @@ static void test_sub() {
}
}
static void test_mul() {
void test_mul() {
uint64_t incr = internal::random<uint64_t>(1, 9999999999);
for (uint64_t i1 = 0; i1 < 100; ++i1) {
for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
@ -84,7 +84,7 @@ static void test_mul() {
}
}
static void test_div() {
void test_div() {
uint64_t incr = internal::random<uint64_t>(1, 9999999999);
for (uint64_t i1 = 0; i1 < 100; ++i1) {
for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
@ -103,7 +103,7 @@ static void test_div() {
}
}
static void test_misc1() {
void test_misc1() {
uint64_t incr = internal::random<uint64_t>(1, 9999999999);
for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
TensorUInt128<static_val<0>, uint64_t> i(0, i2);
@ -118,7 +118,7 @@ static void test_misc1() {
}
}
static void test_misc2() {
void test_misc2() {
int64_t incr = internal::random<int64_t>(1, 100);
for (int64_t log_div = 0; log_div < 63; ++log_div) {
for (int64_t divider = 1; divider <= 1000000 * incr; divider += incr) {