aboutsummaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
authorGravatar Benoit Steiner <benoit.steiner.goog@gmail.com>2016-04-11 17:20:17 -0700
committerGravatar Benoit Steiner <benoit.steiner.goog@gmail.com>2016-04-11 17:20:17 -0700
commitd6e596174d09446236b3f398d8ec39148c638ed9 (patch)
treeccb4116b05dc11d7931bac0129fd1394abe1e0b0 /test
parent3ca1ae2bb761d7738bcdad885639f422a6b7c914 (diff)
parent833efb39bfe4957934982112fe435ab30a0c3b4f (diff)
Pull latest updates from upstream
Diffstat (limited to 'test')
-rw-r--r--test/CMakeLists.txt21
-rw-r--r--test/adjoint.cpp11
-rw-r--r--test/array.cpp130
-rw-r--r--test/array_for_matrix.cpp10
-rw-r--r--test/block.cpp5
-rw-r--r--test/cholmod_support.cpp14
-rw-r--r--test/diagonal.cpp7
-rw-r--r--test/dynalloc.cpp6
-rw-r--r--test/incomplete_cholesky.cpp40
-rw-r--r--test/is_same_dense.cpp11
-rw-r--r--test/main.h6
-rw-r--r--test/mapped_matrix.cpp2
-rw-r--r--test/mixingtypes.cpp41
-rw-r--r--test/nesting_ops.cpp7
-rw-r--r--test/nomalloc.cpp13
-rw-r--r--test/nullary.cpp32
-rw-r--r--test/packetmath.cpp48
-rw-r--r--test/pastix_support.cpp8
-rw-r--r--test/product.h59
-rw-r--r--test/product_large.cpp23
-rw-r--r--test/product_notemporary.cpp6
-rw-r--r--test/qr_colpivoting.cpp173
-rw-r--r--test/sparse_basic.cpp37
-rw-r--r--test/sparse_vector.cpp54
-rw-r--r--test/stable_norm.cpp15
-rw-r--r--test/stddeque_overload.cpp158
-rw-r--r--test/stdlist_overload.cpp192
-rw-r--r--test/vectorization_logic.cpp5
-rw-r--r--test/vectorwiseop.cpp3
-rw-r--r--test/zerosized.cpp20
30 files changed, 1074 insertions, 83 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 11cf12720..802b97bf0 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -226,7 +226,9 @@ ei_add_test(geo_homogeneous)
ei_add_test(stdvector)
ei_add_test(stdvector_overload)
ei_add_test(stdlist)
+ei_add_test(stdlist_overload)
ei_add_test(stddeque)
+ei_add_test(stddeque_overload)
ei_add_test(sparse_basic)
ei_add_test(sparse_block)
ei_add_test(sparse_vector)
@@ -323,10 +325,16 @@ if(EIGEN_TEST_EIGEN2)
endif()
-# NVCC unit tests
-option(EIGEN_TEST_NVCC "Enable NVCC support in unit tests" OFF)
-if(EIGEN_TEST_NVCC)
-
+# CUDA unit tests
+option(EIGEN_TEST_CUDA "Enable CUDA support in unit tests" OFF)
+option(EIGEN_TEST_CUDA_CLANG "Use clang instead of nvcc to compile the CUDA tests" OFF)
+
+if(EIGEN_TEST_CUDA_CLANG AND NOT CMAKE_CXX_COMPILER MATCHES "clang")
+ message(WARNING "EIGEN_TEST_CUDA_CLANG is set, but CMAKE_CXX_COMPILER does not appear to be clang.")
+endif()
+
+if(EIGEN_TEST_CUDA)
+
find_package(CUDA 5.0)
if(CUDA_FOUND)
@@ -334,6 +342,9 @@ if(CUDA_FOUND)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CUDA_NVCC_FLAGS "-ccbin /usr/bin/clang" CACHE STRING "nvcc flags" FORCE)
endif()
+ if(EIGEN_TEST_CUDA_CLANG)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 --cuda-gpu-arch=sm_30")
+ endif()
cuda_include_directories(${CMAKE_CURRENT_BINARY_DIR})
set(EIGEN_ADD_TEST_FILENAME_EXTENSION "cu")
@@ -343,7 +354,7 @@ if(CUDA_FOUND)
endif(CUDA_FOUND)
-endif(EIGEN_TEST_NVCC)
+endif(EIGEN_TEST_CUDA)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/failtests)
diff --git a/test/adjoint.cpp b/test/adjoint.cpp
index 3b2a53c91..9c895e0ac 100644
--- a/test/adjoint.cpp
+++ b/test/adjoint.cpp
@@ -42,6 +42,17 @@ template<> struct adjoint_specific<false> {
VERIFY_IS_APPROX(v1, v1.norm() * v3);
VERIFY_IS_APPROX(v3, v1.normalized());
VERIFY_IS_APPROX(v3.norm(), RealScalar(1));
+
+ // check null inputs
+ VERIFY_IS_APPROX((v1*0).normalized(), (v1*0));
+#if (!EIGEN_ARCH_i386) || defined(EIGEN_VECTORIZE)
+ RealScalar very_small = (std::numeric_limits<RealScalar>::min)();
+ VERIFY( (v1*very_small).norm() == 0 );
+ VERIFY_IS_APPROX((v1*very_small).normalized(), (v1*very_small));
+ v3 = v1*very_small;
+ v3.normalize();
+ VERIFY_IS_APPROX(v3, (v1*very_small));
+#endif
// check compatibility of dot and adjoint
ref = NumTraits<Scalar>::IsInteger ? 0 : (std::max)((std::max)(v1.norm(),v2.norm()),(std::max)((square * v2).norm(),(square.adjoint() * v1).norm()));
diff --git a/test/array.cpp b/test/array.cpp
index 5395721f5..beaa62221 100644
--- a/test/array.cpp
+++ b/test/array.cpp
@@ -202,7 +202,7 @@ template<typename ArrayType> void array_real(const ArrayType& m)
m2 = ArrayType::Random(rows, cols),
m3(rows, cols),
m4 = m1;
-
+
m4 = (m4.abs()==Scalar(0)).select(1,m4);
Scalar s1 = internal::random<Scalar>();
@@ -217,6 +217,12 @@ template<typename ArrayType> void array_real(const ArrayType& m)
VERIFY_IS_APPROX(m1.sinh(), sinh(m1));
VERIFY_IS_APPROX(m1.cosh(), cosh(m1));
VERIFY_IS_APPROX(m1.tanh(), tanh(m1));
+#ifdef EIGEN_HAS_C99_MATH
+ VERIFY_IS_APPROX(m1.lgamma(), lgamma(m1));
+ VERIFY_IS_APPROX(m1.digamma(), digamma(m1));
+ VERIFY_IS_APPROX(m1.erf(), erf(m1));
+ VERIFY_IS_APPROX(m1.erfc(), erfc(m1));
+#endif // EIGEN_HAS_C99_MATH
VERIFY_IS_APPROX(m1.arg(), arg(m1));
VERIFY_IS_APPROX(m1.round(), round(m1));
VERIFY_IS_APPROX(m1.floor(), floor(m1));
@@ -289,7 +295,6 @@ template<typename ArrayType> void array_real(const ArrayType& m)
VERIFY_IS_APPROX(Eigen::pow(m1,2*exponents), m1.square().square());
VERIFY_IS_APPROX(m1.pow(2*exponents), m1.square().square());
VERIFY_IS_APPROX(pow(m1(0,0), exponents), ArrayType::Constant(rows,cols,m1(0,0)*m1(0,0)));
-
VERIFY_IS_APPROX(m3.pow(RealScalar(0.5)), m3.sqrt());
VERIFY_IS_APPROX(pow(m3,RealScalar(0.5)), m3.sqrt());
@@ -304,7 +309,123 @@ template<typename ArrayType> void array_real(const ArrayType& m)
s1 += Scalar(tiny);
m1 += ArrayType::Constant(rows,cols,Scalar(tiny));
VERIFY_IS_APPROX(s1/m1, s1 * m1.inverse());
-
+
+#ifdef EIGEN_HAS_C99_MATH
+ // check special functions (comparing against numpy implementation)
+ if (!NumTraits<Scalar>::IsComplex) {
+ VERIFY_IS_APPROX(numext::digamma(Scalar(1)), RealScalar(-0.5772156649015329));
+ VERIFY_IS_APPROX(numext::digamma(Scalar(1.5)), RealScalar(0.03648997397857645));
+ VERIFY_IS_APPROX(numext::digamma(Scalar(4)), RealScalar(1.2561176684318));
+ VERIFY_IS_APPROX(numext::digamma(Scalar(-10.5)), RealScalar(2.398239129535781));
+ VERIFY_IS_APPROX(numext::digamma(Scalar(10000.5)), RealScalar(9.210340372392849));
+ VERIFY_IS_EQUAL(numext::digamma(Scalar(0)),
+ std::numeric_limits<RealScalar>::infinity());
+ VERIFY_IS_EQUAL(numext::digamma(Scalar(-1)),
+ std::numeric_limits<RealScalar>::infinity());
+
+ // Check the zeta function against scipy.special.zeta
+ VERIFY_IS_APPROX(numext::zeta(Scalar(1.5), Scalar(2)), RealScalar(1.61237534869));
+ VERIFY_IS_APPROX(numext::zeta(Scalar(4), Scalar(1.5)), RealScalar(0.234848505667));
+ VERIFY_IS_APPROX(numext::zeta(Scalar(10.5), Scalar(3)), RealScalar(1.03086757337e-5));
+ VERIFY_IS_APPROX(numext::zeta(Scalar(10000.5), Scalar(1.0001)), RealScalar(0.367879440865));
+ VERIFY_IS_APPROX(numext::zeta(Scalar(3), Scalar(-2.5)), RealScalar(0.054102025820864097));
+ VERIFY_IS_EQUAL(numext::zeta(Scalar(1), Scalar(1.2345)), // The second scalar does not matter
+ std::numeric_limits<RealScalar>::infinity());
+ VERIFY((numext::isnan)(numext::zeta(Scalar(0.9), Scalar(1.2345)))); // The second scalar does not matter
+
+ // Check the polygamma against scipy.special.polygamma examples
+ VERIFY_IS_APPROX(numext::polygamma(Scalar(1), Scalar(2)), RealScalar(0.644934066848));
+ VERIFY_IS_APPROX(numext::polygamma(Scalar(1), Scalar(3)), RealScalar(0.394934066848));
+ VERIFY_IS_APPROX(numext::polygamma(Scalar(1), Scalar(25.5)), RealScalar(0.0399946696496));
+ VERIFY((numext::isnan)(numext::polygamma(Scalar(1.5), Scalar(1.2345)))); // The second scalar does not matter
+
+ // Check the polygamma function over a larger range of values
+ VERIFY_IS_APPROX(numext::polygamma(Scalar(17), Scalar(4.7)), RealScalar(293.334565435));
+ VERIFY_IS_APPROX(numext::polygamma(Scalar(31), Scalar(11.8)), RealScalar(0.445487887616));
+ VERIFY_IS_APPROX(numext::polygamma(Scalar(28), Scalar(17.7)), RealScalar(-2.47810300902e-07));
+ VERIFY_IS_APPROX(numext::polygamma(Scalar(8), Scalar(30.2)), RealScalar(-8.29668781082e-09));
+ /* The following tests only pass for doubles because floats cannot handle the large values of
+ the gamma function.
+ VERIFY_IS_APPROX(numext::polygamma(Scalar(42), Scalar(15.8)), RealScalar(-0.434562276666));
+ VERIFY_IS_APPROX(numext::polygamma(Scalar(147), Scalar(54.1)), RealScalar(0.567742190178));
+ VERIFY_IS_APPROX(numext::polygamma(Scalar(170), Scalar(64)), RealScalar(-0.0108615497927));
+ */
+
+ {
+ // Test various propreties of igamma & igammac. These are normalized
+ // gamma integrals where
+ // igammac(a, x) = Gamma(a, x) / Gamma(a)
+ // igamma(a, x) = gamma(a, x) / Gamma(a)
+ // where Gamma and gamma are considered the standard unnormalized
+ // upper and lower incomplete gamma functions, respectively.
+ ArrayType a = m1.abs() + 2;
+ ArrayType x = m2.abs() + 2;
+ ArrayType zero = ArrayType::Zero(rows, cols);
+ ArrayType one = ArrayType::Constant(rows, cols, Scalar(1.0));
+ ArrayType a_m1 = a - one;
+ ArrayType Gamma_a_x = Eigen::igammac(a, x) * a.lgamma().exp();
+ ArrayType Gamma_a_m1_x = Eigen::igammac(a_m1, x) * a_m1.lgamma().exp();
+ ArrayType gamma_a_x = Eigen::igamma(a, x) * a.lgamma().exp();
+ ArrayType gamma_a_m1_x = Eigen::igamma(a_m1, x) * a_m1.lgamma().exp();
+
+ // Gamma(a, 0) == Gamma(a)
+ VERIFY_IS_APPROX(Eigen::igammac(a, zero), one);
+
+ // Gamma(a, x) + gamma(a, x) == Gamma(a)
+ VERIFY_IS_APPROX(Gamma_a_x + gamma_a_x, a.lgamma().exp());
+
+ // Gamma(a, x) == (a - 1) * Gamma(a-1, x) + x^(a-1) * exp(-x)
+ VERIFY_IS_APPROX(Gamma_a_x, (a - 1) * Gamma_a_m1_x + x.pow(a-1) * (-x).exp());
+
+ // gamma(a, x) == (a - 1) * gamma(a-1, x) - x^(a-1) * exp(-x)
+ VERIFY_IS_APPROX(gamma_a_x, (a - 1) * gamma_a_m1_x - x.pow(a-1) * (-x).exp());
+ }
+
+ // Check exact values of igamma and igammac against a third party calculation.
+ Scalar a_s[] = {Scalar(0), Scalar(1), Scalar(1.5), Scalar(4), Scalar(0.0001), Scalar(1000.5)};
+ Scalar x_s[] = {Scalar(0), Scalar(1), Scalar(1.5), Scalar(4), Scalar(0.0001), Scalar(1000.5)};
+
+ // location i*6+j corresponds to a_s[i], x_s[j].
+ Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
+ Scalar igamma_s[][6] = {{0.0, nan, nan, nan, nan, nan},
+ {0.0, 0.6321205588285578, 0.7768698398515702,
+ 0.9816843611112658, 9.999500016666262e-05, 1.0},
+ {0.0, 0.4275932955291202, 0.608374823728911,
+ 0.9539882943107686, 7.522076445089201e-07, 1.0},
+ {0.0, 0.01898815687615381, 0.06564245437845008,
+ 0.5665298796332909, 4.166333347221828e-18, 1.0},
+ {0.0, 0.9999780593618628, 0.9999899967080838,
+ 0.9999996219837988, 0.9991370418689945, 1.0},
+ {0.0, 0.0, 0.0, 0.0, 0.0, 0.5042041932513908}};
+ Scalar igammac_s[][6] = {{nan, nan, nan, nan, nan, nan},
+ {1.0, 0.36787944117144233, 0.22313016014842982,
+ 0.018315638888734182, 0.9999000049998333, 0.0},
+ {1.0, 0.5724067044708798, 0.3916251762710878,
+ 0.04601170568923136, 0.9999992477923555, 0.0},
+ {1.0, 0.9810118431238462, 0.9343575456215499,
+ 0.4334701203667089, 1.0, 0.0},
+ {1.0, 2.1940638138146658e-05, 1.0003291916285e-05,
+ 3.7801620118431334e-07, 0.0008629581310054535,
+ 0.0},
+ {1.0, 1.0, 1.0, 1.0, 1.0, 0.49579580674813944}};
+ for (int i = 0; i < 6; ++i) {
+ for (int j = 0; j < 6; ++j) {
+ if ((std::isnan)(igamma_s[i][j])) {
+ VERIFY((std::isnan)(numext::igamma(a_s[i], x_s[j])));
+ } else {
+ VERIFY_IS_APPROX(numext::igamma(a_s[i], x_s[j]), igamma_s[i][j]);
+ }
+
+ if ((std::isnan)(igammac_s[i][j])) {
+ VERIFY((std::isnan)(numext::igammac(a_s[i], x_s[j])));
+ } else {
+ VERIFY_IS_APPROX(numext::igammac(a_s[i], x_s[j]), igammac_s[i][j]);
+ }
+ }
+ }
+ }
+#endif // EIGEN_HAS_C99_MATH
+
// check inplace transpose
m3 = m1;
m3.transposeInPlace();
@@ -331,8 +452,6 @@ template<typename ArrayType> void array_complex(const ArrayType& m)
Array<RealScalar, -1, -1> m3(rows, cols);
- Scalar s1 = internal::random<Scalar>();
-
for (Index i = 0; i < m.rows(); ++i)
for (Index j = 0; j < m.cols(); ++j)
m2(i,j) = sqrt(m1(i,j));
@@ -405,6 +524,7 @@ template<typename ArrayType> void array_complex(const ArrayType& m)
VERIFY_IS_APPROX( m1.sign() * m1.abs(), m1);
// scalar by array division
+ Scalar s1 = internal::random<Scalar>();
const RealScalar tiny = sqrt(std::numeric_limits<RealScalar>::epsilon());
s1 += Scalar(tiny);
m1 += ArrayType::Constant(rows,cols,Scalar(tiny));
diff --git a/test/array_for_matrix.cpp b/test/array_for_matrix.cpp
index 9667e1f14..db5f3b34a 100644
--- a/test/array_for_matrix.cpp
+++ b/test/array_for_matrix.cpp
@@ -68,6 +68,16 @@ template<typename MatrixType> void array_for_matrix(const MatrixType& m)
const Scalar& ref_a2 = m.array().matrix().coeffRef(0,0);
VERIFY(&ref_a1 == &ref_m1);
VERIFY(&ref_a2 == &ref_m2);
+
+ // Check write accessors:
+ m1.array().coeffRef(0,0) = 1;
+ VERIFY_IS_APPROX(m1(0,0),Scalar(1));
+ m1.array()(0,0) = 2;
+ VERIFY_IS_APPROX(m1(0,0),Scalar(2));
+ m1.array().matrix().coeffRef(0,0) = 3;
+ VERIFY_IS_APPROX(m1(0,0),Scalar(3));
+ m1.array().matrix()(0,0) = 4;
+ VERIFY_IS_APPROX(m1(0,0),Scalar(4));
}
template<typename MatrixType> void comparisons(const MatrixType& m)
diff --git a/test/block.cpp b/test/block.cpp
index 3b77b704a..1eeb2da27 100644
--- a/test/block.cpp
+++ b/test/block.cpp
@@ -181,6 +181,11 @@ template<typename MatrixType> void block(const MatrixType& m)
dm = m1.row(r1).segment(c1,c2-c1+1).transpose();
dv = m1.transpose().block(c1,r1,c2-c1+1,r2-r1+1).col(0);
VERIFY_IS_EQUAL(dv, dm);
+
+ VERIFY_IS_EQUAL( (m1.template block<Dynamic,1>(1,0,0,1)), m1.block(1,0,0,1));
+ VERIFY_IS_EQUAL( (m1.template block<1,Dynamic>(0,1,1,0)), m1.block(0,1,1,0));
+ VERIFY_IS_EQUAL( ((m1*1).template block<Dynamic,1>(1,0,0,1)), m1.block(1,0,0,1));
+ VERIFY_IS_EQUAL( ((m1*1).template block<1,Dynamic>(0,1,1,0)), m1.block(0,1,1,0));
}
diff --git a/test/cholmod_support.cpp b/test/cholmod_support.cpp
index 87f119b1e..a7eda28f7 100644
--- a/test/cholmod_support.cpp
+++ b/test/cholmod_support.cpp
@@ -41,13 +41,13 @@ template<typename T> void test_cholmod_T()
check_sparse_spd_solving(llt_colmajor_upper);
check_sparse_spd_solving(ldlt_colmajor_lower);
check_sparse_spd_solving(ldlt_colmajor_upper);
-
-// check_sparse_spd_determinant(chol_colmajor_lower);
-// check_sparse_spd_determinant(chol_colmajor_upper);
-// check_sparse_spd_determinant(llt_colmajor_lower);
-// check_sparse_spd_determinant(llt_colmajor_upper);
-// check_sparse_spd_determinant(ldlt_colmajor_lower);
-// check_sparse_spd_determinant(ldlt_colmajor_upper);
+
+ check_sparse_spd_determinant(chol_colmajor_lower);
+ check_sparse_spd_determinant(chol_colmajor_upper);
+ check_sparse_spd_determinant(llt_colmajor_lower);
+ check_sparse_spd_determinant(llt_colmajor_upper);
+ check_sparse_spd_determinant(ldlt_colmajor_lower);
+ check_sparse_spd_determinant(ldlt_colmajor_upper);
}
void test_cholmod_support()
diff --git a/test/diagonal.cpp b/test/diagonal.cpp
index 53814a588..ee00cad55 100644
--- a/test/diagonal.cpp
+++ b/test/diagonal.cpp
@@ -20,6 +20,8 @@ template<typename MatrixType> void diagonal(const MatrixType& m)
MatrixType m1 = MatrixType::Random(rows, cols),
m2 = MatrixType::Random(rows, cols);
+ Scalar s1 = internal::random<Scalar>();
+
//check diagonal()
VERIFY_IS_APPROX(m1.diagonal(), m1.transpose().diagonal());
m2.diagonal() = 2 * m1.diagonal();
@@ -58,6 +60,11 @@ template<typename MatrixType> void diagonal(const MatrixType& m)
VERIFY_IS_APPROX(m2.template diagonal<N2>(), static_cast<Scalar>(2) * m1.diagonal(N2));
m2.diagonal(N2)[0] *= 3;
VERIFY_IS_APPROX(m2.diagonal(N2)[0], static_cast<Scalar>(6) * m1.diagonal(N2)[0]);
+
+ m2.diagonal(N2).x() = s1;
+ VERIFY_IS_APPROX(m2.diagonal(N2).x(), s1);
+ m2.diagonal(N2).coeffRef(0) = Scalar(2)*s1;
+ VERIFY_IS_APPROX(m2.diagonal(N2).coeff(0), Scalar(2)*s1);
}
}
diff --git a/test/dynalloc.cpp b/test/dynalloc.cpp
index 6f22e1ab4..5f587007c 100644
--- a/test/dynalloc.cpp
+++ b/test/dynalloc.cpp
@@ -31,7 +31,7 @@ void check_handmade_aligned_malloc()
void check_aligned_malloc()
{
- for(int i = 1; i < 1000; i++)
+ for(int i = ALIGNMENT; i < 1000; i++)
{
char *p = (char*)internal::aligned_malloc(i);
VERIFY(size_t(p)%ALIGNMENT==0);
@@ -43,7 +43,7 @@ void check_aligned_malloc()
void check_aligned_new()
{
- for(int i = 1; i < 1000; i++)
+ for(int i = ALIGNMENT; i < 1000; i++)
{
float *p = internal::aligned_new<float>(i);
VERIFY(size_t(p)%ALIGNMENT==0);
@@ -55,7 +55,7 @@ void check_aligned_new()
void check_aligned_stack_alloc()
{
- for(int i = 1; i < 400; i++)
+ for(int i = ALIGNMENT; i < 400; i++)
{
ei_declare_aligned_stack_constructed_variable(float,p,i,0);
VERIFY(size_t(p)%ALIGNMENT==0);
diff --git a/test/incomplete_cholesky.cpp b/test/incomplete_cholesky.cpp
index 435e2839a..59ffe9259 100644
--- a/test/incomplete_cholesky.cpp
+++ b/test/incomplete_cholesky.cpp
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
-// Copyright (C) 2015 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2015-2016 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// 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
@@ -15,16 +15,18 @@
template<typename T, typename I> void test_incomplete_cholesky_T()
{
typedef SparseMatrix<T,0,I> SparseMatrixType;
- ConjugateGradient<SparseMatrixType, Lower, IncompleteCholesky<T, Lower, AMDOrdering<I> > > cg_illt_lower_amd;
- ConjugateGradient<SparseMatrixType, Lower, IncompleteCholesky<T, Lower, NaturalOrdering<I> > > cg_illt_lower_nat;
- ConjugateGradient<SparseMatrixType, Upper, IncompleteCholesky<T, Upper, AMDOrdering<I> > > cg_illt_upper_amd;
- ConjugateGradient<SparseMatrixType, Upper, IncompleteCholesky<T, Upper, NaturalOrdering<I> > > cg_illt_upper_nat;
+ ConjugateGradient<SparseMatrixType, Lower, IncompleteCholesky<T, Lower, AMDOrdering<I> > > cg_illt_lower_amd;
+ ConjugateGradient<SparseMatrixType, Lower, IncompleteCholesky<T, Lower, NaturalOrdering<I> > > cg_illt_lower_nat;
+ ConjugateGradient<SparseMatrixType, Upper, IncompleteCholesky<T, Upper, AMDOrdering<I> > > cg_illt_upper_amd;
+ ConjugateGradient<SparseMatrixType, Upper, IncompleteCholesky<T, Upper, NaturalOrdering<I> > > cg_illt_upper_nat;
+ ConjugateGradient<SparseMatrixType, Upper|Lower, IncompleteCholesky<T, Lower, AMDOrdering<I> > > cg_illt_uplo_amd;
CALL_SUBTEST( check_sparse_spd_solving(cg_illt_lower_amd) );
CALL_SUBTEST( check_sparse_spd_solving(cg_illt_lower_nat) );
CALL_SUBTEST( check_sparse_spd_solving(cg_illt_upper_amd) );
CALL_SUBTEST( check_sparse_spd_solving(cg_illt_upper_nat) );
+ CALL_SUBTEST( check_sparse_spd_solving(cg_illt_uplo_amd) );
}
void test_incomplete_cholesky()
@@ -32,4 +34,32 @@ void test_incomplete_cholesky()
CALL_SUBTEST_1(( test_incomplete_cholesky_T<double,int>() ));
CALL_SUBTEST_2(( test_incomplete_cholesky_T<std::complex<double>, int>() ));
CALL_SUBTEST_3(( test_incomplete_cholesky_T<double,long int>() ));
+
+#ifdef EIGEN_TEST_PART_1
+ // regression for bug 1150
+ for(int N = 1; N<20; ++N)
+ {
+ Eigen::MatrixXd b( N, N );
+ b.setOnes();
+
+ Eigen::SparseMatrix<double> m( N, N );
+ m.reserve(Eigen::VectorXi::Constant(N,4));
+ for( int i = 0; i < N; ++i )
+ {
+ m.insert( i, i ) = 1;
+ m.coeffRef( i, i / 2 ) = 2;
+ m.coeffRef( i, i / 3 ) = 2;
+ m.coeffRef( i, i / 4 ) = 2;
+ }
+
+ Eigen::SparseMatrix<double> A;
+ A = m * m.transpose();
+
+ Eigen::ConjugateGradient<Eigen::SparseMatrix<double>,
+ Eigen::Lower | Eigen::Upper,
+ Eigen::IncompleteCholesky<double> > solver( A );
+ VERIFY(solver.preconditioner().info() == Eigen::Success);
+ VERIFY(solver.info() == Eigen::Success);
+ }
+#endif
}
diff --git a/test/is_same_dense.cpp b/test/is_same_dense.cpp
index 318ba8717..6d7904bac 100644
--- a/test/is_same_dense.cpp
+++ b/test/is_same_dense.cpp
@@ -11,9 +11,10 @@
void test_is_same_dense()
{
- MatrixXd m1(10,10);
- Ref<MatrixXd> ref_m1(m1);
- Ref<const MatrixXd> const_ref_m1(m1);
+ typedef Matrix<double,Dynamic,Dynamic,ColMajor> ColMatrixXd;
+ ColMatrixXd m1(10,10);
+ Ref<ColMatrixXd> ref_m1(m1);
+ Ref<const ColMatrixXd> const_ref_m1(m1);
VERIFY(is_same_dense(m1,m1));
VERIFY(is_same_dense(m1,ref_m1));
VERIFY(is_same_dense(const_ref_m1,m1));
@@ -22,9 +23,9 @@ void test_is_same_dense()
VERIFY(is_same_dense(m1.block(0,0,m1.rows(),m1.cols()),m1));
VERIFY(!is_same_dense(m1.row(0),m1.col(0)));
- Ref<const MatrixXd> const_ref_m1_row(m1.row(1));
+ Ref<const ColMatrixXd> const_ref_m1_row(m1.row(1));
VERIFY(!is_same_dense(m1.row(1),const_ref_m1_row));
- Ref<const MatrixXd> const_ref_m1_col(m1.col(1));
+ Ref<const ColMatrixXd> const_ref_m1_col(m1.col(1));
VERIFY(is_same_dense(m1.col(1),const_ref_m1_col));
}
diff --git a/test/main.h b/test/main.h
index 2797e8623..bba5e7570 100644
--- a/test/main.h
+++ b/test/main.h
@@ -58,6 +58,10 @@
#define isnan(X) please_protect_your_isnan_with_parentheses
#define isinf(X) please_protect_your_isinf_with_parentheses
#define isfinite(X) please_protect_your_isfinite_with_parentheses
+#ifdef M_PI
+#undef M_PI
+#endif
+#define M_PI please_use_EIGEN_PI_instead_of_M_PI
#define FORBIDDEN_IDENTIFIER (this_identifier_is_forbidden_to_avoid_clashes) this_identifier_is_forbidden_to_avoid_clashes
// B0 is defined in POSIX header termios.h
@@ -331,11 +335,13 @@ inline bool test_isApprox(const std::complex<double>& a, const std::complex<doub
inline bool test_isMuchSmallerThan(const std::complex<double>& a, const std::complex<double>& b)
{ return internal::isMuchSmallerThan(a, b, test_precision<std::complex<double> >()); }
+#ifndef EIGEN_TEST_NO_LONGDOUBLE
inline bool test_isApprox(const std::complex<long double>& a, const std::complex<long double>& b)
{ return internal::isApprox(a, b, test_precision<std::complex<long double> >()); }
inline bool test_isMuchSmallerThan(const std::complex<long double>& a, const std::complex<long double>& b)
{ return internal::isMuchSmallerThan(a, b, test_precision<std::complex<long double> >()); }
#endif
+#endif
#ifndef EIGEN_TEST_NO_LONGDOUBLE
inline bool test_isApprox(const long double& a, const long double& b)
diff --git a/test/mapped_matrix.cpp b/test/mapped_matrix.cpp
index 7c7099792..88653e887 100644
--- a/test/mapped_matrix.cpp
+++ b/test/mapped_matrix.cpp
@@ -40,7 +40,7 @@ template<typename VectorType> void map_class_vector(const VectorType& m)
VERIFY_IS_EQUAL(ma1, ma3);
VERIFY_IS_EQUAL(ma1, ma4);
#ifdef EIGEN_VECTORIZE
- if(internal::packet_traits<Scalar>::Vectorizable)
+ if(internal::packet_traits<Scalar>::Vectorizable && size>=AlignedMax)
VERIFY_RAISES_ASSERT((Map<VectorType,AlignedMax>(array3unaligned, size)))
#endif
diff --git a/test/mixingtypes.cpp b/test/mixingtypes.cpp
index 32d9d0be9..a3b469af8 100644
--- a/test/mixingtypes.cpp
+++ b/test/mixingtypes.cpp
@@ -44,6 +44,7 @@ template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
Mat_d md = mf.template cast<double>();
Mat_cf mcf = Mat_cf::Random(size,size);
Mat_cd mcd = mcf.template cast<complex<double> >();
+ Mat_cd rcd = mcd;
Vec_f vf = Vec_f::Random(size,1);
Vec_d vd = vf.template cast<double>();
Vec_cf vcf = Vec_cf::Random(size,1);
@@ -103,24 +104,23 @@ template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
VERIFY_IS_APPROX(mcd.array() *= md.array(), mcd2.array() *= md.array().template cast<std::complex<double> >());
// check matrix-matrix products
-
VERIFY_IS_APPROX(sd*md*mcd, (sd*md).template cast<CD>().eval()*mcd);
VERIFY_IS_APPROX(sd*mcd*md, sd*mcd*md.template cast<CD>());
VERIFY_IS_APPROX(scd*md*mcd, scd*md.template cast<CD>().eval()*mcd);
VERIFY_IS_APPROX(scd*mcd*md, scd*mcd*md.template cast<CD>());
-
+
VERIFY_IS_APPROX(sf*mf*mcf, sf*mf.template cast<CF>()*mcf);
VERIFY_IS_APPROX(sf*mcf*mf, sf*mcf*mf.template cast<CF>());
VERIFY_IS_APPROX(scf*mf*mcf, scf*mf.template cast<CF>()*mcf);
VERIFY_IS_APPROX(scf*mcf*mf, scf*mcf*mf.template cast<CF>());
-
+
VERIFY_IS_APPROX(sd*md.adjoint()*mcd, (sd*md).template cast<CD>().eval().adjoint()*mcd);
VERIFY_IS_APPROX(sd*mcd.adjoint()*md, sd*mcd.adjoint()*md.template cast<CD>());
VERIFY_IS_APPROX(sd*md.adjoint()*mcd.adjoint(), (sd*md).template cast<CD>().eval().adjoint()*mcd.adjoint());
VERIFY_IS_APPROX(sd*mcd.adjoint()*md.adjoint(), sd*mcd.adjoint()*md.template cast<CD>().adjoint());
VERIFY_IS_APPROX(sd*md*mcd.adjoint(), (sd*md).template cast<CD>().eval()*mcd.adjoint());
VERIFY_IS_APPROX(sd*mcd*md.adjoint(), sd*mcd*md.template cast<CD>().adjoint());
-
+
VERIFY_IS_APPROX(sf*mf.adjoint()*mcf, (sf*mf).template cast<CF>().eval().adjoint()*mcf);
VERIFY_IS_APPROX(sf*mcf.adjoint()*mf, sf*mcf.adjoint()*mf.template cast<CF>());
VERIFY_IS_APPROX(sf*mf.adjoint()*mcf.adjoint(), (sf*mf).template cast<CF>().eval().adjoint()*mcf.adjoint());
@@ -147,6 +147,39 @@ template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
VERIFY_IS_APPROX(scd*vcd.adjoint()*md, scd*vcd.adjoint()*md.template cast<CD>().eval());
VERIFY_IS_APPROX(sd*vd.adjoint()*mcd, sd*vd.adjoint().template cast<CD>().eval()*mcd);
VERIFY_IS_APPROX(scd*vd.adjoint()*mcd, scd*vd.adjoint().template cast<CD>().eval()*mcd);
+
+ VERIFY_IS_APPROX(sd*vcd.adjoint()*md.template triangularView<Upper>(), sd*vcd.adjoint()*md.template cast<CD>().eval().template triangularView<Upper>());
+ VERIFY_IS_APPROX(scd*vcd.adjoint()*md.template triangularView<Lower>(), scd*vcd.adjoint()*md.template cast<CD>().eval().template triangularView<Lower>());
+ VERIFY_IS_APPROX(sd*vd.adjoint()*mcd.template triangularView<Lower>(), sd*vd.adjoint().template cast<CD>().eval()*mcd.template triangularView<Lower>());
+ VERIFY_IS_APPROX(scd*vd.adjoint()*mcd.template triangularView<Upper>(), scd*vd.adjoint().template cast<CD>().eval()*mcd.template triangularView<Upper>());
+
+ // Not supported yet: trmm
+// VERIFY_IS_APPROX(sd*mcd*md.template triangularView<Lower>(), sd*mcd*md.template cast<CD>().eval().template triangularView<Lower>());
+// VERIFY_IS_APPROX(scd*mcd*md.template triangularView<Upper>(), scd*mcd*md.template cast<CD>().eval().template triangularView<Upper>());
+// VERIFY_IS_APPROX(sd*md*mcd.template triangularView<Lower>(), sd*md.template cast<CD>().eval()*mcd.template triangularView<Lower>());
+// VERIFY_IS_APPROX(scd*md*mcd.template triangularView<Upper>(), scd*md.template cast<CD>().eval()*mcd.template triangularView<Upper>());
+
+ // Not supported yet: symv
+// VERIFY_IS_APPROX(sd*vcd.adjoint()*md.template selfadjointView<Upper>(), sd*vcd.adjoint()*md.template cast<CD>().eval().template selfadjointView<Upper>());
+// VERIFY_IS_APPROX(scd*vcd.adjoint()*md.template selfadjointView<Lower>(), scd*vcd.adjoint()*md.template cast<CD>().eval().template selfadjointView<Lower>());
+// VERIFY_IS_APPROX(sd*vd.adjoint()*mcd.template selfadjointView<Lower>(), sd*vd.adjoint().template cast<CD>().eval()*mcd.template selfadjointView<Lower>());
+// VERIFY_IS_APPROX(scd*vd.adjoint()*mcd.template selfadjointView<Upper>(), scd*vd.adjoint().template cast<CD>().eval()*mcd.template selfadjointView<Upper>());
+
+ // Not supported yet: symm
+// VERIFY_IS_APPROX(sd*vcd.adjoint()*md.template selfadjointView<Upper>(), sd*vcd.adjoint()*md.template cast<CD>().eval().template selfadjointView<Upper>());
+// VERIFY_IS_APPROX(scd*vcd.adjoint()*md.template selfadjointView<Upper>(), scd*vcd.adjoint()*md.template cast<CD>().eval().template selfadjointView<Upper>());
+// VERIFY_IS_APPROX(sd*vd.adjoint()*mcd.template selfadjointView<Upper>(), sd*vd.adjoint().template cast<CD>().eval()*mcd.template selfadjointView<Upper>());
+// VERIFY_IS_APPROX(scd*vd.adjoint()*mcd.template selfadjointView<Upper>(), scd*vd.adjoint().template cast<CD>().eval()*mcd.template selfadjointView<Upper>());
+
+ rcd.setZero();
+ VERIFY_IS_APPROX(Mat_cd(rcd.template triangularView<Upper>() = sd * mcd * md),
+ Mat_cd((sd * mcd * md.template cast<CD>().eval()).template triangularView<Upper>()));
+ VERIFY_IS_APPROX(Mat_cd(rcd.template triangularView<Upper>() = sd * md * mcd),
+ Mat_cd((sd * md.template cast<CD>().eval() * mcd).template triangularView<Upper>()));
+ VERIFY_IS_APPROX(Mat_cd(rcd.template triangularView<Upper>() = scd * mcd * md),
+ Mat_cd((scd * mcd * md.template cast<CD>().eval()).template triangularView<Upper>()));
+ VERIFY_IS_APPROX(Mat_cd(rcd.template triangularView<Upper>() = scd * md * mcd),
+ Mat_cd((scd * md.template cast<CD>().eval() * mcd).template triangularView<Upper>()));
}
void test_mixingtypes()
diff --git a/test/nesting_ops.cpp b/test/nesting_ops.cpp
index 76a63400c..2f5025305 100644
--- a/test/nesting_ops.cpp
+++ b/test/nesting_ops.cpp
@@ -51,6 +51,7 @@ template <typename MatrixType> void run_nesting_ops_2(const MatrixType& _m)
Index rows = _m.rows();
Index cols = _m.cols();
MatrixType m1 = MatrixType::Random(rows,cols);
+ Matrix<Scalar,MatrixType::RowsAtCompileTime,MatrixType::ColsAtCompileTime,ColMajor> m2;
if((MatrixType::SizeAtCompileTime==Dynamic))
{
@@ -79,9 +80,9 @@ template <typename MatrixType> void run_nesting_ops_2(const MatrixType& _m)
}
VERIFY( verify_eval_type<2>(m1+m1, m1+m1) );
VERIFY( verify_eval_type<3>(m1+m1, m1) );
- VERIFY( verify_eval_type<1>(m1*m1.transpose(), m1) );
- VERIFY( verify_eval_type<1>(m1*(m1+m1).transpose(), m1) );
- VERIFY( verify_eval_type<2>(m1*m1.transpose(), m1) );
+ VERIFY( verify_eval_type<1>(m1*m1.transpose(), m2) );
+ VERIFY( verify_eval_type<1>(m1*(m1+m1).transpose(), m2) );
+ VERIFY( verify_eval_type<2>(m1*m1.transpose(), m2) );
VERIFY( verify_eval_type<1>(m1+m1*m1, m1) );
VERIFY( verify_eval_type<1>(m1.template triangularView<Lower>().solve(m1), m1) );
diff --git a/test/nomalloc.cpp b/test/nomalloc.cpp
index 060276a20..50756c2fb 100644
--- a/test/nomalloc.cpp
+++ b/test/nomalloc.cpp
@@ -78,14 +78,15 @@ template<typename MatrixType> void nomalloc(const MatrixType& m)
VERIFY_IS_APPROX(m2,m2);
m2.template selfadjointView<Lower>().rankUpdate(m1.col(0),-1);
- m2.template selfadjointView<Lower>().rankUpdate(m1.row(0),-1);
+ m2.template selfadjointView<Upper>().rankUpdate(m1.row(0),-1);
+ m2.template selfadjointView<Lower>().rankUpdate(m1.col(0), m1.col(0)); // rank-2
// The following fancy matrix-matrix products are not safe yet regarding static allocation
-// m1 += m1.template triangularView<Upper>() * m2.col(;
-// m1.template selfadjointView<Lower>().rankUpdate(m2);
-// m1 += m1.template triangularView<Upper>() * m2;
-// m1 += m1.template selfadjointView<Lower>() * m2;
-// VERIFY_IS_APPROX(m1,m1);
+ m2.template selfadjointView<Lower>().rankUpdate(m1);
+ m2 += m2.template triangularView<Upper>() * m1;
+ m2.template triangularView<Upper>() = m2 * m2;
+ m1 += m1.template selfadjointView<Lower>() * m2;
+ VERIFY_IS_APPROX(m2,m2);
}
template<typename Scalar>
diff --git a/test/nullary.cpp b/test/nullary.cpp
index 4844f2952..cb87695ee 100644
--- a/test/nullary.cpp
+++ b/test/nullary.cpp
@@ -48,30 +48,32 @@ void testVectorType(const VectorType& base)
VectorType m(base);
m.setLinSpaced(size,low,high);
+ if(!NumTraits<Scalar>::IsInteger)
+ {
+ VectorType n(size);
+ for (int i=0; i<size; ++i)
+ n(i) = low+i*step;
+ VERIFY_IS_APPROX(m,n);
+ }
+
VectorType n(size);
for (int i=0; i<size; ++i)
- n(i) = low+i*step;
-
+ n(i) = size==1 ? low : (low + ((high-low)*Scalar(i))/(size-1));
VERIFY_IS_APPROX(m,n);
// random access version
m = VectorType::LinSpaced(size,low,high);
VERIFY_IS_APPROX(m,n);
- // Assignment of a RowVectorXd to a MatrixXd (regression test for bug #79).
- VERIFY( (MatrixXd(RowVectorXd::LinSpaced(3, 0, 1)) - RowVector3d(0, 0.5, 1)).norm() < std::numeric_limits<Scalar>::epsilon() );
-
- // These guys sometimes fail! This is not good. Any ideas how to fix them!?
- //VERIFY( m(m.size()-1) == high );
- //VERIFY( m(0) == low );
+ VERIFY( internal::isApprox(m(m.size()-1),high) );
+ VERIFY( size==1 || internal::isApprox(m(0),low) );
// sequential access version
m = VectorType::LinSpaced(Sequential,size,low,high);
VERIFY_IS_APPROX(m,n);
- // These guys sometimes fail! This is not good. Any ideas how to fix them!?
- //VERIFY( m(m.size()-1) == high );
- //VERIFY( m(0) == low );
+ VERIFY( internal::isApprox(m(m.size()-1),high) );
+ VERIFY( size==1 || internal::isApprox(m(0),low) );
// check whether everything works with row and col major vectors
Matrix<Scalar,Dynamic,1> row_vector(size);
@@ -126,5 +128,13 @@ void test_nullary()
CALL_SUBTEST_8( testVectorType(Vector4f()) );
CALL_SUBTEST_8( testVectorType(Matrix<float,8,1>()) );
CALL_SUBTEST_8( testVectorType(Matrix<float,1,1>()) );
+
+ CALL_SUBTEST_9( testVectorType(VectorXi(internal::random<int>(1,300))) );
+ CALL_SUBTEST_9( testVectorType(Matrix<int,1,1>()) );
}
+
+#ifdef EIGEN_TEST_PART_6
+ // Assignment of a RowVectorXd to a MatrixXd (regression test for bug #79).
+ VERIFY( (MatrixXd(RowVectorXd::LinSpaced(3, 0, 1)) - RowVector3d(0, 0.5, 1)).norm() < std::numeric_limits<double>::epsilon() );
+#endif
}
diff --git a/test/packetmath.cpp b/test/packetmath.cpp
index 009de1393..6faf253a1 100644
--- a/test/packetmath.cpp
+++ b/test/packetmath.cpp
@@ -177,7 +177,7 @@ template<typename Scalar> void packetmath()
internal::pstore(data2, internal::pset1<Packet>(data1[offset]));
VERIFY(areApprox(ref, data2, PacketSize) && "internal::pset1");
}
-
+
{
for (int i=0; i<PacketSize*4; ++i)
ref[i] = data1[i/PacketSize];
@@ -199,9 +199,9 @@ template<typename Scalar> void packetmath()
internal::pstore(data2+1*PacketSize, A1);
VERIFY(areApprox(ref, data2, 2*PacketSize) && "internal::pbroadcast2");
}
-
+
VERIFY(internal::isApprox(data1[0], internal::pfirst(internal::pload<Packet>(data1))) && "internal::pfirst");
-
+
if(PacketSize>1)
{
for(int offset=0;offset<4;++offset)
@@ -212,6 +212,7 @@ template<typename Scalar> void packetmath()
VERIFY(areApprox(ref, data2, PacketSize) && "ploaddup");
}
}
+
if(PacketSize>2)
{
for(int offset=0;offset<4;++offset)
@@ -227,7 +228,7 @@ template<typename Scalar> void packetmath()
for (int i=0; i<PacketSize; ++i)
ref[0] += data1[i];
VERIFY(isApproxAbs(ref[0], internal::predux(internal::pload<Packet>(data1)), refvalue) && "internal::predux");
-
+
{
for (int i=0; i<4; ++i)
ref[i] = 0;
@@ -325,6 +326,12 @@ template<typename Scalar> void packetmath_real()
data2[i] = internal::random<Scalar>(-87,88);
}
CHECK_CWISE1_IF(PacketTraits::HasExp, std::exp, internal::pexp);
+ for (int i=0; i<size; ++i)
+ {
+ data1[i] = internal::random<Scalar>(-1,1) * std::pow(Scalar(10), internal::random<Scalar>(-6,6));
+ data2[i] = internal::random<Scalar>(-1,1) * std::pow(Scalar(10), internal::random<Scalar>(-6,6));
+ }
+ CHECK_CWISE1_IF(PacketTraits::HasTanh, std::tanh, internal::ptanh);
if(PacketTraits::HasExp && PacketTraits::size>=2)
{
data1[0] = std::numeric_limits<Scalar>::quiet_NaN();
@@ -338,7 +345,7 @@ template<typename Scalar> void packetmath_real()
data1[1] = 0;
h.store(data2, internal::pexp(h.load(data1)));
VERIFY_IS_EQUAL(std::exp(-std::numeric_limits<Scalar>::epsilon()), data2[0]);
- VERIFY_IS_EQUAL(std::exp(0), data2[1]);
+ VERIFY_IS_EQUAL(std::exp(Scalar(0)), data2[1]);
data1[0] = (std::numeric_limits<Scalar>::min)();
data1[1] = -(std::numeric_limits<Scalar>::min)();
@@ -353,15 +360,43 @@ template<typename Scalar> void packetmath_real()
VERIFY_IS_EQUAL(std::exp(-std::numeric_limits<Scalar>::denorm_min()), data2[1]);
}
+#ifdef EIGEN_HAS_C99_MATH
+ {
+ data1[0] = std::numeric_limits<Scalar>::quiet_NaN();
+ packet_helper<internal::packet_traits<Scalar>::HasLGamma,Packet> h;
+ h.store(data2, internal::plgamma(h.load(data1)));
+ VERIFY((numext::isnan)(data2[0]));
+ }
+ {
+ data1[0] = std::numeric_limits<Scalar>::quiet_NaN();
+ packet_helper<internal::packet_traits<Scalar>::HasErf,Packet> h;
+ h.store(data2, internal::perf(h.load(data1)));
+ VERIFY((numext::isnan)(data2[0]));
+ }
+ {
+ data1[0] = std::numeric_limits<Scalar>::quiet_NaN();
+ packet_helper<internal::packet_traits<Scalar>::HasErfc,Packet> h;
+ h.store(data2, internal::perfc(h.load(data1)));
+ VERIFY((numext::isnan)(data2[0]));
+ }
+#endif // EIGEN_HAS_C99_MATH
+
for (int i=0; i<size; ++i)
{
data1[i] = internal::random<Scalar>(0,1) * std::pow(Scalar(10), internal::random<Scalar>(-6,6));
data2[i] = internal::random<Scalar>(0,1) * std::pow(Scalar(10), internal::random<Scalar>(-6,6));
}
+
if(internal::random<float>(0,1)<0.1)
data1[internal::random<int>(0, PacketSize)] = 0;
CHECK_CWISE1_IF(PacketTraits::HasSqrt, std::sqrt, internal::psqrt);
CHECK_CWISE1_IF(PacketTraits::HasLog, std::log, internal::plog);
+#if defined(EIGEN_HAS_C99_MATH) && (__cplusplus > 199711L)
+ CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasLGamma, std::lgamma, internal::plgamma);
+ CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasErf, std::erf, internal::perf);
+ CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasErfc, std::erfc, internal::perfc);
+#endif
+
if(PacketTraits::HasLog && PacketTraits::size>=2)
{
data1[0] = std::numeric_limits<Scalar>::quiet_NaN();
@@ -375,7 +410,7 @@ template<typename Scalar> void packetmath_real()
data1[1] = 0;
h.store(data2, internal::plog(h.load(data1)));
VERIFY((numext::isnan)(data2[0]));
- VERIFY_IS_EQUAL(std::log(0), data2[1]);
+ VERIFY_IS_EQUAL(std::log(Scalar(0)), data2[1]);
data1[0] = (std::numeric_limits<Scalar>::min)();
data1[1] = -(std::numeric_limits<Scalar>::min)();
@@ -397,6 +432,7 @@ template<typename Scalar> void packetmath_real()
VERIFY((numext::isnan)(data2[0]));
VERIFY((numext::isnan)(data2[1]));
#endif
+
}
}
diff --git a/test/pastix_support.cpp b/test/pastix_support.cpp
index 49239e3a5..b62f85739 100644
--- a/test/pastix_support.cpp
+++ b/test/pastix_support.cpp
@@ -27,6 +27,14 @@ template<typename T> void test_pastix_T()
check_sparse_spd_solving(pastix_llt_upper);
check_sparse_spd_solving(pastix_ldlt_upper);
check_sparse_square_solving(pastix_lu);
+
+ // Some compilation check:
+ pastix_llt_lower.iparm();
+ pastix_llt_lower.dparm();
+ pastix_ldlt_lower.iparm();
+ pastix_ldlt_lower.dparm();
+ pastix_lu.iparm();
+ pastix_lu.dparm();
}
// There is no support for selfadjoint matrices with PaStiX.
diff --git a/test/product.h b/test/product.h
index 9dfff9303..27976a4ae 100644
--- a/test/product.h
+++ b/test/product.h
@@ -144,15 +144,56 @@ template<typename MatrixType> void product(const MatrixType& m)
VERIFY_IS_APPROX(res.col(r).noalias() = square.adjoint() * square.col(r), (square.adjoint() * square.col(r)).eval());
VERIFY_IS_APPROX(res.col(r).noalias() = square * square.col(r), (square * square.col(r)).eval());
+ // vector at runtime (see bug 1166)
+ {
+ RowSquareMatrixType ref(square);
+ ColSquareMatrixType ref2(square2);
+ ref = res = square;
+ VERIFY_IS_APPROX(res.block(0,0,1,rows).noalias() = m1.col(0).transpose() * square.transpose(), (ref.row(0) = m1.col(0).transpose() * square.transpose()));
+ VERIFY_IS_APPROX(res.block(0,0,1,rows).noalias() = m1.block(0,0,rows,1).transpose() * square.transpose(), (ref.row(0) = m1.col(0).transpose() * square.transpose()));
+ VERIFY_IS_APPROX(res.block(0,0,1,rows).noalias() = m1.col(0).transpose() * square, (ref.row(0) = m1.col(0).transpose() * square));
+ VERIFY_IS_APPROX(res.block(0,0,1,rows).noalias() = m1.block(0,0,rows,1).transpose() * square, (ref.row(0) = m1.col(0).transpose() * square));
+ ref2 = res2 = square2;
+ VERIFY_IS_APPROX(res2.block(0,0,1,cols).noalias() = m1.row(0) * square2.transpose(), (ref2.row(0) = m1.row(0) * square2.transpose()));
+ VERIFY_IS_APPROX(res2.block(0,0,1,cols).noalias() = m1.block(0,0,1,cols) * square2.transpose(), (ref2.row(0) = m1.row(0) * square2.transpose()));
+ VERIFY_IS_APPROX(res2.block(0,0,1,cols).noalias() = m1.row(0) * square2, (ref2.row(0) = m1.row(0) * square2));
+ VERIFY_IS_APPROX(res2.block(0,0,1,cols).noalias() = m1.block(0,0,1,cols) * square2, (ref2.row(0) = m1.row(0) * square2));
+ }
+
// inner product
- Scalar x = square2.row(c) * square2.col(c2);
- VERIFY_IS_APPROX(x, square2.row(c).transpose().cwiseProduct(square2.col(c2)).sum());
-
+ {
+ Scalar x = square2.row(c) * square2.col(c2);
+ VERIFY_IS_APPROX(x, square2.row(c).transpose().cwiseProduct(square2.col(c2)).sum());
+ }
+
// outer product
- VERIFY_IS_APPROX(m1.col(c) * m1.row(r), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
- VERIFY_IS_APPROX(m1.row(r).transpose() * m1.col(c).transpose(), m1.block(r,0,1,cols).transpose() * m1.block(0,c,rows,1).transpose());
- VERIFY_IS_APPROX(m1.block(0,c,rows,1) * m1.row(r), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
- VERIFY_IS_APPROX(m1.col(c) * m1.block(r,0,1,cols), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
- VERIFY_IS_APPROX(m1.leftCols(1) * m1.row(r), m1.block(0,0,rows,1) * m1.block(r,0,1,cols));
- VERIFY_IS_APPROX(m1.col(c) * m1.topRows(1), m1.block(0,c,rows,1) * m1.block(0,0,1,cols));
+ {
+ VERIFY_IS_APPROX(m1.col(c) * m1.row(r), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
+ VERIFY_IS_APPROX(m1.row(r).transpose() * m1.col(c).transpose(), m1.block(r,0,1,cols).transpose() * m1.block(0,c,rows,1).transpose());
+ VERIFY_IS_APPROX(m1.block(0,c,rows,1) * m1.row(r), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
+ VERIFY_IS_APPROX(m1.col(c) * m1.block(r,0,1,cols), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
+ VERIFY_IS_APPROX(m1.leftCols(1) * m1.row(r), m1.block(0,0,rows,1) * m1.block(r,0,1,cols));
+ VERIFY_IS_APPROX(m1.col(c) * m1.topRows(1), m1.block(0,c,rows,1) * m1.block(0,0,1,cols));
+ }
+
+ // Aliasing
+ {
+ ColVectorType x(cols); x.setRandom();
+ ColVectorType z(x);
+ ColVectorType y(cols); y.setZero();
+ ColSquareMatrixType A(cols,cols); A.setRandom();
+ // CwiseBinaryOp
+ VERIFY_IS_APPROX(x = y + A*x, A*z);
+ x = z;
+ // CwiseUnaryOp
+ VERIFY_IS_APPROX(x = Scalar(1.)*(A*x), A*z);
+ }
+
+ // regression for blas_trais
+ {
+ VERIFY_IS_APPROX(square * (square*square).transpose(), square * square.transpose() * square.transpose());
+ VERIFY_IS_APPROX(square * (-(square*square)), -square * square * square);
+ VERIFY_IS_APPROX(square * (s1*(square*square)), s1 * square * square * square);
+ VERIFY_IS_APPROX(square * (square*square).conjugate(), square * square.conjugate() * square.conjugate());
+ }
}
diff --git a/test/product_large.cpp b/test/product_large.cpp
index 7207973c2..98f84c53b 100644
--- a/test/product_large.cpp
+++ b/test/product_large.cpp
@@ -9,6 +9,27 @@
#include "product.h"
+template<typename T>
+void test_aliasing()
+{
+ int rows = internal::random<int>(1,12);
+ int cols = internal::random<int>(1,12);
+ typedef Matrix<T,Dynamic,Dynamic> MatrixType;
+ typedef Matrix<T,Dynamic,1> VectorType;
+ VectorType x(cols); x.setRandom();
+ VectorType z(x);
+ VectorType y(rows); y.setZero();
+ MatrixType A(rows,cols); A.setRandom();
+ // CwiseBinaryOp
+ VERIFY_IS_APPROX(x = y + A*x, A*z); // OK because "y + A*x" is marked as "assume-aliasing"
+ x = z;
+ // CwiseUnaryOp
+ VERIFY_IS_APPROX(x = T(1.)*(A*x), A*z); // OK because 1*(A*x) is replaced by (1*A*x) which is a Product<> expression
+ x = z;
+ // VERIFY_IS_APPROX(x = y-A*x, -A*z); // Not OK in 3.3 because x is resized before A*x gets evaluated
+ x = z;
+}
+
void test_product_large()
{
for(int i = 0; i < g_repeat; i++) {
@@ -17,6 +38,8 @@ void test_product_large()
CALL_SUBTEST_3( product(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
CALL_SUBTEST_4( product(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
CALL_SUBTEST_5( product(Matrix<float,Dynamic,Dynamic,RowMajor>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+
+ CALL_SUBTEST_1( test_aliasing<float>() );
}
#if defined EIGEN_TEST_PART_6
diff --git a/test/product_notemporary.cpp b/test/product_notemporary.cpp
index ff93cb881..5a3f3a01a 100644
--- a/test/product_notemporary.cpp
+++ b/test/product_notemporary.cpp
@@ -43,10 +43,16 @@ template<typename MatrixType> void product_notemporary(const MatrixType& m)
r1 = internal::random<Index>(8,rows-r0);
VERIFY_EVALUATION_COUNT( m3 = (m1 * m2.adjoint()), 1);
+ VERIFY_EVALUATION_COUNT( m3 = (m1 * m2.adjoint()).transpose(), 1);
VERIFY_EVALUATION_COUNT( m3.noalias() = m1 * m2.adjoint(), 0);
+ VERIFY_EVALUATION_COUNT( m3 = s1 * (m1 * m2.transpose()), 1);
+// VERIFY_EVALUATION_COUNT( m3 = m3 + s1 * (m1 * m2.transpose()), 1);
VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * (m1 * m2.transpose()), 0);
+ VERIFY_EVALUATION_COUNT( m3 = m3 + (m1 * m2.adjoint()), 1);
+
+ VERIFY_EVALUATION_COUNT( m3 = m3 + (m1 * m2.adjoint()).transpose(), 1);
VERIFY_EVALUATION_COUNT( m3.noalias() = m3 + m1 * m2.transpose(), 0);
VERIFY_EVALUATION_COUNT( m3.noalias() += m3 + m1 * m2.transpose(), 0);
VERIFY_EVALUATION_COUNT( m3.noalias() -= m3 + m1 * m2.transpose(), 0);
diff --git a/test/qr_colpivoting.cpp b/test/qr_colpivoting.cpp
index e7abd3725..46c54b74f 100644
--- a/test/qr_colpivoting.cpp
+++ b/test/qr_colpivoting.cpp
@@ -10,6 +10,86 @@
#include "main.h"
#include <Eigen/QR>
+#include <Eigen/SVD>
+
+template <typename MatrixType>
+void cod() {
+ typedef typename MatrixType::Index Index;
+
+ Index rows = internal::random<Index>(2, EIGEN_TEST_MAX_SIZE);
+ Index cols = internal::random<Index>(2, EIGEN_TEST_MAX_SIZE);
+ Index cols2 = internal::random<Index>(2, EIGEN_TEST_MAX_SIZE);
+ Index rank = internal::random<Index>(1, (std::min)(rows, cols) - 1);
+
+ typedef typename MatrixType::Scalar Scalar;
+ typedef Matrix<Scalar, MatrixType::RowsAtCompileTime,
+ MatrixType::RowsAtCompileTime>
+ MatrixQType;
+ MatrixType matrix;
+ createRandomPIMatrixOfRank(rank, rows, cols, matrix);
+ CompleteOrthogonalDecomposition<MatrixType> cod(matrix);
+ VERIFY(rank == cod.rank());
+ VERIFY(cols - cod.rank() == cod.dimensionOfKernel());
+ VERIFY(!cod.isInjective());
+ VERIFY(!cod.isInvertible());
+ VERIFY(!cod.isSurjective());
+
+ MatrixQType q = cod.householderQ();
+ VERIFY_IS_UNITARY(q);
+
+ MatrixType z = cod.matrixZ();
+ VERIFY_IS_UNITARY(z);
+
+ MatrixType t;
+ t.setZero(rows, cols);
+ t.topLeftCorner(rank, rank) =
+ cod.matrixT().topLeftCorner(rank, rank).template triangularView<Upper>();
+
+ MatrixType c = q * t * z * cod.colsPermutation().inverse();
+ VERIFY_IS_APPROX(matrix, c);
+
+ MatrixType exact_solution = MatrixType::Random(cols, cols2);
+ MatrixType rhs = matrix * exact_solution;
+ MatrixType cod_solution = cod.solve(rhs);
+ VERIFY_IS_APPROX(rhs, matrix * cod_solution);
+
+ // Verify that we get the same minimum-norm solution as the SVD.
+ JacobiSVD<MatrixType> svd(matrix, ComputeThinU | ComputeThinV);
+ MatrixType svd_solution = svd.solve(rhs);
+ VERIFY_IS_APPROX(cod_solution, svd_solution);
+
+ MatrixType pinv = cod.pseudoInverse();
+ VERIFY_IS_APPROX(cod_solution, pinv * rhs);
+}
+
+template <typename MatrixType, int Cols2>
+void cod_fixedsize() {
+ enum {
+ Rows = MatrixType::RowsAtCompileTime,
+ Cols = MatrixType::ColsAtCompileTime
+ };
+ typedef typename MatrixType::Scalar Scalar;
+ int rank = internal::random<int>(1, (std::min)(int(Rows), int(Cols)) - 1);
+ Matrix<Scalar, Rows, Cols> matrix;
+ createRandomPIMatrixOfRank(rank, Rows, Cols, matrix);
+ CompleteOrthogonalDecomposition<Matrix<Scalar, Rows, Cols> > cod(matrix);
+ VERIFY(rank == cod.rank());
+ VERIFY(Cols - cod.rank() == cod.dimensionOfKernel());
+ VERIFY(cod.isInjective() == (rank == Rows));
+ VERIFY(cod.isSurjective() == (rank == Cols));
+ VERIFY(cod.isInvertible() == (cod.isInjective() && cod.isSurjective()));
+
+ Matrix<Scalar, Cols, Cols2> exact_solution;
+ exact_solution.setRandom(Cols, Cols2);
+ Matrix<Scalar, Rows, Cols2> rhs = matrix * exact_solution;
+ Matrix<Scalar, Cols, Cols2> cod_solution = cod.solve(rhs);
+ VERIFY_IS_APPROX(rhs, matrix * cod_solution);
+
+ // Verify that we get the same minimum-norm solution as the SVD.
+ JacobiSVD<MatrixType> svd(matrix, ComputeFullU | ComputeFullV);
+ Matrix<Scalar, Cols, Cols2> svd_solution = svd.solve(rhs);
+ VERIFY_IS_APPROX(cod_solution, svd_solution);
+}
template<typename MatrixType> void qr()
{
@@ -19,6 +99,7 @@ template<typename MatrixType> void qr()
Index rank = internal::random<Index>(1, (std::min)(rows, cols)-1);
typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType;
MatrixType m1;
createRandomPIMatrixOfRank(rank,rows,cols,m1);
@@ -36,6 +117,24 @@ template<typename MatrixType> void qr()
MatrixType c = q * r * qr.colsPermutation().inverse();
VERIFY_IS_APPROX(m1, c);
+ // Verify that the absolute value of the diagonal elements in R are
+ // non-increasing until they reach the singularity threshold.
+ RealScalar threshold =
+ std::sqrt(RealScalar(rows)) * (std::abs)(r(0, 0)) * NumTraits<Scalar>::epsilon();
+ for (Index i = 0; i < (std::min)(rows, cols) - 1; ++i) {
+ RealScalar x = (std::abs)(r(i, i));
+ RealScalar y = (std::abs)(r(i + 1, i + 1));
+ if (x < threshold && y < threshold) continue;
+ if (!test_isApproxOrLessThan(y, x)) {
+ for (Index j = 0; j < (std::min)(rows, cols); ++j) {
+ std::cout << "i = " << j << ", |r_ii| = " << (std::abs)(r(j, j)) << std::endl;
+ }
+ std::cout << "Failure at i=" << i << ", rank=" << rank
+ << ", threshold=" << threshold << std::endl;
+ }
+ VERIFY_IS_APPROX_OR_LESS_THAN(y, x);
+ }
+
MatrixType m2 = MatrixType::Random(cols,cols2);
MatrixType m3 = m1*m2;
m2 = MatrixType::Random(cols,cols2);
@@ -47,6 +146,7 @@ template<typename MatrixType, int Cols2> void qr_fixedsize()
{
enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
int rank = internal::random<int>(1, (std::min)(int(Rows), int(Cols))-1);
Matrix<Scalar,Rows,Cols> m1;
createRandomPIMatrixOfRank(rank,Rows,Cols,m1);
@@ -66,6 +166,67 @@ template<typename MatrixType, int Cols2> void qr_fixedsize()
m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
m2 = qr.solve(m3);
VERIFY_IS_APPROX(m3, m1*m2);
+ // Verify that the absolute value of the diagonal elements in R are
+ // non-increasing until they reache the singularity threshold.
+ RealScalar threshold =
+ std::sqrt(RealScalar(Rows)) * (std::abs)(r(0, 0)) * NumTraits<Scalar>::epsilon();
+ for (Index i = 0; i < (std::min)(int(Rows), int(Cols)) - 1; ++i) {
+ RealScalar x = (std::abs)(r(i, i));
+ RealScalar y = (std::abs)(r(i + 1, i + 1));
+ if (x < threshold && y < threshold) continue;
+ if (!test_isApproxOrLessThan(y, x)) {
+ for (Index j = 0; j < (std::min)(int(Rows), int(Cols)); ++j) {
+ std::cout << "i = " << j << ", |r_ii| = " << (std::abs)(r(j, j)) << std::endl;
+ }
+ std::cout << "Failure at i=" << i << ", rank=" << rank
+ << ", threshold=" << threshold << std::endl;
+ }
+ VERIFY_IS_APPROX_OR_LESS_THAN(y, x);
+ }
+}
+
+// This test is meant to verify that pivots are chosen such that
+// even for a graded matrix, the diagonal of R falls of roughly
+// monotonically until it reaches the threshold for singularity.
+// We use the so-called Kahan matrix, which is a famous counter-example
+// for rank-revealing QR. See
+// http://www.netlib.org/lapack/lawnspdf/lawn176.pdf
+// page 3 for more detail.
+template<typename MatrixType> void qr_kahan_matrix()
+{
+ typedef typename MatrixType::Index Index;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
+
+ Index rows = 300, cols = rows;
+
+ MatrixType m1;
+ m1.setZero(rows,cols);
+ RealScalar s = std::pow(NumTraits<RealScalar>::epsilon(), 1.0 / rows);
+ RealScalar c = std::sqrt(1 - s*s);
+ for (Index i = 0; i < rows; ++i) {
+ m1(i, i) = pow(s, i);
+ m1.row(i).tail(rows - i - 1) = -pow(s, i) * c * MatrixType::Ones(1, rows - i - 1);
+ }
+ m1 = (m1 + m1.transpose()).eval();
+ ColPivHouseholderQR<MatrixType> qr(m1);
+ MatrixType r = qr.matrixQR().template triangularView<Upper>();
+
+ RealScalar threshold =
+ std::sqrt(RealScalar(rows)) * (std::abs)(r(0, 0)) * NumTraits<Scalar>::epsilon();
+ for (Index i = 0; i < (std::min)(rows, cols) - 1; ++i) {
+ RealScalar x = (std::abs)(r(i, i));
+ RealScalar y = (std::abs)(r(i + 1, i + 1));
+ if (x < threshold && y < threshold) continue;
+ if (!test_isApproxOrLessThan(y, x)) {
+ for (Index j = 0; j < (std::min)(rows, cols); ++j) {
+ std::cout << "i = " << j << ", |r_ii| = " << (std::abs)(r(j, j)) << std::endl;
+ }
+ std::cout << "Failure at i=" << i << ", rank=" << qr.rank()
+ << ", threshold=" << threshold << std::endl;
+ }
+ VERIFY_IS_APPROX_OR_LESS_THAN(y, x);
+ }
}
template<typename MatrixType> void qr_invertible()
@@ -132,6 +293,15 @@ void test_qr_colpivoting()
}
for(int i = 0; i < g_repeat; i++) {
+ CALL_SUBTEST_1( cod<MatrixXf>() );
+ CALL_SUBTEST_2( cod<MatrixXd>() );
+ CALL_SUBTEST_3( cod<MatrixXcd>() );
+ CALL_SUBTEST_4(( cod_fixedsize<Matrix<float,3,5>, 4 >() ));
+ CALL_SUBTEST_5(( cod_fixedsize<Matrix<double,6,2>, 3 >() ));
+ CALL_SUBTEST_5(( cod_fixedsize<Matrix<double,1,1>, 1 >() ));
+ }
+
+ for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_1( qr_invertible<MatrixXf>() );
CALL_SUBTEST_2( qr_invertible<MatrixXd>() );
CALL_SUBTEST_6( qr_invertible<MatrixXcf>() );
@@ -147,4 +317,7 @@ void test_qr_colpivoting()
// Test problem size constructors
CALL_SUBTEST_9(ColPivHouseholderQR<MatrixXf>(10, 20));
+
+ CALL_SUBTEST_1( qr_kahan_matrix<MatrixXf>() );
+ CALL_SUBTEST_2( qr_kahan_matrix<MatrixXd>() );
}
diff --git a/test/sparse_basic.cpp b/test/sparse_basic.cpp
index d803e7dae..cb8ebaedf 100644
--- a/test/sparse_basic.cpp
+++ b/test/sparse_basic.cpp
@@ -21,8 +21,8 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
const Index rows = ref.rows();
const Index cols = ref.cols();
- const Index inner = ref.innerSize();
- const Index outer = ref.outerSize();
+ //const Index inner = ref.innerSize();
+ //const Index outer = ref.outerSize();
typedef typename SparseMatrixType::Scalar Scalar;
enum { Flags = SparseMatrixType::Flags };
@@ -192,6 +192,11 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
VERIFY_IS_APPROX(refM4.cwiseProduct(m3), refM4.cwiseProduct(refM3));
// VERIFY_IS_APPROX(m3.cwise()/refM4, refM3.cwise()/refM4);
+ VERIFY_IS_APPROX(refM4 + m3, refM4 + refM3);
+ VERIFY_IS_APPROX(m3 + refM4, refM3 + refM4);
+ VERIFY_IS_APPROX(refM4 - m3, refM4 - refM3);
+ VERIFY_IS_APPROX(m3 - refM4, refM3 - refM4);
+
// test aliasing
VERIFY_IS_APPROX((m1 = -m1), (refM1 = -refM1));
VERIFY_IS_APPROX((m1 = m1.transpose()), (refM1 = refM1.transpose().eval()));
@@ -322,7 +327,6 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
m3 = m2.template triangularView<Upper>();
VERIFY_IS_APPROX(m3, refMat3);
- if(inner>=outer) // FIXME this should be implemented for outer>inner as well
{
refMat3 = refMat2.template triangularView<UnitUpper>();
m3 = m2.template triangularView<UnitUpper>();
@@ -455,6 +459,33 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
refMat1.setIdentity();
VERIFY_IS_APPROX(m1, refMat1);
}
+
+ // test array/vector of InnerIterator
+ {
+ typedef typename SparseMatrixType::InnerIterator IteratorType;
+
+ DenseMatrix refMat2 = DenseMatrix::Zero(rows, cols);
+ SparseMatrixType m2(rows, cols);
+ initSparse<Scalar>(density, refMat2, m2);
+ IteratorType static_array[2];
+ static_array[0] = IteratorType(m2,0);
+ static_array[1] = IteratorType(m2,m2.outerSize()-1);
+ VERIFY( static_array[0] || m2.innerVector(static_array[0].outer()).nonZeros() == 0 );
+ VERIFY( static_array[1] || m2.innerVector(static_array[1].outer()).nonZeros() == 0 );
+ if(static_array[0] && static_array[1])
+ {
+ ++(static_array[1]);
+ static_array[1] = IteratorType(m2,0);
+ VERIFY( static_array[1] );
+ VERIFY( static_array[1].index() == static_array[0].index() );
+ VERIFY( static_array[1].outer() == static_array[0].outer() );
+ VERIFY( static_array[1].value() == static_array[0].value() );
+ }
+
+ std::vector<IteratorType> iters(2);
+ iters[0] = IteratorType(m2,0);
+ iters[1] = IteratorType(m2,m2.outerSize()-1);
+ }
}
diff --git a/test/sparse_vector.cpp b/test/sparse_vector.cpp
index d3975b99b..d95f301d5 100644
--- a/test/sparse_vector.cpp
+++ b/test/sparse_vector.cpp
@@ -9,14 +9,14 @@
#include "sparse.h"
-template<typename Scalar,typename Index> void sparse_vector(int rows, int cols)
+template<typename Scalar,typename StorageIndex> void sparse_vector(int rows, int cols)
{
double densityMat = (std::max)(8./(rows*cols), 0.01);
double densityVec = (std::max)(8./float(rows), 0.1);
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
typedef Matrix<Scalar,Dynamic,1> DenseVector;
- typedef SparseVector<Scalar,0,Index> SparseVectorType;
- typedef SparseMatrix<Scalar,0,Index> SparseMatrixType;
+ typedef SparseVector<Scalar,0,StorageIndex> SparseVectorType;
+ typedef SparseMatrix<Scalar,0,StorageIndex> SparseMatrixType;
Scalar eps = 1e-6;
SparseMatrixType m1(rows,rows);
@@ -87,8 +87,10 @@ template<typename Scalar,typename Index> void sparse_vector(int rows, int cols)
VERIFY_IS_APPROX(m1*v2, refM1*refV2);
VERIFY_IS_APPROX(v1.dot(m1*v2), refV1.dot(refM1*refV2));
- int i = internal::random<int>(0,rows-1);
- VERIFY_IS_APPROX(v1.dot(m1.col(i)), refV1.dot(refM1.col(i)));
+ {
+ int i = internal::random<int>(0,rows-1);
+ VERIFY_IS_APPROX(v1.dot(m1.col(i)), refV1.dot(refM1.col(i)));
+ }
VERIFY_IS_APPROX(v1.squaredNorm(), refV1.squaredNorm());
@@ -111,15 +113,51 @@ template<typename Scalar,typename Index> void sparse_vector(int rows, int cols)
VERIFY_IS_APPROX(refV3 = v1.transpose(),v1.toDense());
VERIFY_IS_APPROX(DenseVector(v1),v1.toDense());
+ // test conservative resize
+ {
+ std::vector<StorageIndex> inc;
+ if(rows > 3)
+ inc.push_back(-3);
+ inc.push_back(0);
+ inc.push_back(3);
+ inc.push_back(1);
+ inc.push_back(10);
+
+ for(std::size_t i = 0; i< inc.size(); i++) {
+ StorageIndex incRows = inc[i];
+ SparseVectorType vec1(rows);
+ DenseVector refVec1 = DenseVector::Zero(rows);
+ initSparse<Scalar>(densityVec, refVec1, vec1);
+
+ vec1.conservativeResize(rows+incRows);
+ refVec1.conservativeResize(rows+incRows);
+ if (incRows > 0) refVec1.tail(incRows).setZero();
+
+ VERIFY_IS_APPROX(vec1, refVec1);
+
+ // Insert new values
+ if (incRows > 0)
+ vec1.insert(vec1.rows()-1) = refVec1(refVec1.rows()-1) = 1;
+
+ VERIFY_IS_APPROX(vec1, refVec1);
+ }
+ }
+
}
void test_sparse_vector()
{
for(int i = 0; i < g_repeat; i++) {
+ int r = Eigen::internal::random<int>(1,500), c = Eigen::internal::random<int>(1,500);
+ if(Eigen::internal::random<int>(0,4) == 0) {
+ r = c; // check square matrices in 25% of tries
+ }
+ EIGEN_UNUSED_VARIABLE(r+c);
+
CALL_SUBTEST_1(( sparse_vector<double,int>(8, 8) ));
- CALL_SUBTEST_2(( sparse_vector<std::complex<double>, int>(16, 16) ));
- CALL_SUBTEST_1(( sparse_vector<double,long int>(299, 535) ));
- CALL_SUBTEST_1(( sparse_vector<double,short>(299, 535) ));
+ CALL_SUBTEST_2(( sparse_vector<std::complex<double>, int>(r, c) ));
+ CALL_SUBTEST_1(( sparse_vector<double,long int>(r, c) ));
+ CALL_SUBTEST_1(( sparse_vector<double,short>(r, c) ));
}
}
diff --git a/test/stable_norm.cpp b/test/stable_norm.cpp
index 7561ae8be..c3eb5ff31 100644
--- a/test/stable_norm.cpp
+++ b/test/stable_norm.cpp
@@ -163,6 +163,21 @@ template<typename MatrixType> void stable_norm(const MatrixType& m)
VERIFY(!(numext::isfinite)(v.blueNorm())); VERIFY((numext::isnan)(v.blueNorm()));
VERIFY(!(numext::isfinite)(v.hypotNorm())); VERIFY((numext::isnan)(v.hypotNorm()));
}
+
+ // stableNormalize[d]
+ {
+ VERIFY_IS_APPROX(vrand.stableNormalized(), vrand.normalized());
+ MatrixType vcopy(vrand);
+ vcopy.stableNormalize();
+ VERIFY_IS_APPROX(vcopy, vrand.normalized());
+ VERIFY_IS_APPROX((vrand.stableNormalized()).norm(), RealScalar(1));
+ VERIFY_IS_APPROX(vcopy.norm(), RealScalar(1));
+ VERIFY_IS_APPROX((vbig.stableNormalized()).norm(), RealScalar(1));
+ VERIFY_IS_APPROX((vsmall.stableNormalized()).norm(), RealScalar(1));
+ RealScalar big_scaling = ((std::numeric_limits<RealScalar>::max)() * RealScalar(1e-4));
+ VERIFY_IS_APPROX(vbig/big_scaling, (vbig.stableNorm() * vbig.stableNormalized()).eval()/big_scaling);
+ VERIFY_IS_APPROX(vsmall, vsmall.stableNorm() * vsmall.stableNormalized());
+ }
}
void test_stable_norm()
diff --git a/test/stddeque_overload.cpp b/test/stddeque_overload.cpp
new file mode 100644
index 000000000..4da618bbf
--- /dev/null
+++ b/test/stddeque_overload.cpp
@@ -0,0 +1,158 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
+//
+// 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
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+#include <Eigen/StdDeque>
+#include <Eigen/Geometry>
+
+EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Vector4f)
+
+EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Matrix2f)
+EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Matrix4f)
+EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Matrix4d)
+
+EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Affine3f)
+EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Affine3d)
+
+EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Quaternionf)
+EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Quaterniond)
+
+template<typename MatrixType>
+void check_stddeque_matrix(const MatrixType& m)
+{
+ typename MatrixType::Index rows = m.rows();
+ typename MatrixType::Index cols = m.cols();
+ MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
+ std::deque<MatrixType> v(10, MatrixType(rows,cols)), w(20, y);
+ v[5] = x;
+ w[6] = v[5];
+ VERIFY_IS_APPROX(w[6], v[5]);
+ v = w;
+ for(int i = 0; i < 20; i++)
+ {
+ VERIFY_IS_APPROX(w[i], v[i]);
+ }
+
+ v.resize(21);
+ v[20] = x;
+ VERIFY_IS_APPROX(v[20], x);
+ v.resize(22,y);
+ VERIFY_IS_APPROX(v[21], y);
+ v.push_back(x);
+ VERIFY_IS_APPROX(v[22], x);
+
+ // do a lot of push_back such that the deque gets internally resized
+ // (with memory reallocation)
+ MatrixType* ref = &w[0];
+ for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+ v.push_back(w[i%w.size()]);
+ for(unsigned int i=23; i<v.size(); ++i)
+ {
+ VERIFY(v[i]==w[(i-23)%w.size()]);
+ }
+}
+
+template<typename TransformType>
+void check_stddeque_transform(const TransformType&)
+{
+ typedef typename TransformType::MatrixType MatrixType;
+ TransformType x(MatrixType::Random()), y(MatrixType::Random());
+ std::deque<TransformType> v(10), w(20, y);
+ v[5] = x;
+ w[6] = v[5];
+ VERIFY_IS_APPROX(w[6], v[5]);
+ v = w;
+ for(int i = 0; i < 20; i++)
+ {
+ VERIFY_IS_APPROX(w[i], v[i]);
+ }
+
+ v.resize(21);
+ v[20] = x;
+ VERIFY_IS_APPROX(v[20], x);
+ v.resize(22,y);
+ VERIFY_IS_APPROX(v[21], y);
+ v.push_back(x);
+ VERIFY_IS_APPROX(v[22], x);
+
+ // do a lot of push_back such that the deque gets internally resized
+ // (with memory reallocation)
+ TransformType* ref = &w[0];
+ for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+ v.push_back(w[i%w.size()]);
+ for(unsigned int i=23; i<v.size(); ++i)
+ {
+ VERIFY(v[i].matrix()==w[(i-23)%w.size()].matrix());
+ }
+}
+
+template<typename QuaternionType>
+void check_stddeque_quaternion(const QuaternionType&)
+{
+ typedef typename QuaternionType::Coefficients Coefficients;
+ QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
+ std::deque<QuaternionType> v(10), w(20, y);
+ v[5] = x;
+ w[6] = v[5];
+ VERIFY_IS_APPROX(w[6], v[5]);
+ v = w;
+ for(int i = 0; i < 20; i++)
+ {
+ VERIFY_IS_APPROX(w[i], v[i]);
+ }
+
+ v.resize(21);
+ v[20] = x;
+ VERIFY_IS_APPROX(v[20], x);
+ v.resize(22,y);
+ VERIFY_IS_APPROX(v[21], y);
+ v.push_back(x);
+ VERIFY_IS_APPROX(v[22], x);
+
+ // do a lot of push_back such that the deque gets internally resized
+ // (with memory reallocation)
+ QuaternionType* ref = &w[0];
+ for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+ v.push_back(w[i%w.size()]);
+ for(unsigned int i=23; i<v.size(); ++i)
+ {
+ VERIFY(v[i].coeffs()==w[(i-23)%w.size()].coeffs());
+ }
+}
+
+void test_stddeque_overload()
+{
+ // some non vectorizable fixed sizes
+ CALL_SUBTEST_1(check_stddeque_matrix(Vector2f()));
+ CALL_SUBTEST_1(check_stddeque_matrix(Matrix3f()));
+ CALL_SUBTEST_2(check_stddeque_matrix(Matrix3d()));
+
+ // some vectorizable fixed sizes
+ CALL_SUBTEST_1(check_stddeque_matrix(Matrix2f()));
+ CALL_SUBTEST_1(check_stddeque_matrix(Vector4f()));
+ CALL_SUBTEST_1(check_stddeque_matrix(Matrix4f()));
+ CALL_SUBTEST_2(check_stddeque_matrix(Matrix4d()));
+
+ // some dynamic sizes
+ CALL_SUBTEST_3(check_stddeque_matrix(MatrixXd(1,1)));
+ CALL_SUBTEST_3(check_stddeque_matrix(VectorXd(20)));
+ CALL_SUBTEST_3(check_stddeque_matrix(RowVectorXf(20)));
+ CALL_SUBTEST_3(check_stddeque_matrix(MatrixXcf(10,10)));
+
+ // some Transform
+ CALL_SUBTEST_4(check_stddeque_transform(Affine2f())); // does not need the specialization (2+1)^2 = 9
+ CALL_SUBTEST_4(check_stddeque_transform(Affine3f()));
+ CALL_SUBTEST_4(check_stddeque_transform(Affine3d()));
+
+ // some Quaternion
+ CALL_SUBTEST_5(check_stddeque_quaternion(Quaternionf()));
+ CALL_SUBTEST_5(check_stddeque_quaternion(Quaterniond()));
+}
diff --git a/test/stdlist_overload.cpp b/test/stdlist_overload.cpp
new file mode 100644
index 000000000..bb910bd43
--- /dev/null
+++ b/test/stdlist_overload.cpp
@@ -0,0 +1,192 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
+//
+// 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
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+#include <Eigen/StdList>
+#include <Eigen/Geometry>
+
+EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Vector4f)
+
+EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Matrix2f)
+EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Matrix4f)
+EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Matrix4d)
+
+EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Affine3f)
+EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Affine3d)
+
+EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Quaternionf)
+EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Quaterniond)
+
+template <class Container, class Position>
+typename Container::iterator get(Container & c, Position position)
+{
+ typename Container::iterator it = c.begin();
+ std::advance(it, position);
+ return it;
+}
+
+template <class Container, class Position, class Value>
+void set(Container & c, Position position, const Value & value)
+{
+ typename Container::iterator it = c.begin();
+ std::advance(it, position);
+ *it = value;
+}
+
+template<typename MatrixType>
+void check_stdlist_matrix(const MatrixType& m)
+{
+ typename MatrixType::Index rows = m.rows();
+ typename MatrixType::Index cols = m.cols();
+ MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
+ std::list<MatrixType> v(10, MatrixType(rows,cols)), w(20, y);
+ typename std::list<MatrixType>::iterator itv = get(v, 5);
+ typename std::list<MatrixType>::iterator itw = get(w, 6);
+ *itv = x;
+ *itw = *itv;
+ VERIFY_IS_APPROX(*itw, *itv);
+ v = w;
+ itv = v.begin();
+ itw = w.begin();
+ for(int i = 0; i < 20; i++)
+ {
+ VERIFY_IS_APPROX(*itw, *itv);
+ ++itv;
+ ++itw;
+ }
+
+ v.resize(21);
+ set(v, 20, x);
+ VERIFY_IS_APPROX(*get(v, 20), x);
+ v.resize(22,y);
+ VERIFY_IS_APPROX(*get(v, 21), y);
+ v.push_back(x);
+ VERIFY_IS_APPROX(*get(v, 22), x);
+
+ // do a lot of push_back such that the list gets internally resized
+ // (with memory reallocation)
+ MatrixType* ref = &(*get(w, 0));
+ for(int i=0; i<30 || ((ref==&(*get(w, 0))) && i<300); ++i)
+ v.push_back(*get(w, i%w.size()));
+ for(unsigned int i=23; i<v.size(); ++i)
+ {
+ VERIFY((*get(v, i))==(*get(w, (i-23)%w.size())));
+ }
+}
+
+template<typename TransformType>
+void check_stdlist_transform(const TransformType&)
+{
+ typedef typename TransformType::MatrixType MatrixType;
+ TransformType x(MatrixType::Random()), y(MatrixType::Random());
+ std::list<TransformType> v(10), w(20, y);
+ typename std::list<TransformType>::iterator itv = get(v, 5);
+ typename std::list<TransformType>::iterator itw = get(w, 6);
+ *itv = x;
+ *itw = *itv;
+ VERIFY_IS_APPROX(*itw, *itv);
+ v = w;
+ itv = v.begin();
+ itw = w.begin();
+ for(int i = 0; i < 20; i++)
+ {
+ VERIFY_IS_APPROX(*itw, *itv);
+ ++itv;
+ ++itw;
+ }
+
+ v.resize(21);
+ set(v, 20, x);
+ VERIFY_IS_APPROX(*get(v, 20), x);
+ v.resize(22,y);
+ VERIFY_IS_APPROX(*get(v, 21), y);
+ v.push_back(x);
+ VERIFY_IS_APPROX(*get(v, 22), x);
+
+ // do a lot of push_back such that the list gets internally resized
+ // (with memory reallocation)
+ TransformType* ref = &(*get(w, 0));
+ for(int i=0; i<30 || ((ref==&(*get(w, 0))) && i<300); ++i)
+ v.push_back(*get(w, i%w.size()));
+ for(unsigned int i=23; i<v.size(); ++i)
+ {
+ VERIFY(get(v, i)->matrix()==get(w, (i-23)%w.size())->matrix());
+ }
+}
+
+template<typename QuaternionType>
+void check_stdlist_quaternion(const QuaternionType&)
+{
+ typedef typename QuaternionType::Coefficients Coefficients;
+ QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
+ std::list<QuaternionType> v(10), w(20, y);
+ typename std::list<QuaternionType>::iterator itv = get(v, 5);
+ typename std::list<QuaternionType>::iterator itw = get(w, 6);
+ *itv = x;
+ *itw = *itv;
+ VERIFY_IS_APPROX(*itw, *itv);
+ v = w;
+ itv = v.begin();
+ itw = w.begin();
+ for(int i = 0; i < 20; i++)
+ {
+ VERIFY_IS_APPROX(*itw, *itv);
+ ++itv;
+ ++itw;
+ }
+
+ v.resize(21);
+ set(v, 20, x);
+ VERIFY_IS_APPROX(*get(v, 20), x);
+ v.resize(22,y);
+ VERIFY_IS_APPROX(*get(v, 21), y);
+ v.push_back(x);
+ VERIFY_IS_APPROX(*get(v, 22), x);
+
+ // do a lot of push_back such that the list gets internally resized
+ // (with memory reallocation)
+ QuaternionType* ref = &(*get(w, 0));
+ for(int i=0; i<30 || ((ref==&(*get(w, 0))) && i<300); ++i)
+ v.push_back(*get(w, i%w.size()));
+ for(unsigned int i=23; i<v.size(); ++i)
+ {
+ VERIFY(get(v, i)->coeffs()==get(w, (i-23)%w.size())->coeffs());
+ }
+}
+
+void test_stdlist_overload()
+{
+ // some non vectorizable fixed sizes
+ CALL_SUBTEST_1(check_stdlist_matrix(Vector2f()));
+ CALL_SUBTEST_1(check_stdlist_matrix(Matrix3f()));
+ CALL_SUBTEST_2(check_stdlist_matrix(Matrix3d()));
+
+ // some vectorizable fixed sizes
+ CALL_SUBTEST_1(check_stdlist_matrix(Matrix2f()));
+ CALL_SUBTEST_1(check_stdlist_matrix(Vector4f()));
+ CALL_SUBTEST_1(check_stdlist_matrix(Matrix4f()));
+ CALL_SUBTEST_2(check_stdlist_matrix(Matrix4d()));
+
+ // some dynamic sizes
+ CALL_SUBTEST_3(check_stdlist_matrix(MatrixXd(1,1)));
+ CALL_SUBTEST_3(check_stdlist_matrix(VectorXd(20)));
+ CALL_SUBTEST_3(check_stdlist_matrix(RowVectorXf(20)));
+ CALL_SUBTEST_3(check_stdlist_matrix(MatrixXcf(10,10)));
+
+ // some Transform
+ CALL_SUBTEST_4(check_stdlist_transform(Affine2f())); // does not need the specialization (2+1)^2 = 9
+ CALL_SUBTEST_4(check_stdlist_transform(Affine3f()));
+ CALL_SUBTEST_4(check_stdlist_transform(Affine3d()));
+
+ // some Quaternion
+ CALL_SUBTEST_5(check_stdlist_quaternion(Quaternionf()));
+ CALL_SUBTEST_5(check_stdlist_quaternion(Quaterniond()));
+}
diff --git a/test/vectorization_logic.cpp b/test/vectorization_logic.cpp
index da60a2f3a..35fbb9781 100644
--- a/test/vectorization_logic.cpp
+++ b/test/vectorization_logic.cpp
@@ -1,12 +1,15 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2015 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// 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
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
+#undef EIGEN_DEFAULT_TO_ROW_MAJOR
+#endif
#define EIGEN_DEBUG_ASSIGN
#include "main.h"
#include <typeinfo>
diff --git a/test/vectorwiseop.cpp b/test/vectorwiseop.cpp
index 87476f95b..3cc198772 100644
--- a/test/vectorwiseop.cpp
+++ b/test/vectorwiseop.cpp
@@ -210,6 +210,9 @@ template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m)
VERIFY_IS_APPROX(m1.cwiseAbs().colwise().maxCoeff(), m1.colwise().template lpNorm<Infinity>());
VERIFY_IS_APPROX(m1.cwiseAbs().rowwise().maxCoeff(), m1.rowwise().template lpNorm<Infinity>());
+ // regression for bug 1158
+ VERIFY_IS_APPROX(m1.cwiseAbs().colwise().sum().x(), m1.col(0).cwiseAbs().sum());
+
// test normalized
m2 = m1.colwise().normalized();
VERIFY_IS_APPROX(m2.col(c), m1.col(c).normalized());
diff --git a/test/zerosized.cpp b/test/zerosized.cpp
index da7dd0481..477ff0070 100644
--- a/test/zerosized.cpp
+++ b/test/zerosized.cpp
@@ -25,6 +25,7 @@ template<typename MatrixType> void zeroReduction(const MatrixType& m) {
template<typename MatrixType> void zeroSizedMatrix()
{
MatrixType t1;
+ typedef typename MatrixType::Scalar Scalar;
if (MatrixType::SizeAtCompileTime == Dynamic || MatrixType::SizeAtCompileTime == 0)
{
@@ -37,7 +38,7 @@ template<typename MatrixType> void zeroSizedMatrix()
if (MatrixType::RowsAtCompileTime == Dynamic && MatrixType::ColsAtCompileTime == Dynamic)
{
- MatrixType t2(0, 0);
+ MatrixType t2(0, 0), t3(t1);
VERIFY(t2.rows() == 0);
VERIFY(t2.cols() == 0);
@@ -45,6 +46,23 @@ template<typename MatrixType> void zeroSizedMatrix()
VERIFY(t1==t2);
}
}
+
+ if(MatrixType::MaxColsAtCompileTime!=0 && MatrixType::MaxRowsAtCompileTime!=0)
+ {
+ Index rows = MatrixType::RowsAtCompileTime==Dynamic ? internal::random<Index>(1,10) : Index(MatrixType::RowsAtCompileTime);
+ Index cols = MatrixType::ColsAtCompileTime==Dynamic ? internal::random<Index>(1,10) : Index(MatrixType::ColsAtCompileTime);
+ MatrixType m(rows,cols);
+ zeroReduction(m.template block<0,MatrixType::ColsAtCompileTime>(0,0,0,cols));
+ zeroReduction(m.template block<MatrixType::RowsAtCompileTime,0>(0,0,rows,0));
+ zeroReduction(m.template block<0,1>(0,0));
+ zeroReduction(m.template block<1,0>(0,0));
+ Matrix<Scalar,Dynamic,Dynamic> prod = m.template block<MatrixType::RowsAtCompileTime,0>(0,0,rows,0) * m.template block<0,MatrixType::ColsAtCompileTime>(0,0,0,cols);
+ VERIFY(prod.rows()==rows && prod.cols()==cols);
+ VERIFY(prod.isZero());
+ prod = m.template block<1,0>(0,0) * m.template block<0,1>(0,0);
+ VERIFY(prod.size()==1);
+ VERIFY(prod.isZero());
+ }
}
template<typename VectorType> void zeroSizedVector()