mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-01-24 14:45:14 +08:00
Pulled latest updates from trunk
This commit is contained in:
commit
86486eee2d
@ -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;
|
||||
|
@ -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 *
|
||||
****************************************************************************/
|
||||
|
@ -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; };
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user