diff options
author | Gael Guennebaud <g.gael@free.fr> | 2009-12-22 22:51:08 +0100 |
---|---|---|
committer | Gael Guennebaud <g.gael@free.fr> | 2009-12-22 22:51:08 +0100 |
commit | eaaba30cacf078335ad41314bf1e4ce993f0b3b4 (patch) | |
tree | 61156273b56dc19fc4e661a5aeb42d8e6112a307 /test | |
parent | e182e9c6166840b8db44e0be459a2e26d26fda0f (diff) | |
parent | eeec7d842e05394703c42e7569230835f7842089 (diff) |
merge with default branch
Diffstat (limited to 'test')
-rw-r--r-- | test/CMakeLists.txt | 8 | ||||
-rw-r--r-- | test/adjoint.cpp | 8 | ||||
-rw-r--r-- | test/bandmatrix.cpp | 4 | ||||
-rwxr-xr-x | test/buildtests.in | 21 | ||||
-rw-r--r-- | test/cholesky.cpp | 4 | ||||
-rw-r--r-- | test/eigensolver_complex.cpp | 1 | ||||
-rw-r--r-- | test/geo_hyperplane.cpp | 2 | ||||
-rw-r--r-- | test/geo_quaternion.cpp | 2 | ||||
-rw-r--r-- | test/inverse.cpp | 19 | ||||
-rw-r--r-- | test/jacobisvd.cpp | 3 | ||||
-rw-r--r-- | test/lu.cpp | 17 | ||||
-rw-r--r-- | test/main.h | 102 | ||||
-rw-r--r-- | test/permutationmatrices.cpp | 35 | ||||
-rw-r--r-- | test/prec_inverse_4x4.cpp | 80 | ||||
-rw-r--r-- | test/product.h | 2 | ||||
-rw-r--r-- | test/product_selfadjoint.cpp | 8 | ||||
-rw-r--r-- | test/product_syrk.cpp | 12 | ||||
-rw-r--r-- | test/product_trsm.cpp | 2 | ||||
-rw-r--r-- | test/qr.cpp | 10 | ||||
-rw-r--r-- | test/qr_colpivoting.cpp | 36 | ||||
-rw-r--r-- | test/qr_fullpivoting.cpp | 5 | ||||
-rwxr-xr-x | test/runtest.sh | 2 | ||||
-rw-r--r-- | test/sparse_basic.cpp | 4 | ||||
-rw-r--r-- | test/stable_norm.cpp | 8 | ||||
-rw-r--r-- | test/testsuite.cmake | 8 | ||||
-rw-r--r-- | test/triangular.cpp | 196 | ||||
-rw-r--r-- | test/unalignedassert.cpp | 1 | ||||
-rw-r--r-- | test/vectorization_logic.cpp | 55 |
28 files changed, 455 insertions, 200 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c6e282a0e..c29331db5 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -3,10 +3,6 @@ add_custom_target(buildtests) add_custom_target(check COMMAND "ctest") add_dependencies(check buildtests) - -include(EigenTesting) -ei_init_testing() - option(EIGEN_SPLIT_LARGE_TESTS "Split large tests into smaller executables" ON) find_package(GSL) @@ -162,6 +158,8 @@ ei_add_test(conservative_resize) ei_add_test(permutationmatrices) ei_add_test(eigen2support) +ei_add_test(prec_inverse_4x4) + ei_add_property(EIGEN_TESTING_SUMMARY "CXX: ${CMAKE_CXX_COMPILER}\n") if(CMAKE_COMPILER_IS_GNUCXX) execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version COMMAND head -n 1 OUTPUT_VARIABLE EIGEN_CXX_VERSION_STRING OUTPUT_STRIP_TRAILING_WHITESPACE) @@ -169,5 +167,3 @@ if(CMAKE_COMPILER_IS_GNUCXX) endif(CMAKE_COMPILER_IS_GNUCXX) ei_add_property(EIGEN_TESTING_SUMMARY "CXX_FLAGS: ${CMAKE_CXX_FLAGS}\n") ei_add_property(EIGEN_TESTING_SUMMARY "Sparse lib flags: ${SPARSE_LIBS}\n") - -configure_file(buildtests.in ${CMAKE_BINARY_DIR}/buildtests) diff --git a/test/adjoint.cpp b/test/adjoint.cpp index 344399257..b34112249 100644 --- a/test/adjoint.cpp +++ b/test/adjoint.cpp @@ -128,6 +128,14 @@ void test_adjoint() VERIFY_RAISES_ASSERT(a = a.adjoint()); VERIFY_RAISES_ASSERT(a = a.adjoint() + b); VERIFY_RAISES_ASSERT(a = b + a.adjoint()); + + // no assertion should be triggered for these cases: + a.transpose() = a.transpose(); + a.transpose() += a.transpose(); + a.transpose() += a.transpose() + b; + a.transpose() = a.adjoint(); + a.transpose() += a.adjoint(); + a.transpose() += a.adjoint() + b; } #endif } diff --git a/test/bandmatrix.cpp b/test/bandmatrix.cpp index ecb7304db..e243dffe5 100644 --- a/test/bandmatrix.cpp +++ b/test/bandmatrix.cpp @@ -53,7 +53,7 @@ template<typename MatrixType> void bandmatrix(const MatrixType& _m) dm1.diagonal(-i).setConstant(-static_cast<RealScalar>(i)); } //std::cerr << m.m_data << "\n\n" << m.toDense() << "\n\n" << dm1 << "\n\n\n\n"; - VERIFY_IS_APPROX(dm1,m.toDense()); + VERIFY_IS_APPROX(dm1,m.toDenseMatrix()); for (int i=0; i<cols; ++i) { @@ -68,7 +68,7 @@ template<typename MatrixType> void bandmatrix(const MatrixType& _m) dm1.block(subs+1,0,rows-subs-1-b,rows-subs-1-b).template triangularView<LowerTriangular>().setZero(); if(b>0) dm1.block(d+subs,0,b,cols).setZero(); //std::cerr << m.m_data << "\n\n" << m.toDense() << "\n\n" << dm1 << "\n\n"; - VERIFY_IS_APPROX(dm1,m.toDense()); + VERIFY_IS_APPROX(dm1,m.toDenseMatrix()); } diff --git a/test/buildtests.in b/test/buildtests.in deleted file mode 100755 index 52cc66281..000000000 --- a/test/buildtests.in +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -if [ $# == 0 -o $# -ge 3 ] -then - echo "usage: ./buildtests regexp [jobs]" - echo " makes tests matching the regexp, with <jobs> concurrent make jobs" - exit 0 -fi - -TESTSLIST="${cmake_tests_list}" -targets_to_make=`echo "$TESTSLIST" | grep "$1" | sed s/^/test_/g | xargs echo` - -if [ $# == 1 ] -then - make $targets_to_make -fi - -if [ $# == 2 ] -then - make -j $2 $targets_to_make -fi diff --git a/test/cholesky.cpp b/test/cholesky.cpp index c3ef96752..c658b902c 100644 --- a/test/cholesky.cpp +++ b/test/cholesky.cpp @@ -95,7 +95,7 @@ template<typename MatrixType> void cholesky(const MatrixType& m) { LLT<SquareMatrixType,LowerTriangular> chollo(symmLo); - VERIFY_IS_APPROX(symm, chollo.matrixL().toDense() * chollo.matrixL().adjoint().toDense()); + VERIFY_IS_APPROX(symm, chollo.matrixL().toDenseMatrix() * chollo.matrixL().adjoint().toDenseMatrix()); vecX = chollo.solve(vecB); VERIFY_IS_APPROX(symm * vecX, vecB); matX = chollo.solve(matB); @@ -103,7 +103,7 @@ template<typename MatrixType> void cholesky(const MatrixType& m) // test the upper mode LLT<SquareMatrixType,UpperTriangular> cholup(symmUp); - VERIFY_IS_APPROX(symm, cholup.matrixL().toDense() * cholup.matrixL().adjoint().toDense()); + VERIFY_IS_APPROX(symm, cholup.matrixL().toDenseMatrix() * cholup.matrixL().adjoint().toDenseMatrix()); vecX = cholup.solve(vecB); VERIFY_IS_APPROX(symm * vecX, vecB); matX = cholup.solve(matB); diff --git a/test/eigensolver_complex.cpp b/test/eigensolver_complex.cpp index 11b7be5f7..fa052a9ae 100644 --- a/test/eigensolver_complex.cpp +++ b/test/eigensolver_complex.cpp @@ -60,5 +60,6 @@ void test_eigensolver_complex() for(int i = 0; i < g_repeat; i++) { CALL_SUBTEST_1( eigensolver(Matrix4cf()) ); CALL_SUBTEST_2( eigensolver(MatrixXcd(14,14)) ); + CALL_SUBTEST_3( eigensolver(Matrix<std::complex<float>, 1, 1>()) ); } } diff --git a/test/geo_hyperplane.cpp b/test/geo_hyperplane.cpp index 3cf5655c2..1fd1e281a 100644 --- a/test/geo_hyperplane.cpp +++ b/test/geo_hyperplane.cpp @@ -64,7 +64,7 @@ template<typename HyperplaneType> void hyperplane(const HyperplaneType& _plane) // transform if (!NumTraits<Scalar>::IsComplex) { - MatrixType rot = MatrixType::Random(dim,dim).householderQr().matrixQ(); + MatrixType rot = MatrixType::Random(dim,dim).householderQr().householderQ(); DiagonalMatrix<Scalar,HyperplaneType::AmbientDimAtCompileTime> scaling(VectorType::Random()); Translation<Scalar,HyperplaneType::AmbientDimAtCompileTime> translation(VectorType::Random()); diff --git a/test/geo_quaternion.cpp b/test/geo_quaternion.cpp index 19eb6e78c..a73ff19ec 100644 --- a/test/geo_quaternion.cpp +++ b/test/geo_quaternion.cpp @@ -43,7 +43,7 @@ template<typename Scalar> void quaternion(void) if (ei_is_same_type<Scalar,float>::ret) largeEps = 1e-3f; - Scalar eps = ei_random<Scalar>() * 1e-2; + Scalar eps = ei_random<Scalar>() * Scalar(1e-2); Vector3 v0 = Vector3::Random(), v1 = Vector3::Random(), diff --git a/test/inverse.cpp b/test/inverse.cpp index 3ed61d356..b80e139e0 100644 --- a/test/inverse.cpp +++ b/test/inverse.cpp @@ -38,18 +38,11 @@ template<typename MatrixType> void inverse(const MatrixType& m) typedef typename NumTraits<Scalar>::Real RealScalar; typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType; - MatrixType m1 = MatrixType::Random(rows, cols), + MatrixType m1(rows, cols), m2(rows, cols), mzero = MatrixType::Zero(rows, cols), identity = MatrixType::Identity(rows, rows); - - if (ei_is_same_type<RealScalar,float>::ret) - { - // let's build a more stable to inverse matrix - MatrixType a = MatrixType::Random(rows,cols); - m1 += m1 * m1.adjoint() + a * a.adjoint(); - } - + createRandomMatrixOfRank(rows,rows,rows,m1); m2 = m1.inverse(); VERIFY_IS_APPROX(m1, m2.inverse() ); @@ -104,12 +97,4 @@ void test_inverse() s = ei_random<int>(25,100); CALL_SUBTEST_6( inverse(MatrixXcd(s,s)) ); } - -#ifdef EIGEN_TEST_PART_4 - // test some tricky cases for 4x4 matrices - VERIFY_IS_APPROX((Matrix4f() << 0,0,1,0, 1,0,0,0, 0,1,0,0, 0,0,0,1).finished().inverse(), - (Matrix4f() << 0,1,0,0, 0,0,1,0, 1,0,0,0, 0,0,0,1).finished()); - VERIFY_IS_APPROX((Matrix4f() << 1,0,0,0, 0,0,1,0, 0,0,0,1, 0,1,0,0).finished().inverse(), - (Matrix4f() << 1,0,0,0, 0,0,0,1, 0,1,0,0, 0,0,1,0).finished()); -#endif } diff --git a/test/jacobisvd.cpp b/test/jacobisvd.cpp index f3a143e3c..587bc7572 100644 --- a/test/jacobisvd.cpp +++ b/test/jacobisvd.cpp @@ -54,6 +54,9 @@ template<typename MatrixType, unsigned int Options> void svd(const MatrixType& m MatrixUType u = svd.matrixU(); MatrixVType v = svd.matrixV(); + std::cout << "a\n" << a << std::endl; + std::cout << "b\n" << u * sigma * v.adjoint() << std::endl; + VERIFY_IS_APPROX(a, u * sigma * v.adjoint()); VERIFY_IS_UNITARY(u); VERIFY_IS_UNITARY(v); diff --git a/test/lu.cpp b/test/lu.cpp index 9dcebbeaa..c2237febf 100644 --- a/test/lu.cpp +++ b/test/lu.cpp @@ -24,9 +24,11 @@ #include "main.h" #include <Eigen/LU> +using namespace std; template<typename MatrixType> void lu_non_invertible() { + typedef typename MatrixType::Scalar Scalar; /* this test covers the following files: LU.h */ @@ -65,7 +67,20 @@ template<typename MatrixType> void lu_non_invertible() createRandomMatrixOfRank(rank, rows, cols, m1); FullPivLU<MatrixType> lu(m1); - std::cout << lu.kernel().rows() << " " << lu.kernel().cols() << std::endl; + // FIXME need better way to construct trapezoid matrices. extend triangularView to support rectangular. + DynamicMatrixType u(rows,cols); + for(int i = 0; i < rows; i++) + for(int j = 0; j < cols; j++) + u(i,j) = i>j ? Scalar(0) : lu.matrixLU()(i,j); + DynamicMatrixType l(rows,rows); + for(int i = 0; i < rows; i++) + for(int j = 0; j < rows; j++) + l(i,j) = (i<j || j>=cols) ? Scalar(0) + : i==j ? Scalar(1) + : lu.matrixLU()(i,j); + + VERIFY_IS_APPROX(lu.permutationP() * m1 * lu.permutationQ(), l*u); + KernelMatrixType m1kernel = lu.kernel(); ImageMatrixType m1image = lu.image(m1); diff --git a/test/main.h b/test/main.h index 0b9b0bc4c..06c17a9ae 100644 --- a/test/main.h +++ b/test/main.h @@ -24,6 +24,7 @@ // Eigen. If not, see <http://www.gnu.org/licenses/>. #include <cstdlib> +#include <cerrno> #include <ctime> #include <iostream> #include <string> @@ -49,6 +50,8 @@ namespace Eigen { static std::vector<std::string> g_test_stack; static int g_repeat; + static unsigned int g_seed; + static bool g_has_set_repeat, g_has_set_seed; } #define EI_PP_MAKE_STRING2(S) #S @@ -350,17 +353,30 @@ void createRandomMatrixOfRank(int desired_rank, int rows, int cols, MatrixType& typedef Matrix<Scalar, Rows, Rows> MatrixAType; typedef Matrix<Scalar, Cols, Cols> MatrixBType; + if(desired_rank == 0) + { + m.setZero(rows,cols); + return; + } + + if(desired_rank == 1) + { + m = VectorType::Random(rows) * VectorType::Random(cols).transpose(); + return; + } + MatrixAType a = MatrixAType::Random(rows,rows); MatrixType d = MatrixType::Identity(rows,cols); MatrixBType b = MatrixBType::Random(cols,cols); // set the diagonal such that only desired_rank non-zero entries reamain const int diag_size = std::min(d.rows(),d.cols()); - d.diagonal().segment(desired_rank, diag_size-desired_rank) = VectorType::Zero(diag_size-desired_rank); + if(diag_size != desired_rank) + d.diagonal().segment(desired_rank, diag_size-desired_rank) = VectorType::Zero(diag_size-desired_rank); HouseholderQR<MatrixAType> qra(a); HouseholderQR<MatrixBType> qrb(b); - m = qra.matrixQ() * d * qrb.matrixQ(); + m = qra.householderQ() * d * qrb.householderQ(); } } // end namespace Eigen @@ -372,51 +388,68 @@ template<> struct GetDifferentType<double> { typedef float type; }; template<typename T> struct GetDifferentType<std::complex<T> > { typedef std::complex<typename GetDifferentType<T>::type> type; }; +template<typename T> std::string type_name() { return "other"; } +template<> std::string type_name<float>() { return "float"; } +template<> std::string type_name<double>() { return "double"; } +template<> std::string type_name<int>() { return "int"; } +template<> std::string type_name<std::complex<float> >() { return "complex<float>"; } +template<> std::string type_name<std::complex<double> >() { return "complex<double>"; } +template<> std::string type_name<std::complex<int> >() { return "complex<int>"; } + // forward declaration of the main test function void EIGEN_CAT(test_,EIGEN_TEST_FUNC)(); using namespace Eigen; +void set_repeat_from_string(const char *str) +{ + errno = 0; + g_repeat = int(strtoul(str, 0, 10)); + if(errno || g_repeat <= 0) + { + std::cout << "Invalid repeat value " << str << std::endl; + exit(EXIT_FAILURE); + } + g_has_set_repeat = true; +} + +void set_seed_from_string(const char *str) +{ + errno = 0; + g_seed = strtoul(str, 0, 10); + if(errno || g_seed == 0) + { + std::cout << "Invalid seed value " << str << std::endl; + exit(EXIT_FAILURE); + } + g_has_set_seed = true; +} + int main(int argc, char *argv[]) { - bool has_set_repeat = false; - bool has_set_seed = false; + g_has_set_repeat = false; + g_has_set_seed = false; bool need_help = false; - unsigned int seed = 0; - int repeat = DEFAULT_REPEAT; for(int i = 1; i < argc; i++) { if(argv[i][0] == 'r') { - if(has_set_repeat) + if(g_has_set_repeat) { std::cout << "Argument " << argv[i] << " conflicting with a former argument" << std::endl; return 1; } - repeat = atoi(argv[i]+1); - has_set_repeat = true; - if(repeat <= 0) - { - std::cout << "Invalid \'repeat\' value " << argv[i]+1 << std::endl; - return 1; - } + set_repeat_from_string(argv[i]+1); } else if(argv[i][0] == 's') { - if(has_set_seed) + if(g_has_set_seed) { std::cout << "Argument " << argv[i] << " conflicting with a former argument" << std::endl; return 1; } - seed = int(strtoul(argv[i]+1, 0, 10)); - has_set_seed = true; - bool ok = seed!=0; - if(!ok) - { - std::cout << "Invalid \'seed\' value " << argv[i]+1 << std::endl; - return 1; - } + set_seed_from_string(argv[i]+1); } else { @@ -429,22 +462,29 @@ int main(int argc, char *argv[]) std::cout << "This test application takes the following optional arguments:" << std::endl; std::cout << " rN Repeat each test N times (default: " << DEFAULT_REPEAT << ")" << std::endl; std::cout << " sN Use N as seed for random numbers (default: based on current time)" << std::endl; + std::cout << std::endl; + std::cout << "If defined, the environment variables EIGEN_REPEAT and EIGEN_SEED" << std::endl; + std::cout << "will be used as default values for these parameters." << std::endl; return 1; } - if(!has_set_seed) seed = (unsigned int) time(NULL); - if(!has_set_repeat) repeat = DEFAULT_REPEAT; + char *env_EIGEN_REPEAT = getenv("EIGEN_REPEAT"); + if(!g_has_set_repeat && env_EIGEN_REPEAT) + set_repeat_from_string(env_EIGEN_REPEAT); + char *env_EIGEN_SEED = getenv("EIGEN_SEED"); + if(!g_has_set_seed && env_EIGEN_SEED) + set_seed_from_string(env_EIGEN_SEED); - std::cout << "Initializing random number generator with seed " << seed << std::endl; - srand(seed); - std::cout << "Repeating each test " << repeat << " times" << std::endl; + if(!g_has_set_seed) g_seed = (unsigned int) time(NULL); + if(!g_has_set_repeat) g_repeat = DEFAULT_REPEAT; + + std::cout << "Initializing random number generator with seed " << g_seed << std::endl; + srand(g_seed); + std::cout << "Repeating each test " << g_repeat << " times" << std::endl; - Eigen::g_repeat = repeat; Eigen::g_test_stack.push_back(EI_PP_MAKE_STRING(EIGEN_TEST_FUNC)); EIGEN_CAT(test_,EIGEN_TEST_FUNC)(); return 0; } - - diff --git a/test/permutationmatrices.cpp b/test/permutationmatrices.cpp index 13b01cd83..0ef0a371a 100644 --- a/test/permutationmatrices.cpp +++ b/test/permutationmatrices.cpp @@ -66,12 +66,45 @@ template<typename MatrixType> void permutationmatrices(const MatrixType& m) for (int i=0; i<rows; i++) for (int j=0; j<cols; j++) - VERIFY_IS_APPROX(m_original(lv(i),j), m_permuted(i,rv(j))); + VERIFY_IS_APPROX(m_permuted(lv(i),j), m_original(i,rv(j))); Matrix<Scalar,Rows,Rows> lm(lp); Matrix<Scalar,Cols,Cols> rm(rp); VERIFY_IS_APPROX(m_permuted, lm*m_original*rm); + + VERIFY_IS_APPROX(lp.inverse()*m_permuted*rp.inverse(), m_original); + VERIFY((lp*lp.inverse()).toDenseMatrix().isIdentity()); + + LeftPermutationVectorType lv2; + randomPermutationVector(lv2, rows); + LeftPermutationType lp2(lv2); + Matrix<Scalar,Rows,Rows> lm2(lp2); + VERIFY_IS_APPROX((lp*lp2).toDenseMatrix().template cast<Scalar>(), lm*lm2); + + LeftPermutationType identityp; + identityp.setIdentity(rows); + VERIFY_IS_APPROX(m_original, identityp*m_original); + + if(rows>1 && cols>1) + { + lp2 = lp; + int i = ei_random<int>(0, rows-1); + int j; + do j = ei_random<int>(0, rows-1); while(j==i); + lp2.applyTranspositionOnTheLeft(i, j); + lm = lp; + lm.row(i).swap(lm.row(j)); + VERIFY_IS_APPROX(lm, lp2.toDenseMatrix().template cast<Scalar>()); + + RightPermutationType rp2 = rp; + i = ei_random<int>(0, cols-1); + do j = ei_random<int>(0, cols-1); while(j==i); + rp2.applyTranspositionOnTheRight(i, j); + rm = rp; + rm.col(i).swap(rm.col(j)); + VERIFY_IS_APPROX(rm, rp2.toDenseMatrix().template cast<Scalar>()); + } } void test_permutationmatrices() diff --git a/test/prec_inverse_4x4.cpp b/test/prec_inverse_4x4.cpp new file mode 100644 index 000000000..e1b05aa0d --- /dev/null +++ b/test/prec_inverse_4x4.cpp @@ -0,0 +1,80 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com> +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see <http://www.gnu.org/licenses/>. + +#include "main.h" +#include <Eigen/LU> +#include <algorithm> + +template<typename MatrixType> void inverse_permutation_4x4() +{ + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + Vector4i indices(0,1,2,3); + for(int i = 0; i < 24; ++i) + { + MatrixType m = PermutationMatrix<4>(indices); + MatrixType inv = m.inverse(); + double error = double( (m*inv-MatrixType::Identity()).norm() / epsilon<Scalar>() ); + VERIFY(error == 0.0); + std::next_permutation(indices.data(),indices.data()+4); + } +} + +template<typename MatrixType> void inverse_general_4x4(int repeat) +{ + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + double error_sum = 0., error_max = 0.; + for(int i = 0; i < repeat; ++i) + { + MatrixType m; + RealScalar absdet; + do { + m = MatrixType::Random(); + absdet = ei_abs(m.determinant()); + } while(absdet < epsilon<Scalar>()); + MatrixType inv = m.inverse(); + double error = double( (m*inv-MatrixType::Identity()).norm() * absdet / epsilon<Scalar>() ); + error_sum += error; + error_max = std::max(error_max, error); + } + std::cerr << "inverse_general_4x4, Scalar = " << type_name<Scalar>() << std::endl; + double error_avg = error_sum / repeat; + EIGEN_DEBUG_VAR(error_avg); + EIGEN_DEBUG_VAR(error_max); + VERIFY(error_avg < (NumTraits<Scalar>::IsComplex ? 8.0 : 1.0)); + VERIFY(error_max < (NumTraits<Scalar>::IsComplex ? 64.0 : 20.0)); +} + +void test_prec_inverse_4x4() +{ + CALL_SUBTEST_1((inverse_permutation_4x4<Matrix4f>())); + CALL_SUBTEST_1(( inverse_general_4x4<Matrix4f>(200000 * g_repeat) )); + + CALL_SUBTEST_2((inverse_permutation_4x4<Matrix<double,4,4,RowMajor> >())); + CALL_SUBTEST_2(( inverse_general_4x4<Matrix<double,4,4,RowMajor> >(200000 * g_repeat) )); + + CALL_SUBTEST_3((inverse_permutation_4x4<Matrix4cf>())); + CALL_SUBTEST_3((inverse_general_4x4<Matrix4cf>(50000 * g_repeat))); +} diff --git a/test/product.h b/test/product.h index 1dcc636e3..c389c33ed 100644 --- a/test/product.h +++ b/test/product.h @@ -27,7 +27,7 @@ #include <Eigen/QR> template<typename Derived1, typename Derived2> -bool areNotApprox(const MatrixBase<Derived1>& m1, const MatrixBase<Derived2>& m2, typename Derived1::RealScalar epsilon = precision<typename Derived1::RealScalar>()) +bool areNotApprox(const MatrixBase<Derived1>& m1, const MatrixBase<Derived2>& m2, typename Derived1::RealScalar epsilon = dummy_precision<typename Derived1::RealScalar>()) { return !((m1-m2).cwiseAbs2().maxCoeff() < epsilon * epsilon * std::max(m1.cwiseAbs2().maxCoeff(), m2.cwiseAbs2().maxCoeff())); diff --git a/test/product_selfadjoint.cpp b/test/product_selfadjoint.cpp index aa8da37bd..2e9f8be80 100644 --- a/test/product_selfadjoint.cpp +++ b/test/product_selfadjoint.cpp @@ -55,15 +55,15 @@ template<typename MatrixType> void product_selfadjoint(const MatrixType& m) // rank2 update m2 = m1.template triangularView<LowerTriangular>(); m2.template selfadjointView<LowerTriangular>().rankUpdate(v1,v2); - VERIFY_IS_APPROX(m2, (m1 + v1 * v2.adjoint()+ v2 * v1.adjoint()).template triangularView<LowerTriangular>().toDense()); + VERIFY_IS_APPROX(m2, (m1 + v1 * v2.adjoint()+ v2 * v1.adjoint()).template triangularView<LowerTriangular>().toDenseMatrix()); m2 = m1.template triangularView<UpperTriangular>(); m2.template selfadjointView<UpperTriangular>().rankUpdate(-v1,s2*v2,s3); - VERIFY_IS_APPROX(m2, (m1 + (-s2*s3) * (v1 * v2.adjoint()+ v2 * v1.adjoint())).template triangularView<UpperTriangular>().toDense()); + VERIFY_IS_APPROX(m2, (m1 + (-s2*s3) * (v1 * v2.adjoint()+ v2 * v1.adjoint())).template triangularView<UpperTriangular>().toDenseMatrix()); m2 = m1.template triangularView<UpperTriangular>(); m2.template selfadjointView<UpperTriangular>().rankUpdate(-r1.adjoint(),r2.adjoint()*s3,s1); - VERIFY_IS_APPROX(m2, (m1 + (-s3*s1) * (r1.adjoint() * r2 + r2.adjoint() * r1)).template triangularView<UpperTriangular>().toDense()); + VERIFY_IS_APPROX(m2, (m1 + (-s3*s1) * (r1.adjoint() * r2 + r2.adjoint() * r1)).template triangularView<UpperTriangular>().toDenseMatrix()); if (rows>1) { @@ -71,7 +71,7 @@ template<typename MatrixType> void product_selfadjoint(const MatrixType& m) m2.block(1,1,rows-1,cols-1).template selfadjointView<LowerTriangular>().rankUpdate(v1.end(rows-1),v2.start(cols-1)); m3 = m1; m3.block(1,1,rows-1,cols-1) += v1.end(rows-1) * v2.start(cols-1).adjoint()+ v2.start(cols-1) * v1.end(rows-1).adjoint(); - VERIFY_IS_APPROX(m2, m3.template triangularView<LowerTriangular>().toDense()); + VERIFY_IS_APPROX(m2, m3.template triangularView<LowerTriangular>().toDenseMatrix()); } } diff --git a/test/product_syrk.cpp b/test/product_syrk.cpp index 37d54bf16..9f6aec0e2 100644 --- a/test/product_syrk.cpp +++ b/test/product_syrk.cpp @@ -46,27 +46,27 @@ template<typename MatrixType> void syrk(const MatrixType& m) m2.setZero(); VERIFY_IS_APPROX((m2.template selfadjointView<LowerTriangular>().rankUpdate(rhs2,s1)._expression()), - ((s1 * rhs2 * rhs2.adjoint()).eval().template triangularView<LowerTriangular>().toDense())); + ((s1 * rhs2 * rhs2.adjoint()).eval().template triangularView<LowerTriangular>().toDenseMatrix())); m2.setZero(); VERIFY_IS_APPROX(m2.template selfadjointView<UpperTriangular>().rankUpdate(rhs2,s1)._expression(), - (s1 * rhs2 * rhs2.adjoint()).eval().template triangularView<UpperTriangular>().toDense()); + (s1 * rhs2 * rhs2.adjoint()).eval().template triangularView<UpperTriangular>().toDenseMatrix()); m2.setZero(); VERIFY_IS_APPROX(m2.template selfadjointView<LowerTriangular>().rankUpdate(rhs1.adjoint(),s1)._expression(), - (s1 * rhs1.adjoint() * rhs1).eval().template triangularView<LowerTriangular>().toDense()); + (s1 * rhs1.adjoint() * rhs1).eval().template triangularView<LowerTriangular>().toDenseMatrix()); m2.setZero(); VERIFY_IS_APPROX(m2.template selfadjointView<UpperTriangular>().rankUpdate(rhs1.adjoint(),s1)._expression(), - (s1 * rhs1.adjoint() * rhs1).eval().template triangularView<UpperTriangular>().toDense()); + (s1 * rhs1.adjoint() * rhs1).eval().template triangularView<UpperTriangular>().toDenseMatrix()); m2.setZero(); VERIFY_IS_APPROX(m2.template selfadjointView<LowerTriangular>().rankUpdate(rhs3.adjoint(),s1)._expression(), - (s1 * rhs3.adjoint() * rhs3).eval().template triangularView<LowerTriangular>().toDense()); + (s1 * rhs3.adjoint() * rhs3).eval().template triangularView<LowerTriangular>().toDenseMatrix()); m2.setZero(); VERIFY_IS_APPROX(m2.template selfadjointView<UpperTriangular>().rankUpdate(rhs3.adjoint(),s1)._expression(), - (s1 * rhs3.adjoint() * rhs3).eval().template triangularView<UpperTriangular>().toDense()); + (s1 * rhs3.adjoint() * rhs3).eval().template triangularView<UpperTriangular>().toDenseMatrix()); } void test_product_syrk() diff --git a/test/product_trsm.cpp b/test/product_trsm.cpp index 6c5ca274a..e884f3180 100644 --- a/test/product_trsm.cpp +++ b/test/product_trsm.cpp @@ -27,7 +27,7 @@ #define VERIFY_TRSM(TRI,XB) { \ (XB).setRandom(); ref = (XB); \ (TRI).solveInPlace(XB); \ - VERIFY_IS_APPROX((TRI).toDense() * (XB), ref); \ + VERIFY_IS_APPROX((TRI).toDenseMatrix() * (XB), ref); \ } template<typename Scalar> void trsm(int size,int cols) diff --git a/test/qr.cpp b/test/qr.cpp index 90b5c4446..3848ce0a5 100644 --- a/test/qr.cpp +++ b/test/qr.cpp @@ -38,13 +38,13 @@ template<typename MatrixType> void qr(const MatrixType& m) HouseholderQR<MatrixType> qrOfA(a); MatrixType r = qrOfA.matrixQR(); - MatrixQType q = qrOfA.matrixQ(); + MatrixQType q = qrOfA.householderQ(); VERIFY_IS_UNITARY(q); // FIXME need better way to construct trapezoid for(int i = 0; i < rows; i++) for(int j = 0; j < cols; j++) if(i>j) r(i,j) = Scalar(0); - VERIFY_IS_APPROX(a, qrOfA.matrixQ() * r); + VERIFY_IS_APPROX(a, qrOfA.householderQ() * r); } template<typename MatrixType, int Cols2> void qr_fixedsize() @@ -58,7 +58,7 @@ template<typename MatrixType, int Cols2> void qr_fixedsize() // FIXME need better way to construct trapezoid for(int i = 0; i < Rows; i++) for(int j = 0; j < Cols; j++) if(i>j) r(i,j) = Scalar(0); - VERIFY_IS_APPROX(m1, qr.matrixQ() * r); + VERIFY_IS_APPROX(m1, qr.householderQ() * r); Matrix<Scalar,Cols,Cols2> m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2); Matrix<Scalar,Rows,Cols2> m3 = m1*m2; @@ -93,7 +93,7 @@ template<typename MatrixType> void qr_invertible() m1.setZero(); for(int i = 0; i < size; i++) m1(i,i) = ei_random<Scalar>(); RealScalar absdet = ei_abs(m1.diagonal().prod()); - m3 = qr.matrixQ(); // get a unitary + m3 = qr.householderQ(); // get a unitary m1 = m3 * m1 * m3; qr.compute(m1); VERIFY_IS_APPROX(absdet, qr.absDeterminant()); @@ -107,7 +107,7 @@ template<typename MatrixType> void qr_verify_assert() HouseholderQR<MatrixType> qr; VERIFY_RAISES_ASSERT(qr.matrixQR()) VERIFY_RAISES_ASSERT(qr.solve(tmp)) - VERIFY_RAISES_ASSERT(qr.matrixQ()) + VERIFY_RAISES_ASSERT(qr.householderQ()) VERIFY_RAISES_ASSERT(qr.absDeterminant()) VERIFY_RAISES_ASSERT(qr.logAbsDeterminant()) } diff --git a/test/qr_colpivoting.cpp b/test/qr_colpivoting.cpp index 763c12067..8b56cd296 100644 --- a/test/qr_colpivoting.cpp +++ b/test/qr_colpivoting.cpp @@ -28,10 +28,11 @@ template<typename MatrixType> void qr() { - int rows = ei_random<int>(20,200), cols = ei_random<int>(20,200), cols2 = ei_random<int>(20,200); + int rows = ei_random<int>(2,200), cols = ei_random<int>(2,200), cols2 = ei_random<int>(2,200); int rank = ei_random<int>(1, std::min(rows, cols)-1); typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType; typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType; MatrixType m1; @@ -43,19 +44,11 @@ template<typename MatrixType> void qr() VERIFY(!qr.isInvertible()); VERIFY(!qr.isSurjective()); - MatrixType r = qr.matrixQR(); - - MatrixQType q = qr.matrixQ(); + MatrixQType q = qr.householderQ(); VERIFY_IS_UNITARY(q); - - // FIXME need better way to construct trapezoid - for(int i = 0; i < rows; i++) for(int j = 0; j < cols; j++) if(i>j) r(i,j) = Scalar(0); - MatrixType b = qr.matrixQ() * r; - - MatrixType c = MatrixType::Zero(rows,cols); - - for(int i = 0; i < cols; ++i) c.col(qr.colsPermutation().coeff(i)) = b.col(i); + MatrixType r = qr.matrixQR().template triangularView<UpperTriangular>(); + MatrixType c = q * r * qr.colsPermutation().inverse(); VERIFY_IS_APPROX(m1, c); MatrixType m2 = MatrixType::Random(cols,cols2); @@ -79,15 +72,8 @@ template<typename MatrixType, int Cols2> void qr_fixedsize() VERIFY(!qr.isInvertible()); VERIFY(!qr.isSurjective()); - Matrix<Scalar,Rows,Cols> r = qr.matrixQR(); - // FIXME need better way to construct trapezoid - for(int i = 0; i < Rows; i++) for(int j = 0; j < Cols; j++) if(i>j) r(i,j) = Scalar(0); - - Matrix<Scalar,Rows,Cols> b = qr.matrixQ() * r; - - Matrix<Scalar,Rows,Cols> c = MatrixType::Zero(Rows,Cols); - - for(int i = 0; i < Cols; ++i) c.col(qr.colsPermutation().coeff(i)) = b.col(i); + Matrix<Scalar,Rows,Cols> r = qr.matrixQR().template triangularView<UpperTriangular>(); + Matrix<Scalar,Rows,Cols> c = qr.householderQ() * r * qr.colsPermutation().inverse(); VERIFY_IS_APPROX(m1, c); Matrix<Scalar,Cols,Cols2> m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2); @@ -117,13 +103,13 @@ template<typename MatrixType> void qr_invertible() ColPivHouseholderQR<MatrixType> qr(m1); m3 = MatrixType::Random(size,size); m2 = qr.solve(m3); - VERIFY_IS_APPROX(m3, m1*m2); + //VERIFY_IS_APPROX(m3, m1*m2); // now construct a matrix with prescribed determinant m1.setZero(); for(int i = 0; i < size; i++) m1(i,i) = ei_random<Scalar>(); RealScalar absdet = ei_abs(m1.diagonal().prod()); - m3 = qr.matrixQ(); // get a unitary + m3 = qr.householderQ(); // get a unitary m1 = m3 * m1 * m3; qr.compute(m1); VERIFY_IS_APPROX(absdet, qr.absDeterminant()); @@ -137,7 +123,7 @@ template<typename MatrixType> void qr_verify_assert() ColPivHouseholderQR<MatrixType> qr; VERIFY_RAISES_ASSERT(qr.matrixQR()) VERIFY_RAISES_ASSERT(qr.solve(tmp)) - VERIFY_RAISES_ASSERT(qr.matrixQ()) + VERIFY_RAISES_ASSERT(qr.householderQ()) VERIFY_RAISES_ASSERT(qr.dimensionOfKernel()) VERIFY_RAISES_ASSERT(qr.isInjective()) VERIFY_RAISES_ASSERT(qr.isSurjective()) @@ -149,7 +135,7 @@ template<typename MatrixType> void qr_verify_assert() void test_qr_colpivoting() { - for(int i = 0; i < 1; i++) { + for(int i = 0; i < g_repeat; i++) { CALL_SUBTEST_1( qr<MatrixXf>() ); CALL_SUBTEST_2( qr<MatrixXd>() ); CALL_SUBTEST_3( qr<MatrixXcd>() ); diff --git a/test/qr_fullpivoting.cpp b/test/qr_fullpivoting.cpp index 65d9a071f..c82ba4c7e 100644 --- a/test/qr_fullpivoting.cpp +++ b/test/qr_fullpivoting.cpp @@ -51,11 +51,8 @@ template<typename MatrixType> void qr() // FIXME need better way to construct trapezoid for(int i = 0; i < rows; i++) for(int j = 0; j < cols; j++) if(i>j) r(i,j) = Scalar(0); - MatrixType b = qr.matrixQ() * r; + MatrixType c = qr.matrixQ() * r * qr.colsPermutation().inverse(); - MatrixType c = MatrixType::Zero(rows,cols); - - for(int i = 0; i < cols; ++i) c.col(qr.colsPermutation().coeff(i)) = b.col(i); VERIFY_IS_APPROX(m1, c); MatrixType m2 = MatrixType::Random(cols,cols2); diff --git a/test/runtest.sh b/test/runtest.sh index 31d1ca654..2be250819 100755 --- a/test/runtest.sh +++ b/test/runtest.sh @@ -9,7 +9,7 @@ magenta='\E[35m' cyan='\E[36m' white='\E[37m' -if ! ./test_$1 > /dev/null 2> .runtest.log ; then +if ! ./$1 > /dev/null 2> .runtest.log ; then echo -e $red Test $1 failed: $black echo -e $blue cat .runtest.log diff --git a/test/sparse_basic.cpp b/test/sparse_basic.cpp index dd3245fb1..9de156d38 100644 --- a/test/sparse_basic.cpp +++ b/test/sparse_basic.cpp @@ -34,7 +34,7 @@ bool test_random_setter(SparseMatrix<Scalar,Options>& sm, const DenseType& ref, std::vector<Vector2i> remaining = nonzeroCoords; while(!remaining.empty()) { - int i = ei_random<int>(0,remaining.size()-1); + int i = ei_random<int>(0,static_cast<int>(remaining.size())-1); w(remaining[i].x(),remaining[i].y()) = ref.coeff(remaining[i].x(),remaining[i].y()); remaining[i] = remaining.back(); remaining.pop_back(); @@ -50,7 +50,7 @@ bool test_random_setter(DynamicSparseMatrix<T>& sm, const DenseType& ref, const std::vector<Vector2i> remaining = nonzeroCoords; while(!remaining.empty()) { - int i = ei_random<int>(0,remaining.size()-1); + int i = ei_random<int>(0,static_cast<int>(remaining.size())-1); sm.coeffRef(remaining[i].x(),remaining[i].y()) = ref.coeff(remaining[i].x(),remaining[i].y()); remaining[i] = remaining.back(); remaining.pop_back(); diff --git a/test/stable_norm.cpp b/test/stable_norm.cpp index 7661fc893..10531dc5d 100644 --- a/test/stable_norm.cpp +++ b/test/stable_norm.cpp @@ -79,6 +79,14 @@ template<typename MatrixType> void stable_norm(const MatrixType& m) VERIFY_IS_APPROX(static_cast<Scalar>(vsmall.stableNorm()), ei_sqrt(size)*small); VERIFY_IS_APPROX(static_cast<Scalar>(vsmall.blueNorm()), ei_sqrt(size)*small); VERIFY_IS_APPROX(static_cast<Scalar>(vsmall.hypotNorm()), ei_sqrt(size)*small); + +// Test compilation of cwise() version + VERIFY_IS_APPROX(vrand.colwise().stableNorm(), vrand.colwise().norm()); + VERIFY_IS_APPROX(vrand.colwise().blueNorm(), vrand.colwise().norm()); + VERIFY_IS_APPROX(vrand.colwise().hypotNorm(), vrand.colwise().norm()); + VERIFY_IS_APPROX(vrand.rowwise().stableNorm(), vrand.rowwise().norm()); + VERIFY_IS_APPROX(vrand.rowwise().blueNorm(), vrand.rowwise().norm()); + VERIFY_IS_APPROX(vrand.rowwise().hypotNorm(), vrand.rowwise().norm()); } void test_stable_norm() diff --git a/test/testsuite.cmake b/test/testsuite.cmake index 9c38e48b1..90edf2853 100644 --- a/test/testsuite.cmake +++ b/test/testsuite.cmake @@ -4,7 +4,7 @@ # Usage: # - create a new folder, let's call it cdash # - in that folder, do: -# ctest -S path/to/eigen2/test/testsuite.cmake[,option1=value1[,option2=value2]] +# ctest -S path/to/eigen/test/testsuite.cmake[,option1=value1[,option2=value2]] # # Options: # - EIGEN_CXX: compiler, eg.: g++-4.2 @@ -44,9 +44,9 @@ # ARCH=`uname -m` # SITE=`hostname` # VERSION=opensuse-11.1 -# WORK_DIR=/home/gael/Coding/eigen2/cdash +# WORK_DIR=/home/gael/Coding/eigen/cdash # # get the last version of the script -# wget http://bitbucket.org/eigen/eigen2/raw/tip/test/testsuite.cmake -o $WORK_DIR/testsuite.cmake +# wget http://bitbucket.org/eigen/eigen/raw/tip/test/testsuite.cmake -o $WORK_DIR/testsuite.cmake # COMMON="ctest -S $WORK_DIR/testsuite.cmake,EIGEN_WORK_DIR=$WORK_DIR,EIGEN_SITE=$SITE,EIGEN_MODE=$1,EIGEN_BUILD_STRING=$OS_VERSION-$ARCH" # $COMMON-gcc-3.4.6,EIGEN_CXX=g++-3.4 # $COMMON-gcc-4.0.1,EIGEN_CXX=g++-4.0.1 @@ -141,7 +141,7 @@ endif(NOT EIGEN_MODE) if(NOT EIGEN_NO_UPDATE) SET (CTEST_CVS_COMMAND "hg") - SET (CTEST_CVS_CHECKOUT "${CTEST_CVS_COMMAND} clone http://bitbucket.org/eigen/eigen2 \"${CTEST_SOURCE_DIRECTORY}\"") + SET (CTEST_CVS_CHECKOUT "${CTEST_CVS_COMMAND} clone http://bitbucket.org/eigen/eigen \"${CTEST_SOURCE_DIRECTORY}\"") SET(CTEST_BACKUP_AND_RESTORE TRUE) # the backup is CVS related ... endif(NOT EIGEN_NO_UPDATE) diff --git a/test/triangular.cpp b/test/triangular.cpp index 2a583710d..111774b75 100644 --- a/test/triangular.cpp +++ b/test/triangular.cpp @@ -24,7 +24,9 @@ #include "main.h" -template<typename MatrixType> void triangular(const MatrixType& m) + + +template<typename MatrixType> void triangular_square(const MatrixType& m) { typedef typename MatrixType::Scalar Scalar; typedef typename NumTraits<Scalar>::Real RealScalar; @@ -51,8 +53,8 @@ template<typename MatrixType> void triangular(const MatrixType& m) v2 = VectorType::Random(rows), vzero = VectorType::Zero(rows); - MatrixType m1up = m1.template triangularView<Eigen::UpperTriangular>(); - MatrixType m2up = m2.template triangularView<Eigen::UpperTriangular>(); + MatrixType m1up = m1.template triangularView<UpperTriangular>(); + MatrixType m2up = m2.template triangularView<UpperTriangular>(); if (rows*cols>1) { @@ -66,83 +68,197 @@ template<typename MatrixType> void triangular(const MatrixType& m) // test overloaded operator+= r1.setZero(); r2.setZero(); - r1.template triangularView<Eigen::UpperTriangular>() += m1; + r1.template triangularView<UpperTriangular>() += m1; r2 += m1up; VERIFY_IS_APPROX(r1,r2); // test overloaded operator= m1.setZero(); - m1.template triangularView<Eigen::UpperTriangular>() = m2.transpose() + m2; + m1.template triangularView<UpperTriangular>() = m2.transpose() + m2; m3 = m2.transpose() + m2; - VERIFY_IS_APPROX(m3.template triangularView<Eigen::LowerTriangular>().transpose().toDense(), m1); + VERIFY_IS_APPROX(m3.template triangularView<LowerTriangular>().transpose().toDenseMatrix(), m1); // test overloaded operator= m1.setZero(); - m1.template triangularView<Eigen::LowerTriangular>() = m2.transpose() + m2; - VERIFY_IS_APPROX(m3.template triangularView<Eigen::LowerTriangular>().toDense(), m1); + m1.template triangularView<LowerTriangular>() = m2.transpose() + m2; + VERIFY_IS_APPROX(m3.template triangularView<LowerTriangular>().toDenseMatrix(), m1); m1 = MatrixType::Random(rows, cols); for (int i=0; i<rows; ++i) - while (ei_abs2(m1(i,i))<1e-3) m1(i,i) = ei_random<Scalar>(); + while (ei_abs2(m1(i,i))<1e-1) m1(i,i) = ei_random<Scalar>(); Transpose<MatrixType> trm4(m4); // test back and forward subsitution with a vector as the rhs - m3 = m1.template triangularView<Eigen::UpperTriangular>(); - VERIFY(v2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<Eigen::LowerTriangular>().solve(v2)), largerEps)); - m3 = m1.template triangularView<Eigen::LowerTriangular>(); - VERIFY(v2.isApprox(m3.transpose() * (m1.transpose().template triangularView<Eigen::UpperTriangular>().solve(v2)), largerEps)); - m3 = m1.template triangularView<Eigen::UpperTriangular>(); - VERIFY(v2.isApprox(m3 * (m1.template triangularView<Eigen::UpperTriangular>().solve(v2)), largerEps)); - m3 = m1.template triangularView<Eigen::LowerTriangular>(); - VERIFY(v2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<Eigen::LowerTriangular>().solve(v2)), largerEps)); + m3 = m1.template triangularView<UpperTriangular>(); + VERIFY(v2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<LowerTriangular>().solve(v2)), largerEps)); + m3 = m1.template triangularView<LowerTriangular>(); + VERIFY(v2.isApprox(m3.transpose() * (m1.transpose().template triangularView<UpperTriangular>().solve(v2)), largerEps)); + m3 = m1.template triangularView<UpperTriangular>(); + VERIFY(v2.isApprox(m3 * (m1.template triangularView<UpperTriangular>().solve(v2)), largerEps)); + m3 = m1.template triangularView<LowerTriangular>(); + VERIFY(v2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<LowerTriangular>().solve(v2)), largerEps)); // test back and forward subsitution with a matrix as the rhs - m3 = m1.template triangularView<Eigen::UpperTriangular>(); - VERIFY(m2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<Eigen::LowerTriangular>().solve(m2)), largerEps)); - m3 = m1.template triangularView<Eigen::LowerTriangular>(); - VERIFY(m2.isApprox(m3.transpose() * (m1.transpose().template triangularView<Eigen::UpperTriangular>().solve(m2)), largerEps)); - m3 = m1.template triangularView<Eigen::UpperTriangular>(); - VERIFY(m2.isApprox(m3 * (m1.template triangularView<Eigen::UpperTriangular>().solve(m2)), largerEps)); - m3 = m1.template triangularView<Eigen::LowerTriangular>(); - VERIFY(m2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<Eigen::LowerTriangular>().solve(m2)), largerEps)); + m3 = m1.template triangularView<UpperTriangular>(); + VERIFY(m2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<LowerTriangular>().solve(m2)), largerEps)); + m3 = m1.template triangularView<LowerTriangular>(); + VERIFY(m2.isApprox(m3.transpose() * (m1.transpose().template triangularView<UpperTriangular>().solve(m2)), largerEps)); + m3 = m1.template triangularView<UpperTriangular>(); + VERIFY(m2.isApprox(m3 * (m1.template triangularView<UpperTriangular>().solve(m2)), largerEps)); + m3 = m1.template triangularView<LowerTriangular>(); + VERIFY(m2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<LowerTriangular>().solve(m2)), largerEps)); // check M * inv(L) using in place API m4 = m3; +<<<<<<< local m3.transpose().template triangularView<Eigen::UpperTriangular>().solveInPlace(trm4); VERIFY(m4.cwiseAbs().isIdentity(test_precision<RealScalar>())); +======= + m3.transpose().template triangularView<UpperTriangular>().solveInPlace(trm4); + VERIFY(m4.cwise().abs().isIdentity(test_precision<RealScalar>())); +>>>>>>> other // check M * inv(U) using in place API - m3 = m1.template triangularView<Eigen::UpperTriangular>(); + m3 = m1.template triangularView<UpperTriangular>(); m4 = m3; +<<<<<<< local m3.transpose().template triangularView<Eigen::LowerTriangular>().solveInPlace(trm4); VERIFY(m4.cwiseAbs().isIdentity(test_precision<RealScalar>())); +======= + m3.transpose().template triangularView<LowerTriangular>().solveInPlace(trm4); + VERIFY(m4.cwise().abs().isIdentity(test_precision<RealScalar>())); +>>>>>>> other // check solve with unit diagonal - m3 = m1.template triangularView<Eigen::UnitUpperTriangular>(); - VERIFY(m2.isApprox(m3 * (m1.template triangularView<Eigen::UnitUpperTriangular>().solve(m2)), largerEps)); + m3 = m1.template triangularView<UnitUpperTriangular>(); + VERIFY(m2.isApprox(m3 * (m1.template triangularView<UnitUpperTriangular>().solve(m2)), largerEps)); -// VERIFY(( m1.template triangularView<Eigen::UpperTriangular>() -// * m2.template triangularView<Eigen::UpperTriangular>()).isUpperTriangular()); +// VERIFY(( m1.template triangularView<UpperTriangular>() +// * m2.template triangularView<UpperTriangular>()).isUpperTriangular()); // test swap m1.setOnes(); m2.setZero(); - m2.template triangularView<Eigen::UpperTriangular>().swap(m1); + m2.template triangularView<UpperTriangular>().swap(m1); m3.setZero(); - m3.template triangularView<Eigen::UpperTriangular>().setOnes(); + m3.template triangularView<UpperTriangular>().setOnes(); VERIFY_IS_APPROX(m2,m3); } + +template<typename MatrixType> void triangular_rect(const MatrixType& m) +{ + typedef typename MatrixType::Scalar Scalar; + typedef typename NumTraits<Scalar>::Real RealScalar; + enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime }; + typedef Matrix<Scalar, Rows, 1> VectorType; + typedef Matrix<Scalar, Rows, Rows> RMatrixType; + + + int rows = m.rows(); + int cols = m.cols(); + + MatrixType m1 = MatrixType::Random(rows, cols), + m2 = MatrixType::Random(rows, cols), + m3(rows, cols), + m4(rows, cols), + r1(rows, cols), + r2(rows, cols), + mzero = MatrixType::Zero(rows, cols), + mones = MatrixType::Ones(rows, cols); + RMatrixType identity = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> + ::Identity(rows, rows), + square = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> + ::Random(rows, rows); + VectorType v1 = VectorType::Random(rows), + v2 = VectorType::Random(rows), + vzero = VectorType::Zero(rows); + + MatrixType m1up = m1.template triangularView<UpperTriangular>(); + MatrixType m2up = m2.template triangularView<UpperTriangular>(); + + if (rows*cols>1) + { + VERIFY(m1up.isUpperTriangular()); + VERIFY(m2up.transpose().isLowerTriangular()); + VERIFY(!m2.isLowerTriangular()); + } + + // test overloaded operator+= + r1.setZero(); + r2.setZero(); + r1.template triangularView<UpperTriangular>() += m1; + r2 += m1up; + VERIFY_IS_APPROX(r1,r2); + + // test overloaded operator= + m1.setZero(); + m1.template triangularView<UpperTriangular>() = 3 * m2; + m3 = 3 * m2; + VERIFY_IS_APPROX(m3.template triangularView<UpperTriangular>().toDenseMatrix(), m1); + + + m1.setZero(); + m1.template triangularView<LowerTriangular>() = 3 * m2; + VERIFY_IS_APPROX(m3.template triangularView<LowerTriangular>().toDenseMatrix(), m1); + + m1.setZero(); + m1.template triangularView<StrictlyUpperTriangular>() = 3 * m2; + VERIFY_IS_APPROX(m3.template triangularView<StrictlyUpperTriangular>().toDenseMatrix(), m1); + + + m1.setZero(); + m1.template triangularView<StrictlyLowerTriangular>() = 3 * m2; + VERIFY_IS_APPROX(m3.template triangularView<StrictlyLowerTriangular>().toDenseMatrix(), m1); + m1.setRandom(); + m2 = m1.template triangularView<UpperTriangular>(); + VERIFY(m2.isUpperTriangular()); + VERIFY(!m2.isLowerTriangular()); + m2 = m1.template triangularView<StrictlyUpperTriangular>(); + VERIFY(m2.isUpperTriangular()); + VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1))); + m2 = m1.template triangularView<UnitUpperTriangular>(); + VERIFY(m2.isUpperTriangular()); + m2.diagonal().cwise() -= Scalar(1); + VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1))); + m2 = m1.template triangularView<LowerTriangular>(); + VERIFY(m2.isLowerTriangular()); + VERIFY(!m2.isUpperTriangular()); + m2 = m1.template triangularView<StrictlyLowerTriangular>(); + VERIFY(m2.isLowerTriangular()); + VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1))); + m2 = m1.template triangularView<UnitLowerTriangular>(); + VERIFY(m2.isLowerTriangular()); + m2.diagonal().cwise() -= Scalar(1); + VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1))); + // test swap + m1.setOnes(); + m2.setZero(); + m2.template triangularView<UpperTriangular>().swap(m1); + m3.setZero(); + m3.template triangularView<UpperTriangular>().setOnes(); + VERIFY_IS_APPROX(m2,m3); +} + void test_triangular() { - for(int i = 0; i < g_repeat ; i++) { - CALL_SUBTEST_1( triangular(Matrix<float, 1, 1>()) ); - CALL_SUBTEST_2( triangular(Matrix<float, 2, 2>()) ); - CALL_SUBTEST_3( triangular(Matrix3d()) ); - CALL_SUBTEST_4( triangular(MatrixXcf(4, 4)) ); - CALL_SUBTEST_5( triangular(Matrix<std::complex<float>,8, 8>()) ); - CALL_SUBTEST_6( triangular(MatrixXcd(17,17)) ); - CALL_SUBTEST_7( triangular(Matrix<float,Dynamic,Dynamic,RowMajor>(5, 5)) ); + for(int i = 0; i < g_repeat ; i++) + { + EIGEN_UNUSED int r = ei_random<int>(2,20); + EIGEN_UNUSED int c = ei_random<int>(2,20); + + CALL_SUBTEST_1( triangular_square(Matrix<float, 1, 1>()) ); + CALL_SUBTEST_2( triangular_square(Matrix<float, 2, 2>()) ); + CALL_SUBTEST_3( triangular_square(Matrix3d()) ); + CALL_SUBTEST_4( triangular_square(Matrix<std::complex<float>,8, 8>()) ); + CALL_SUBTEST_5( triangular_square(MatrixXcd(r,r)) ); + CALL_SUBTEST_6( triangular_square(Matrix<float,Dynamic,Dynamic,RowMajor>(r, r)) ); + + CALL_SUBTEST_7( triangular_rect(Matrix<float, 4, 5>()) ); + CALL_SUBTEST_8( triangular_rect(Matrix<double, 6, 2>()) ); + CALL_SUBTEST_9( triangular_rect(MatrixXcf(r, c)) ); + CALL_SUBTEST_5( triangular_rect(MatrixXcd(r, c)) ); + CALL_SUBTEST_6( triangular_rect(Matrix<float,Dynamic,Dynamic,RowMajor>(r, c)) ); } } diff --git a/test/unalignedassert.cpp b/test/unalignedassert.cpp index 2b819417e..85a83b7b5 100644 --- a/test/unalignedassert.cpp +++ b/test/unalignedassert.cpp @@ -87,6 +87,7 @@ void construct_at_boundary(int boundary) _buf += (16 - (_buf % 16)); // make 16-byte aligned _buf += boundary; // make exact boundary-aligned T *x = ::new(reinterpret_cast<void*>(_buf)) T; + x[0].setZero(); // just in order to silence warnings x->~T(); } #endif diff --git a/test/vectorization_logic.cpp b/test/vectorization_logic.cpp index 71214485c..5d86df7b3 100644 --- a/test/vectorization_logic.cpp +++ b/test/vectorization_logic.cpp @@ -26,17 +26,18 @@ #include <typeinfo> template<typename Dst, typename Src> -bool test_assign(const Dst&, const Src&, int vectorization, int unrolling) +bool test_assign(const Dst&, const Src&, int traversal, int unrolling) { - return ei_assign_traits<Dst,Src>::Vectorization==vectorization + ei_assign_traits<Dst,Src>::debug(); + return ei_assign_traits<Dst,Src>::Traversal==traversal && ei_assign_traits<Dst,Src>::Unrolling==unrolling; } template<typename Xpr> -bool test_redux(const Xpr&, int vectorization, int unrolling) +bool test_redux(const Xpr&, int traversal, int unrolling) { typedef ei_redux_traits<ei_scalar_sum_op<typename Xpr::Scalar>,Xpr> traits; - return traits::Vectorization==vectorization && traits::Unrolling==unrolling; + return traits::Traversal==traversal && traits::Unrolling==unrolling; } void test_vectorization_logic() @@ -45,61 +46,67 @@ void test_vectorization_logic() #ifdef EIGEN_VECTORIZE VERIFY(test_assign(Vector4f(),Vector4f(), - InnerVectorization,CompleteUnrolling)); + InnerVectorizedTraversal,CompleteUnrolling)); VERIFY(test_assign(Vector4f(),Vector4f()+Vector4f(), - InnerVectorization,CompleteUnrolling)); + InnerVectorizedTraversal,CompleteUnrolling)); VERIFY(test_assign(Vector4f(),Vector4f().cwiseProduct(Vector4f()), - InnerVectorization,CompleteUnrolling)); + InnerVectorizedTraversal,CompleteUnrolling)); VERIFY(test_assign(Vector4f(),Vector4f().cast<float>(), - InnerVectorization,CompleteUnrolling)); + InnerVectorizedTraversal,CompleteUnrolling)); VERIFY(test_assign(Matrix4f(),Matrix4f(), - InnerVectorization,CompleteUnrolling)); + InnerVectorizedTraversal,CompleteUnrolling)); VERIFY(test_assign(Matrix4f(),Matrix4f()+Matrix4f(), - InnerVectorization,CompleteUnrolling)); + InnerVectorizedTraversal,CompleteUnrolling)); VERIFY(test_assign(Matrix4f(),Matrix4f().cwiseProduct(Matrix4f()), - InnerVectorization,CompleteUnrolling)); + InnerVectorizedTraversal,CompleteUnrolling)); VERIFY(test_assign(Matrix<float,16,16>(),Matrix<float,16,16>()+Matrix<float,16,16>(), - InnerVectorization,InnerUnrolling)); + InnerVectorizedTraversal,InnerUnrolling)); VERIFY(test_assign(Matrix<float,16,16,DontAlign>(),Matrix<float,16,16>()+Matrix<float,16,16>(), - NoVectorization,InnerUnrolling)); + LinearTraversal,NoUnrolling)); + + VERIFY(test_assign(Matrix<float,2,2,DontAlign>(),Matrix<float,2,2>()+Matrix<float,2,2>(), + LinearTraversal,CompleteUnrolling)); VERIFY(test_assign(Matrix<float,6,2>(),Matrix<float,6,2>().cwiseQuotient(Matrix<float,6,2>()), - LinearVectorization,CompleteUnrolling)); + LinearVectorizedTraversal,CompleteUnrolling)); VERIFY(test_assign(Matrix<float,17,17>(),Matrix<float,17,17>()+Matrix<float,17,17>(), - NoVectorization,InnerUnrolling)); + LinearTraversal,NoUnrolling)); + + VERIFY(test_assign(Matrix<float,3,3>(),Matrix<float,3,3>()+Matrix<float,3,3>(), + LinearTraversal,CompleteUnrolling)); VERIFY(test_assign(Matrix<float,4,4>(),Matrix<float,17,17>().block<4,4>(2,3)+Matrix<float,17,17>().block<4,4>(10,4), - NoVectorization,CompleteUnrolling)); + DefaultTraversal,CompleteUnrolling)); VERIFY(test_assign(MatrixXf(10,10),MatrixXf(20,20).block(10,10,2,3), - SliceVectorization,NoUnrolling)); + SliceVectorizedTraversal,NoUnrolling)); VERIFY(test_redux(VectorXf(10), - LinearVectorization,NoUnrolling)); + LinearVectorizedTraversal,NoUnrolling)); VERIFY(test_redux(Matrix<float,5,2>(), - NoVectorization,CompleteUnrolling)); + DefaultTraversal,CompleteUnrolling)); VERIFY(test_redux(Matrix<float,6,2>(), - LinearVectorization,CompleteUnrolling)); + LinearVectorizedTraversal,CompleteUnrolling)); VERIFY(test_redux(Matrix<float,16,16>(), - LinearVectorization,NoUnrolling)); + LinearVectorizedTraversal,NoUnrolling)); VERIFY(test_redux(Matrix<float,16,16>().block<4,4>(1,2), - NoVectorization,CompleteUnrolling)); + DefaultTraversal,CompleteUnrolling)); VERIFY(test_redux(Matrix<float,16,16>().block<8,1>(1,2), - LinearVectorization,CompleteUnrolling)); + LinearVectorizedTraversal,CompleteUnrolling)); VERIFY(test_redux(Matrix<double,7,3>(), - NoVectorization,CompleteUnrolling)); + DefaultTraversal,CompleteUnrolling)); #endif // EIGEN_VECTORIZE |