diff --git a/Eigen/src/Core/ArrayBase.h b/Eigen/src/Core/ArrayBase.h index 66813c8ea..b4c24a27a 100644 --- a/Eigen/src/Core/ArrayBase.h +++ b/Eigen/src/Core/ArrayBase.h @@ -53,6 +53,7 @@ template class ArrayBase typedef DenseBase Base; using Base::operator*; + using Base::operator/; using Base::RowsAtCompileTime; using Base::ColsAtCompileTime; using Base::SizeAtCompileTime; diff --git a/Eigen/src/Core/MathFunctions.h b/Eigen/src/Core/MathFunctions.h index 2ac6f4c67..fe1dafe83 100644 --- a/Eigen/src/Core/MathFunctions.h +++ b/Eigen/src/Core/MathFunctions.h @@ -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 +EIGEN_DEVICE_FUNC +typename internal::enable_if::value,bool>::type +isnan_impl(const T&) { return false; } + +template +EIGEN_DEVICE_FUNC +typename internal::enable_if::value,bool>::type +isinf_impl(const T&) { return false; } + +template +EIGEN_DEVICE_FUNC +typename internal::enable_if::value,bool>::type +isfinite_impl(const T&) { return true; } + +template +EIGEN_DEVICE_FUNC +typename internal::enable_if<(!internal::is_integral::value)&&(!NumTraits::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::highest() && x>NumTraits::lowest(); + #endif +} + +template +EIGEN_DEVICE_FUNC +typename internal::enable_if<(!internal::is_integral::value)&&(!NumTraits::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::highest() || x::lowest(); + #endif +} + +template +EIGEN_DEVICE_FUNC +typename internal::enable_if<(!internal::is_integral::value)&&(!NumTraits::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 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 bool isfinite_impl(const std::complex& x); +template bool isnan_impl(const std::complex& x); +template bool isinf_impl(const std::complex& 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 -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::highest() && x>NumTraits::lowest(); - #endif -} - -template -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::highest() || x::lowest(); - #endif -} - -template -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 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 -bool (isfinite)(const std::complex& x) -{ - return (numext::isfinite)(numext::real(x)) && (numext::isfinite)(numext::imag(x)); -} - -template -bool (isnan)(const std::complex& x) -{ - return (numext::isnan)(numext::real(x)) || (numext::isnan)(numext::imag(x)); -} - -template -bool (isinf)(const std::complex& x) -{ - return ((numext::isinf)(numext::real(x)) || (numext::isinf)(numext::imag(x))) && (!(numext::isnan)(x)); -} +template EIGEN_DEVICE_FUNC bool (isnan) (const T &x) { return internal::isnan_impl(x); } +template EIGEN_DEVICE_FUNC bool (isinf) (const T &x) { return internal::isinf_impl(x); } +template EIGEN_DEVICE_FUNC bool (isfinite)(const T &x) { return internal::isfinite_impl(x); } template EIGEN_DEVICE_FUNC @@ -962,6 +973,24 @@ inline int log2(int x) namespace internal { +template +bool isfinite_impl(const std::complex& x) +{ + return (numext::isfinite)(numext::real(x)) && (numext::isfinite)(numext::imag(x)); +} + +template +bool isnan_impl(const std::complex& x) +{ + return (numext::isnan)(numext::real(x)) || (numext::isnan)(numext::imag(x)); +} + +template +bool isinf_impl(const std::complex& x) +{ + return ((numext::isinf)(numext::real(x)) || (numext::isinf)(numext::imag(x))) && (!(numext::isnan)(x)); +} + /**************************************************************************** * Implementation of fuzzy comparisons * ****************************************************************************/ diff --git a/Eigen/src/Core/util/Meta.h b/Eigen/src/Core/util/Meta.h index e7fa2a1f1..15b80abd9 100644 --- a/Eigen/src/Core/util/Meta.h +++ b/Eigen/src/Core/util/Meta.h @@ -73,6 +73,18 @@ template<> struct is_arithmetic { enum { value = true }; }; template<> struct is_arithmetic { enum { value = true }; }; template<> struct is_arithmetic { enum { value = true }; }; +template struct is_integral { enum { value = false }; }; +template<> struct is_integral { enum { value = true }; }; +template<> struct is_integral { enum { value = true }; }; +template<> struct is_integral { enum { value = true }; }; +template<> struct is_integral { enum { value = true }; }; +template<> struct is_integral { enum { value = true }; }; +template<> struct is_integral { enum { value = true }; }; +template<> struct is_integral { enum { value = true }; }; +template<> struct is_integral { enum { value = true }; }; +template<> struct is_integral { enum { value = true }; }; +template<> struct is_integral { enum { value = true }; }; + template struct add_const { typedef const T type; }; template struct add_const { typedef T& type; }; diff --git a/Eigen/src/SuperLUSupport/SuperLUSupport.h b/Eigen/src/SuperLUSupport/SuperLUSupport.h index 7c644eef6..afb5904e0 100644 --- a/Eigen/src/SuperLUSupport/SuperLUSupport.h +++ b/Eigen/src/SuperLUSupport/SuperLUSupport.h @@ -659,7 +659,7 @@ void SuperLU::_solve_impl(const MatrixBase &b, MatrixBase &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; diff --git a/test/array.cpp b/test/array.cpp index e2b20f9e9..d437105da 100644 --- a/test/array.cpp +++ b/test/array.cpp @@ -365,11 +365,15 @@ template void array_complex(const ArrayType& m) std::complex 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 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); diff --git a/test/linearstructure.cpp b/test/linearstructure.cpp index 3c7cdbe41..292f33969 100644 --- a/test/linearstructure.cpp +++ b/test/linearstructure.cpp @@ -108,9 +108,11 @@ void test_linearstructure() CALL_SUBTEST_7( linearStructure(MatrixXi (internal::random(1,EIGEN_TEST_MAX_SIZE), internal::random(1,EIGEN_TEST_MAX_SIZE))) ); CALL_SUBTEST_8( linearStructure(MatrixXcd(internal::random(1,EIGEN_TEST_MAX_SIZE/2), internal::random(1,EIGEN_TEST_MAX_SIZE/2))) ); CALL_SUBTEST_9( linearStructure(ArrayXXf (internal::random(1,EIGEN_TEST_MAX_SIZE), internal::random(1,EIGEN_TEST_MAX_SIZE))) ); + CALL_SUBTEST_10( linearStructure(ArrayXXcf (internal::random(1,EIGEN_TEST_MAX_SIZE), internal::random(1,EIGEN_TEST_MAX_SIZE))) ); - CALL_SUBTEST_10( real_complex() ); - CALL_SUBTEST_10( real_complex(10,10) ); + CALL_SUBTEST_11( real_complex() ); + CALL_SUBTEST_11( real_complex(10,10) ); + CALL_SUBTEST_11( real_complex(10,10) ); } #ifdef EIGEN_TEST_PART_4 diff --git a/unsupported/test/cxx11_tensor_intdiv.cpp b/unsupported/test/cxx11_tensor_intdiv.cpp index c6e1890df..48aa6d368 100644 --- a/unsupported/test/cxx11_tensor_intdiv.cpp +++ b/unsupported/test/cxx11_tensor_intdiv.cpp @@ -15,10 +15,10 @@ void test_signed_32bit() { // Divide by one - const Eigen::internal::TensorIntDivisor div(1); + const Eigen::internal::TensorIntDivisor 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); } diff --git a/unsupported/test/cxx11_tensor_uint128.cpp b/unsupported/test/cxx11_tensor_uint128.cpp index 53c09ff0b..ee3767e58 100644 --- a/unsupported/test/cxx11_tensor_uint128.cpp +++ b/unsupported/test/cxx11_tensor_uint128.cpp @@ -14,7 +14,7 @@ using Eigen::internal::TensorUInt128; using Eigen::internal::static_val; -static void VERIFY_EQUAL(TensorUInt128 actual, __uint128_t expected) { +void VERIFY_EQUAL(TensorUInt128 actual, __uint128_t expected) { bool matchl = actual.lower() == static_cast(expected); bool matchh = actual.upper() == static_cast(expected >> 64); if (!matchl || !matchh) { @@ -27,7 +27,7 @@ static void VERIFY_EQUAL(TensorUInt128 actual, __uint128_t e } -static void test_add() { +void test_add() { uint64_t incr = internal::random(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(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(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(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(1, 9999999999); for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) { TensorUInt128, 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(1, 100); for (int64_t log_div = 0; log_div < 63; ++log_div) { for (int64_t divider = 1; divider <= 1000000 * incr; divider += incr) {