aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/CMakeLists.txt217
-rw-r--r--test/adjoint.cpp42
-rw-r--r--test/array.cpp243
-rw-r--r--test/array_for_matrix.cpp34
-rw-r--r--test/array_of_string.cpp32
-rw-r--r--test/array_replicate.cpp13
-rw-r--r--test/array_reverse.cpp32
-rw-r--r--test/bandmatrix.cpp3
-rw-r--r--test/basicstuff.cpp86
-rw-r--r--test/bdcsvd.cpp111
-rw-r--r--test/bicgstab.cpp16
-rw-r--r--test/block.cpp31
-rw-r--r--test/boostmultiprec.cpp201
-rw-r--r--test/bug1213.cpp13
-rw-r--r--test/bug1213.h8
-rw-r--r--test/bug1213_main.cpp18
-rw-r--r--test/cholesky.cpp157
-rw-r--r--test/cholmod_support.cpp15
-rw-r--r--test/commainitializer.cpp60
-rw-r--r--test/conjugate_gradient.cpp18
-rw-r--r--test/constructor.cpp84
-rw-r--r--test/ctorleak.cpp69
-rw-r--r--test/cuda_basic.cu173
-rw-r--r--test/cuda_common.h101
-rw-r--r--test/cwiseop.cpp184
-rw-r--r--test/dense_storage.cpp76
-rw-r--r--test/diagonal.cpp24
-rw-r--r--test/diagonalmatrices.cpp27
-rw-r--r--test/dynalloc.cpp89
-rw-r--r--test/eigen2/CMakeLists.txt61
-rw-r--r--test/eigen2/eigen2_adjoint.cpp99
-rw-r--r--test/eigen2/eigen2_alignedbox.cpp60
-rw-r--r--test/eigen2/eigen2_array.cpp142
-rw-r--r--test/eigen2/eigen2_basicstuff.cpp105
-rw-r--r--test/eigen2/eigen2_bug_132.cpp26
-rw-r--r--test/eigen2/eigen2_cholesky.cpp113
-rw-r--r--test/eigen2/eigen2_commainitializer.cpp46
-rw-r--r--test/eigen2/eigen2_cwiseop.cpp155
-rw-r--r--test/eigen2/eigen2_determinant.cpp61
-rw-r--r--test/eigen2/eigen2_dynalloc.cpp131
-rw-r--r--test/eigen2/eigen2_eigensolver.cpp146
-rw-r--r--test/eigen2/eigen2_first_aligned.cpp49
-rw-r--r--test/eigen2/eigen2_geometry.cpp432
-rw-r--r--test/eigen2/eigen2_geometry_with_eigen2_prefix.cpp435
-rw-r--r--test/eigen2/eigen2_hyperplane.cpp126
-rw-r--r--test/eigen2/eigen2_inverse.cpp62
-rw-r--r--test/eigen2/eigen2_linearstructure.cpp83
-rw-r--r--test/eigen2/eigen2_lu.cpp122
-rw-r--r--test/eigen2/eigen2_map.cpp114
-rw-r--r--test/eigen2/eigen2_meta.cpp60
-rw-r--r--test/eigen2/eigen2_miscmatrices.cpp48
-rw-r--r--test/eigen2/eigen2_mixingtypes.cpp77
-rw-r--r--test/eigen2/eigen2_nomalloc.cpp53
-rw-r--r--test/eigen2/eigen2_packetmath.cpp132
-rw-r--r--test/eigen2/eigen2_parametrizedline.cpp62
-rw-r--r--test/eigen2/eigen2_prec_inverse_4x4.cpp84
-rw-r--r--test/eigen2/eigen2_product_large.cpp45
-rw-r--r--test/eigen2/eigen2_product_small.cpp22
-rw-r--r--test/eigen2/eigen2_qr.cpp69
-rw-r--r--test/eigen2/eigen2_qtvector.cpp158
-rw-r--r--test/eigen2/eigen2_regression.cpp136
-rw-r--r--test/eigen2/eigen2_sizeof.cpp31
-rw-r--r--test/eigen2/eigen2_smallvectors.cpp42
-rw-r--r--test/eigen2/eigen2_sparse_basic.cpp317
-rw-r--r--test/eigen2/eigen2_sparse_product.cpp115
-rw-r--r--test/eigen2/eigen2_sparse_solvers.cpp200
-rw-r--r--test/eigen2/eigen2_sparse_vector.cpp84
-rw-r--r--test/eigen2/eigen2_stdvector.cpp148
-rw-r--r--test/eigen2/eigen2_submatrices.cpp142
-rw-r--r--test/eigen2/eigen2_sum.cpp71
-rw-r--r--test/eigen2/eigen2_svd.cpp87
-rw-r--r--test/eigen2/eigen2_swap.cpp83
-rw-r--r--test/eigen2/eigen2_triangular.cpp148
-rw-r--r--test/eigen2/eigen2_unalignedassert.cpp116
-rw-r--r--test/eigen2/eigen2_visitor.cpp116
-rw-r--r--test/eigen2/gsl_helper.h175
-rw-r--r--test/eigen2/main.h399
-rw-r--r--test/eigen2/product.h129
-rwxr-xr-xtest/eigen2/runtest.sh28
-rw-r--r--test/eigen2/sparse.h154
-rw-r--r--test/eigen2/testsuite.cmake197
-rw-r--r--test/eigen2support.cpp1
-rw-r--r--test/eigensolver_complex.cpp71
-rw-r--r--test/eigensolver_generalized_real.cpp54
-rw-r--r--test/eigensolver_generic.cpp49
-rw-r--r--test/eigensolver_selfadjoint.cpp180
-rw-r--r--test/evaluator_common.h0
-rw-r--r--test/evaluators.cpp499
-rw-r--r--test/fastmath.cpp99
-rw-r--r--test/first_aligned.cpp6
-rw-r--r--test/geo_alignedbox.cpp13
-rw-r--r--test/geo_eulerangles.cpp20
-rw-r--r--test/geo_homogeneous.cpp26
-rw-r--r--test/geo_hyperplane.cpp39
-rw-r--r--test/geo_orthomethods.cpp14
-rw-r--r--test/geo_parametrizedline.cpp10
-rw-r--r--test/geo_quaternion.cpp51
-rwxr-xr-x[-rw-r--r--]test/geo_transformations.cpp91
-rw-r--r--test/half_float.cpp252
-rw-r--r--test/incomplete_cholesky.cpp65
-rw-r--r--test/inplace_decomposition.cpp110
-rw-r--r--test/integer_types.cpp8
-rw-r--r--test/inverse.cpp15
-rw-r--r--test/is_same_dense.cpp33
-rw-r--r--test/jacobisvd.cpp386
-rw-r--r--test/linearstructure.cpp67
-rw-r--r--test/lscg.cpp29
-rw-r--r--test/lu.cpp83
-rw-r--r--test/main.h284
-rw-r--r--test/mapped_matrix.cpp86
-rw-r--r--test/mapstaticmethods.cpp6
-rw-r--r--test/mapstride.cpp43
-rw-r--r--test/meta.cpp24
-rw-r--r--test/metis_support.cpp22
-rw-r--r--test/mixingtypes.cpp202
-rw-r--r--test/mpl2only.cpp22
-rw-r--r--test/nesting_ops.cpp86
-rw-r--r--test/nomalloc.cpp59
-rw-r--r--test/nullary.cpp225
-rw-r--r--test/packetmath.cpp424
-rw-r--r--test/pastix_support.cpp10
-rw-r--r--test/permutationmatrices.cpp62
-rw-r--r--test/prec_inverse_4x4.cpp15
-rw-r--r--test/product.h101
-rw-r--r--test/product_extra.cpp146
-rw-r--r--test/product_large.cpp49
-rw-r--r--test/product_mmtr.cpp28
-rw-r--r--test/product_notemporary.cpp60
-rw-r--r--test/product_selfadjoint.cpp9
-rw-r--r--test/product_small.cpp247
-rw-r--r--test/product_symm.cpp18
-rw-r--r--test/product_syrk.cpp5
-rw-r--r--test/product_trmm.cpp22
-rw-r--r--test/product_trmv.cpp6
-rw-r--r--test/product_trsolve.cpp18
-rw-r--r--test/qr.cpp9
-rw-r--r--test/qr_colpivoting.cpp206
-rw-r--r--test/qr_fullpivoting.cpp34
-rw-r--r--test/rand.cpp118
-rw-r--r--test/real_qz.cpp16
-rw-r--r--test/redux.cpp21
-rw-r--r--test/ref.cpp38
-rwxr-xr-xtest/runtest.sh20
-rw-r--r--test/rvalue_types.cpp64
-rw-r--r--test/schur_complex.cpp4
-rw-r--r--test/schur_real.cpp4
-rw-r--r--test/selfadjoint.cpp15
-rw-r--r--test/simplicial_cholesky.cpp28
-rw-r--r--test/sizeof.cpp17
-rw-r--r--test/sizeoverflow.cpp2
-rw-r--r--test/sparse.h23
-rw-r--r--test/sparse_basic.cpp678
-rw-r--r--test/sparse_block.cpp317
-rw-r--r--test/sparse_permutations.cpp95
-rw-r--r--test/sparse_product.cpp203
-rw-r--r--test/sparse_ref.cpp139
-rw-r--r--test/sparse_solver.h405
-rw-r--r--test/sparse_vector.cpp75
-rw-r--r--test/sparselu.cpp28
-rw-r--r--test/sparseqr.cpp12
-rw-r--r--test/spqr_support.cpp8
-rw-r--r--test/stable_norm.cpp105
-rw-r--r--test/stddeque_overload.cpp (renamed from test/eigen2/eigen2_newstdvector.cpp)77
-rw-r--r--test/stdlist_overload.cpp192
-rw-r--r--test/stdvector.cpp6
-rw-r--r--test/stdvector_overload.cpp6
-rw-r--r--test/superlu_support.cpp1
-rw-r--r--test/svd_common.h483
-rw-r--r--test/svd_fill.h119
-rw-r--r--test/swap.cpp23
-rw-r--r--test/testsuite.cmake229
-rw-r--r--test/triangular.cpp19
-rw-r--r--test/umfpack_support.cpp1
-rw-r--r--test/unalignedassert.cpp93
-rw-r--r--test/unalignedcount.cpp9
-rw-r--r--test/upperbidiagonalization.cpp2
-rw-r--r--test/vectorization_logic.cpp292
-rw-r--r--test/vectorwiseop.cpp87
-rw-r--r--test/visitor.cpp5
-rw-r--r--test/zerosized.cpp20
180 files changed, 8939 insertions, 8432 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index f5f208a37..2141d07c2 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,22 +1,38 @@
-
-# generate split test header file
-message(STATUS ${CMAKE_CURRENT_BINARY_DIR})
-file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/split_test_helper.h "")
-foreach(i RANGE 1 999)
- file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/split_test_helper.h
- "#ifdef EIGEN_TEST_PART_${i}\n"
- "#define CALL_SUBTEST_${i}(FUNC) CALL_SUBTEST(FUNC)\n"
- "#else\n"
- "#define CALL_SUBTEST_${i}(FUNC)\n"
- "#endif\n\n"
+# generate split test header file only if it does not yet exist
+# in order to prevent a rebuild everytime cmake is configured
+if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/split_test_helper.h)
+ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/split_test_helper.h "")
+ foreach(i RANGE 1 999)
+ file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/split_test_helper.h
+ "#ifdef EIGEN_TEST_PART_${i}\n"
+ "#define CALL_SUBTEST_${i}(FUNC) CALL_SUBTEST(FUNC)\n"
+ "#else\n"
+ "#define CALL_SUBTEST_${i}(FUNC)\n"
+ "#endif\n\n"
)
-endforeach()
+ endforeach()
+endif()
+
+# check if we have a Fortran compiler
+include("../cmake/language_support.cmake")
+
+workaround_9220(Fortran EIGEN_Fortran_COMPILER_WORKS)
+
+if(EIGEN_Fortran_COMPILER_WORKS)
+ enable_language(Fortran OPTIONAL)
+ if(NOT CMAKE_Fortran_COMPILER)
+ set(EIGEN_Fortran_COMPILER_WORKS OFF)
+ endif()
+endif()
+
+if(NOT EIGEN_Fortran_COMPILER_WORKS)
+ # search for a default Lapack library to complete Eigen's one
+ find_package(LAPACK)
+endif()
# configure blas/lapack (use Eigen's ones)
-set(BLAS_FOUND TRUE)
-set(LAPACK_FOUND TRUE)
-set(BLAS_LIBRARIES eigen_blas)
-set(LAPACK_LIBRARIES eigen_lapack)
+set(EIGEN_BLAS_LIBRARIES eigen_blas)
+set(EIGEN_LAPACK_LIBRARIES eigen_lapack)
set(EIGEN_TEST_MATRIX_DIR "" CACHE STRING "Enable testing of realword sparse matrices contained in the specified path")
if(EIGEN_TEST_MATRIX_DIR)
@@ -31,33 +47,33 @@ endif(EIGEN_TEST_MATRIX_DIR)
set(SPARSE_LIBS " ")
find_package(Cholmod)
-if(CHOLMOD_FOUND AND BLAS_FOUND AND LAPACK_FOUND)
+if(CHOLMOD_FOUND)
add_definitions("-DEIGEN_CHOLMOD_SUPPORT")
include_directories(${CHOLMOD_INCLUDES})
- set(SPARSE_LIBS ${SPARSE_LIBS} ${CHOLMOD_LIBRARIES} ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES})
- set(CHOLMOD_ALL_LIBS ${CHOLMOD_LIBRARIES} ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES})
+ set(SPARSE_LIBS ${SPARSE_LIBS} ${CHOLMOD_LIBRARIES} ${EIGEN_BLAS_LIBRARIES} ${EIGEN_LAPACK_LIBRARIES})
+ set(CHOLMOD_ALL_LIBS ${CHOLMOD_LIBRARIES} ${EIGEN_BLAS_LIBRARIES} ${EIGEN_LAPACK_LIBRARIES})
ei_add_property(EIGEN_TESTED_BACKENDS "Cholmod, ")
else()
ei_add_property(EIGEN_MISSING_BACKENDS "Cholmod, ")
endif()
find_package(Umfpack)
-if(UMFPACK_FOUND AND BLAS_FOUND)
+if(UMFPACK_FOUND)
add_definitions("-DEIGEN_UMFPACK_SUPPORT")
include_directories(${UMFPACK_INCLUDES})
- set(SPARSE_LIBS ${SPARSE_LIBS} ${UMFPACK_LIBRARIES} ${BLAS_LIBRARIES})
- set(UMFPACK_ALL_LIBS ${UMFPACK_LIBRARIES} ${BLAS_LIBRARIES})
+ set(SPARSE_LIBS ${SPARSE_LIBS} ${UMFPACK_LIBRARIES} ${EIGEN_BLAS_LIBRARIES})
+ set(UMFPACK_ALL_LIBS ${UMFPACK_LIBRARIES} ${EIGEN_BLAS_LIBRARIES})
ei_add_property(EIGEN_TESTED_BACKENDS "UmfPack, ")
else()
ei_add_property(EIGEN_MISSING_BACKENDS "UmfPack, ")
endif()
-find_package(SuperLU)
-if(SUPERLU_FOUND AND BLAS_FOUND)
+find_package(SuperLU 4.0)
+if(SUPERLU_FOUND)
add_definitions("-DEIGEN_SUPERLU_SUPPORT")
include_directories(${SUPERLU_INCLUDES})
- set(SPARSE_LIBS ${SPARSE_LIBS} ${SUPERLU_LIBRARIES} ${BLAS_LIBRARIES})
- set(SUPERLU_ALL_LIBS ${SUPERLU_LIBRARIES} ${BLAS_LIBRARIES})
+ set(SPARSE_LIBS ${SPARSE_LIBS} ${SUPERLU_LIBRARIES} ${EIGEN_BLAS_LIBRARIES})
+ set(SUPERLU_ALL_LIBS ${SUPERLU_LIBRARIES} ${EIGEN_BLAS_LIBRARIES})
ei_add_property(EIGEN_TESTED_BACKENDS "SuperLU, ")
else()
ei_add_property(EIGEN_MISSING_BACKENDS "SuperLU, ")
@@ -67,7 +83,7 @@ endif()
find_package(Pastix)
find_package(Scotch)
find_package(Metis 5.0 REQUIRED)
-if(PASTIX_FOUND AND BLAS_FOUND)
+if(PASTIX_FOUND)
add_definitions("-DEIGEN_PASTIX_SUPPORT")
include_directories(${PASTIX_INCLUDES})
if(SCOTCH_FOUND)
@@ -79,8 +95,8 @@ if(PASTIX_FOUND AND BLAS_FOUND)
else(SCOTCH_FOUND)
ei_add_property(EIGEN_MISSING_BACKENDS "PaStiX, ")
endif(SCOTCH_FOUND)
- set(SPARSE_LIBS ${SPARSE_LIBS} ${PASTIX_LIBRARIES} ${ORDERING_LIBRARIES} ${BLAS_LIBRARIES})
- set(PASTIX_ALL_LIBS ${PASTIX_LIBRARIES} ${BLAS_LIBRARIES})
+ set(SPARSE_LIBS ${SPARSE_LIBS} ${PASTIX_LIBRARIES} ${ORDERING_LIBRARIES} ${EIGEN_BLAS_LIBRARIES})
+ set(PASTIX_ALL_LIBS ${PASTIX_LIBRARIES} ${EIGEN_BLAS_LIBRARIES})
ei_add_property(EIGEN_TESTED_BACKENDS "PaStiX, ")
else()
ei_add_property(EIGEN_MISSING_BACKENDS "PaStiX, ")
@@ -95,16 +111,14 @@ else()
endif()
find_package(SPQR)
-if(SPQR_FOUND AND BLAS_FOUND AND LAPACK_FOUND)
- if(CHOLMOD_FOUND)
- add_definitions("-DEIGEN_SPQR_SUPPORT")
- include_directories(${SPQR_INCLUDES})
- set(SPQR_ALL_LIBS ${SPQR_LIBRARIES} ${CHOLMOD_LIBRARIES} ${LAPACK_LIBRARIES} ${BLAS_LIBRARIES})
- set(SPARSE_LIBS ${SPARSE_LIBS} ${SPQR_ALL_LIBS})
- ei_add_property(EIGEN_TESTED_BACKENDS "SPQR, ")
- else(CHOLMOD_FOUND)
- ei_add_property(EIGEN_MISSING_BACKENDS "SPQR, ")
- endif(CHOLMOD_FOUND)
+if(SPQR_FOUND AND CHOLMOD_FOUND AND (EIGEN_Fortran_COMPILER_WORKS OR LAPACK_FOUND) )
+ add_definitions("-DEIGEN_SPQR_SUPPORT")
+ include_directories(${SPQR_INCLUDES})
+ set(SPQR_ALL_LIBS ${SPQR_LIBRARIES} ${CHOLMOD_LIBRARIES} ${EIGEN_LAPACK_LIBRARIES} ${EIGEN_BLAS_LIBRARIES} ${LAPACK_LIBRARIES})
+ set(SPARSE_LIBS ${SPARSE_LIBS} ${SPQR_ALL_LIBS})
+ ei_add_property(EIGEN_TESTED_BACKENDS "SPQR, ")
+else()
+ ei_add_property(EIGEN_MISSING_BACKENDS "SPQR, ")
endif()
option(EIGEN_TEST_NOQT "Disable Qt support in unit tests" OFF)
@@ -125,25 +139,32 @@ endif(TEST_LIB)
set_property(GLOBAL PROPERTY EIGEN_CURRENT_SUBPROJECT "Official")
add_custom_target(BuildOfficial)
+ei_add_test(rand)
ei_add_test(meta)
ei_add_test(sizeof)
ei_add_test(dynalloc)
ei_add_test(nomalloc)
ei_add_test(first_aligned)
+ei_add_test(nullary)
ei_add_test(mixingtypes)
-ei_add_test(packetmath)
+ei_add_test(packetmath "-DEIGEN_FAST_MATH=1")
ei_add_test(unalignedassert)
ei_add_test(vectorization_logic)
ei_add_test(basicstuff)
+ei_add_test(constructor)
ei_add_test(linearstructure)
ei_add_test(integer_types)
-ei_add_test(cwiseop)
ei_add_test(unalignedcount)
-ei_add_test(exceptions)
+if(NOT EIGEN_TEST_NO_EXCEPTIONS)
+ ei_add_test(exceptions)
+endif()
ei_add_test(redux)
ei_add_test(visitor)
ei_add_test(block)
ei_add_test(corners)
+ei_add_test(swap)
+ei_add_test(resize)
+ei_add_test(conservative_resize)
ei_add_test(product_small)
ei_add_test(product_large)
ei_add_test(product_extra)
@@ -161,6 +182,7 @@ ei_add_test(array_for_matrix)
ei_add_test(array_replicate)
ei_add_test(array_reverse)
ei_add_test(ref)
+ei_add_test(is_same_dense)
ei_add_test(triangular)
ei_add_test(selfadjoint)
ei_add_test(product_selfadjoint)
@@ -172,6 +194,7 @@ ei_add_test(product_trsolve)
ei_add_test(product_mmtr)
ei_add_test(product_notemporary)
ei_add_test(stable_norm)
+ei_add_test(permutationmatrices)
ei_add_test(bandmatrix)
ei_add_test(cholesky)
ei_add_test(lu)
@@ -191,52 +214,75 @@ ei_add_test(real_qz)
ei_add_test(eigensolver_generalized_real)
ei_add_test(jacobi)
ei_add_test(jacobisvd)
+ei_add_test(bdcsvd)
+ei_add_test(householder)
ei_add_test(geo_orthomethods)
-ei_add_test(geo_homogeneous)
ei_add_test(geo_quaternion)
-ei_add_test(geo_transformations)
ei_add_test(geo_eulerangles)
-ei_add_test(geo_hyperplane)
ei_add_test(geo_parametrizedline)
ei_add_test(geo_alignedbox)
+ei_add_test(geo_hyperplane)
+ei_add_test(geo_transformations)
+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(resize)
-ei_add_test(sparse_vector)
+ei_add_test(stddeque_overload)
ei_add_test(sparse_basic)
+ei_add_test(sparse_block)
+ei_add_test(sparse_vector)
ei_add_test(sparse_product)
+ei_add_test(sparse_ref)
ei_add_test(sparse_solvers)
-ei_add_test(umeyama)
-ei_add_test(householder)
-ei_add_test(swap)
-ei_add_test(conservative_resize)
-ei_add_test(permutationmatrices)
ei_add_test(sparse_permutations)
-ei_add_test(nullary)
+ei_add_test(simplicial_cholesky)
+ei_add_test(conjugate_gradient)
+ei_add_test(incomplete_cholesky)
+ei_add_test(bicgstab)
+ei_add_test(lscg)
+ei_add_test(sparselu)
+ei_add_test(sparseqr)
+ei_add_test(umeyama)
ei_add_test(nesting_ops "${CMAKE_CXX_FLAGS_DEBUG}")
ei_add_test(zerosized)
ei_add_test(dontalign)
-ei_add_test(sizeoverflow)
+ei_add_test(evaluators)
+if(NOT EIGEN_TEST_NO_EXCEPTIONS)
+ ei_add_test(sizeoverflow)
+endif()
ei_add_test(prec_inverse_4x4)
ei_add_test(vectorwiseop)
ei_add_test(special_numbers)
+ei_add_test(rvalue_types)
+ei_add_test(dense_storage)
+ei_add_test(ctorleak)
+ei_add_test(mpl2only)
+ei_add_test(inplace_decomposition)
+ei_add_test(half_float)
+ei_add_test(array_of_string)
-ei_add_test(simplicial_cholesky)
-ei_add_test(conjugate_gradient)
-ei_add_test(bicgstab)
-ei_add_test(sparselu)
-ei_add_test(sparseqr)
+add_executable(bug1213 bug1213.cpp bug1213_main.cpp)
+
+check_cxx_compiler_flag("-ffast-math" COMPILER_SUPPORT_FASTMATH)
+if(COMPILER_SUPPORT_FASTMATH)
+ set(EIGEN_FASTMATH_FLAGS "-ffast-math")
+else()
+ check_cxx_compiler_flag("/fp:fast" COMPILER_SUPPORT_FPFAST)
+ if(COMPILER_SUPPORT_FPFAST)
+ set(EIGEN_FASTMATH_FLAGS "/fp:fast")
+ endif()
+endif()
-# ei_add_test(denseLM)
+ei_add_test(fastmath " ${EIGEN_FASTMATH_FLAGS} ")
+
+# # ei_add_test(denseLM)
if(QT4_FOUND)
ei_add_test(qtvector "" "${QT_QTCORE_LIBRARY}")
endif(QT4_FOUND)
-ei_add_test(eigen2support)
-
if(UMFPACK_FOUND)
ei_add_test(umfpack_support "" "${UMFPACK_ALL_LIBS}")
endif()
@@ -281,9 +327,54 @@ ei_add_property(EIGEN_TESTING_SUMMARY "Sparse lib flags: ${SPARSE_LIBS}\n")
option(EIGEN_TEST_EIGEN2 "Run whole Eigen2 test suite against EIGEN2_SUPPORT" OFF)
mark_as_advanced(EIGEN_TEST_EIGEN2)
if(EIGEN_TEST_EIGEN2)
- add_subdirectory(eigen2)
+ message(WARNING "The Eigen2 test suite has been removed")
+endif()
+
+# boost MP unit test
+find_package(Boost)
+if(Boost_FOUND)
+ include_directories(${Boost_INCLUDE_DIRS})
+ ei_add_test(boostmultiprec "" "${Boost_LIBRARIES}")
+ ei_add_property(EIGEN_TESTED_BACKENDS "Boost.Multiprecision, ")
+else()
+ ei_add_property(EIGEN_MISSING_BACKENDS "Boost.Multiprecision, ")
+endif()
+
+
+# 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)
+
+ set(CUDA_PROPAGATE_HOST_FLAGS OFF)
+ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ set(CUDA_NVCC_FLAGS "-ccbin ${CMAKE_C_COMPILER}" 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")
+
+ ei_add_test(cuda_basic)
+
+ unset(EIGEN_ADD_TEST_FILENAME_EXTENSION)
+
+endif(CUDA_FOUND)
+
+endif(EIGEN_TEST_CUDA)
+
+
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/failtests)
+add_test(NAME failtests WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/failtests COMMAND ${CMAKE_COMMAND} ${Eigen_SOURCE_DIR} -G "${CMAKE_GENERATOR}" -DEIGEN_FAILTEST=ON)
option(EIGEN_TEST_BUILD_DOCUMENTATION "Test building the doxygen documentation" OFF)
IF(EIGEN_TEST_BUILD_DOCUMENTATION)
diff --git a/test/adjoint.cpp b/test/adjoint.cpp
index ea36f7841..bdea51c10 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()));
@@ -64,6 +75,7 @@ template<typename MatrixType> void adjoint(const MatrixType& m)
typedef typename NumTraits<Scalar>::Real RealScalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
+ const Index PacketSize = internal::packet_traits<Scalar>::size;
Index rows = m.rows();
Index cols = m.cols();
@@ -108,6 +120,17 @@ template<typename MatrixType> void adjoint(const MatrixType& m)
VERIFY_IS_APPROX(m3,m1.transpose());
m3.transposeInPlace();
VERIFY_IS_APPROX(m3,m1);
+
+ if(PacketSize<m3.rows() && PacketSize<m3.cols())
+ {
+ m3 = m1;
+ Index i = internal::random<Index>(0,m3.rows()-PacketSize);
+ Index j = internal::random<Index>(0,m3.cols()-PacketSize);
+ m3.template block<PacketSize,PacketSize>(i,j).transposeInPlace();
+ VERIFY_IS_APPROX( (m3.template block<PacketSize,PacketSize>(i,j)), (m1.template block<PacketSize,PacketSize>(i,j).transpose()) );
+ m3.template block<PacketSize,PacketSize>(i,j).transposeInPlace();
+ VERIFY_IS_APPROX(m3,m1);
+ }
// check inplace adjoint
m3 = m1;
@@ -129,14 +152,24 @@ void test_adjoint()
CALL_SUBTEST_1( adjoint(Matrix<float, 1, 1>()) );
CALL_SUBTEST_2( adjoint(Matrix3d()) );
CALL_SUBTEST_3( adjoint(Matrix4f()) );
+
CALL_SUBTEST_4( adjoint(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
CALL_SUBTEST_5( adjoint(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
CALL_SUBTEST_6( adjoint(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+
+ // Complement for 128 bits vectorization:
+ CALL_SUBTEST_8( adjoint(Matrix2d()) );
+ CALL_SUBTEST_9( adjoint(Matrix<int,4,4>()) );
+
+ // 256 bits vectorization:
+ CALL_SUBTEST_10( adjoint(Matrix<float,8,8>()) );
+ CALL_SUBTEST_11( adjoint(Matrix<double,4,4>()) );
+ CALL_SUBTEST_12( adjoint(Matrix<int,8,8>()) );
}
// test a large static matrix only once
CALL_SUBTEST_7( adjoint(Matrix<float, 100, 100>()) );
-#ifdef EIGEN_TEST_PART_4
+#ifdef EIGEN_TEST_PART_13
{
MatrixXcf a(10,10), b(10,10);
VERIFY_RAISES_ASSERT(a = a.transpose());
@@ -154,6 +187,13 @@ void test_adjoint()
a.transpose() = a.adjoint();
a.transpose() += a.adjoint();
a.transpose() += a.adjoint() + b;
+
+ // regression tests for check_for_aliasing
+ MatrixXd c(10,10);
+ c = 1.0 * MatrixXd::Ones(10,10) + c;
+ c = MatrixXd::Ones(10,10) * 1.0 + c;
+ c = c + MatrixXd::Ones(10,10) .cwiseProduct( MatrixXd::Zero(10,10) );
+ c = MatrixXd::Ones(10,10) * MatrixXd::Zero(10,10);
}
#endif
}
diff --git a/test/array.cpp b/test/array.cpp
index 68f6b3d7a..15c3266a9 100644
--- a/test/array.cpp
+++ b/test/array.cpp
@@ -13,6 +13,7 @@ template<typename ArrayType> void array(const ArrayType& m)
{
typedef typename ArrayType::Index Index;
typedef typename ArrayType::Scalar Scalar;
+ typedef typename ArrayType::RealScalar RealScalar;
typedef Array<Scalar, ArrayType::RowsAtCompileTime, 1> ColVectorType;
typedef Array<Scalar, 1, ArrayType::ColsAtCompileTime> RowVectorType;
@@ -22,6 +23,8 @@ template<typename ArrayType> void array(const ArrayType& m)
ArrayType m1 = ArrayType::Random(rows, cols),
m2 = ArrayType::Random(rows, cols),
m3(rows, cols);
+ ArrayType m4 = m1; // copy constructor
+ VERIFY_IS_APPROX(m1, m4);
ColVectorType cv1 = ColVectorType::Random(rows);
RowVectorType rv1 = RowVectorType::Random(cols);
@@ -70,7 +73,7 @@ template<typename ArrayType> void array(const ArrayType& m)
VERIFY_IS_MUCH_SMALLER_THAN(abs(m1.rowwise().sum().sum() - m1.sum()), m1.abs().sum());
if (!internal::isMuchSmallerThan(abs(m1.sum() - (m1+m2).sum()), m1.abs().sum(), test_precision<Scalar>()))
VERIFY_IS_NOT_APPROX(((m1+m2).rowwise().sum()).sum(), m1.sum());
- VERIFY_IS_APPROX(m1.colwise().sum(), m1.colwise().redux(internal::scalar_sum_op<Scalar>()));
+ VERIFY_IS_APPROX(m1.colwise().sum(), m1.colwise().redux(internal::scalar_sum_op<Scalar,Scalar>()));
// vector-wise ops
m3 = m1;
@@ -81,6 +84,47 @@ template<typename ArrayType> void array(const ArrayType& m)
VERIFY_IS_APPROX(m3.rowwise() += rv1, m1.rowwise() + rv1);
m3 = m1;
VERIFY_IS_APPROX(m3.rowwise() -= rv1, m1.rowwise() - rv1);
+
+ // Conversion from scalar
+ VERIFY_IS_APPROX((m3 = s1), ArrayType::Constant(rows,cols,s1));
+ VERIFY_IS_APPROX((m3 = 1), ArrayType::Constant(rows,cols,1));
+ VERIFY_IS_APPROX((m3.topLeftCorner(rows,cols) = 1), ArrayType::Constant(rows,cols,1));
+ typedef Array<Scalar,
+ ArrayType::RowsAtCompileTime==Dynamic?2:ArrayType::RowsAtCompileTime,
+ ArrayType::ColsAtCompileTime==Dynamic?2:ArrayType::ColsAtCompileTime,
+ ArrayType::Options> FixedArrayType;
+ FixedArrayType f1(s1);
+ VERIFY_IS_APPROX(f1, FixedArrayType::Constant(s1));
+ FixedArrayType f2(numext::real(s1));
+ VERIFY_IS_APPROX(f2, FixedArrayType::Constant(numext::real(s1)));
+ FixedArrayType f3((int)100*numext::real(s1));
+ VERIFY_IS_APPROX(f3, FixedArrayType::Constant((int)100*numext::real(s1)));
+ f1.setRandom();
+ FixedArrayType f4(f1.data());
+ VERIFY_IS_APPROX(f4, f1);
+
+ // pow
+ VERIFY_IS_APPROX(m1.pow(2), m1.square());
+ VERIFY_IS_APPROX(pow(m1,2), m1.square());
+ VERIFY_IS_APPROX(m1.pow(3), m1.cube());
+ VERIFY_IS_APPROX(pow(m1,3), m1.cube());
+ VERIFY_IS_APPROX((-m1).pow(3), -m1.cube());
+ VERIFY_IS_APPROX(pow(2*m1,3), 8*m1.cube());
+ ArrayType exponents = ArrayType::Constant(rows, cols, RealScalar(2));
+ VERIFY_IS_APPROX(Eigen::pow(m1,exponents), m1.square());
+ VERIFY_IS_APPROX(m1.pow(exponents), m1.square());
+ VERIFY_IS_APPROX(Eigen::pow(2*m1,exponents), 4*m1.square());
+ VERIFY_IS_APPROX((2*m1).pow(exponents), 4*m1.square());
+ VERIFY_IS_APPROX(Eigen::pow(m1,2*exponents), m1.square().square());
+ VERIFY_IS_APPROX(m1.pow(2*exponents), m1.square().square());
+ VERIFY_IS_APPROX(Eigen::pow(m1(0,0), exponents), ArrayType::Constant(rows,cols,m1(0,0)*m1(0,0)));
+
+ // Check possible conflicts with 1D ctor
+ typedef Array<Scalar, Dynamic, 1> OneDArrayType;
+ OneDArrayType o1(rows);
+ VERIFY(o1.size()==rows);
+ OneDArrayType o4((int)rows);
+ VERIFY(o4.size()==rows);
}
template<typename ArrayType> void comparisons(const ArrayType& m)
@@ -97,8 +141,11 @@ template<typename ArrayType> void comparisons(const ArrayType& m)
c = internal::random<Index>(0, cols-1);
ArrayType m1 = ArrayType::Random(rows, cols),
- m2 = ArrayType::Random(rows, cols),
- m3(rows, cols);
+ m2 = ArrayType::Random(rows, cols),
+ m3(rows, cols),
+ m4 = m1;
+
+ m4 = (m4.abs()==Scalar(0)).select(1,m4);
VERIFY(((m1 + Scalar(1)) > m1).all());
VERIFY(((m1 - Scalar(1)) < m1).all());
@@ -112,11 +159,17 @@ template<typename ArrayType> void comparisons(const ArrayType& m)
VERIFY(!(m1 > m2 && m1 < m2).any());
VERIFY((m1 <= m2 || m1 >= m2).all());
- // comparisons to scalar
+ // comparisons array to scalar
VERIFY( (m1 != (m1(r,c)+1) ).any() );
- VERIFY( (m1 > (m1(r,c)-1) ).any() );
- VERIFY( (m1 < (m1(r,c)+1) ).any() );
- VERIFY( (m1 == m1(r,c) ).any() );
+ VERIFY( (m1 > (m1(r,c)-1) ).any() );
+ VERIFY( (m1 < (m1(r,c)+1) ).any() );
+ VERIFY( (m1 == m1(r,c) ).any() );
+
+ // comparisons scalar to array
+ VERIFY( ( (m1(r,c)+1) != m1).any() );
+ VERIFY( ( (m1(r,c)-1) < m1).any() );
+ VERIFY( ( (m1(r,c)+1) > m1).any() );
+ VERIFY( ( m1(r,c) == m1).any() );
// test Select
VERIFY_IS_APPROX( (m1<m2).select(m1,m2), m1.cwiseMin(m2) );
@@ -164,21 +217,69 @@ template<typename ArrayType> void array_real(const ArrayType& m)
ArrayType m1 = ArrayType::Random(rows, cols),
m2 = ArrayType::Random(rows, cols),
- m3(rows, cols);
+ m3(rows, cols),
+ m4 = m1;
+
+ m4 = (m4.abs()==Scalar(0)).select(1,m4);
Scalar s1 = internal::random<Scalar>();
- // these tests are mostly to check possible compilation issues.
+ // these tests are mostly to check possible compilation issues with free-functions.
VERIFY_IS_APPROX(m1.sin(), sin(m1));
VERIFY_IS_APPROX(m1.cos(), cos(m1));
+ VERIFY_IS_APPROX(m1.tan(), tan(m1));
VERIFY_IS_APPROX(m1.asin(), asin(m1));
VERIFY_IS_APPROX(m1.acos(), acos(m1));
- VERIFY_IS_APPROX(m1.tan(), tan(m1));
-
+ VERIFY_IS_APPROX(m1.atan(), atan(m1));
+ VERIFY_IS_APPROX(m1.sinh(), sinh(m1));
+ VERIFY_IS_APPROX(m1.cosh(), cosh(m1));
+ VERIFY_IS_APPROX(m1.tanh(), tanh(m1));
+
+ VERIFY_IS_APPROX(m1.arg(), arg(m1));
+ VERIFY_IS_APPROX(m1.round(), round(m1));
+ VERIFY_IS_APPROX(m1.floor(), floor(m1));
+ VERIFY_IS_APPROX(m1.ceil(), ceil(m1));
+ VERIFY((m1.isNaN() == (Eigen::isnan)(m1)).all());
+ VERIFY((m1.isInf() == (Eigen::isinf)(m1)).all());
+ VERIFY((m1.isFinite() == (Eigen::isfinite)(m1)).all());
+ VERIFY_IS_APPROX(m1.inverse(), inverse(m1));
+ VERIFY_IS_APPROX(m1.abs(), abs(m1));
+ VERIFY_IS_APPROX(m1.abs2(), abs2(m1));
+ VERIFY_IS_APPROX(m1.square(), square(m1));
+ VERIFY_IS_APPROX(m1.cube(), cube(m1));
VERIFY_IS_APPROX(cos(m1+RealScalar(3)*m2), cos((m1+RealScalar(3)*m2).eval()));
+ VERIFY_IS_APPROX(m1.sign(), sign(m1));
+
- VERIFY_IS_APPROX(m1.abs().sqrt(), sqrt(abs(m1)));
- VERIFY_IS_APPROX(m1.abs(), sqrt(numext::abs2(m1)));
+ // avoid NaNs with abs() so verification doesn't fail
+ m3 = m1.abs();
+ VERIFY_IS_APPROX(m3.sqrt(), sqrt(abs(m1)));
+ VERIFY_IS_APPROX(m3.rsqrt(), Scalar(1)/sqrt(abs(m1)));
+ VERIFY_IS_APPROX(rsqrt(m3), Scalar(1)/sqrt(abs(m1)));
+ VERIFY_IS_APPROX(m3.log(), log(m3));
+ VERIFY_IS_APPROX(m3.log1p(), log1p(m3));
+ VERIFY_IS_APPROX(m3.log10(), log10(m3));
+
+
+ VERIFY((!(m1>m2) == (m1<=m2)).all());
+
+ VERIFY_IS_APPROX(sin(m1.asin()), m1);
+ VERIFY_IS_APPROX(cos(m1.acos()), m1);
+ VERIFY_IS_APPROX(tan(m1.atan()), m1);
+ VERIFY_IS_APPROX(sinh(m1), 0.5*(exp(m1)-exp(-m1)));
+ VERIFY_IS_APPROX(cosh(m1), 0.5*(exp(m1)+exp(-m1)));
+ VERIFY_IS_APPROX(tanh(m1), (0.5*(exp(m1)-exp(-m1)))/(0.5*(exp(m1)+exp(-m1))));
+ VERIFY_IS_APPROX(arg(m1), ((m1<0).template cast<Scalar>())*std::acos(-1.0));
+ VERIFY((round(m1) <= ceil(m1) && round(m1) >= floor(m1)).all());
+ VERIFY((Eigen::isnan)((m1*0.0)/0.0).all());
+ VERIFY((Eigen::isinf)(m4/0.0).all());
+ VERIFY(((Eigen::isfinite)(m1) && (!(Eigen::isfinite)(m1*0.0/0.0)) && (!(Eigen::isfinite)(m4/0.0))).all());
+ VERIFY_IS_APPROX(inverse(inverse(m1)),m1);
+ VERIFY((abs(m1) == m1 || abs(m1) == -m1).all());
+ VERIFY_IS_APPROX(m3, sqrt(abs2(m1)));
+ VERIFY_IS_APPROX( m1.sign(), -(-m1).sign() );
+ VERIFY_IS_APPROX( m1*m1.sign(),m1.abs());
+ VERIFY_IS_APPROX(m1.sign() * m1.abs(), m1);
VERIFY_IS_APPROX(numext::abs2(numext::real(m1)) + numext::abs2(numext::imag(m1)), numext::abs2(m1));
VERIFY_IS_APPROX(numext::abs2(real(m1)) + numext::abs2(imag(m1)), numext::abs2(m1));
@@ -187,52 +288,138 @@ template<typename ArrayType> void array_real(const ArrayType& m)
// shift argument of logarithm so that it is not zero
Scalar smallNumber = NumTraits<Scalar>::dummy_precision();
- VERIFY_IS_APPROX((m1.abs() + smallNumber).log() , log(abs(m1) + smallNumber));
+ VERIFY_IS_APPROX((m3 + smallNumber).log() , log(abs(m1) + smallNumber));
+ VERIFY_IS_APPROX((m3 + smallNumber + 1).log() , log1p(abs(m1) + smallNumber));
VERIFY_IS_APPROX(m1.exp() * m2.exp(), exp(m1+m2));
VERIFY_IS_APPROX(m1.exp(), exp(m1));
VERIFY_IS_APPROX(m1.exp() / m2.exp(),(m1-m2).exp());
- VERIFY_IS_APPROX(m1.pow(2), m1.square());
- VERIFY_IS_APPROX(pow(m1,2), m1.square());
-
- ArrayType exponents = ArrayType::Constant(rows, cols, RealScalar(2));
- VERIFY_IS_APPROX(Eigen::pow(m1,exponents), m1.square());
-
- m3 = m1.abs();
VERIFY_IS_APPROX(m3.pow(RealScalar(0.5)), m3.sqrt());
VERIFY_IS_APPROX(pow(m3,RealScalar(0.5)), m3.sqrt());
+ VERIFY_IS_APPROX(m3.pow(RealScalar(-0.5)), m3.rsqrt());
+ VERIFY_IS_APPROX(pow(m3,RealScalar(-0.5)), m3.rsqrt());
+
+ VERIFY_IS_APPROX(log10(m3), log(m3)/log(10));
+
// scalar by array division
const RealScalar tiny = sqrt(std::numeric_limits<RealScalar>::epsilon());
s1 += Scalar(tiny);
m1 += ArrayType::Constant(rows,cols,Scalar(tiny));
VERIFY_IS_APPROX(s1/m1, s1 * m1.inverse());
-
+
// check inplace transpose
m3 = m1;
m3.transposeInPlace();
- VERIFY_IS_APPROX(m3,m1.transpose());
+ VERIFY_IS_APPROX(m3, m1.transpose());
m3.transposeInPlace();
- VERIFY_IS_APPROX(m3,m1);
+ VERIFY_IS_APPROX(m3, m1);
}
template<typename ArrayType> void array_complex(const ArrayType& m)
{
typedef typename ArrayType::Index Index;
+ typedef typename ArrayType::Scalar Scalar;
+ typedef typename NumTraits<Scalar>::Real RealScalar;
Index rows = m.rows();
Index cols = m.cols();
ArrayType m1 = ArrayType::Random(rows, cols),
- m2(rows, cols);
+ m2(rows, cols),
+ m4 = m1;
+
+ m4.real() = (m4.real().abs()==RealScalar(0)).select(RealScalar(1),m4.real());
+ m4.imag() = (m4.imag().abs()==RealScalar(0)).select(RealScalar(1),m4.imag());
+
+ Array<RealScalar, -1, -1> m3(rows, cols);
for (Index i = 0; i < m.rows(); ++i)
for (Index j = 0; j < m.cols(); ++j)
m2(i,j) = sqrt(m1(i,j));
- VERIFY_IS_APPROX(m1.sqrt(), m2);
- VERIFY_IS_APPROX(m1.sqrt(), Eigen::sqrt(m1));
+ // these tests are mostly to check possible compilation issues with free-functions.
+ VERIFY_IS_APPROX(m1.sin(), sin(m1));
+ VERIFY_IS_APPROX(m1.cos(), cos(m1));
+ VERIFY_IS_APPROX(m1.tan(), tan(m1));
+ VERIFY_IS_APPROX(m1.sinh(), sinh(m1));
+ VERIFY_IS_APPROX(m1.cosh(), cosh(m1));
+ VERIFY_IS_APPROX(m1.tanh(), tanh(m1));
+ VERIFY_IS_APPROX(m1.arg(), arg(m1));
+ VERIFY((m1.isNaN() == (Eigen::isnan)(m1)).all());
+ VERIFY((m1.isInf() == (Eigen::isinf)(m1)).all());
+ VERIFY((m1.isFinite() == (Eigen::isfinite)(m1)).all());
+ VERIFY_IS_APPROX(m1.inverse(), inverse(m1));
+ VERIFY_IS_APPROX(m1.log(), log(m1));
+ VERIFY_IS_APPROX(m1.log10(), log10(m1));
+ VERIFY_IS_APPROX(m1.abs(), abs(m1));
+ VERIFY_IS_APPROX(m1.abs2(), abs2(m1));
+ VERIFY_IS_APPROX(m1.sqrt(), sqrt(m1));
+ VERIFY_IS_APPROX(m1.square(), square(m1));
+ VERIFY_IS_APPROX(m1.cube(), cube(m1));
+ VERIFY_IS_APPROX(cos(m1+RealScalar(3)*m2), cos((m1+RealScalar(3)*m2).eval()));
+ VERIFY_IS_APPROX(m1.sign(), sign(m1));
+
+
+ VERIFY_IS_APPROX(m1.exp() * m2.exp(), exp(m1+m2));
+ VERIFY_IS_APPROX(m1.exp(), exp(m1));
+ VERIFY_IS_APPROX(m1.exp() / m2.exp(),(m1-m2).exp());
+
+ VERIFY_IS_APPROX(sinh(m1), 0.5*(exp(m1)-exp(-m1)));
+ VERIFY_IS_APPROX(cosh(m1), 0.5*(exp(m1)+exp(-m1)));
+ VERIFY_IS_APPROX(tanh(m1), (0.5*(exp(m1)-exp(-m1)))/(0.5*(exp(m1)+exp(-m1))));
+
+ for (Index i = 0; i < m.rows(); ++i)
+ for (Index j = 0; j < m.cols(); ++j)
+ m3(i,j) = std::atan2(imag(m1(i,j)), real(m1(i,j)));
+ VERIFY_IS_APPROX(arg(m1), m3);
+
+ std::complex<RealScalar> zero(0.0,0.0);
+ VERIFY((Eigen::isnan)(m1*zero/zero).all());
+#if EIGEN_COMP_MSVC
+ // msvc complex division is not robust
+ VERIFY((Eigen::isinf)(m4/RealScalar(0)).all());
+#else
+#if EIGEN_COMP_CLANG
+ // clang's complex division is notoriously broken too
+ if((numext::isinf)(m4(0,0)/RealScalar(0))) {
+#endif
+ VERIFY((Eigen::isinf)(m4/zero).all());
+#if EIGEN_COMP_CLANG
+ }
+ else
+ {
+ VERIFY((Eigen::isinf)(m4.real()/zero.real()).all());
+ }
+#endif
+#endif // MSVC
+
+ VERIFY(((Eigen::isfinite)(m1) && (!(Eigen::isfinite)(m1*zero/zero)) && (!(Eigen::isfinite)(m1/zero))).all());
+
+ VERIFY_IS_APPROX(inverse(inverse(m1)),m1);
+ VERIFY_IS_APPROX(conj(m1.conjugate()), m1);
+ VERIFY_IS_APPROX(abs(m1), sqrt(square(real(m1))+square(imag(m1))));
+ VERIFY_IS_APPROX(abs(m1), sqrt(abs2(m1)));
+ VERIFY_IS_APPROX(log10(m1), log(m1)/log(10));
+
+ VERIFY_IS_APPROX( m1.sign(), -(-m1).sign() );
+ VERIFY_IS_APPROX( m1.sign() * m1.abs(), m1);
+
+ // scalar by array division
+ Scalar s1 = internal::random<Scalar>();
+ const RealScalar tiny = std::sqrt(std::numeric_limits<RealScalar>::epsilon());
+ s1 += Scalar(tiny);
+ m1 += ArrayType::Constant(rows,cols,Scalar(tiny));
+ VERIFY_IS_APPROX(s1/m1, s1 * m1.inverse());
+
+ // check inplace transpose
+ m2 = m1;
+ m2.transposeInPlace();
+ VERIFY_IS_APPROX(m2, m1.transpose());
+ m2.transposeInPlace();
+ VERIFY_IS_APPROX(m2, m1);
+
}
template<typename ArrayType> void min_max(const ArrayType& m)
@@ -301,7 +488,7 @@ void test_array()
VERIFY((internal::is_same< internal::global_math_functions_filtering_base<int>::type, int >::value));
VERIFY((internal::is_same< internal::global_math_functions_filtering_base<float>::type, float >::value));
VERIFY((internal::is_same< internal::global_math_functions_filtering_base<Array2i>::type, ArrayBase<Array2i> >::value));
- typedef CwiseUnaryOp<internal::scalar_sum_op<double>, ArrayXd > Xpr;
+ typedef CwiseUnaryOp<internal::scalar_abs_op<double>, ArrayXd > Xpr;
VERIFY((internal::is_same< internal::global_math_functions_filtering_base<Xpr>::type,
ArrayBase<Xpr>
>::value));
diff --git a/test/array_for_matrix.cpp b/test/array_for_matrix.cpp
index 9667e1f14..c1501947b 100644
--- a/test/array_for_matrix.cpp
+++ b/test/array_for_matrix.cpp
@@ -45,7 +45,7 @@ template<typename MatrixType> void array_for_matrix(const MatrixType& m)
VERIFY_IS_MUCH_SMALLER_THAN(m1.rowwise().sum().sum() - m1.sum(), m1.squaredNorm());
VERIFY_IS_MUCH_SMALLER_THAN(m1.colwise().sum() + m2.colwise().sum() - (m1+m2).colwise().sum(), (m1+m2).squaredNorm());
VERIFY_IS_MUCH_SMALLER_THAN(m1.rowwise().sum() - m2.rowwise().sum() - (m1-m2).rowwise().sum(), (m1-m2).squaredNorm());
- VERIFY_IS_APPROX(m1.colwise().sum(), m1.colwise().redux(internal::scalar_sum_op<Scalar>()));
+ VERIFY_IS_APPROX(m1.colwise().sum(), m1.colwise().redux(internal::scalar_sum_op<Scalar,Scalar>()));
// vector-wise ops
m3 = m1;
@@ -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)
@@ -124,6 +134,12 @@ template<typename MatrixType> void comparisons(const MatrixType& m)
// count
VERIFY(((m1.array().abs()+1)>RealScalar(0.1)).count() == rows*cols);
+ // and/or
+ VERIFY( ((m1.array()<RealScalar(0)).matrix() && (m1.array()>RealScalar(0)).matrix()).count() == 0);
+ VERIFY( ((m1.array()<RealScalar(0)).matrix() || (m1.array()>=RealScalar(0)).matrix()).count() == rows*cols);
+ RealScalar a = m1.cwiseAbs().mean();
+ VERIFY( ((m1.array()<-a).matrix() || (m1.array()>a).matrix()).count() == (m1.cwiseAbs().array()>a).count());
+
typedef Matrix<typename MatrixType::Index, Dynamic, 1> VectorOfIndices;
// TODO allows colwise/rowwise for array
@@ -134,9 +150,21 @@ template<typename MatrixType> void comparisons(const MatrixType& m)
template<typename VectorType> void lpNorm(const VectorType& v)
{
using std::sqrt;
+ typedef typename VectorType::RealScalar RealScalar;
VectorType u = VectorType::Random(v.size());
- VERIFY_IS_APPROX(u.template lpNorm<Infinity>(), u.cwiseAbs().maxCoeff());
+ if(v.size()==0)
+ {
+ VERIFY_IS_APPROX(u.template lpNorm<Infinity>(), RealScalar(0));
+ VERIFY_IS_APPROX(u.template lpNorm<1>(), RealScalar(0));
+ VERIFY_IS_APPROX(u.template lpNorm<2>(), RealScalar(0));
+ VERIFY_IS_APPROX(u.template lpNorm<5>(), RealScalar(0));
+ }
+ else
+ {
+ VERIFY_IS_APPROX(u.template lpNorm<Infinity>(), u.cwiseAbs().maxCoeff());
+ }
+
VERIFY_IS_APPROX(u.template lpNorm<1>(), u.cwiseAbs().sum());
VERIFY_IS_APPROX(u.template lpNorm<2>(), sqrt(u.array().abs().square().sum()));
VERIFY_IS_APPROX(numext::pow(u.template lpNorm<5>(), typename VectorType::RealScalar(5)), u.array().abs().pow(5).sum());
@@ -245,6 +273,8 @@ void test_array_for_matrix()
CALL_SUBTEST_5( lpNorm(VectorXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
CALL_SUBTEST_4( lpNorm(VectorXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
}
+ CALL_SUBTEST_5( lpNorm(VectorXf(0)) );
+ CALL_SUBTEST_4( lpNorm(VectorXcf(0)) );
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_4( resize(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
CALL_SUBTEST_5( resize(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
diff --git a/test/array_of_string.cpp b/test/array_of_string.cpp
new file mode 100644
index 000000000..e23b7c59e
--- /dev/null
+++ b/test/array_of_string.cpp
@@ -0,0 +1,32 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 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
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+void test_array_of_string()
+{
+ typedef Array<std::string,1,Dynamic> ArrayXs;
+ ArrayXs a1(3), a2(3), a3(3), a3ref(3);
+ a1 << "one", "two", "three";
+ a2 << "1", "2", "3";
+ a3ref << "one (1)", "two (2)", "three (3)";
+ std::stringstream s1;
+ s1 << a1;
+ VERIFY_IS_EQUAL(s1.str(), std::string(" one two three"));
+ a3 = a1 + std::string(" (") + a2 + std::string(")");
+ VERIFY((a3==a3ref).all());
+
+ a3 = a1;
+ a3 += std::string(" (") + a2 + std::string(")");
+ VERIFY((a3==a3ref).all());
+
+ a1.swap(a3);
+ VERIFY((a1==a3ref).all());
+ VERIFY((a3!=a3ref).all());
+}
diff --git a/test/array_replicate.cpp b/test/array_replicate.cpp
index f412d1aed..779c8fc2f 100644
--- a/test/array_replicate.cpp
+++ b/test/array_replicate.cpp
@@ -44,6 +44,19 @@ template<typename MatrixType> void replicate(const MatrixType& m)
x2 << m2, m2, m2,
m2, m2, m2;
VERIFY_IS_APPROX(x2, (m2.template replicate<2,3>()));
+
+ x2.resize(rows,3*cols);
+ x2 << m2, m2, m2;
+ VERIFY_IS_APPROX(x2, (m2.template replicate<1,3>()));
+
+ vx1.resize(3*rows,cols);
+ vx1 << m2, m2, m2;
+ VERIFY_IS_APPROX(vx1+vx1, vx1+(m2.template replicate<3,1>()));
+
+ vx1=m2+(m2.colwise().replicate(1));
+
+ if(m2.cols()==1)
+ VERIFY_IS_APPROX(m2.coeff(0), (m2.template replicate<3,1>().coeff(m2.rows())));
x2.resize(rows,f1);
for (int j=0; j<f1; ++j)
diff --git a/test/array_reverse.cpp b/test/array_reverse.cpp
index fbe7a9901..c9d9f90c3 100644
--- a/test/array_reverse.cpp
+++ b/test/array_reverse.cpp
@@ -24,7 +24,7 @@ template<typename MatrixType> void reverse(const MatrixType& m)
// this test relies a lot on Random.h, and there's not much more that we can do
// to test it, hence I consider that we will have tested Random.h
- MatrixType m1 = MatrixType::Random(rows, cols);
+ MatrixType m1 = MatrixType::Random(rows, cols), m2;
VectorType v1 = VectorType::Random(rows);
MatrixType m1_r = m1.reverse();
@@ -96,14 +96,32 @@ template<typename MatrixType> void reverse(const MatrixType& m)
m1.reverse()(r, c) = x;
VERIFY_IS_APPROX(x, m1(rows - 1 - r, cols - 1 - c));
+
+ m2 = m1;
+ m2.reverseInPlace();
+ VERIFY_IS_APPROX(m2,m1.reverse().eval());
+
+ m2 = m1;
+ m2.col(0).reverseInPlace();
+ VERIFY_IS_APPROX(m2.col(0),m1.col(0).reverse().eval());
+
+ m2 = m1;
+ m2.row(0).reverseInPlace();
+ VERIFY_IS_APPROX(m2.row(0),m1.row(0).reverse().eval());
+
+ m2 = m1;
+ m2.rowwise().reverseInPlace();
+ VERIFY_IS_APPROX(m2,m1.rowwise().reverse().eval());
+
+ m2 = m1;
+ m2.colwise().reverseInPlace();
+ VERIFY_IS_APPROX(m2,m1.colwise().reverse().eval());
- /*
m1.colwise().reverse()(r, c) = x;
VERIFY_IS_APPROX(x, m1(rows - 1 - r, c));
m1.rowwise().reverse()(r, c) = x;
VERIFY_IS_APPROX(x, m1(r, cols - 1 - c));
- */
}
void test_array_reverse()
@@ -113,11 +131,11 @@ void test_array_reverse()
CALL_SUBTEST_2( reverse(Matrix2f()) );
CALL_SUBTEST_3( reverse(Matrix4f()) );
CALL_SUBTEST_4( reverse(Matrix4d()) );
- CALL_SUBTEST_5( reverse(MatrixXcf(3, 3)) );
- CALL_SUBTEST_6( reverse(MatrixXi(6, 3)) );
- CALL_SUBTEST_7( reverse(MatrixXcd(20, 20)) );
+ CALL_SUBTEST_5( reverse(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+ CALL_SUBTEST_6( reverse(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+ CALL_SUBTEST_7( reverse(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
CALL_SUBTEST_8( reverse(Matrix<float, 100, 100>()) );
- CALL_SUBTEST_9( reverse(Matrix<float,Dynamic,Dynamic,RowMajor>(6,3)) );
+ CALL_SUBTEST_9( reverse(Matrix<float,Dynamic,Dynamic,RowMajor>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
}
#ifdef EIGEN_TEST_PART_3
Vector4f x; x << 1, 2, 3, 4;
diff --git a/test/bandmatrix.cpp b/test/bandmatrix.cpp
index 5e4e8e07b..f8c38f7c3 100644
--- a/test/bandmatrix.cpp
+++ b/test/bandmatrix.cpp
@@ -11,7 +11,6 @@
template<typename MatrixType> void bandmatrix(const MatrixType& _m)
{
- typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrixType;
@@ -62,8 +61,6 @@ using Eigen::internal::BandMatrix;
void test_bandmatrix()
{
- typedef BandMatrix<float>::Index Index;
-
for(int i = 0; i < 10*g_repeat ; i++) {
Index rows = internal::random<Index>(1,10);
Index cols = internal::random<Index>(1,10);
diff --git a/test/basicstuff.cpp b/test/basicstuff.cpp
index 8c0621ecd..99d91f9da 100644
--- a/test/basicstuff.cpp
+++ b/test/basicstuff.cpp
@@ -126,6 +126,20 @@ template<typename MatrixType> void basicStuff(const MatrixType& m)
for(typename MatrixType::Index i=0;i<rows;++i)
sm2.col(i).noalias() -= sm1.row(i);
VERIFY_IS_APPROX(sm2,-sm1.transpose());
+
+ // check ternary usage
+ {
+ bool b = internal::random<int>(0,10)>5;
+ m3 = b ? m1 : m2;
+ if(b) VERIFY_IS_APPROX(m3,m1);
+ else VERIFY_IS_APPROX(m3,m2);
+ m3 = b ? -m1 : m2;
+ if(b) VERIFY_IS_APPROX(m3,-m1);
+ else VERIFY_IS_APPROX(m3,m2);
+ m3 = b ? m1 : -m2;
+ if(b) VERIFY_IS_APPROX(m3,m1);
+ else VERIFY_IS_APPROX(m3,-m2);
+ }
}
template<typename MatrixType> void basicStuffComplex(const MatrixType& m)
@@ -180,15 +194,64 @@ void casting()
template <typename Scalar>
void fixedSizeMatrixConstruction()
{
- const Scalar raw[3] = {1,2,3};
- Matrix<Scalar,3,1> m(raw);
- Array<Scalar,3,1> a(raw);
- VERIFY(m(0) == 1);
- VERIFY(m(1) == 2);
- VERIFY(m(2) == 3);
- VERIFY(a(0) == 1);
- VERIFY(a(1) == 2);
- VERIFY(a(2) == 3);
+ Scalar raw[4];
+ for(int k=0; k<4; ++k)
+ raw[k] = internal::random<Scalar>();
+
+ {
+ Matrix<Scalar,4,1> m(raw);
+ Array<Scalar,4,1> a(raw);
+ for(int k=0; k<4; ++k) VERIFY(m(k) == raw[k]);
+ for(int k=0; k<4; ++k) VERIFY(a(k) == raw[k]);
+ VERIFY_IS_EQUAL(m,(Matrix<Scalar,4,1>(raw[0],raw[1],raw[2],raw[3])));
+ VERIFY((a==(Array<Scalar,4,1>(raw[0],raw[1],raw[2],raw[3]))).all());
+ }
+ {
+ Matrix<Scalar,3,1> m(raw);
+ Array<Scalar,3,1> a(raw);
+ for(int k=0; k<3; ++k) VERIFY(m(k) == raw[k]);
+ for(int k=0; k<3; ++k) VERIFY(a(k) == raw[k]);
+ VERIFY_IS_EQUAL(m,(Matrix<Scalar,3,1>(raw[0],raw[1],raw[2])));
+ VERIFY((a==Array<Scalar,3,1>(raw[0],raw[1],raw[2])).all());
+ }
+ {
+ Matrix<Scalar,2,1> m(raw), m2( (DenseIndex(raw[0])), (DenseIndex(raw[1])) );
+ Array<Scalar,2,1> a(raw), a2( (DenseIndex(raw[0])), (DenseIndex(raw[1])) );
+ for(int k=0; k<2; ++k) VERIFY(m(k) == raw[k]);
+ for(int k=0; k<2; ++k) VERIFY(a(k) == raw[k]);
+ VERIFY_IS_EQUAL(m,(Matrix<Scalar,2,1>(raw[0],raw[1])));
+ VERIFY((a==Array<Scalar,2,1>(raw[0],raw[1])).all());
+ for(int k=0; k<2; ++k) VERIFY(m2(k) == DenseIndex(raw[k]));
+ for(int k=0; k<2; ++k) VERIFY(a2(k) == DenseIndex(raw[k]));
+ }
+ {
+ Matrix<Scalar,1,2> m(raw),
+ m2( (DenseIndex(raw[0])), (DenseIndex(raw[1])) ),
+ m3( (int(raw[0])), (int(raw[1])) ),
+ m4( (float(raw[0])), (float(raw[1])) );
+ Array<Scalar,1,2> a(raw), a2( (DenseIndex(raw[0])), (DenseIndex(raw[1])) );
+ for(int k=0; k<2; ++k) VERIFY(m(k) == raw[k]);
+ for(int k=0; k<2; ++k) VERIFY(a(k) == raw[k]);
+ VERIFY_IS_EQUAL(m,(Matrix<Scalar,1,2>(raw[0],raw[1])));
+ VERIFY((a==Array<Scalar,1,2>(raw[0],raw[1])).all());
+ for(int k=0; k<2; ++k) VERIFY(m2(k) == DenseIndex(raw[k]));
+ for(int k=0; k<2; ++k) VERIFY(a2(k) == DenseIndex(raw[k]));
+ for(int k=0; k<2; ++k) VERIFY(m3(k) == int(raw[k]));
+ for(int k=0; k<2; ++k) VERIFY((m4(k)) == Scalar(float(raw[k])));
+ }
+ {
+ Matrix<Scalar,1,1> m(raw), m1(raw[0]), m2( (DenseIndex(raw[0])) ), m3( (int(raw[0])) );
+ Array<Scalar,1,1> a(raw), a1(raw[0]), a2( (DenseIndex(raw[0])) );
+ VERIFY(m(0) == raw[0]);
+ VERIFY(a(0) == raw[0]);
+ VERIFY(m1(0) == raw[0]);
+ VERIFY(a1(0) == raw[0]);
+ VERIFY(m2(0) == DenseIndex(raw[0]));
+ VERIFY(a2(0) == DenseIndex(raw[0]));
+ VERIFY(m3(0) == int(raw[0]));
+ VERIFY_IS_EQUAL(m,(Matrix<Scalar,1,1>(raw[0])));
+ VERIFY((a==Array<Scalar,1,1>(raw[0])).all());
+ }
}
void test_basicstuff()
@@ -207,8 +270,11 @@ void test_basicstuff()
}
CALL_SUBTEST_1(fixedSizeMatrixConstruction<unsigned char>());
+ CALL_SUBTEST_1(fixedSizeMatrixConstruction<float>());
CALL_SUBTEST_1(fixedSizeMatrixConstruction<double>());
- CALL_SUBTEST_1(fixedSizeMatrixConstruction<double>());
+ CALL_SUBTEST_1(fixedSizeMatrixConstruction<int>());
+ CALL_SUBTEST_1(fixedSizeMatrixConstruction<long int>());
+ CALL_SUBTEST_1(fixedSizeMatrixConstruction<std::ptrdiff_t>());
CALL_SUBTEST_2(casting());
}
diff --git a/test/bdcsvd.cpp b/test/bdcsvd.cpp
new file mode 100644
index 000000000..f9f687aac
--- /dev/null
+++ b/test/bdcsvd.cpp
@@ -0,0 +1,111 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2013 Gauthier Brun <brun.gauthier@gmail.com>
+// Copyright (C) 2013 Nicolas Carre <nicolas.carre@ensimag.fr>
+// Copyright (C) 2013 Jean Ceccato <jean.ceccato@ensimag.fr>
+// Copyright (C) 2013 Pierre Zoppitelli <pierre.zoppitelli@ensimag.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/
+
+// discard stack allocation as that too bypasses malloc
+#define EIGEN_STACK_ALLOCATION_LIMIT 0
+#define EIGEN_RUNTIME_NO_MALLOC
+
+#include "main.h"
+#include <Eigen/SVD>
+#include <iostream>
+#include <Eigen/LU>
+
+
+#define SVD_DEFAULT(M) BDCSVD<M>
+#define SVD_FOR_MIN_NORM(M) BDCSVD<M>
+#include "svd_common.h"
+
+// Check all variants of JacobiSVD
+template<typename MatrixType>
+void bdcsvd(const MatrixType& a = MatrixType(), bool pickrandom = true)
+{
+ MatrixType m = a;
+ if(pickrandom)
+ svd_fill_random(m);
+
+ CALL_SUBTEST(( svd_test_all_computation_options<BDCSVD<MatrixType> >(m, false) ));
+}
+
+template<typename MatrixType>
+void bdcsvd_method()
+{
+ enum { Size = MatrixType::RowsAtCompileTime };
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef Matrix<RealScalar, Size, 1> RealVecType;
+ MatrixType m = MatrixType::Identity();
+ VERIFY_IS_APPROX(m.bdcSvd().singularValues(), RealVecType::Ones());
+ VERIFY_RAISES_ASSERT(m.bdcSvd().matrixU());
+ VERIFY_RAISES_ASSERT(m.bdcSvd().matrixV());
+ VERIFY_IS_APPROX(m.bdcSvd(ComputeFullU|ComputeFullV).solve(m), m);
+}
+
+// compare the Singular values returned with Jacobi and Bdc
+template<typename MatrixType>
+void compare_bdc_jacobi(const MatrixType& a = MatrixType(), unsigned int computationOptions = 0)
+{
+ MatrixType m = MatrixType::Random(a.rows(), a.cols());
+ BDCSVD<MatrixType> bdc_svd(m);
+ JacobiSVD<MatrixType> jacobi_svd(m);
+ VERIFY_IS_APPROX(bdc_svd.singularValues(), jacobi_svd.singularValues());
+ if(computationOptions & ComputeFullU) VERIFY_IS_APPROX(bdc_svd.matrixU(), jacobi_svd.matrixU());
+ if(computationOptions & ComputeThinU) VERIFY_IS_APPROX(bdc_svd.matrixU(), jacobi_svd.matrixU());
+ if(computationOptions & ComputeFullV) VERIFY_IS_APPROX(bdc_svd.matrixV(), jacobi_svd.matrixV());
+ if(computationOptions & ComputeThinV) VERIFY_IS_APPROX(bdc_svd.matrixV(), jacobi_svd.matrixV());
+}
+
+void test_bdcsvd()
+{
+ CALL_SUBTEST_3(( svd_verify_assert<BDCSVD<Matrix3f> >(Matrix3f()) ));
+ CALL_SUBTEST_4(( svd_verify_assert<BDCSVD<Matrix4d> >(Matrix4d()) ));
+ CALL_SUBTEST_7(( svd_verify_assert<BDCSVD<MatrixXf> >(MatrixXf(10,12)) ));
+ CALL_SUBTEST_8(( svd_verify_assert<BDCSVD<MatrixXcd> >(MatrixXcd(7,5)) ));
+
+ CALL_SUBTEST_101(( svd_all_trivial_2x2(bdcsvd<Matrix2cd>) ));
+ CALL_SUBTEST_102(( svd_all_trivial_2x2(bdcsvd<Matrix2d>) ));
+
+ for(int i = 0; i < g_repeat; i++) {
+ CALL_SUBTEST_3(( bdcsvd<Matrix3f>() ));
+ CALL_SUBTEST_4(( bdcsvd<Matrix4d>() ));
+ CALL_SUBTEST_5(( bdcsvd<Matrix<float,3,5> >() ));
+
+ int r = internal::random<int>(1, EIGEN_TEST_MAX_SIZE/2),
+ c = internal::random<int>(1, EIGEN_TEST_MAX_SIZE/2);
+
+ TEST_SET_BUT_UNUSED_VARIABLE(r)
+ TEST_SET_BUT_UNUSED_VARIABLE(c)
+
+ CALL_SUBTEST_6(( bdcsvd(Matrix<double,Dynamic,2>(r,2)) ));
+ CALL_SUBTEST_7(( bdcsvd(MatrixXf(r,c)) ));
+ CALL_SUBTEST_7(( compare_bdc_jacobi(MatrixXf(r,c)) ));
+ CALL_SUBTEST_10(( bdcsvd(MatrixXd(r,c)) ));
+ CALL_SUBTEST_10(( compare_bdc_jacobi(MatrixXd(r,c)) ));
+ CALL_SUBTEST_8(( bdcsvd(MatrixXcd(r,c)) ));
+ CALL_SUBTEST_8(( compare_bdc_jacobi(MatrixXcd(r,c)) ));
+
+ // Test on inf/nan matrix
+ CALL_SUBTEST_7( (svd_inf_nan<BDCSVD<MatrixXf>, MatrixXf>()) );
+ CALL_SUBTEST_10( (svd_inf_nan<BDCSVD<MatrixXd>, MatrixXd>()) );
+ }
+
+ // test matrixbase method
+ CALL_SUBTEST_1(( bdcsvd_method<Matrix2cd>() ));
+ CALL_SUBTEST_3(( bdcsvd_method<Matrix3f>() ));
+
+ // Test problem size constructors
+ CALL_SUBTEST_7( BDCSVD<MatrixXf>(10,10) );
+
+ // Check that preallocation avoids subsequent mallocs
+ CALL_SUBTEST_9( svd_preallocate<void>() );
+
+ CALL_SUBTEST_2( svd_underoverflow<void>() );
+}
+
diff --git a/test/bicgstab.cpp b/test/bicgstab.cpp
index f327e2fac..4cc0dd31c 100644
--- a/test/bicgstab.cpp
+++ b/test/bicgstab.cpp
@@ -10,13 +10,16 @@
#include "sparse_solver.h"
#include <Eigen/IterativeLinearSolvers>
-template<typename T> void test_bicgstab_T()
+template<typename T, typename I> void test_bicgstab_T()
{
- BiCGSTAB<SparseMatrix<T>, DiagonalPreconditioner<T> > bicgstab_colmajor_diag;
- BiCGSTAB<SparseMatrix<T>, IdentityPreconditioner > bicgstab_colmajor_I;
- BiCGSTAB<SparseMatrix<T>, IncompleteLUT<T> > bicgstab_colmajor_ilut;
+ BiCGSTAB<SparseMatrix<T,0,I>, DiagonalPreconditioner<T> > bicgstab_colmajor_diag;
+ BiCGSTAB<SparseMatrix<T,0,I>, IdentityPreconditioner > bicgstab_colmajor_I;
+ BiCGSTAB<SparseMatrix<T,0,I>, IncompleteLUT<T,I> > bicgstab_colmajor_ilut;
//BiCGSTAB<SparseMatrix<T>, SSORPreconditioner<T> > bicgstab_colmajor_ssor;
+ bicgstab_colmajor_diag.setTolerance(NumTraits<T>::epsilon()*4);
+ bicgstab_colmajor_ilut.setTolerance(NumTraits<T>::epsilon()*4);
+
CALL_SUBTEST( check_sparse_square_solving(bicgstab_colmajor_diag) );
// CALL_SUBTEST( check_sparse_square_solving(bicgstab_colmajor_I) );
CALL_SUBTEST( check_sparse_square_solving(bicgstab_colmajor_ilut) );
@@ -25,6 +28,7 @@ template<typename T> void test_bicgstab_T()
void test_bicgstab()
{
- CALL_SUBTEST_1(test_bicgstab_T<double>());
- CALL_SUBTEST_2(test_bicgstab_T<std::complex<double> >());
+ CALL_SUBTEST_1((test_bicgstab_T<double,int>()) );
+ CALL_SUBTEST_2((test_bicgstab_T<std::complex<double>, int>()));
+ CALL_SUBTEST_3((test_bicgstab_T<double,long int>()));
}
diff --git a/test/block.cpp b/test/block.cpp
index 9ed5d7bc5..39565af83 100644
--- a/test/block.cpp
+++ b/test/block.cpp
@@ -130,6 +130,14 @@ template<typename MatrixType> void block(const MatrixType& m)
VERIFY(numext::real(ones.col(c1).dot(ones.col(c2))) == RealScalar(rows));
VERIFY(numext::real(ones.row(r1).dot(ones.row(r2))) == RealScalar(cols));
+
+ // chekc that linear acccessors works on blocks
+ m1 = m1_copy;
+ if((MatrixType::Flags&RowMajorBit)==0)
+ VERIFY_IS_EQUAL(m1.leftCols(c1).coeff(r1+c1*rows), m1(r1,c1));
+ else
+ VERIFY_IS_EQUAL(m1.topRows(r1).coeff(c1+r1*cols), m1(r1,c1));
+
// now test some block-inside-of-block.
@@ -141,11 +149,11 @@ template<typename MatrixType> void block(const MatrixType& m)
VERIFY_IS_EQUAL( (m1.transpose().block(c1,r1,c2-c1+1,r2-r1+1).col(0)) , (m1.row(r1).segment(c1,c2-c1+1)).transpose() );
// expressions without direct access
- VERIFY_IS_EQUAL( ((m1+m2).block(r1,c1,rows-r1,cols-c1).block(r2-r1,c2-c1,rows-r2,cols-c2)) , ((m1+m2).block(r2,c2,rows-r2,cols-c2)) );
- VERIFY_IS_EQUAL( ((m1+m2).block(r1,c1,r2-r1+1,c2-c1+1).row(0)) , ((m1+m2).row(r1).segment(c1,c2-c1+1)) );
- VERIFY_IS_EQUAL( ((m1+m2).block(r1,c1,r2-r1+1,c2-c1+1).col(0)) , ((m1+m2).col(c1).segment(r1,r2-r1+1)) );
- VERIFY_IS_EQUAL( ((m1+m2).block(r1,c1,r2-r1+1,c2-c1+1).transpose().col(0)) , ((m1+m2).row(r1).segment(c1,c2-c1+1)).transpose() );
- VERIFY_IS_EQUAL( ((m1+m2).transpose().block(c1,r1,c2-c1+1,r2-r1+1).col(0)) , ((m1+m2).row(r1).segment(c1,c2-c1+1)).transpose() );
+ VERIFY_IS_APPROX( ((m1+m2).block(r1,c1,rows-r1,cols-c1).block(r2-r1,c2-c1,rows-r2,cols-c2)) , ((m1+m2).block(r2,c2,rows-r2,cols-c2)) );
+ VERIFY_IS_APPROX( ((m1+m2).block(r1,c1,r2-r1+1,c2-c1+1).row(0)) , ((m1+m2).row(r1).segment(c1,c2-c1+1)) );
+ VERIFY_IS_APPROX( ((m1+m2).block(r1,c1,r2-r1+1,c2-c1+1).col(0)) , ((m1+m2).col(c1).segment(r1,r2-r1+1)) );
+ VERIFY_IS_APPROX( ((m1+m2).block(r1,c1,r2-r1+1,c2-c1+1).transpose().col(0)) , ((m1+m2).row(r1).segment(c1,c2-c1+1)).transpose() );
+ VERIFY_IS_APPROX( ((m1+m2).transpose().block(c1,r1,c2-c1+1,r2-r1+1).col(0)) , ((m1+m2).row(r1).segment(c1,c2-c1+1)).transpose() );
// evaluation into plain matrices from expressions with direct access (stress MapBase)
DynamicMatrixType dm;
@@ -173,6 +181,19 @@ 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));
+
+ if (rows>=2 && cols>=2)
+ {
+ VERIFY_RAISES_ASSERT( m1 += m1.col(0) );
+ VERIFY_RAISES_ASSERT( m1 -= m1.col(0) );
+ VERIFY_RAISES_ASSERT( m1.array() *= m1.col(0).array() );
+ VERIFY_RAISES_ASSERT( m1.array() /= m1.col(0).array() );
+ }
}
diff --git a/test/boostmultiprec.cpp b/test/boostmultiprec.cpp
new file mode 100644
index 000000000..e06e9bdaf
--- /dev/null
+++ b/test/boostmultiprec.cpp
@@ -0,0 +1,201 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 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
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <sstream>
+
+#ifdef EIGEN_TEST_MAX_SIZE
+#undef EIGEN_TEST_MAX_SIZE
+#endif
+
+#define EIGEN_TEST_MAX_SIZE 50
+
+#ifdef EIGEN_TEST_PART_1
+#include "cholesky.cpp"
+#endif
+
+#ifdef EIGEN_TEST_PART_2
+#include "lu.cpp"
+#endif
+
+#ifdef EIGEN_TEST_PART_3
+#include "qr.cpp"
+#endif
+
+#ifdef EIGEN_TEST_PART_4
+#include "qr_colpivoting.cpp"
+#endif
+
+#ifdef EIGEN_TEST_PART_5
+#include "qr_fullpivoting.cpp"
+#endif
+
+#ifdef EIGEN_TEST_PART_6
+#include "eigensolver_selfadjoint.cpp"
+#endif
+
+#ifdef EIGEN_TEST_PART_7
+#include "eigensolver_generic.cpp"
+#endif
+
+#ifdef EIGEN_TEST_PART_8
+#include "eigensolver_generalized_real.cpp"
+#endif
+
+#ifdef EIGEN_TEST_PART_9
+#include "jacobisvd.cpp"
+#endif
+
+#ifdef EIGEN_TEST_PART_10
+#include "bdcsvd.cpp"
+#endif
+
+#include <Eigen/Dense>
+
+#undef min
+#undef max
+#undef isnan
+#undef isinf
+#undef isfinite
+
+#include <boost/multiprecision/cpp_dec_float.hpp>
+#include <boost/multiprecision/number.hpp>
+#include <boost/math/special_functions.hpp>
+#include <boost/math/complex.hpp>
+
+namespace mp = boost::multiprecision;
+typedef mp::number<mp::cpp_dec_float<100>, mp::et_on> Real;
+
+namespace Eigen {
+ template<> struct NumTraits<Real> : GenericNumTraits<Real> {
+ static inline Real dummy_precision() { return 1e-50; }
+ };
+
+ template<typename T1,typename T2,typename T3,typename T4,typename T5>
+ struct NumTraits<boost::multiprecision::detail::expression<T1,T2,T3,T4,T5> > : NumTraits<Real> {};
+
+ template<>
+ Real test_precision<Real>() { return 1e-50; }
+
+ // needed in C++93 mode where number does not support explicit cast.
+ namespace internal {
+ template<typename NewType>
+ struct cast_impl<Real,NewType> {
+ static inline NewType run(const Real& x) {
+ return x.template convert_to<NewType>();
+ }
+ };
+
+ template<>
+ struct cast_impl<Real,std::complex<Real> > {
+ static inline std::complex<Real> run(const Real& x) {
+ return std::complex<Real>(x);
+ }
+ };
+ }
+}
+
+namespace boost {
+namespace multiprecision {
+ // to make ADL works as expected:
+ using boost::math::isfinite;
+ using boost::math::isnan;
+ using boost::math::isinf;
+ using boost::math::copysign;
+ using boost::math::hypot;
+
+ // The following is needed for std::complex<Real>:
+ Real fabs(const Real& a) { return abs EIGEN_NOT_A_MACRO (a); }
+ Real fmax(const Real& a, const Real& b) { using std::max; return max(a,b); }
+
+ // some specialization for the unit tests:
+ inline bool test_isMuchSmallerThan(const Real& a, const Real& b) {
+ return internal::isMuchSmallerThan(a, b, test_precision<Real>());
+ }
+
+ inline bool test_isApprox(const Real& a, const Real& b) {
+ return internal::isApprox(a, b, test_precision<Real>());
+ }
+
+ inline bool test_isApproxOrLessThan(const Real& a, const Real& b) {
+ return internal::isApproxOrLessThan(a, b, test_precision<Real>());
+ }
+
+ Real get_test_precision(const Real&) {
+ return test_precision<Real>();
+ }
+
+ Real test_relative_error(const Real &a, const Real &b) {
+ using Eigen::numext::abs2;
+ return sqrt(abs2<Real>(a-b)/Eigen::numext::mini<Real>(abs2(a),abs2(b)));
+ }
+}
+}
+
+namespace Eigen {
+
+}
+
+void test_boostmultiprec()
+{
+ typedef Matrix<Real,Dynamic,Dynamic> Mat;
+ typedef Matrix<std::complex<Real>,Dynamic,Dynamic> MatC;
+
+ std::cout << "NumTraits<Real>::epsilon() = " << NumTraits<Real>::epsilon() << std::endl;
+ std::cout << "NumTraits<Real>::dummy_precision() = " << NumTraits<Real>::dummy_precision() << std::endl;
+ std::cout << "NumTraits<Real>::lowest() = " << NumTraits<Real>::lowest() << std::endl;
+ std::cout << "NumTraits<Real>::highest() = " << NumTraits<Real>::highest() << std::endl;
+ std::cout << "NumTraits<Real>::digits10() = " << NumTraits<Real>::digits10() << std::endl;
+
+ // chekc stream output
+ {
+ Mat A(10,10);
+ A.setRandom();
+ std::stringstream ss;
+ ss << A;
+ }
+ {
+ MatC A(10,10);
+ A.setRandom();
+ std::stringstream ss;
+ ss << A;
+ }
+
+ for(int i = 0; i < g_repeat; i++) {
+ int s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
+
+ CALL_SUBTEST_1( cholesky(Mat(s,s)) );
+
+ CALL_SUBTEST_2( lu_non_invertible<Mat>() );
+ CALL_SUBTEST_2( lu_invertible<Mat>() );
+ CALL_SUBTEST_2( lu_non_invertible<MatC>() );
+ CALL_SUBTEST_2( lu_invertible<MatC>() );
+
+ CALL_SUBTEST_3( qr(Mat(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+ CALL_SUBTEST_3( qr_invertible<Mat>() );
+
+ CALL_SUBTEST_4( qr<Mat>() );
+ CALL_SUBTEST_4( cod<Mat>() );
+ CALL_SUBTEST_4( qr_invertible<Mat>() );
+
+ CALL_SUBTEST_5( qr<Mat>() );
+ CALL_SUBTEST_5( qr_invertible<Mat>() );
+
+ CALL_SUBTEST_6( selfadjointeigensolver(Mat(s,s)) );
+
+ CALL_SUBTEST_7( eigensolver(Mat(s,s)) );
+
+ CALL_SUBTEST_8( generalized_eigensolver_real(Mat(s,s)) );
+
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
+ }
+
+ CALL_SUBTEST_9(( jacobisvd(Mat(internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE), internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/2))) ));
+ CALL_SUBTEST_10(( bdcsvd(Mat(internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE), internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/2))) ));
+}
+
diff --git a/test/bug1213.cpp b/test/bug1213.cpp
new file mode 100644
index 000000000..581760c1a
--- /dev/null
+++ b/test/bug1213.cpp
@@ -0,0 +1,13 @@
+
+// This anonymous enum is essential to trigger the linking issue
+enum {
+ Foo
+};
+
+#include "bug1213.h"
+
+bool bug1213_1(const Eigen::Vector3f& x)
+{
+ return bug1213_2(x);
+}
+
diff --git a/test/bug1213.h b/test/bug1213.h
new file mode 100644
index 000000000..040e5a470
--- /dev/null
+++ b/test/bug1213.h
@@ -0,0 +1,8 @@
+
+#include <Eigen/Core>
+
+template<typename T, int dim>
+bool bug1213_2(const Eigen::Matrix<T,dim,1>& x);
+
+bool bug1213_1(const Eigen::Vector3f& x);
+
diff --git a/test/bug1213_main.cpp b/test/bug1213_main.cpp
new file mode 100644
index 000000000..4802c0003
--- /dev/null
+++ b/test/bug1213_main.cpp
@@ -0,0 +1,18 @@
+
+// This is a regression unit regarding a weird linking issue with gcc.
+
+#include "bug1213.h"
+
+int main()
+{
+ return 0;
+}
+
+
+template<typename T, int dim>
+bool bug1213_2(const Eigen::Matrix<T,dim,1>& )
+{
+ return true;
+}
+
+template bool bug1213_2<float,3>(const Eigen::Vector3f&);
diff --git a/test/cholesky.cpp b/test/cholesky.cpp
index 56885deb7..8ad5ac639 100644
--- a/test/cholesky.cpp
+++ b/test/cholesky.cpp
@@ -11,20 +11,17 @@
#define EIGEN_NO_ASSERTION_CHECKING
#endif
-static int nb_temporaries;
-
-#define EIGEN_DENSE_STORAGE_CTOR_PLUGIN { if(size!=0) nb_temporaries++; }
+#define TEST_ENABLE_TEMPORARY_TRACKING
#include "main.h"
#include <Eigen/Cholesky>
#include <Eigen/QR>
-#define VERIFY_EVALUATION_COUNT(XPR,N) {\
- nb_temporaries = 0; \
- XPR; \
- if(nb_temporaries!=N) std::cerr << "nb_temporaries == " << nb_temporaries << "\n"; \
- VERIFY( (#XPR) && nb_temporaries==N ); \
- }
+template<typename MatrixType, int UpLo>
+typename MatrixType::RealScalar matrix_l1_norm(const MatrixType& m) {
+ MatrixType symm = m.template selfadjointView<UpLo>();
+ return symm.cwiseAbs().colwise().sum().maxCoeff();
+}
template<typename MatrixType,template <typename,int> class CholType> void test_chol_update(const MatrixType& symm)
{
@@ -83,14 +80,10 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
symm += a1 * a1.adjoint();
}
- // to test if really Cholesky only uses the upper triangular part, uncomment the following
- // FIXME: currently that fails !!
- //symm.template part<StrictlyLower>().setZero();
-
{
SquareMatrixType symmUp = symm.template triangularView<Upper>();
SquareMatrixType symmLo = symm.template triangularView<Lower>();
-
+
LLT<SquareMatrixType,Lower> chollo(symmLo);
VERIFY_IS_APPROX(symm, chollo.reconstructedMatrix());
vecX = chollo.solve(vecB);
@@ -98,6 +91,14 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
matX = chollo.solve(matB);
VERIFY_IS_APPROX(symm * matX, matB);
+ const MatrixType symmLo_inverse = chollo.solve(MatrixType::Identity(rows,cols));
+ RealScalar rcond = (RealScalar(1) / matrix_l1_norm<MatrixType, Lower>(symmLo)) /
+ matrix_l1_norm<MatrixType, Lower>(symmLo_inverse);
+ RealScalar rcond_est = chollo.rcond();
+ // Verify that the estimated condition number is within a factor of 10 of the
+ // truth.
+ VERIFY(rcond_est > rcond / 10 && rcond_est < rcond * 10);
+
// test the upper mode
LLT<SquareMatrixType,Upper> cholup(symmUp);
VERIFY_IS_APPROX(symm, cholup.reconstructedMatrix());
@@ -106,6 +107,15 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
matX = cholup.solve(matB);
VERIFY_IS_APPROX(symm * matX, matB);
+ // Verify that the estimated condition number is within a factor of 10 of the
+ // truth.
+ const MatrixType symmUp_inverse = cholup.solve(MatrixType::Identity(rows,cols));
+ rcond = (RealScalar(1) / matrix_l1_norm<MatrixType, Upper>(symmUp)) /
+ matrix_l1_norm<MatrixType, Upper>(symmUp_inverse);
+ rcond_est = cholup.rcond();
+ VERIFY(rcond_est > rcond / 10 && rcond_est < rcond * 10);
+
+
MatrixType neg = -symmLo;
chollo.compute(neg);
VERIFY(chollo.info()==NumericalIssue);
@@ -114,7 +124,7 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
VERIFY_IS_APPROX(MatrixType(chollo.matrixU().transpose().conjugate()), MatrixType(chollo.matrixL()));
VERIFY_IS_APPROX(MatrixType(cholup.matrixL().transpose().conjugate()), MatrixType(cholup.matrixU()));
VERIFY_IS_APPROX(MatrixType(cholup.matrixU().transpose().conjugate()), MatrixType(cholup.matrixL()));
-
+
// test some special use cases of SelfCwiseBinaryOp:
MatrixType m1 = MatrixType::Random(rows,cols), m2(rows,cols);
m2 = m1;
@@ -144,19 +154,38 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
SquareMatrixType symmLo = symm.template triangularView<Lower>();
LDLT<SquareMatrixType,Lower> ldltlo(symmLo);
+ VERIFY(ldltlo.info()==Success);
VERIFY_IS_APPROX(symm, ldltlo.reconstructedMatrix());
vecX = ldltlo.solve(vecB);
VERIFY_IS_APPROX(symm * vecX, vecB);
matX = ldltlo.solve(matB);
VERIFY_IS_APPROX(symm * matX, matB);
+ const MatrixType symmLo_inverse = ldltlo.solve(MatrixType::Identity(rows,cols));
+ RealScalar rcond = (RealScalar(1) / matrix_l1_norm<MatrixType, Lower>(symmLo)) /
+ matrix_l1_norm<MatrixType, Lower>(symmLo_inverse);
+ RealScalar rcond_est = ldltlo.rcond();
+ // Verify that the estimated condition number is within a factor of 10 of the
+ // truth.
+ VERIFY(rcond_est > rcond / 10 && rcond_est < rcond * 10);
+
+
LDLT<SquareMatrixType,Upper> ldltup(symmUp);
+ VERIFY(ldltup.info()==Success);
VERIFY_IS_APPROX(symm, ldltup.reconstructedMatrix());
vecX = ldltup.solve(vecB);
VERIFY_IS_APPROX(symm * vecX, vecB);
matX = ldltup.solve(matB);
VERIFY_IS_APPROX(symm * matX, matB);
+ // Verify that the estimated condition number is within a factor of 10 of the
+ // truth.
+ const MatrixType symmUp_inverse = ldltup.solve(MatrixType::Identity(rows,cols));
+ rcond = (RealScalar(1) / matrix_l1_norm<MatrixType, Upper>(symmUp)) /
+ matrix_l1_norm<MatrixType, Upper>(symmUp_inverse);
+ rcond_est = ldltup.rcond();
+ VERIFY(rcond_est > rcond / 10 && rcond_est < rcond * 10);
+
VERIFY_IS_APPROX(MatrixType(ldltlo.matrixL().transpose().conjugate()), MatrixType(ldltlo.matrixU()));
VERIFY_IS_APPROX(MatrixType(ldltlo.matrixU().transpose().conjugate()), MatrixType(ldltlo.matrixL()));
VERIFY_IS_APPROX(MatrixType(ldltup.matrixL().transpose().conjugate()), MatrixType(ldltup.matrixU()));
@@ -185,7 +214,7 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
if(rows>=3)
{
SquareMatrixType A = symm;
- int c = internal::random<int>(0,rows-2);
+ Index c = internal::random<Index>(0,rows-2);
A.bottomRightCorner(c,c).setZero();
// Make sure a solution exists:
vecX.setRandom();
@@ -196,11 +225,11 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
vecX = ldltlo.solve(vecB);
VERIFY_IS_APPROX(A * vecX, vecB);
}
-
+
// check non-full rank matrices
if(rows>=3)
{
- int r = internal::random<int>(1,rows-1);
+ Index r = internal::random<Index>(1,rows-1);
Matrix<Scalar,Dynamic,Dynamic> a = Matrix<Scalar,Dynamic,Dynamic>::Random(rows,r);
SquareMatrixType A = a * a.adjoint();
// Make sure a solution exists:
@@ -212,15 +241,17 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
vecX = ldltlo.solve(vecB);
VERIFY_IS_APPROX(A * vecX, vecB);
}
-
+
// check matrices with a wide spectrum
if(rows>=3)
{
+ using std::pow;
+ using std::sqrt;
RealScalar s = (std::min)(16,std::numeric_limits<RealScalar>::max_exponent10/8);
Matrix<Scalar,Dynamic,Dynamic> a = Matrix<Scalar,Dynamic,Dynamic>::Random(rows,rows);
Matrix<RealScalar,Dynamic,1> d = Matrix<RealScalar,Dynamic,1>::Random(rows);
- for(int k=0; k<rows; ++k)
- d(k) = d(k)*std::pow(RealScalar(10),internal::random<RealScalar>(-s,s));
+ for(Index k=0; k<rows; ++k)
+ d(k) = d(k)*pow(RealScalar(10),internal::random<RealScalar>(-s,s));
SquareMatrixType A = a * d.asDiagonal() * a.adjoint();
// Make sure a solution exists:
vecX.setRandom();
@@ -229,7 +260,20 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
ldltlo.compute(A);
VERIFY_IS_APPROX(A, ldltlo.reconstructedMatrix());
vecX = ldltlo.solve(vecB);
- VERIFY_IS_APPROX(A * vecX, vecB);
+
+ if(ldltlo.vectorD().real().cwiseAbs().minCoeff()>RealScalar(0))
+ {
+ VERIFY_IS_APPROX(A * vecX,vecB);
+ }
+ else
+ {
+ RealScalar large_tol = sqrt(test_precision<RealScalar>());
+ VERIFY((A * vecX).isApprox(vecB, large_tol));
+
+ ++g_test_level;
+ VERIFY_IS_APPROX(A * vecX,vecB);
+ --g_test_level;
+ }
}
}
@@ -289,6 +333,7 @@ template<typename MatrixType> void cholesky_cplx(const MatrixType& m)
RealMatrixType symmLo = symm.template triangularView<Lower>();
LDLT<RealMatrixType,Lower> ldltlo(symmLo);
+ VERIFY(ldltlo.info()==Success);
VERIFY_IS_APPROX(symm, ldltlo.reconstructedMatrix());
vecX = ldltlo.solve(vecB);
VERIFY_IS_APPROX(symm * vecX, vecB);
@@ -314,46 +359,101 @@ template<typename MatrixType> void cholesky_bug241(const MatrixType& m)
}
// LDLT is not guaranteed to work for indefinite matrices, but happens to work fine if matrix is diagonal.
-// This test checks that LDLT reports correctly that matrix is indefinite.
+// This test checks that LDLT reports correctly that matrix is indefinite.
// See http://forum.kde.org/viewtopic.php?f=74&t=106942 and bug 736
template<typename MatrixType> void cholesky_definiteness(const MatrixType& m)
{
eigen_assert(m.rows() == 2 && m.cols() == 2);
MatrixType mat;
LDLT<MatrixType> ldlt(2);
-
+
{
mat << 1, 0, 0, -1;
ldlt.compute(mat);
+ VERIFY(ldlt.info()==Success);
VERIFY(!ldlt.isNegative());
VERIFY(!ldlt.isPositive());
}
{
mat << 1, 2, 2, 1;
ldlt.compute(mat);
+ VERIFY(ldlt.info()==Success);
VERIFY(!ldlt.isNegative());
VERIFY(!ldlt.isPositive());
}
{
mat << 0, 0, 0, 0;
ldlt.compute(mat);
+ VERIFY(ldlt.info()==Success);
VERIFY(ldlt.isNegative());
VERIFY(ldlt.isPositive());
}
{
mat << 0, 0, 0, 1;
ldlt.compute(mat);
+ VERIFY(ldlt.info()==Success);
VERIFY(!ldlt.isNegative());
VERIFY(ldlt.isPositive());
}
{
mat << -1, 0, 0, 0;
ldlt.compute(mat);
+ VERIFY(ldlt.info()==Success);
VERIFY(ldlt.isNegative());
VERIFY(!ldlt.isPositive());
}
}
+template<typename>
+void cholesky_faillure_cases()
+{
+ MatrixXd mat;
+ LDLT<MatrixXd> ldlt;
+
+ {
+ mat.resize(2,2);
+ mat << 0, 1, 1, 0;
+ ldlt.compute(mat);
+ VERIFY_IS_NOT_APPROX(mat,ldlt.reconstructedMatrix());
+ VERIFY(ldlt.info()==NumericalIssue);
+ }
+#if (!EIGEN_ARCH_i386) || defined(EIGEN_VECTORIZE_SSE2)
+ {
+ mat.resize(3,3);
+ mat << -1, -3, 3,
+ -3, -8.9999999999999999999, 1,
+ 3, 1, 0;
+ ldlt.compute(mat);
+ VERIFY(ldlt.info()==NumericalIssue);
+ VERIFY_IS_NOT_APPROX(mat,ldlt.reconstructedMatrix());
+ }
+#endif
+ {
+ mat.resize(3,3);
+ mat << 1, 2, 3,
+ 2, 4, 1,
+ 3, 1, 0;
+ ldlt.compute(mat);
+ VERIFY(ldlt.info()==NumericalIssue);
+ VERIFY_IS_NOT_APPROX(mat,ldlt.reconstructedMatrix());
+ }
+
+ {
+ mat.resize(8,8);
+ mat << 0.1, 0, -0.1, 0, 0, 0, 1, 0,
+ 0, 4.24667, 0, 2.00333, 0, 0, 0, 0,
+ -0.1, 0, 0.2, 0, -0.1, 0, 0, 0,
+ 0, 2.00333, 0, 8.49333, 0, 2.00333, 0, 0,
+ 0, 0, -0.1, 0, 0.1, 0, 0, 1,
+ 0, 0, 0, 2.00333, 0, 4.24667, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0;
+ ldlt.compute(mat);
+ VERIFY(ldlt.info()==NumericalIssue);
+ VERIFY_IS_NOT_APPROX(mat,ldlt.reconstructedMatrix());
+ }
+}
+
template<typename MatrixType> void cholesky_verify_assert()
{
MatrixType tmp;
@@ -384,10 +484,14 @@ void test_cholesky()
CALL_SUBTEST_3( cholesky_definiteness(Matrix2d()) );
CALL_SUBTEST_4( cholesky(Matrix3f()) );
CALL_SUBTEST_5( cholesky(Matrix4d()) );
+
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
CALL_SUBTEST_2( cholesky(MatrixXd(s,s)) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
+
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
CALL_SUBTEST_6( cholesky_cplx(MatrixXcd(s,s)) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
}
CALL_SUBTEST_4( cholesky_verify_assert<Matrix3f>() );
@@ -398,7 +502,8 @@ void test_cholesky()
// Test problem size constructors
CALL_SUBTEST_9( LLT<MatrixXf>(10) );
CALL_SUBTEST_9( LDLT<MatrixXf>(10) );
-
- TEST_SET_BUT_UNUSED_VARIABLE(s)
+
+ CALL_SUBTEST_2( cholesky_faillure_cases<void>() );
+
TEST_SET_BUT_UNUSED_VARIABLE(nb_temporaries)
}
diff --git a/test/cholmod_support.cpp b/test/cholmod_support.cpp
index 8f8be3c0e..a7eda28f7 100644
--- a/test/cholmod_support.cpp
+++ b/test/cholmod_support.cpp
@@ -7,6 +7,7 @@
// 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/.
+#define EIGEN_NO_DEBUG_SMALL_PRODUCT_BLOCKS
#include "sparse_solver.h"
#include <Eigen/CholmodSupport>
@@ -40,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/commainitializer.cpp b/test/commainitializer.cpp
index 99102b966..9844adbd2 100644
--- a/test/commainitializer.cpp
+++ b/test/commainitializer.cpp
@@ -9,6 +9,62 @@
#include "main.h"
+
+template<int M1, int M2, int N1, int N2>
+void test_blocks()
+{
+ Matrix<int, M1+M2, N1+N2> m_fixed;
+ MatrixXi m_dynamic(M1+M2, N1+N2);
+
+ Matrix<int, M1, N1> mat11; mat11.setRandom();
+ Matrix<int, M1, N2> mat12; mat12.setRandom();
+ Matrix<int, M2, N1> mat21; mat21.setRandom();
+ Matrix<int, M2, N2> mat22; mat22.setRandom();
+
+ MatrixXi matx11 = mat11, matx12 = mat12, matx21 = mat21, matx22 = mat22;
+
+ {
+ VERIFY_IS_EQUAL((m_fixed << mat11, mat12, mat21, matx22).finished(), (m_dynamic << mat11, matx12, mat21, matx22).finished());
+ VERIFY_IS_EQUAL((m_fixed.template topLeftCorner<M1,N1>()), mat11);
+ VERIFY_IS_EQUAL((m_fixed.template topRightCorner<M1,N2>()), mat12);
+ VERIFY_IS_EQUAL((m_fixed.template bottomLeftCorner<M2,N1>()), mat21);
+ VERIFY_IS_EQUAL((m_fixed.template bottomRightCorner<M2,N2>()), mat22);
+ VERIFY_IS_EQUAL((m_fixed << mat12, mat11, matx21, mat22).finished(), (m_dynamic << mat12, matx11, matx21, mat22).finished());
+ }
+
+ if(N1 > 0)
+ {
+ VERIFY_RAISES_ASSERT((m_fixed << mat11, mat12, mat11, mat21, mat22));
+ VERIFY_RAISES_ASSERT((m_fixed << mat11, mat12, mat21, mat21, mat22));
+ }
+ else
+ {
+ // allow insertion of zero-column blocks:
+ VERIFY_IS_EQUAL((m_fixed << mat11, mat12, mat11, mat11, mat21, mat21, mat22).finished(), (m_dynamic << mat12, mat22).finished());
+ }
+ if(M1 != M2)
+ {
+ VERIFY_RAISES_ASSERT((m_fixed << mat11, mat21, mat12, mat22));
+ }
+}
+
+
+template<int N>
+struct test_block_recursion
+{
+ static void run()
+ {
+ test_blocks<(N>>6)&3, (N>>4)&3, (N>>2)&3, N & 3>();
+ test_block_recursion<N-1>::run();
+ }
+};
+
+template<>
+struct test_block_recursion<-1>
+{
+ static void run() { }
+};
+
void test_commainitializer()
{
Matrix3d m3;
@@ -43,4 +99,8 @@ void test_commainitializer()
4, 5, 6,
vec[2].transpose();
VERIFY_IS_APPROX(m3, ref);
+
+
+ // recursively test all block-sizes from 0 to 3:
+ test_block_recursion<(1<<8) - 1>();
}
diff --git a/test/conjugate_gradient.cpp b/test/conjugate_gradient.cpp
index 019cc4d64..9622fd86d 100644
--- a/test/conjugate_gradient.cpp
+++ b/test/conjugate_gradient.cpp
@@ -10,13 +10,14 @@
#include "sparse_solver.h"
#include <Eigen/IterativeLinearSolvers>
-template<typename T> void test_conjugate_gradient_T()
+template<typename T, typename I> void test_conjugate_gradient_T()
{
- ConjugateGradient<SparseMatrix<T>, Lower > cg_colmajor_lower_diag;
- ConjugateGradient<SparseMatrix<T>, Upper > cg_colmajor_upper_diag;
- ConjugateGradient<SparseMatrix<T>, Lower|Upper> cg_colmajor_loup_diag;
- ConjugateGradient<SparseMatrix<T>, Lower, IdentityPreconditioner> cg_colmajor_lower_I;
- ConjugateGradient<SparseMatrix<T>, Upper, IdentityPreconditioner> cg_colmajor_upper_I;
+ typedef SparseMatrix<T,0,I> SparseMatrixType;
+ ConjugateGradient<SparseMatrixType, Lower > cg_colmajor_lower_diag;
+ ConjugateGradient<SparseMatrixType, Upper > cg_colmajor_upper_diag;
+ ConjugateGradient<SparseMatrixType, Lower|Upper> cg_colmajor_loup_diag;
+ ConjugateGradient<SparseMatrixType, Lower, IdentityPreconditioner> cg_colmajor_lower_I;
+ ConjugateGradient<SparseMatrixType, Upper, IdentityPreconditioner> cg_colmajor_upper_I;
CALL_SUBTEST( check_sparse_spd_solving(cg_colmajor_lower_diag) );
CALL_SUBTEST( check_sparse_spd_solving(cg_colmajor_upper_diag) );
@@ -27,6 +28,7 @@ template<typename T> void test_conjugate_gradient_T()
void test_conjugate_gradient()
{
- CALL_SUBTEST_1(test_conjugate_gradient_T<double>());
- CALL_SUBTEST_2(test_conjugate_gradient_T<std::complex<double> >());
+ CALL_SUBTEST_1(( test_conjugate_gradient_T<double,int>() ));
+ CALL_SUBTEST_2(( test_conjugate_gradient_T<std::complex<double>, int>() ));
+ CALL_SUBTEST_3(( test_conjugate_gradient_T<double,long int>() ));
}
diff --git a/test/constructor.cpp b/test/constructor.cpp
new file mode 100644
index 000000000..eec9e2192
--- /dev/null
+++ b/test/constructor.cpp
@@ -0,0 +1,84 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2017 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/.
+
+
+#define TEST_ENABLE_TEMPORARY_TRACKING
+
+#include "main.h"
+
+template<typename MatrixType> struct Wrapper
+{
+ MatrixType m_mat;
+ inline Wrapper(const MatrixType &x) : m_mat(x) {}
+ inline operator const MatrixType& () const { return m_mat; }
+ inline operator MatrixType& () { return m_mat; }
+};
+
+template<typename MatrixType> void ctor_init1(const MatrixType& m)
+{
+ // Check logic in PlainObjectBase::_init1
+ Index rows = m.rows();
+ Index cols = m.cols();
+
+ MatrixType m0 = MatrixType::Random(rows,cols);
+
+ VERIFY_EVALUATION_COUNT( MatrixType m1(m0), 1);
+ VERIFY_EVALUATION_COUNT( MatrixType m2(m0+m0), 1);
+ VERIFY_EVALUATION_COUNT( MatrixType m2(m0.block(0,0,rows,cols)) , 1);
+
+ Wrapper<MatrixType> wrapper(m0);
+ VERIFY_EVALUATION_COUNT( MatrixType m3(wrapper) , 1);
+}
+
+
+void test_constructor()
+{
+ for(int i = 0; i < g_repeat; i++) {
+ CALL_SUBTEST_1( ctor_init1(Matrix<float, 1, 1>()) );
+ CALL_SUBTEST_1( ctor_init1(Matrix4d()) );
+ CALL_SUBTEST_1( ctor_init1(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+ CALL_SUBTEST_1( ctor_init1(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+ }
+ {
+ Matrix<Index,1,1> a(123);
+ VERIFY_IS_EQUAL(a[0], 123);
+ }
+ {
+ Matrix<Index,1,1> a(123.0);
+ VERIFY_IS_EQUAL(a[0], 123);
+ }
+ {
+ Matrix<float,1,1> a(123);
+ VERIFY_IS_EQUAL(a[0], 123.f);
+ }
+ {
+ Array<Index,1,1> a(123);
+ VERIFY_IS_EQUAL(a[0], 123);
+ }
+ {
+ Array<Index,1,1> a(123.0);
+ VERIFY_IS_EQUAL(a[0], 123);
+ }
+ {
+ Array<float,1,1> a(123);
+ VERIFY_IS_EQUAL(a[0], 123.f);
+ }
+ {
+ Array<Index,3,3> a(123);
+ VERIFY_IS_EQUAL(a(4), 123);
+ }
+ {
+ Array<Index,3,3> a(123.0);
+ VERIFY_IS_EQUAL(a(4), 123);
+ }
+ {
+ Array<float,3,3> a(123);
+ VERIFY_IS_EQUAL(a(4), 123.f);
+ }
+}
diff --git a/test/ctorleak.cpp b/test/ctorleak.cpp
new file mode 100644
index 000000000..c158f5e4e
--- /dev/null
+++ b/test/ctorleak.cpp
@@ -0,0 +1,69 @@
+#include "main.h"
+
+#include <exception> // std::exception
+
+struct Foo
+{
+ static Index object_count;
+ static Index object_limit;
+ int dummy;
+
+ Foo()
+ {
+#ifdef EIGEN_EXCEPTIONS
+ // TODO: Is this the correct way to handle this?
+ if (Foo::object_count > Foo::object_limit) { std::cout << "\nThrow!\n"; throw Foo::Fail(); }
+#endif
+ std::cout << '+';
+ ++Foo::object_count;
+ }
+
+ ~Foo()
+ {
+ std::cout << '-';
+ --Foo::object_count;
+ }
+
+ class Fail : public std::exception {};
+};
+
+Index Foo::object_count = 0;
+Index Foo::object_limit = 0;
+
+#undef EIGEN_TEST_MAX_SIZE
+#define EIGEN_TEST_MAX_SIZE 3
+
+void test_ctorleak()
+{
+ typedef Matrix<Foo, Dynamic, Dynamic> MatrixX;
+ typedef Matrix<Foo, Dynamic, 1> VectorX;
+ Foo::object_count = 0;
+ for(int i = 0; i < g_repeat; i++) {
+ Index rows = internal::random<Index>(2,EIGEN_TEST_MAX_SIZE), cols = internal::random<Index>(2,EIGEN_TEST_MAX_SIZE);
+ Foo::object_limit = internal::random<Index>(0, rows*cols - 2);
+ std::cout << "object_limit =" << Foo::object_limit << std::endl;
+#ifdef EIGEN_EXCEPTIONS
+ try
+ {
+#endif
+ std::cout << "\nMatrixX m(" << rows << ", " << cols << ");\n";
+ MatrixX m(rows, cols);
+#ifdef EIGEN_EXCEPTIONS
+ VERIFY(false); // not reached if exceptions are enabled
+ }
+ catch (const Foo::Fail&) { /* ignore */ }
+#endif
+ VERIFY_IS_EQUAL(Index(0), Foo::object_count);
+
+ {
+ Foo::object_limit = (rows+1)*(cols+1);
+ MatrixX A(rows, cols);
+ VERIFY_IS_EQUAL(Foo::object_count, rows*cols);
+ VectorX v=A.row(0);
+ VERIFY_IS_EQUAL(Foo::object_count, (rows+1)*cols);
+ v = A.col(0);
+ VERIFY_IS_EQUAL(Foo::object_count, rows*(cols+1));
+ }
+ VERIFY_IS_EQUAL(Index(0), Foo::object_count);
+ }
+}
diff --git a/test/cuda_basic.cu b/test/cuda_basic.cu
new file mode 100644
index 000000000..cb2e4167a
--- /dev/null
+++ b/test/cuda_basic.cu
@@ -0,0 +1,173 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// 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
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// workaround issue between gcc >= 4.7 and cuda 5.5
+#if (defined __GNUC__) && (__GNUC__>4 || __GNUC_MINOR__>=7)
+ #undef _GLIBCXX_ATOMIC_BUILTINS
+ #undef _GLIBCXX_USE_INT128
+#endif
+
+#define EIGEN_TEST_NO_LONGDOUBLE
+#define EIGEN_TEST_NO_COMPLEX
+#define EIGEN_TEST_FUNC cuda_basic
+#define EIGEN_DEFAULT_DENSE_INDEX_TYPE int
+
+#include <math_constants.h>
+#include <cuda.h>
+#if defined __CUDACC_VER__ && __CUDACC_VER__ >= 70500
+#include <cuda_fp16.h>
+#endif
+#include "main.h"
+#include "cuda_common.h"
+
+// Check that dense modules can be properly parsed by nvcc
+#include <Eigen/Dense>
+
+// struct Foo{
+// EIGEN_DEVICE_FUNC
+// void operator()(int i, const float* mats, float* vecs) const {
+// using namespace Eigen;
+// // Matrix3f M(data);
+// // Vector3f x(data+9);
+// // Map<Vector3f>(data+9) = M.inverse() * x;
+// Matrix3f M(mats+i/16);
+// Vector3f x(vecs+i*3);
+// // using std::min;
+// // using std::sqrt;
+// Map<Vector3f>(vecs+i*3) << x.minCoeff(), 1, 2;// / x.dot(x);//(M.inverse() * x) / x.x();
+// //x = x*2 + x.y() * x + x * x.maxCoeff() - x / x.sum();
+// }
+// };
+
+template<typename T>
+struct coeff_wise {
+ EIGEN_DEVICE_FUNC
+ void operator()(int i, const typename T::Scalar* in, typename T::Scalar* out) const
+ {
+ using namespace Eigen;
+ T x1(in+i);
+ T x2(in+i+1);
+ T x3(in+i+2);
+ Map<T> res(out+i*T::MaxSizeAtCompileTime);
+
+ res.array() += (in[0] * x1 + x2).array() * x3.array();
+ }
+};
+
+template<typename T>
+struct replicate {
+ EIGEN_DEVICE_FUNC
+ void operator()(int i, const typename T::Scalar* in, typename T::Scalar* out) const
+ {
+ using namespace Eigen;
+ T x1(in+i);
+ int step = x1.size() * 4;
+ int stride = 3 * step;
+
+ typedef Map<Array<typename T::Scalar,Dynamic,Dynamic> > MapType;
+ MapType(out+i*stride+0*step, x1.rows()*2, x1.cols()*2) = x1.replicate(2,2);
+ MapType(out+i*stride+1*step, x1.rows()*3, x1.cols()) = in[i] * x1.colwise().replicate(3);
+ MapType(out+i*stride+2*step, x1.rows(), x1.cols()*3) = in[i] * x1.rowwise().replicate(3);
+ }
+};
+
+template<typename T>
+struct redux {
+ EIGEN_DEVICE_FUNC
+ void operator()(int i, const typename T::Scalar* in, typename T::Scalar* out) const
+ {
+ using namespace Eigen;
+ int N = 10;
+ T x1(in+i);
+ out[i*N+0] = x1.minCoeff();
+ out[i*N+1] = x1.maxCoeff();
+ out[i*N+2] = x1.sum();
+ out[i*N+3] = x1.prod();
+ out[i*N+4] = x1.matrix().squaredNorm();
+ out[i*N+5] = x1.matrix().norm();
+ out[i*N+6] = x1.colwise().sum().maxCoeff();
+ out[i*N+7] = x1.rowwise().maxCoeff().sum();
+ out[i*N+8] = x1.matrix().colwise().squaredNorm().sum();
+ }
+};
+
+template<typename T1, typename T2>
+struct prod_test {
+ EIGEN_DEVICE_FUNC
+ void operator()(int i, const typename T1::Scalar* in, typename T1::Scalar* out) const
+ {
+ using namespace Eigen;
+ typedef Matrix<typename T1::Scalar, T1::RowsAtCompileTime, T2::ColsAtCompileTime> T3;
+ T1 x1(in+i);
+ T2 x2(in+i+1);
+ Map<T3> res(out+i*T3::MaxSizeAtCompileTime);
+ res += in[i] * x1 * x2;
+ }
+};
+
+template<typename T1, typename T2>
+struct diagonal {
+ EIGEN_DEVICE_FUNC
+ void operator()(int i, const typename T1::Scalar* in, typename T1::Scalar* out) const
+ {
+ using namespace Eigen;
+ T1 x1(in+i);
+ Map<T2> res(out+i*T2::MaxSizeAtCompileTime);
+ res += x1.diagonal();
+ }
+};
+
+template<typename T>
+struct eigenvalues {
+ EIGEN_DEVICE_FUNC
+ void operator()(int i, const typename T::Scalar* in, typename T::Scalar* out) const
+ {
+ using namespace Eigen;
+ typedef Matrix<typename T::Scalar, T::RowsAtCompileTime, 1> Vec;
+ T M(in+i);
+ Map<Vec> res(out+i*Vec::MaxSizeAtCompileTime);
+ T A = M*M.adjoint();
+ SelfAdjointEigenSolver<T> eig;
+ eig.computeDirect(M);
+ res = eig.eigenvalues();
+ }
+};
+
+void test_cuda_basic()
+{
+ ei_test_init_cuda();
+
+ int nthreads = 100;
+ Eigen::VectorXf in, out;
+
+ #ifndef __CUDA_ARCH__
+ int data_size = nthreads * 512;
+ in.setRandom(data_size);
+ out.setRandom(data_size);
+ #endif
+
+ CALL_SUBTEST( run_and_compare_to_cuda(coeff_wise<Vector3f>(), nthreads, in, out) );
+ CALL_SUBTEST( run_and_compare_to_cuda(coeff_wise<Array44f>(), nthreads, in, out) );
+
+ CALL_SUBTEST( run_and_compare_to_cuda(replicate<Array4f>(), nthreads, in, out) );
+ CALL_SUBTEST( run_and_compare_to_cuda(replicate<Array33f>(), nthreads, in, out) );
+
+ CALL_SUBTEST( run_and_compare_to_cuda(redux<Array4f>(), nthreads, in, out) );
+ CALL_SUBTEST( run_and_compare_to_cuda(redux<Matrix3f>(), nthreads, in, out) );
+
+ CALL_SUBTEST( run_and_compare_to_cuda(prod_test<Matrix3f,Matrix3f>(), nthreads, in, out) );
+ CALL_SUBTEST( run_and_compare_to_cuda(prod_test<Matrix4f,Vector4f>(), nthreads, in, out) );
+
+ CALL_SUBTEST( run_and_compare_to_cuda(diagonal<Matrix3f,Vector3f>(), nthreads, in, out) );
+ CALL_SUBTEST( run_and_compare_to_cuda(diagonal<Matrix4f,Vector4f>(), nthreads, in, out) );
+
+ CALL_SUBTEST( run_and_compare_to_cuda(eigenvalues<Matrix3f>(), nthreads, in, out) );
+ CALL_SUBTEST( run_and_compare_to_cuda(eigenvalues<Matrix2f>(), nthreads, in, out) );
+
+}
diff --git a/test/cuda_common.h b/test/cuda_common.h
new file mode 100644
index 000000000..9737693ac
--- /dev/null
+++ b/test/cuda_common.h
@@ -0,0 +1,101 @@
+
+#ifndef EIGEN_TEST_CUDA_COMMON_H
+#define EIGEN_TEST_CUDA_COMMON_H
+
+#include <cuda.h>
+#include <cuda_runtime.h>
+#include <cuda_runtime_api.h>
+#include <iostream>
+
+#ifndef __CUDACC__
+dim3 threadIdx, blockDim, blockIdx;
+#endif
+
+template<typename Kernel, typename Input, typename Output>
+void run_on_cpu(const Kernel& ker, int n, const Input& in, Output& out)
+{
+ for(int i=0; i<n; i++)
+ ker(i, in.data(), out.data());
+}
+
+
+template<typename Kernel, typename Input, typename Output>
+__global__
+void run_on_cuda_meta_kernel(const Kernel ker, int n, const Input* in, Output* out)
+{
+ int i = threadIdx.x + blockIdx.x*blockDim.x;
+ if(i<n) {
+ ker(i, in, out);
+ }
+}
+
+
+template<typename Kernel, typename Input, typename Output>
+void run_on_cuda(const Kernel& ker, int n, const Input& in, Output& out)
+{
+ typename Input::Scalar* d_in;
+ typename Output::Scalar* d_out;
+ std::ptrdiff_t in_bytes = in.size() * sizeof(typename Input::Scalar);
+ std::ptrdiff_t out_bytes = out.size() * sizeof(typename Output::Scalar);
+
+ cudaMalloc((void**)(&d_in), in_bytes);
+ cudaMalloc((void**)(&d_out), out_bytes);
+
+ cudaMemcpy(d_in, in.data(), in_bytes, cudaMemcpyHostToDevice);
+ cudaMemcpy(d_out, out.data(), out_bytes, cudaMemcpyHostToDevice);
+
+ // Simple and non-optimal 1D mapping assuming n is not too large
+ // That's only for unit testing!
+ dim3 Blocks(128);
+ dim3 Grids( (n+int(Blocks.x)-1)/int(Blocks.x) );
+
+ cudaThreadSynchronize();
+ run_on_cuda_meta_kernel<<<Grids,Blocks>>>(ker, n, d_in, d_out);
+ cudaThreadSynchronize();
+
+ // check inputs have not been modified
+ cudaMemcpy(const_cast<typename Input::Scalar*>(in.data()), d_in, in_bytes, cudaMemcpyDeviceToHost);
+ cudaMemcpy(out.data(), d_out, out_bytes, cudaMemcpyDeviceToHost);
+
+ cudaFree(d_in);
+ cudaFree(d_out);
+}
+
+
+template<typename Kernel, typename Input, typename Output>
+void run_and_compare_to_cuda(const Kernel& ker, int n, const Input& in, Output& out)
+{
+ Input in_ref, in_cuda;
+ Output out_ref, out_cuda;
+ #ifndef __CUDA_ARCH__
+ in_ref = in_cuda = in;
+ out_ref = out_cuda = out;
+ #endif
+ run_on_cpu (ker, n, in_ref, out_ref);
+ run_on_cuda(ker, n, in_cuda, out_cuda);
+ #ifndef __CUDA_ARCH__
+ VERIFY_IS_APPROX(in_ref, in_cuda);
+ VERIFY_IS_APPROX(out_ref, out_cuda);
+ #endif
+}
+
+
+void ei_test_init_cuda()
+{
+ int device = 0;
+ cudaDeviceProp deviceProp;
+ cudaGetDeviceProperties(&deviceProp, device);
+ std::cout << "CUDA device info:\n";
+ std::cout << " name: " << deviceProp.name << "\n";
+ std::cout << " capability: " << deviceProp.major << "." << deviceProp.minor << "\n";
+ std::cout << " multiProcessorCount: " << deviceProp.multiProcessorCount << "\n";
+ std::cout << " maxThreadsPerMultiProcessor: " << deviceProp.maxThreadsPerMultiProcessor << "\n";
+ std::cout << " warpSize: " << deviceProp.warpSize << "\n";
+ std::cout << " regsPerBlock: " << deviceProp.regsPerBlock << "\n";
+ std::cout << " concurrentKernels: " << deviceProp.concurrentKernels << "\n";
+ std::cout << " clockRate: " << deviceProp.clockRate << "\n";
+ std::cout << " canMapHostMemory: " << deviceProp.canMapHostMemory << "\n";
+ std::cout << " computeMode: " << deviceProp.computeMode << "\n";
+}
+
+#endif // EIGEN_TEST_CUDA_COMMON_H
diff --git a/test/cwiseop.cpp b/test/cwiseop.cpp
deleted file mode 100644
index e3361da17..000000000
--- a/test/cwiseop.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-// 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) 2006-2008 Benoit Jacob <jacob.benoit.1@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/.
-
-#define EIGEN2_SUPPORT
-#define EIGEN_NO_EIGEN2_DEPRECATED_WARNING
-
-#define EIGEN_NO_STATIC_ASSERT
-#include "main.h"
-#include <functional>
-
-#ifdef min
-#undef min
-#endif
-
-#ifdef max
-#undef max
-#endif
-
-using namespace std;
-
-template<typename Scalar> struct AddIfNull {
- const Scalar operator() (const Scalar a, const Scalar b) const {return a<=1e-3 ? b : a;}
- enum { Cost = NumTraits<Scalar>::AddCost };
-};
-
-template<typename MatrixType>
-typename Eigen::internal::enable_if<!NumTraits<typename MatrixType::Scalar>::IsInteger,typename MatrixType::Scalar>::type
-cwiseops_real_only(MatrixType& m1, MatrixType& m2, MatrixType& m3, MatrixType& mones)
-{
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
-
- VERIFY_IS_APPROX(m1.cwise() / m2, m1.cwise() * (m2.cwise().inverse()));
- m3 = m1.cwise().abs().cwise().sqrt();
- VERIFY_IS_APPROX(m3.cwise().square(), m1.cwise().abs());
- VERIFY_IS_APPROX(m1.cwise().square().cwise().sqrt(), m1.cwise().abs());
- VERIFY_IS_APPROX(m1.cwise().abs().cwise().log().cwise().exp() , m1.cwise().abs());
-
- VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().square());
- m3 = (m1.cwise().abs().cwise()<=RealScalar(0.01)).select(mones,m1);
- VERIFY_IS_APPROX(m3.cwise().pow(-1), m3.cwise().inverse());
- m3 = m1.cwise().abs();
- VERIFY_IS_APPROX(m3.cwise().pow(RealScalar(0.5)), m3.cwise().sqrt());
-
-// VERIFY_IS_APPROX(m1.cwise().tan(), m1.cwise().sin().cwise() / m1.cwise().cos());
- VERIFY_IS_APPROX(mones, m1.cwise().sin().cwise().square() + m1.cwise().cos().cwise().square());
- m3 = m1;
- m3.cwise() /= m2;
- VERIFY_IS_APPROX(m3, m1.cwise() / m2);
-
- return Scalar(0);
-}
-
-template<typename MatrixType>
-typename Eigen::internal::enable_if<NumTraits<typename MatrixType::Scalar>::IsInteger,typename MatrixType::Scalar>::type
-cwiseops_real_only(MatrixType& , MatrixType& , MatrixType& , MatrixType& )
-{
- return 0;
-}
-
-template<typename MatrixType> void cwiseops(const MatrixType& m)
-{
- typedef typename MatrixType::Index Index;
- typedef typename MatrixType::Scalar Scalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
-
- Index rows = m.rows();
- Index cols = m.cols();
-
- MatrixType m1 = MatrixType::Random(rows, cols),
- m1bis = m1,
- m2 = MatrixType::Random(rows, cols),
- m3(rows, cols),
- m4(rows, cols),
- mzero = MatrixType::Zero(rows, cols),
- mones = MatrixType::Ones(rows, cols),
- identity = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
- ::Identity(rows, rows);
- VectorType vzero = VectorType::Zero(rows),
- vones = VectorType::Ones(rows),
- v3(rows);
-
- Index r = internal::random<Index>(0, rows-1),
- c = internal::random<Index>(0, cols-1);
-
- Scalar s1 = internal::random<Scalar>();
-
- // test Zero, Ones, Constant, and the set* variants
- m3 = MatrixType::Constant(rows, cols, s1);
- for (int j=0; j<cols; ++j)
- for (int i=0; i<rows; ++i)
- {
- VERIFY_IS_APPROX(mzero(i,j), Scalar(0));
- VERIFY_IS_APPROX(mones(i,j), Scalar(1));
- VERIFY_IS_APPROX(m3(i,j), s1);
- }
- VERIFY(mzero.isZero());
- VERIFY(mones.isOnes());
- VERIFY(m3.isConstant(s1));
- VERIFY(identity.isIdentity());
- VERIFY_IS_APPROX(m4.setConstant(s1), m3);
- VERIFY_IS_APPROX(m4.setConstant(rows,cols,s1), m3);
- VERIFY_IS_APPROX(m4.setZero(), mzero);
- VERIFY_IS_APPROX(m4.setZero(rows,cols), mzero);
- VERIFY_IS_APPROX(m4.setOnes(), mones);
- VERIFY_IS_APPROX(m4.setOnes(rows,cols), mones);
- m4.fill(s1);
- VERIFY_IS_APPROX(m4, m3);
-
- VERIFY_IS_APPROX(v3.setConstant(rows, s1), VectorType::Constant(rows,s1));
- VERIFY_IS_APPROX(v3.setZero(rows), vzero);
- VERIFY_IS_APPROX(v3.setOnes(rows), vones);
-
- m2 = m2.template binaryExpr<AddIfNull<Scalar> >(mones);
-
- VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().abs2());
- VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().square());
- VERIFY_IS_APPROX(m1.cwise().pow(3), m1.cwise().cube());
-
- VERIFY_IS_APPROX(m1 + mones, m1.cwise()+Scalar(1));
- VERIFY_IS_APPROX(m1 - mones, m1.cwise()-Scalar(1));
- m3 = m1; m3.cwise() += 1;
- VERIFY_IS_APPROX(m1 + mones, m3);
- m3 = m1; m3.cwise() -= 1;
- VERIFY_IS_APPROX(m1 - mones, m3);
-
- VERIFY_IS_APPROX(m2, m2.cwise() * mones);
- VERIFY_IS_APPROX(m1.cwise() * m2, m2.cwise() * m1);
- m3 = m1;
- m3.cwise() *= m2;
- VERIFY_IS_APPROX(m3, m1.cwise() * m2);
-
- VERIFY_IS_APPROX(mones, m2.cwise()/m2);
-
- // check min
- VERIFY_IS_APPROX( m1.cwise().min(m2), m2.cwise().min(m1) );
- VERIFY_IS_APPROX( m1.cwise().min(m1+mones), m1 );
- VERIFY_IS_APPROX( m1.cwise().min(m1-mones), m1-mones );
-
- // check max
- VERIFY_IS_APPROX( m1.cwise().max(m2), m2.cwise().max(m1) );
- VERIFY_IS_APPROX( m1.cwise().max(m1-mones), m1 );
- VERIFY_IS_APPROX( m1.cwise().max(m1+mones), m1+mones );
-
- VERIFY( (m1.cwise() == m1).all() );
- VERIFY( (m1.cwise() != m2).any() );
- VERIFY(!(m1.cwise() == (m1+mones)).any() );
- if (rows*cols>1)
- {
- m3 = m1;
- m3(r,c) += 1;
- VERIFY( (m1.cwise() == m3).any() );
- VERIFY( !(m1.cwise() == m3).all() );
- }
- VERIFY( (m1.cwise().min(m2).cwise() <= m2).all() );
- VERIFY( (m1.cwise().max(m2).cwise() >= m2).all() );
- VERIFY( (m1.cwise().min(m2).cwise() < (m1+mones)).all() );
- VERIFY( (m1.cwise().max(m2).cwise() > (m1-mones)).all() );
-
- VERIFY( (m1.cwise()<m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).all() );
- VERIFY( !(m1.cwise()<m1bis.unaryExpr(bind2nd(minus<Scalar>(), Scalar(1)))).all() );
- VERIFY( !(m1.cwise()>m1bis.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).any() );
-
- cwiseops_real_only(m1, m2, m3, mones);
-}
-
-void test_cwiseop()
-{
- for(int i = 0; i < g_repeat ; i++) {
- CALL_SUBTEST_1( cwiseops(Matrix<float, 1, 1>()) );
- CALL_SUBTEST_2( cwiseops(Matrix4d()) );
- CALL_SUBTEST_3( cwiseops(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
- CALL_SUBTEST_4( cwiseops(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
- CALL_SUBTEST_5( cwiseops(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
- CALL_SUBTEST_6( cwiseops(MatrixXd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
- }
-}
diff --git a/test/dense_storage.cpp b/test/dense_storage.cpp
new file mode 100644
index 000000000..e63712b1a
--- /dev/null
+++ b/test/dense_storage.cpp
@@ -0,0 +1,76 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2013 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/Core>
+
+template <typename T, int Rows, int Cols>
+void dense_storage_copy()
+{
+ static const int Size = ((Rows==Dynamic || Cols==Dynamic) ? Dynamic : Rows*Cols);
+ typedef DenseStorage<T,Size, Rows,Cols, 0> DenseStorageType;
+
+ const int rows = (Rows==Dynamic) ? 4 : Rows;
+ const int cols = (Cols==Dynamic) ? 3 : Cols;
+ const int size = rows*cols;
+ DenseStorageType reference(size, rows, cols);
+ T* raw_reference = reference.data();
+ for (int i=0; i<size; ++i)
+ raw_reference[i] = static_cast<T>(i);
+
+ DenseStorageType copied_reference(reference);
+ const T* raw_copied_reference = copied_reference.data();
+ for (int i=0; i<size; ++i)
+ VERIFY_IS_EQUAL(raw_reference[i], raw_copied_reference[i]);
+}
+
+template <typename T, int Rows, int Cols>
+void dense_storage_assignment()
+{
+ static const int Size = ((Rows==Dynamic || Cols==Dynamic) ? Dynamic : Rows*Cols);
+ typedef DenseStorage<T,Size, Rows,Cols, 0> DenseStorageType;
+
+ const int rows = (Rows==Dynamic) ? 4 : Rows;
+ const int cols = (Cols==Dynamic) ? 3 : Cols;
+ const int size = rows*cols;
+ DenseStorageType reference(size, rows, cols);
+ T* raw_reference = reference.data();
+ for (int i=0; i<size; ++i)
+ raw_reference[i] = static_cast<T>(i);
+
+ DenseStorageType copied_reference;
+ copied_reference = reference;
+ const T* raw_copied_reference = copied_reference.data();
+ for (int i=0; i<size; ++i)
+ VERIFY_IS_EQUAL(raw_reference[i], raw_copied_reference[i]);
+}
+
+void test_dense_storage()
+{
+ dense_storage_copy<int,Dynamic,Dynamic>();
+ dense_storage_copy<int,Dynamic,3>();
+ dense_storage_copy<int,4,Dynamic>();
+ dense_storage_copy<int,4,3>();
+
+ dense_storage_copy<float,Dynamic,Dynamic>();
+ dense_storage_copy<float,Dynamic,3>();
+ dense_storage_copy<float,4,Dynamic>();
+ dense_storage_copy<float,4,3>();
+
+ dense_storage_assignment<int,Dynamic,Dynamic>();
+ dense_storage_assignment<int,Dynamic,3>();
+ dense_storage_assignment<int,4,Dynamic>();
+ dense_storage_assignment<int,4,3>();
+
+ dense_storage_assignment<float,Dynamic,Dynamic>();
+ dense_storage_assignment<float,Dynamic,3>();
+ dense_storage_assignment<float,4,Dynamic>();
+ dense_storage_assignment<float,4,3>();
+}
diff --git a/test/diagonal.cpp b/test/diagonal.cpp
index 53814a588..c1546e97d 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,26 @@ 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);
+ }
+}
+
+template<typename MatrixType> void diagonal_assert(const MatrixType& m) {
+ Index rows = m.rows();
+ Index cols = m.cols();
+
+ MatrixType m1 = MatrixType::Random(rows, cols);
+
+ if (rows>=2 && cols>=2)
+ {
+ VERIFY_RAISES_ASSERT( m1 += m1.diagonal() );
+ VERIFY_RAISES_ASSERT( m1 -= m1.diagonal() );
+ VERIFY_RAISES_ASSERT( m1.array() *= m1.diagonal().array() );
+ VERIFY_RAISES_ASSERT( m1.array() /= m1.diagonal().array() );
}
}
@@ -74,4 +96,6 @@ void test_diagonal()
CALL_SUBTEST_1( diagonal(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
CALL_SUBTEST_1( diagonal(Matrix<float,Dynamic,4>(3, 4)) );
}
+
+ CALL_SUBTEST_1( diagonal_assert(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
}
diff --git a/test/diagonalmatrices.cpp b/test/diagonalmatrices.cpp
index 149f1db2f..cd6dc8cf0 100644
--- a/test/diagonalmatrices.cpp
+++ b/test/diagonalmatrices.cpp
@@ -17,6 +17,7 @@ template<typename MatrixType> void diagonalmatrices(const MatrixType& m)
typedef Matrix<Scalar, Rows, 1> VectorType;
typedef Matrix<Scalar, 1, Cols> RowVectorType;
typedef Matrix<Scalar, Rows, Rows> SquareMatrixType;
+ typedef Matrix<Scalar, Dynamic, Dynamic> DynMatrixType;
typedef DiagonalMatrix<Scalar, Rows> LeftDiagonalMatrix;
typedef DiagonalMatrix<Scalar, Cols> RightDiagonalMatrix;
typedef Matrix<Scalar, Rows==Dynamic?Dynamic:2*Rows, Cols==Dynamic?Dynamic:2*Cols> BigMatrix;
@@ -64,6 +65,13 @@ template<typename MatrixType> void diagonalmatrices(const MatrixType& m)
VERIFY_IS_APPROX( (((v1+v2).asDiagonal() * (m1+m2))(i,j)) , (v1+v2)(i) * (m1+m2)(i,j) );
VERIFY_IS_APPROX( ((m1 * (rv1+rv2).asDiagonal())(i,j)) , (rv1+rv2)(j) * m1(i,j) );
VERIFY_IS_APPROX( (((m1+m2) * (rv1+rv2).asDiagonal())(i,j)) , (rv1+rv2)(j) * (m1+m2)(i,j) );
+
+ if(rows>1)
+ {
+ DynMatrixType tmp = m1.topRows(rows/2), res;
+ VERIFY_IS_APPROX( (res = m1.topRows(rows/2) * rv1.asDiagonal()), tmp * rv1.asDiagonal() );
+ VERIFY_IS_APPROX( (res = v1.head(rows/2).asDiagonal()*m1.topRows(rows/2)), v1.head(rows/2).asDiagonal()*tmp );
+ }
BigMatrix big;
big.setZero(2*rows, 2*cols);
@@ -84,6 +92,24 @@ template<typename MatrixType> void diagonalmatrices(const MatrixType& m)
VERIFY_IS_APPROX(m1 * (rdm1 * s1), (m1 * rdm1) * s1);
VERIFY_IS_APPROX(m1 * (s1 * rdm1), (m1 * rdm1) * s1);
+
+ // Diagonal to dense
+ sq_m1.setRandom();
+ sq_m2 = sq_m1;
+ VERIFY_IS_APPROX( (sq_m1 += (s1*v1).asDiagonal()), sq_m2 += (s1*v1).asDiagonal().toDenseMatrix() );
+ VERIFY_IS_APPROX( (sq_m1 -= (s1*v1).asDiagonal()), sq_m2 -= (s1*v1).asDiagonal().toDenseMatrix() );
+ VERIFY_IS_APPROX( (sq_m1 = (s1*v1).asDiagonal()), (s1*v1).asDiagonal().toDenseMatrix() );
+}
+
+template<int>
+void bug987()
+{
+ Matrix3Xd points = Matrix3Xd::Random(3, 3);
+ Vector2d diag = Vector2d::Random();
+ Matrix2Xd tmp1 = points.topRows<2>(), res1, res2;
+ VERIFY_IS_APPROX( res1 = diag.asDiagonal() * points.topRows<2>(), res2 = diag.asDiagonal() * tmp1 );
+ Matrix2d tmp2 = points.topLeftCorner<2,2>();
+ VERIFY_IS_APPROX(( res1 = points.topLeftCorner<2,2>()*diag.asDiagonal()) , res2 = tmp2*diag.asDiagonal() );
}
void test_diagonalmatrices()
@@ -99,4 +125,5 @@ void test_diagonalmatrices()
CALL_SUBTEST_8( diagonalmatrices(Matrix<double,Dynamic,Dynamic,RowMajor>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
CALL_SUBTEST_9( diagonalmatrices(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
}
+ CALL_SUBTEST_10( bug987<0>() );
}
diff --git a/test/dynalloc.cpp b/test/dynalloc.cpp
index 7e41bfa97..f1cc70bee 100644
--- a/test/dynalloc.cpp
+++ b/test/dynalloc.cpp
@@ -9,18 +9,20 @@
#include "main.h"
-#if EIGEN_ALIGN
-#define ALIGNMENT 16
+#if EIGEN_MAX_ALIGN_BYTES>0
+#define ALIGNMENT EIGEN_MAX_ALIGN_BYTES
#else
#define ALIGNMENT 1
#endif
+typedef Matrix<float,8,1> Vector8f;
+
void check_handmade_aligned_malloc()
{
for(int i = 1; i < 1000; i++)
{
char *p = (char*)internal::handmade_aligned_malloc(i);
- VERIFY(size_t(p)%ALIGNMENT==0);
+ VERIFY(internal::UIntPtr(p)%ALIGNMENT==0);
// if the buffer is wrongly allocated this will give a bad write --> check with valgrind
for(int j = 0; j < i; j++) p[j]=0;
internal::handmade_aligned_free(p);
@@ -29,10 +31,10 @@ 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);
+ VERIFY(internal::UIntPtr(p)%ALIGNMENT==0);
// if the buffer is wrongly allocated this will give a bad write --> check with valgrind
for(int j = 0; j < i; j++) p[j]=0;
internal::aligned_free(p);
@@ -41,10 +43,10 @@ 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);
+ VERIFY(internal::UIntPtr(p)%ALIGNMENT==0);
// if the buffer is wrongly allocated this will give a bad write --> check with valgrind
for(int j = 0; j < i; j++) p[j]=0;
internal::aligned_delete(p,i);
@@ -53,10 +55,10 @@ 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);
+ VERIFY(internal::UIntPtr(p)%ALIGNMENT==0);
// if the buffer is wrongly allocated this will give a bad write --> check with valgrind
for(int j = 0; j < i; j++) p[j]=0;
}
@@ -68,7 +70,7 @@ struct MyStruct
{
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
char dummychar;
- Vector4f avec;
+ Vector8f avec;
};
class MyClassA
@@ -76,15 +78,45 @@ class MyClassA
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
char dummychar;
- Vector4f avec;
+ Vector8f avec;
};
template<typename T> void check_dynaligned()
{
- T* obj = new T;
- VERIFY(T::NeedsToAlign==1);
- VERIFY(size_t(obj)%ALIGNMENT==0);
- delete obj;
+ // TODO have to be updated once we support multiple alignment values
+ if(T::SizeAtCompileTime % ALIGNMENT == 0)
+ {
+ T* obj = new T;
+ VERIFY(T::NeedsToAlign==1);
+ VERIFY(internal::UIntPtr(obj)%ALIGNMENT==0);
+ delete obj;
+ }
+}
+
+template<typename T> void check_custom_new_delete()
+{
+ {
+ T* t = new T;
+ delete t;
+ }
+
+ {
+ std::size_t N = internal::random<std::size_t>(1,10);
+ T* t = new T[N];
+ delete[] t;
+ }
+
+#if EIGEN_MAX_ALIGN_BYTES>0
+ {
+ T* t = static_cast<T *>((T::operator new)(sizeof(T)));
+ (T::operator delete)(t, sizeof(T));
+ }
+
+ {
+ T* t = static_cast<T *>((T::operator new)(sizeof(T)));
+ (T::operator delete)(t);
+ }
+#endif
}
void test_dynalloc()
@@ -97,25 +129,34 @@ void test_dynalloc()
for (int i=0; i<g_repeat*100; ++i)
{
+ CALL_SUBTEST( check_custom_new_delete<Vector4f>() );
+ CALL_SUBTEST( check_custom_new_delete<Vector2f>() );
+ CALL_SUBTEST( check_custom_new_delete<Matrix4f>() );
+ CALL_SUBTEST( check_custom_new_delete<MatrixXi>() );
+ }
+
+ // check static allocation, who knows ?
+ #if EIGEN_MAX_STATIC_ALIGN_BYTES
+ for (int i=0; i<g_repeat*100; ++i)
+ {
CALL_SUBTEST(check_dynaligned<Vector4f>() );
CALL_SUBTEST(check_dynaligned<Vector2d>() );
CALL_SUBTEST(check_dynaligned<Matrix4f>() );
CALL_SUBTEST(check_dynaligned<Vector4d>() );
CALL_SUBTEST(check_dynaligned<Vector4i>() );
+ CALL_SUBTEST(check_dynaligned<Vector8f>() );
}
-
- // check static allocation, who knows ?
- #if EIGEN_ALIGN_STATICALLY
+
{
- MyStruct foo0; VERIFY(size_t(foo0.avec.data())%ALIGNMENT==0);
- MyClassA fooA; VERIFY(size_t(fooA.avec.data())%ALIGNMENT==0);
+ MyStruct foo0; VERIFY(internal::UIntPtr(foo0.avec.data())%ALIGNMENT==0);
+ MyClassA fooA; VERIFY(internal::UIntPtr(fooA.avec.data())%ALIGNMENT==0);
}
// dynamic allocation, single object
for (int i=0; i<g_repeat*100; ++i)
{
- MyStruct *foo0 = new MyStruct(); VERIFY(size_t(foo0->avec.data())%ALIGNMENT==0);
- MyClassA *fooA = new MyClassA(); VERIFY(size_t(fooA->avec.data())%ALIGNMENT==0);
+ MyStruct *foo0 = new MyStruct(); VERIFY(internal::UIntPtr(foo0->avec.data())%ALIGNMENT==0);
+ MyClassA *fooA = new MyClassA(); VERIFY(internal::UIntPtr(fooA->avec.data())%ALIGNMENT==0);
delete foo0;
delete fooA;
}
@@ -124,8 +165,8 @@ void test_dynalloc()
const int N = 10;
for (int i=0; i<g_repeat*100; ++i)
{
- MyStruct *foo0 = new MyStruct[N]; VERIFY(size_t(foo0->avec.data())%ALIGNMENT==0);
- MyClassA *fooA = new MyClassA[N]; VERIFY(size_t(fooA->avec.data())%ALIGNMENT==0);
+ MyStruct *foo0 = new MyStruct[N]; VERIFY(internal::UIntPtr(foo0->avec.data())%ALIGNMENT==0);
+ MyClassA *fooA = new MyClassA[N]; VERIFY(internal::UIntPtr(fooA->avec.data())%ALIGNMENT==0);
delete[] foo0;
delete[] fooA;
}
diff --git a/test/eigen2/CMakeLists.txt b/test/eigen2/CMakeLists.txt
deleted file mode 100644
index 9615a6026..000000000
--- a/test/eigen2/CMakeLists.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-add_custom_target(eigen2_buildtests)
-add_custom_target(eigen2_check COMMAND "ctest -R eigen2")
-add_dependencies(eigen2_check eigen2_buildtests)
-add_dependencies(buildtests eigen2_buildtests)
-
-add_definitions("-DEIGEN2_SUPPORT_STAGE10_FULL_EIGEN2_API")
-add_definitions("-DEIGEN_NO_EIGEN2_DEPRECATED_WARNING")
-
-ei_add_test(eigen2_meta)
-ei_add_test(eigen2_sizeof)
-ei_add_test(eigen2_dynalloc)
-ei_add_test(eigen2_nomalloc)
-#ei_add_test(eigen2_first_aligned)
-ei_add_test(eigen2_mixingtypes)
-#ei_add_test(eigen2_packetmath)
-ei_add_test(eigen2_unalignedassert)
-#ei_add_test(eigen2_vectorization_logic)
-ei_add_test(eigen2_basicstuff)
-ei_add_test(eigen2_linearstructure)
-ei_add_test(eigen2_cwiseop)
-ei_add_test(eigen2_sum)
-ei_add_test(eigen2_product_small)
-ei_add_test(eigen2_product_large ${EI_OFLAG})
-ei_add_test(eigen2_adjoint)
-ei_add_test(eigen2_submatrices)
-ei_add_test(eigen2_miscmatrices)
-ei_add_test(eigen2_commainitializer)
-ei_add_test(eigen2_smallvectors)
-ei_add_test(eigen2_map)
-ei_add_test(eigen2_array)
-ei_add_test(eigen2_triangular)
-ei_add_test(eigen2_cholesky " " "${GSL_LIBRARIES}")
-ei_add_test(eigen2_lu ${EI_OFLAG})
-ei_add_test(eigen2_determinant ${EI_OFLAG})
-ei_add_test(eigen2_inverse)
-ei_add_test(eigen2_qr)
-ei_add_test(eigen2_eigensolver " " "${GSL_LIBRARIES}")
-ei_add_test(eigen2_svd)
-ei_add_test(eigen2_geometry)
-ei_add_test(eigen2_geometry_with_eigen2_prefix)
-ei_add_test(eigen2_hyperplane)
-ei_add_test(eigen2_parametrizedline)
-ei_add_test(eigen2_alignedbox)
-ei_add_test(eigen2_regression)
-ei_add_test(eigen2_stdvector)
-ei_add_test(eigen2_newstdvector)
-if(QT4_FOUND)
- ei_add_test(eigen2_qtvector " " "${QT_QTCORE_LIBRARY}")
-endif(QT4_FOUND)
-# no support for eigen2 sparse module
-# if(NOT EIGEN_DEFAULT_TO_ROW_MAJOR)
-# ei_add_test(eigen2_sparse_vector)
-# ei_add_test(eigen2_sparse_basic)
-# ei_add_test(eigen2_sparse_solvers " " "${SPARSE_LIBS}")
-# ei_add_test(eigen2_sparse_product)
-# endif()
-ei_add_test(eigen2_swap)
-ei_add_test(eigen2_visitor)
-ei_add_test(eigen2_bug_132)
-
-ei_add_test(eigen2_prec_inverse_4x4 ${EI_OFLAG})
diff --git a/test/eigen2/eigen2_adjoint.cpp b/test/eigen2/eigen2_adjoint.cpp
deleted file mode 100644
index c0f811459..000000000
--- a/test/eigen2/eigen2_adjoint.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@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"
-
-template<typename MatrixType> void adjoint(const MatrixType& m)
-{
- /* this test covers the following files:
- Transpose.h Conjugate.h Dot.h
- */
-
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
- int rows = m.rows();
- int cols = m.cols();
-
- RealScalar largerEps = test_precision<RealScalar>();
- if (ei_is_same_type<RealScalar,float>::ret)
- largerEps = RealScalar(1e-3f);
-
- MatrixType m1 = MatrixType::Random(rows, cols),
- m2 = MatrixType::Random(rows, cols),
- m3(rows, cols),
- square = SquareMatrixType::Random(rows, rows);
- VectorType v1 = VectorType::Random(rows),
- v2 = VectorType::Random(rows),
- v3 = VectorType::Random(rows),
- vzero = VectorType::Zero(rows);
-
- Scalar s1 = ei_random<Scalar>(),
- s2 = ei_random<Scalar>();
-
- // check basic compatibility of adjoint, transpose, conjugate
- VERIFY_IS_APPROX(m1.transpose().conjugate().adjoint(), m1);
- VERIFY_IS_APPROX(m1.adjoint().conjugate().transpose(), m1);
-
- // check multiplicative behavior
- VERIFY_IS_APPROX((m1.adjoint() * m2).adjoint(), m2.adjoint() * m1);
- VERIFY_IS_APPROX((s1 * m1).adjoint(), ei_conj(s1) * m1.adjoint());
-
- // check basic properties of dot, norm, norm2
- typedef typename NumTraits<Scalar>::Real RealScalar;
- VERIFY(ei_isApprox((s1 * v1 + s2 * v2).eigen2_dot(v3), s1 * v1.eigen2_dot(v3) + s2 * v2.eigen2_dot(v3), largerEps));
- VERIFY(ei_isApprox(v3.eigen2_dot(s1 * v1 + s2 * v2), ei_conj(s1)*v3.eigen2_dot(v1)+ei_conj(s2)*v3.eigen2_dot(v2), largerEps));
- VERIFY_IS_APPROX(ei_conj(v1.eigen2_dot(v2)), v2.eigen2_dot(v1));
- VERIFY_IS_APPROX(ei_real(v1.eigen2_dot(v1)), v1.squaredNorm());
- if(NumTraits<Scalar>::HasFloatingPoint)
- VERIFY_IS_APPROX(v1.squaredNorm(), v1.norm() * v1.norm());
- VERIFY_IS_MUCH_SMALLER_THAN(ei_abs(vzero.eigen2_dot(v1)), static_cast<RealScalar>(1));
- if(NumTraits<Scalar>::HasFloatingPoint)
- VERIFY_IS_MUCH_SMALLER_THAN(vzero.norm(), static_cast<RealScalar>(1));
-
- // check compatibility of dot and adjoint
- VERIFY(ei_isApprox(v1.eigen2_dot(square * v2), (square.adjoint() * v1).eigen2_dot(v2), largerEps));
-
- // like in testBasicStuff, test operator() to check const-qualification
- int r = ei_random<int>(0, rows-1),
- c = ei_random<int>(0, cols-1);
- VERIFY_IS_APPROX(m1.conjugate()(r,c), ei_conj(m1(r,c)));
- VERIFY_IS_APPROX(m1.adjoint()(c,r), ei_conj(m1(r,c)));
-
- if(NumTraits<Scalar>::HasFloatingPoint)
- {
- // check that Random().normalized() works: tricky as the random xpr must be evaluated by
- // normalized() in order to produce a consistent result.
- VERIFY_IS_APPROX(VectorType::Random(rows).normalized().norm(), RealScalar(1));
- }
-
- // check inplace transpose
- m3 = m1;
- m3.transposeInPlace();
- VERIFY_IS_APPROX(m3,m1.transpose());
- m3.transposeInPlace();
- VERIFY_IS_APPROX(m3,m1);
-
-}
-
-void test_eigen2_adjoint()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( adjoint(Matrix<float, 1, 1>()) );
- CALL_SUBTEST_2( adjoint(Matrix3d()) );
- CALL_SUBTEST_3( adjoint(Matrix4f()) );
- CALL_SUBTEST_4( adjoint(MatrixXcf(4, 4)) );
- CALL_SUBTEST_5( adjoint(MatrixXi(8, 12)) );
- CALL_SUBTEST_6( adjoint(MatrixXf(21, 21)) );
- }
- // test a large matrix only once
- CALL_SUBTEST_7( adjoint(Matrix<float, 100, 100>()) );
-}
-
diff --git a/test/eigen2/eigen2_alignedbox.cpp b/test/eigen2/eigen2_alignedbox.cpp
deleted file mode 100644
index 35043b958..000000000
--- a/test/eigen2/eigen2_alignedbox.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
-
-#include "main.h"
-#include <Eigen/Geometry>
-#include <Eigen/LU>
-#include <Eigen/QR>
-
-template<typename BoxType> void alignedbox(const BoxType& _box)
-{
- /* this test covers the following files:
- AlignedBox.h
- */
-
- const int dim = _box.dim();
- typedef typename BoxType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Matrix<Scalar, BoxType::AmbientDimAtCompileTime, 1> VectorType;
-
- VectorType p0 = VectorType::Random(dim);
- VectorType p1 = VectorType::Random(dim);
- RealScalar s1 = ei_random<RealScalar>(0,1);
-
- BoxType b0(dim);
- BoxType b1(VectorType::Random(dim),VectorType::Random(dim));
- BoxType b2;
-
- b0.extend(p0);
- b0.extend(p1);
- VERIFY(b0.contains(p0*s1+(Scalar(1)-s1)*p1));
- VERIFY(!b0.contains(p0 + (1+s1)*(p1-p0)));
-
- (b2 = b0).extend(b1);
- VERIFY(b2.contains(b0));
- VERIFY(b2.contains(b1));
- VERIFY_IS_APPROX(b2.clamp(b0), b0);
-
- // casting
- const int Dim = BoxType::AmbientDimAtCompileTime;
- typedef typename GetDifferentType<Scalar>::type OtherScalar;
- AlignedBox<OtherScalar,Dim> hp1f = b0.template cast<OtherScalar>();
- VERIFY_IS_APPROX(hp1f.template cast<Scalar>(),b0);
- AlignedBox<Scalar,Dim> hp1d = b0.template cast<Scalar>();
- VERIFY_IS_APPROX(hp1d.template cast<Scalar>(),b0);
-}
-
-void test_eigen2_alignedbox()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( alignedbox(AlignedBox<float,2>()) );
- CALL_SUBTEST_2( alignedbox(AlignedBox<float,3>()) );
- CALL_SUBTEST_3( alignedbox(AlignedBox<double,4>()) );
- }
-}
diff --git a/test/eigen2/eigen2_array.cpp b/test/eigen2/eigen2_array.cpp
deleted file mode 100644
index c1ff40ce7..000000000
--- a/test/eigen2/eigen2_array.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
-
-#include "main.h"
-#include <Eigen/Array>
-
-template<typename MatrixType> void array(const MatrixType& m)
-{
- /* this test covers the following files:
- Array.cpp
- */
-
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
-
- int rows = m.rows();
- int cols = m.cols();
-
- MatrixType m1 = MatrixType::Random(rows, cols),
- m2 = MatrixType::Random(rows, cols),
- m3(rows, cols);
-
- Scalar s1 = ei_random<Scalar>(),
- s2 = ei_random<Scalar>();
-
- // scalar addition
- VERIFY_IS_APPROX(m1.cwise() + s1, s1 + m1.cwise());
- VERIFY_IS_APPROX(m1.cwise() + s1, MatrixType::Constant(rows,cols,s1) + m1);
- VERIFY_IS_APPROX((m1*Scalar(2)).cwise() - s2, (m1+m1) - MatrixType::Constant(rows,cols,s2) );
- m3 = m1;
- m3.cwise() += s2;
- VERIFY_IS_APPROX(m3, m1.cwise() + s2);
- m3 = m1;
- m3.cwise() -= s1;
- VERIFY_IS_APPROX(m3, m1.cwise() - s1);
-
- // reductions
- VERIFY_IS_APPROX(m1.colwise().sum().sum(), m1.sum());
- VERIFY_IS_APPROX(m1.rowwise().sum().sum(), m1.sum());
- if (!ei_isApprox(m1.sum(), (m1+m2).sum()))
- VERIFY_IS_NOT_APPROX(((m1+m2).rowwise().sum()).sum(), m1.sum());
- VERIFY_IS_APPROX(m1.colwise().sum(), m1.colwise().redux(internal::scalar_sum_op<Scalar>()));
-}
-
-template<typename MatrixType> void comparisons(const MatrixType& m)
-{
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
-
- int rows = m.rows();
- int cols = m.cols();
-
- int r = ei_random<int>(0, rows-1),
- c = ei_random<int>(0, cols-1);
-
- MatrixType m1 = MatrixType::Random(rows, cols),
- m2 = MatrixType::Random(rows, cols),
- m3(rows, cols);
-
- VERIFY(((m1.cwise() + Scalar(1)).cwise() > m1).all());
- VERIFY(((m1.cwise() - Scalar(1)).cwise() < m1).all());
- if (rows*cols>1)
- {
- m3 = m1;
- m3(r,c) += 1;
- VERIFY(! (m1.cwise() < m3).all() );
- VERIFY(! (m1.cwise() > m3).all() );
- }
-
- // comparisons to scalar
- VERIFY( (m1.cwise() != (m1(r,c)+1) ).any() );
- VERIFY( (m1.cwise() > (m1(r,c)-1) ).any() );
- VERIFY( (m1.cwise() < (m1(r,c)+1) ).any() );
- VERIFY( (m1.cwise() == m1(r,c) ).any() );
-
- // test Select
- VERIFY_IS_APPROX( (m1.cwise()<m2).select(m1,m2), m1.cwise().min(m2) );
- VERIFY_IS_APPROX( (m1.cwise()>m2).select(m1,m2), m1.cwise().max(m2) );
- Scalar mid = (m1.cwise().abs().minCoeff() + m1.cwise().abs().maxCoeff())/Scalar(2);
- for (int j=0; j<cols; ++j)
- for (int i=0; i<rows; ++i)
- m3(i,j) = ei_abs(m1(i,j))<mid ? 0 : m1(i,j);
- VERIFY_IS_APPROX( (m1.cwise().abs().cwise()<MatrixType::Constant(rows,cols,mid))
- .select(MatrixType::Zero(rows,cols),m1), m3);
- // shorter versions:
- VERIFY_IS_APPROX( (m1.cwise().abs().cwise()<MatrixType::Constant(rows,cols,mid))
- .select(0,m1), m3);
- VERIFY_IS_APPROX( (m1.cwise().abs().cwise()>=MatrixType::Constant(rows,cols,mid))
- .select(m1,0), m3);
- // even shorter version:
- VERIFY_IS_APPROX( (m1.cwise().abs().cwise()<mid).select(0,m1), m3);
-
- // count
- VERIFY(((m1.cwise().abs().cwise()+1).cwise()>RealScalar(0.1)).count() == rows*cols);
- VERIFY_IS_APPROX(((m1.cwise().abs().cwise()+1).cwise()>RealScalar(0.1)).colwise().count().template cast<int>(), RowVectorXi::Constant(cols,rows));
- VERIFY_IS_APPROX(((m1.cwise().abs().cwise()+1).cwise()>RealScalar(0.1)).rowwise().count().template cast<int>(), VectorXi::Constant(rows, cols));
-}
-
-template<typename VectorType> void lpNorm(const VectorType& v)
-{
- VectorType u = VectorType::Random(v.size());
-
- VERIFY_IS_APPROX(u.template lpNorm<Infinity>(), u.cwise().abs().maxCoeff());
- VERIFY_IS_APPROX(u.template lpNorm<1>(), u.cwise().abs().sum());
- VERIFY_IS_APPROX(u.template lpNorm<2>(), ei_sqrt(u.cwise().abs().cwise().square().sum()));
- VERIFY_IS_APPROX(ei_pow(u.template lpNorm<5>(), typename VectorType::RealScalar(5)), u.cwise().abs().cwise().pow(5).sum());
-}
-
-void test_eigen2_array()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( array(Matrix<float, 1, 1>()) );
- CALL_SUBTEST_2( array(Matrix2f()) );
- CALL_SUBTEST_3( array(Matrix4d()) );
- CALL_SUBTEST_4( array(MatrixXcf(3, 3)) );
- CALL_SUBTEST_5( array(MatrixXf(8, 12)) );
- CALL_SUBTEST_6( array(MatrixXi(8, 12)) );
- }
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( comparisons(Matrix<float, 1, 1>()) );
- CALL_SUBTEST_2( comparisons(Matrix2f()) );
- CALL_SUBTEST_3( comparisons(Matrix4d()) );
- CALL_SUBTEST_5( comparisons(MatrixXf(8, 12)) );
- CALL_SUBTEST_6( comparisons(MatrixXi(8, 12)) );
- }
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( lpNorm(Matrix<float, 1, 1>()) );
- CALL_SUBTEST_2( lpNorm(Vector2f()) );
- CALL_SUBTEST_3( lpNorm(Vector3d()) );
- CALL_SUBTEST_4( lpNorm(Vector4f()) );
- CALL_SUBTEST_5( lpNorm(VectorXf(16)) );
- CALL_SUBTEST_7( lpNorm(VectorXcd(10)) );
- }
-}
diff --git a/test/eigen2/eigen2_basicstuff.cpp b/test/eigen2/eigen2_basicstuff.cpp
deleted file mode 100644
index dd2dec1ef..000000000
--- a/test/eigen2/eigen2_basicstuff.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@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"
-
-template<typename MatrixType> void basicStuff(const MatrixType& m)
-{
- typedef typename MatrixType::Scalar Scalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
-
- int rows = m.rows();
- int cols = m.cols();
-
- // this test relies a lot on Random.h, and there's not much more that we can do
- // to test it, hence I consider that we will have tested Random.h
- MatrixType m1 = MatrixType::Random(rows, cols),
- m2 = MatrixType::Random(rows, cols),
- m3(rows, cols),
- mzero = MatrixType::Zero(rows, cols),
- square = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>::Random(rows, rows);
- VectorType v1 = VectorType::Random(rows),
- vzero = VectorType::Zero(rows);
-
- Scalar x = ei_random<Scalar>();
-
- int r = ei_random<int>(0, rows-1),
- c = ei_random<int>(0, cols-1);
-
- m1.coeffRef(r,c) = x;
- VERIFY_IS_APPROX(x, m1.coeff(r,c));
- m1(r,c) = x;
- VERIFY_IS_APPROX(x, m1(r,c));
- v1.coeffRef(r) = x;
- VERIFY_IS_APPROX(x, v1.coeff(r));
- v1(r) = x;
- VERIFY_IS_APPROX(x, v1(r));
- v1[r] = x;
- VERIFY_IS_APPROX(x, v1[r]);
-
- VERIFY_IS_APPROX( v1, v1);
- VERIFY_IS_NOT_APPROX( v1, 2*v1);
- VERIFY_IS_MUCH_SMALLER_THAN( vzero, v1);
- if(NumTraits<Scalar>::HasFloatingPoint)
- VERIFY_IS_MUCH_SMALLER_THAN( vzero, v1.norm());
- VERIFY_IS_NOT_MUCH_SMALLER_THAN(v1, v1);
- VERIFY_IS_APPROX( vzero, v1-v1);
- VERIFY_IS_APPROX( m1, m1);
- VERIFY_IS_NOT_APPROX( m1, 2*m1);
- VERIFY_IS_MUCH_SMALLER_THAN( mzero, m1);
- VERIFY_IS_NOT_MUCH_SMALLER_THAN(m1, m1);
- VERIFY_IS_APPROX( mzero, m1-m1);
-
- // always test operator() on each read-only expression class,
- // in order to check const-qualifiers.
- // indeed, if an expression class (here Zero) is meant to be read-only,
- // hence has no _write() method, the corresponding MatrixBase method (here zero())
- // should return a const-qualified object so that it is the const-qualified
- // operator() that gets called, which in turn calls _read().
- VERIFY_IS_MUCH_SMALLER_THAN(MatrixType::Zero(rows,cols)(r,c), static_cast<Scalar>(1));
-
- // now test copying a row-vector into a (column-)vector and conversely.
- square.col(r) = square.row(r).eval();
- Matrix<Scalar, 1, MatrixType::RowsAtCompileTime> rv(rows);
- Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> cv(rows);
- rv = square.row(r);
- cv = square.col(r);
- VERIFY_IS_APPROX(rv, cv.transpose());
-
- if(cols!=1 && rows!=1 && MatrixType::SizeAtCompileTime!=Dynamic)
- {
- VERIFY_RAISES_ASSERT(m1 = (m2.block(0,0, rows-1, cols-1)));
- }
-
- VERIFY_IS_APPROX(m3 = m1,m1);
- MatrixType m4;
- VERIFY_IS_APPROX(m4 = m1,m1);
-
- // test swap
- m3 = m1;
- m1.swap(m2);
- VERIFY_IS_APPROX(m3, m2);
- if(rows*cols>=3)
- {
- VERIFY_IS_NOT_APPROX(m3, m1);
- }
-}
-
-void test_eigen2_basicstuff()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( basicStuff(Matrix<float, 1, 1>()) );
- CALL_SUBTEST_2( basicStuff(Matrix4d()) );
- CALL_SUBTEST_3( basicStuff(MatrixXcf(3, 3)) );
- CALL_SUBTEST_4( basicStuff(MatrixXi(8, 12)) );
- CALL_SUBTEST_5( basicStuff(MatrixXcd(20, 20)) );
- CALL_SUBTEST_6( basicStuff(Matrix<float, 100, 100>()) );
- CALL_SUBTEST_7( basicStuff(Matrix<long double,Dynamic,Dynamic>(10,10)) );
- }
-}
diff --git a/test/eigen2/eigen2_bug_132.cpp b/test/eigen2/eigen2_bug_132.cpp
deleted file mode 100644
index 7fe3610ce..000000000
--- a/test/eigen2/eigen2_bug_132.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@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"
-
-void test_eigen2_bug_132() {
- int size = 100;
- MatrixXd A(size, size);
- VectorXd b(size), c(size);
- {
- VectorXd y = A.transpose() * (b-c); // bug 132: infinite recursion in coeffRef
- VectorXd z = (b-c).transpose() * A; // bug 132: infinite recursion in coeffRef
- }
-
- // the following ones weren't failing, but let's include them for completeness:
- {
- VectorXd y = A * (b-c);
- VectorXd z = (b-c).transpose() * A.transpose();
- }
-}
diff --git a/test/eigen2/eigen2_cholesky.cpp b/test/eigen2/eigen2_cholesky.cpp
deleted file mode 100644
index 9c4b6f561..000000000
--- a/test/eigen2/eigen2_cholesky.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
-
-#define EIGEN_NO_ASSERTION_CHECKING
-#include "main.h"
-#include <Eigen/Cholesky>
-#include <Eigen/LU>
-
-#ifdef HAS_GSL
-#include "gsl_helper.h"
-#endif
-
-template<typename MatrixType> void cholesky(const MatrixType& m)
-{
- /* this test covers the following files:
- LLT.h LDLT.h
- */
- int rows = m.rows();
- int cols = m.cols();
-
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
-
- MatrixType a0 = MatrixType::Random(rows,cols);
- VectorType vecB = VectorType::Random(rows), vecX(rows);
- MatrixType matB = MatrixType::Random(rows,cols), matX(rows,cols);
- SquareMatrixType symm = a0 * a0.adjoint();
- // let's make sure the matrix is not singular or near singular
- MatrixType a1 = MatrixType::Random(rows,cols);
- symm += a1 * a1.adjoint();
-
- #ifdef HAS_GSL
- if (ei_is_same_type<RealScalar,double>::ret)
- {
- typedef GslTraits<Scalar> Gsl;
- typename Gsl::Matrix gMatA=0, gSymm=0;
- typename Gsl::Vector gVecB=0, gVecX=0;
- convert<MatrixType>(symm, gSymm);
- convert<MatrixType>(symm, gMatA);
- convert<VectorType>(vecB, gVecB);
- convert<VectorType>(vecB, gVecX);
- Gsl::cholesky(gMatA);
- Gsl::cholesky_solve(gMatA, gVecB, gVecX);
- VectorType vecX(rows), _vecX, _vecB;
- convert(gVecX, _vecX);
- symm.llt().solve(vecB, &vecX);
- Gsl::prod(gSymm, gVecX, gVecB);
- convert(gVecB, _vecB);
- // test gsl itself !
- VERIFY_IS_APPROX(vecB, _vecB);
- VERIFY_IS_APPROX(vecX, _vecX);
-
- Gsl::free(gMatA);
- Gsl::free(gSymm);
- Gsl::free(gVecB);
- Gsl::free(gVecX);
- }
- #endif
-
- {
- LDLT<SquareMatrixType> ldlt(symm);
- VERIFY(ldlt.isPositiveDefinite());
- // in eigen3, LDLT is pivoting
- //VERIFY_IS_APPROX(symm, ldlt.matrixL() * ldlt.vectorD().asDiagonal() * ldlt.matrixL().adjoint());
- ldlt.solve(vecB, &vecX);
- VERIFY_IS_APPROX(symm * vecX, vecB);
- ldlt.solve(matB, &matX);
- VERIFY_IS_APPROX(symm * matX, matB);
- }
-
- {
- LLT<SquareMatrixType> chol(symm);
- VERIFY(chol.isPositiveDefinite());
- VERIFY_IS_APPROX(symm, chol.matrixL() * chol.matrixL().adjoint());
- chol.solve(vecB, &vecX);
- VERIFY_IS_APPROX(symm * vecX, vecB);
- chol.solve(matB, &matX);
- VERIFY_IS_APPROX(symm * matX, matB);
- }
-
-#if 0 // cholesky is not rank-revealing anyway
- // test isPositiveDefinite on non definite matrix
- if (rows>4)
- {
- SquareMatrixType symm = a0.block(0,0,rows,cols-4) * a0.block(0,0,rows,cols-4).adjoint();
- LLT<SquareMatrixType> chol(symm);
- VERIFY(!chol.isPositiveDefinite());
- LDLT<SquareMatrixType> cholnosqrt(symm);
- VERIFY(!cholnosqrt.isPositiveDefinite());
- }
-#endif
-}
-
-void test_eigen2_cholesky()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( cholesky(Matrix<double,1,1>()) );
- CALL_SUBTEST_2( cholesky(Matrix2d()) );
- CALL_SUBTEST_3( cholesky(Matrix3f()) );
- CALL_SUBTEST_4( cholesky(Matrix4d()) );
- CALL_SUBTEST_5( cholesky(MatrixXcd(7,7)) );
- CALL_SUBTEST_6( cholesky(MatrixXf(17,17)) );
- CALL_SUBTEST_7( cholesky(MatrixXd(33,33)) );
- }
-}
diff --git a/test/eigen2/eigen2_commainitializer.cpp b/test/eigen2/eigen2_commainitializer.cpp
deleted file mode 100644
index e0f901e0b..000000000
--- a/test/eigen2/eigen2_commainitializer.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
-
-#include "main.h"
-
-void test_eigen2_commainitializer()
-{
- Matrix3d m3;
- Matrix4d m4;
-
- VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8) );
-
- #ifndef _MSC_VER
- VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) );
- #endif
-
- double data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- Matrix3d ref = Map<Matrix<double,3,3,RowMajor> >(data);
-
- m3 = Matrix3d::Random();
- m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9;
- VERIFY_IS_APPROX(m3, ref );
-
- Vector3d vec[3];
- vec[0] << 1, 4, 7;
- vec[1] << 2, 5, 8;
- vec[2] << 3, 6, 9;
- m3 = Matrix3d::Random();
- m3 << vec[0], vec[1], vec[2];
- VERIFY_IS_APPROX(m3, ref);
-
- vec[0] << 1, 2, 3;
- vec[1] << 4, 5, 6;
- vec[2] << 7, 8, 9;
- m3 = Matrix3d::Random();
- m3 << vec[0].transpose(),
- 4, 5, 6,
- vec[2].transpose();
- VERIFY_IS_APPROX(m3, ref);
-}
diff --git a/test/eigen2/eigen2_cwiseop.cpp b/test/eigen2/eigen2_cwiseop.cpp
deleted file mode 100644
index 22e1cc342..000000000
--- a/test/eigen2/eigen2_cwiseop.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@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 <functional>
-#include <Eigen/Array>
-
-using namespace std;
-
-template<typename Scalar> struct AddIfNull {
- const Scalar operator() (const Scalar a, const Scalar b) const {return a<=1e-3 ? b : a;}
- enum { Cost = NumTraits<Scalar>::AddCost };
-};
-
-template<typename MatrixType> void cwiseops(const MatrixType& m)
-{
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
-
- 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),
- mzero = MatrixType::Zero(rows, cols),
- mones = MatrixType::Ones(rows, cols),
- identity = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
- ::Identity(rows, rows);
- VectorType vzero = VectorType::Zero(rows),
- vones = VectorType::Ones(rows),
- v3(rows);
-
- int r = ei_random<int>(0, rows-1),
- c = ei_random<int>(0, cols-1);
-
- Scalar s1 = ei_random<Scalar>();
-
- // test Zero, Ones, Constant, and the set* variants
- m3 = MatrixType::Constant(rows, cols, s1);
- for (int j=0; j<cols; ++j)
- for (int i=0; i<rows; ++i)
- {
- VERIFY_IS_APPROX(mzero(i,j), Scalar(0));
- VERIFY_IS_APPROX(mones(i,j), Scalar(1));
- VERIFY_IS_APPROX(m3(i,j), s1);
- }
- VERIFY(mzero.isZero());
- VERIFY(mones.isOnes());
- VERIFY(m3.isConstant(s1));
- VERIFY(identity.isIdentity());
- VERIFY_IS_APPROX(m4.setConstant(s1), m3);
- VERIFY_IS_APPROX(m4.setConstant(rows,cols,s1), m3);
- VERIFY_IS_APPROX(m4.setZero(), mzero);
- VERIFY_IS_APPROX(m4.setZero(rows,cols), mzero);
- VERIFY_IS_APPROX(m4.setOnes(), mones);
- VERIFY_IS_APPROX(m4.setOnes(rows,cols), mones);
- m4.fill(s1);
- VERIFY_IS_APPROX(m4, m3);
-
- VERIFY_IS_APPROX(v3.setConstant(rows, s1), VectorType::Constant(rows,s1));
- VERIFY_IS_APPROX(v3.setZero(rows), vzero);
- VERIFY_IS_APPROX(v3.setOnes(rows), vones);
-
- m2 = m2.template binaryExpr<AddIfNull<Scalar> >(mones);
-
- VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().abs2());
- VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().square());
- VERIFY_IS_APPROX(m1.cwise().pow(3), m1.cwise().cube());
-
- VERIFY_IS_APPROX(m1 + mones, m1.cwise()+Scalar(1));
- VERIFY_IS_APPROX(m1 - mones, m1.cwise()-Scalar(1));
- m3 = m1; m3.cwise() += 1;
- VERIFY_IS_APPROX(m1 + mones, m3);
- m3 = m1; m3.cwise() -= 1;
- VERIFY_IS_APPROX(m1 - mones, m3);
-
- VERIFY_IS_APPROX(m2, m2.cwise() * mones);
- VERIFY_IS_APPROX(m1.cwise() * m2, m2.cwise() * m1);
- m3 = m1;
- m3.cwise() *= m2;
- VERIFY_IS_APPROX(m3, m1.cwise() * m2);
-
- VERIFY_IS_APPROX(mones, m2.cwise()/m2);
- if(NumTraits<Scalar>::HasFloatingPoint)
- {
- VERIFY_IS_APPROX(m1.cwise() / m2, m1.cwise() * (m2.cwise().inverse()));
- m3 = m1.cwise().abs().cwise().sqrt();
- VERIFY_IS_APPROX(m3.cwise().square(), m1.cwise().abs());
- VERIFY_IS_APPROX(m1.cwise().square().cwise().sqrt(), m1.cwise().abs());
- VERIFY_IS_APPROX(m1.cwise().abs().cwise().log().cwise().exp() , m1.cwise().abs());
-
- VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().square());
- m3 = (m1.cwise().abs().cwise()<=RealScalar(0.01)).select(mones,m1);
- VERIFY_IS_APPROX(m3.cwise().pow(-1), m3.cwise().inverse());
- m3 = m1.cwise().abs();
- VERIFY_IS_APPROX(m3.cwise().pow(RealScalar(0.5)), m3.cwise().sqrt());
-
-// VERIFY_IS_APPROX(m1.cwise().tan(), m1.cwise().sin().cwise() / m1.cwise().cos());
- VERIFY_IS_APPROX(mones, m1.cwise().sin().cwise().square() + m1.cwise().cos().cwise().square());
- m3 = m1;
- m3.cwise() /= m2;
- VERIFY_IS_APPROX(m3, m1.cwise() / m2);
- }
-
- // check min
- VERIFY_IS_APPROX( m1.cwise().min(m2), m2.cwise().min(m1) );
- VERIFY_IS_APPROX( m1.cwise().min(m1+mones), m1 );
- VERIFY_IS_APPROX( m1.cwise().min(m1-mones), m1-mones );
-
- // check max
- VERIFY_IS_APPROX( m1.cwise().max(m2), m2.cwise().max(m1) );
- VERIFY_IS_APPROX( m1.cwise().max(m1-mones), m1 );
- VERIFY_IS_APPROX( m1.cwise().max(m1+mones), m1+mones );
-
- VERIFY( (m1.cwise() == m1).all() );
- VERIFY( (m1.cwise() != m2).any() );
- VERIFY(!(m1.cwise() == (m1+mones)).any() );
- if (rows*cols>1)
- {
- m3 = m1;
- m3(r,c) += 1;
- VERIFY( (m1.cwise() == m3).any() );
- VERIFY( !(m1.cwise() == m3).all() );
- }
- VERIFY( (m1.cwise().min(m2).cwise() <= m2).all() );
- VERIFY( (m1.cwise().max(m2).cwise() >= m2).all() );
- VERIFY( (m1.cwise().min(m2).cwise() < (m1+mones)).all() );
- VERIFY( (m1.cwise().max(m2).cwise() > (m1-mones)).all() );
-
- VERIFY( (m1.cwise()<m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).all() );
- VERIFY( !(m1.cwise()<m1.unaryExpr(bind2nd(minus<Scalar>(), Scalar(1)))).all() );
- VERIFY( !(m1.cwise()>m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).any() );
-}
-
-void test_eigen2_cwiseop()
-{
- for(int i = 0; i < g_repeat ; i++) {
- CALL_SUBTEST_1( cwiseops(Matrix<float, 1, 1>()) );
- CALL_SUBTEST_2( cwiseops(Matrix4d()) );
- CALL_SUBTEST_3( cwiseops(MatrixXf(3, 3)) );
- CALL_SUBTEST_3( cwiseops(MatrixXf(22, 22)) );
- CALL_SUBTEST_4( cwiseops(MatrixXi(8, 12)) );
- CALL_SUBTEST_5( cwiseops(MatrixXd(20, 20)) );
- }
-}
diff --git a/test/eigen2/eigen2_determinant.cpp b/test/eigen2/eigen2_determinant.cpp
deleted file mode 100644
index c7b4ad053..000000000
--- a/test/eigen2/eigen2_determinant.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
-
-#include "main.h"
-#include <Eigen/LU>
-
-template<typename MatrixType> void determinant(const MatrixType& m)
-{
- /* this test covers the following files:
- Determinant.h
- */
- int size = m.rows();
-
- MatrixType m1(size, size), m2(size, size);
- m1.setRandom();
- m2.setRandom();
- typedef typename MatrixType::Scalar Scalar;
- Scalar x = ei_random<Scalar>();
- VERIFY_IS_APPROX(MatrixType::Identity(size, size).determinant(), Scalar(1));
- VERIFY_IS_APPROX((m1*m2).determinant(), m1.determinant() * m2.determinant());
- if(size==1) return;
- int i = ei_random<int>(0, size-1);
- int j;
- do {
- j = ei_random<int>(0, size-1);
- } while(j==i);
- m2 = m1;
- m2.row(i).swap(m2.row(j));
- VERIFY_IS_APPROX(m2.determinant(), -m1.determinant());
- m2 = m1;
- m2.col(i).swap(m2.col(j));
- VERIFY_IS_APPROX(m2.determinant(), -m1.determinant());
- VERIFY_IS_APPROX(m2.determinant(), m2.transpose().determinant());
- VERIFY_IS_APPROX(ei_conj(m2.determinant()), m2.adjoint().determinant());
- m2 = m1;
- m2.row(i) += x*m2.row(j);
- VERIFY_IS_APPROX(m2.determinant(), m1.determinant());
- m2 = m1;
- m2.row(i) *= x;
- VERIFY_IS_APPROX(m2.determinant(), m1.determinant() * x);
-}
-
-void test_eigen2_determinant()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( determinant(Matrix<float, 1, 1>()) );
- CALL_SUBTEST_2( determinant(Matrix<double, 2, 2>()) );
- CALL_SUBTEST_3( determinant(Matrix<double, 3, 3>()) );
- CALL_SUBTEST_4( determinant(Matrix<double, 4, 4>()) );
- CALL_SUBTEST_5( determinant(Matrix<std::complex<double>, 10, 10>()) );
- CALL_SUBTEST_6( determinant(MatrixXd(20, 20)) );
- }
- CALL_SUBTEST_6( determinant(MatrixXd(200, 200)) );
-}
diff --git a/test/eigen2/eigen2_dynalloc.cpp b/test/eigen2/eigen2_dynalloc.cpp
deleted file mode 100644
index 1891a9e33..000000000
--- a/test/eigen2/eigen2_dynalloc.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
-
-#include "main.h"
-
-#if EIGEN_ARCH_WANTS_ALIGNMENT
-#define ALIGNMENT 16
-#else
-#define ALIGNMENT 1
-#endif
-
-void check_handmade_aligned_malloc()
-{
- for(int i = 1; i < 1000; i++)
- {
- char *p = (char*)ei_handmade_aligned_malloc(i);
- VERIFY(std::size_t(p)%ALIGNMENT==0);
- // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
- for(int j = 0; j < i; j++) p[j]=0;
- ei_handmade_aligned_free(p);
- }
-}
-
-void check_aligned_malloc()
-{
- for(int i = 1; i < 1000; i++)
- {
- char *p = (char*)ei_aligned_malloc(i);
- VERIFY(std::size_t(p)%ALIGNMENT==0);
- // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
- for(int j = 0; j < i; j++) p[j]=0;
- ei_aligned_free(p);
- }
-}
-
-void check_aligned_new()
-{
- for(int i = 1; i < 1000; i++)
- {
- float *p = ei_aligned_new<float>(i);
- VERIFY(std::size_t(p)%ALIGNMENT==0);
- // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
- for(int j = 0; j < i; j++) p[j]=0;
- ei_aligned_delete(p,i);
- }
-}
-
-void check_aligned_stack_alloc()
-{
- for(int i = 1; i < 1000; i++)
- {
- ei_declare_aligned_stack_constructed_variable(float, p, i, 0);
- VERIFY(std::size_t(p)%ALIGNMENT==0);
- // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
- for(int j = 0; j < i; j++) p[j]=0;
- }
-}
-
-
-// test compilation with both a struct and a class...
-struct MyStruct
-{
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW
- char dummychar;
- Vector4f avec;
-};
-
-class MyClassA
-{
- public:
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW
- char dummychar;
- Vector4f avec;
-};
-
-template<typename T> void check_dynaligned()
-{
- T* obj = new T;
- VERIFY(std::size_t(obj)%ALIGNMENT==0);
- delete obj;
-}
-
-void test_eigen2_dynalloc()
-{
- // low level dynamic memory allocation
- CALL_SUBTEST(check_handmade_aligned_malloc());
- CALL_SUBTEST(check_aligned_malloc());
- CALL_SUBTEST(check_aligned_new());
- CALL_SUBTEST(check_aligned_stack_alloc());
-
- for (int i=0; i<g_repeat*100; ++i)
- {
- CALL_SUBTEST( check_dynaligned<Vector4f>() );
- CALL_SUBTEST( check_dynaligned<Vector2d>() );
- CALL_SUBTEST( check_dynaligned<Matrix4f>() );
- CALL_SUBTEST( check_dynaligned<Vector4d>() );
- CALL_SUBTEST( check_dynaligned<Vector4i>() );
- }
-
- // check static allocation, who knows ?
- {
- MyStruct foo0; VERIFY(std::size_t(foo0.avec.data())%ALIGNMENT==0);
- MyClassA fooA; VERIFY(std::size_t(fooA.avec.data())%ALIGNMENT==0);
- }
-
- // dynamic allocation, single object
- for (int i=0; i<g_repeat*100; ++i)
- {
- MyStruct *foo0 = new MyStruct(); VERIFY(std::size_t(foo0->avec.data())%ALIGNMENT==0);
- MyClassA *fooA = new MyClassA(); VERIFY(std::size_t(fooA->avec.data())%ALIGNMENT==0);
- delete foo0;
- delete fooA;
- }
-
- // dynamic allocation, array
- const int N = 10;
- for (int i=0; i<g_repeat*100; ++i)
- {
- MyStruct *foo0 = new MyStruct[N]; VERIFY(std::size_t(foo0->avec.data())%ALIGNMENT==0);
- MyClassA *fooA = new MyClassA[N]; VERIFY(std::size_t(fooA->avec.data())%ALIGNMENT==0);
- delete[] foo0;
- delete[] fooA;
- }
-
-}
diff --git a/test/eigen2/eigen2_eigensolver.cpp b/test/eigen2/eigen2_eigensolver.cpp
deleted file mode 100644
index 48b4ace43..000000000
--- a/test/eigen2/eigen2_eigensolver.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
-
-#include "main.h"
-#include <Eigen/QR>
-
-#ifdef HAS_GSL
-#include "gsl_helper.h"
-#endif
-
-template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m)
-{
- /* this test covers the following files:
- EigenSolver.h, SelfAdjointEigenSolver.h (and indirectly: Tridiagonalization.h)
- */
- int rows = m.rows();
- int cols = m.cols();
-
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
- typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
- typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;
-
- RealScalar largerEps = 10*test_precision<RealScalar>();
-
- MatrixType a = MatrixType::Random(rows,cols);
- MatrixType a1 = MatrixType::Random(rows,cols);
- MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1;
-
- MatrixType b = MatrixType::Random(rows,cols);
- MatrixType b1 = MatrixType::Random(rows,cols);
- MatrixType symmB = b.adjoint() * b + b1.adjoint() * b1;
-
- SelfAdjointEigenSolver<MatrixType> eiSymm(symmA);
- // generalized eigen pb
- SelfAdjointEigenSolver<MatrixType> eiSymmGen(symmA, symmB);
-
- #ifdef HAS_GSL
- if (ei_is_same_type<RealScalar,double>::ret)
- {
- typedef GslTraits<Scalar> Gsl;
- typename Gsl::Matrix gEvec=0, gSymmA=0, gSymmB=0;
- typename GslTraits<RealScalar>::Vector gEval=0;
- RealVectorType _eval;
- MatrixType _evec;
- convert<MatrixType>(symmA, gSymmA);
- convert<MatrixType>(symmB, gSymmB);
- convert<MatrixType>(symmA, gEvec);
- gEval = GslTraits<RealScalar>::createVector(rows);
-
- Gsl::eigen_symm(gSymmA, gEval, gEvec);
- convert(gEval, _eval);
- convert(gEvec, _evec);
-
- // test gsl itself !
- VERIFY((symmA * _evec).isApprox(_evec * _eval.asDiagonal(), largerEps));
-
- // compare with eigen
- VERIFY_IS_APPROX(_eval, eiSymm.eigenvalues());
- VERIFY_IS_APPROX(_evec.cwise().abs(), eiSymm.eigenvectors().cwise().abs());
-
- // generalized pb
- Gsl::eigen_symm_gen(gSymmA, gSymmB, gEval, gEvec);
- convert(gEval, _eval);
- convert(gEvec, _evec);
- // test GSL itself:
- VERIFY((symmA * _evec).isApprox(symmB * (_evec * _eval.asDiagonal()), largerEps));
-
- // compare with eigen
- MatrixType normalized_eivec = eiSymmGen.eigenvectors()*eiSymmGen.eigenvectors().colwise().norm().asDiagonal().inverse();
- VERIFY_IS_APPROX(_eval, eiSymmGen.eigenvalues());
- VERIFY_IS_APPROX(_evec.cwiseAbs(), normalized_eivec.cwiseAbs());
-
- Gsl::free(gSymmA);
- Gsl::free(gSymmB);
- GslTraits<RealScalar>::free(gEval);
- Gsl::free(gEvec);
- }
- #endif
-
- VERIFY((symmA * eiSymm.eigenvectors()).isApprox(
- eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal(), largerEps));
-
- // generalized eigen problem Ax = lBx
- VERIFY((symmA * eiSymmGen.eigenvectors()).isApprox(
- symmB * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));
-
- MatrixType sqrtSymmA = eiSymm.operatorSqrt();
- VERIFY_IS_APPROX(symmA, sqrtSymmA*sqrtSymmA);
- VERIFY_IS_APPROX(sqrtSymmA, symmA*eiSymm.operatorInverseSqrt());
-}
-
-template<typename MatrixType> void eigensolver(const MatrixType& m)
-{
- /* this test covers the following files:
- EigenSolver.h
- */
- int rows = m.rows();
- int cols = m.cols();
-
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
- typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
- typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;
-
- // RealScalar largerEps = 10*test_precision<RealScalar>();
-
- MatrixType a = MatrixType::Random(rows,cols);
- MatrixType a1 = MatrixType::Random(rows,cols);
- MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1;
-
- EigenSolver<MatrixType> ei0(symmA);
- VERIFY_IS_APPROX(symmA * ei0.pseudoEigenvectors(), ei0.pseudoEigenvectors() * ei0.pseudoEigenvalueMatrix());
- VERIFY_IS_APPROX((symmA.template cast<Complex>()) * (ei0.pseudoEigenvectors().template cast<Complex>()),
- (ei0.pseudoEigenvectors().template cast<Complex>()) * (ei0.eigenvalues().asDiagonal()));
-
- EigenSolver<MatrixType> ei1(a);
- VERIFY_IS_APPROX(a * ei1.pseudoEigenvectors(), ei1.pseudoEigenvectors() * ei1.pseudoEigenvalueMatrix());
- VERIFY_IS_APPROX(a.template cast<Complex>() * ei1.eigenvectors(),
- ei1.eigenvectors() * ei1.eigenvalues().asDiagonal());
-
-}
-
-void test_eigen2_eigensolver()
-{
- for(int i = 0; i < g_repeat; i++) {
- // very important to test a 3x3 matrix since we provide a special path for it
- CALL_SUBTEST_1( selfadjointeigensolver(Matrix3f()) );
- CALL_SUBTEST_2( selfadjointeigensolver(Matrix4d()) );
- CALL_SUBTEST_3( selfadjointeigensolver(MatrixXf(7,7)) );
- CALL_SUBTEST_4( selfadjointeigensolver(MatrixXcd(5,5)) );
- CALL_SUBTEST_5( selfadjointeigensolver(MatrixXd(19,19)) );
-
- CALL_SUBTEST_6( eigensolver(Matrix4f()) );
- CALL_SUBTEST_5( eigensolver(MatrixXd(17,17)) );
- }
-}
-
diff --git a/test/eigen2/eigen2_first_aligned.cpp b/test/eigen2/eigen2_first_aligned.cpp
deleted file mode 100644
index 51bb3cad1..000000000
--- a/test/eigen2/eigen2_first_aligned.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@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"
-
-template<typename Scalar>
-void test_eigen2_first_aligned_helper(Scalar *array, int size)
-{
- const int packet_size = sizeof(Scalar) * ei_packet_traits<Scalar>::size;
- VERIFY(((std::size_t(array) + sizeof(Scalar) * ei_alignmentOffset(array, size)) % packet_size) == 0);
-}
-
-template<typename Scalar>
-void test_eigen2_none_aligned_helper(Scalar *array, int size)
-{
- VERIFY(ei_packet_traits<Scalar>::size == 1 || ei_alignmentOffset(array, size) == size);
-}
-
-struct some_non_vectorizable_type { float x; };
-
-void test_eigen2_first_aligned()
-{
- EIGEN_ALIGN_128 float array_float[100];
- test_first_aligned_helper(array_float, 50);
- test_first_aligned_helper(array_float+1, 50);
- test_first_aligned_helper(array_float+2, 50);
- test_first_aligned_helper(array_float+3, 50);
- test_first_aligned_helper(array_float+4, 50);
- test_first_aligned_helper(array_float+5, 50);
-
- EIGEN_ALIGN_128 double array_double[100];
- test_first_aligned_helper(array_double, 50);
- test_first_aligned_helper(array_double+1, 50);
- test_first_aligned_helper(array_double+2, 50);
-
- double *array_double_plus_4_bytes = (double*)(std::size_t(array_double)+4);
- test_none_aligned_helper(array_double_plus_4_bytes, 50);
- test_none_aligned_helper(array_double_plus_4_bytes+1, 50);
-
- some_non_vectorizable_type array_nonvec[100];
- test_first_aligned_helper(array_nonvec, 100);
- test_none_aligned_helper(array_nonvec, 100);
-}
diff --git a/test/eigen2/eigen2_geometry.cpp b/test/eigen2/eigen2_geometry.cpp
deleted file mode 100644
index 514040774..000000000
--- a/test/eigen2/eigen2_geometry.cpp
+++ /dev/null
@@ -1,432 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
-
-#include "main.h"
-#include <Eigen/Geometry>
-#include <Eigen/LU>
-#include <Eigen/SVD>
-
-template<typename Scalar> void geometry(void)
-{
- /* this test covers the following files:
- Cross.h Quaternion.h, Transform.cpp
- */
-
- typedef Matrix<Scalar,2,2> Matrix2;
- typedef Matrix<Scalar,3,3> Matrix3;
- typedef Matrix<Scalar,4,4> Matrix4;
- typedef Matrix<Scalar,2,1> Vector2;
- typedef Matrix<Scalar,3,1> Vector3;
- typedef Matrix<Scalar,4,1> Vector4;
- typedef Quaternion<Scalar> Quaternionx;
- typedef AngleAxis<Scalar> AngleAxisx;
- typedef Transform<Scalar,2> Transform2;
- typedef Transform<Scalar,3> Transform3;
- typedef Scaling<Scalar,2> Scaling2;
- typedef Scaling<Scalar,3> Scaling3;
- typedef Translation<Scalar,2> Translation2;
- typedef Translation<Scalar,3> Translation3;
-
- Scalar largeEps = test_precision<Scalar>();
- if (ei_is_same_type<Scalar,float>::ret)
- largeEps = 1e-2f;
-
- Vector3 v0 = Vector3::Random(),
- v1 = Vector3::Random(),
- v2 = Vector3::Random();
- Vector2 u0 = Vector2::Random();
- Matrix3 matrot1;
-
- Scalar a = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
-
- // cross product
- VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).eigen2_dot(v1), Scalar(1));
- Matrix3 m;
- m << v0.normalized(),
- (v0.cross(v1)).normalized(),
- (v0.cross(v1).cross(v0)).normalized();
- VERIFY(m.isUnitary());
-
- // Quaternion: Identity(), setIdentity();
- Quaternionx q1, q2;
- q2.setIdentity();
- VERIFY_IS_APPROX(Quaternionx(Quaternionx::Identity()).coeffs(), q2.coeffs());
- q1.coeffs().setRandom();
- VERIFY_IS_APPROX(q1.coeffs(), (q1*q2).coeffs());
-
- // unitOrthogonal
- VERIFY_IS_MUCH_SMALLER_THAN(u0.unitOrthogonal().eigen2_dot(u0), Scalar(1));
- VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().eigen2_dot(v0), Scalar(1));
- VERIFY_IS_APPROX(u0.unitOrthogonal().norm(), Scalar(1));
- VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), Scalar(1));
-
-
- VERIFY_IS_APPROX(v0, AngleAxisx(a, v0.normalized()) * v0);
- VERIFY_IS_APPROX(-v0, AngleAxisx(Scalar(M_PI), v0.unitOrthogonal()) * v0);
- VERIFY_IS_APPROX(ei_cos(a)*v0.squaredNorm(), v0.eigen2_dot(AngleAxisx(a, v0.unitOrthogonal()) * v0));
- m = AngleAxisx(a, v0.normalized()).toRotationMatrix().adjoint();
- VERIFY_IS_APPROX(Matrix3::Identity(), m * AngleAxisx(a, v0.normalized()));
- VERIFY_IS_APPROX(Matrix3::Identity(), AngleAxisx(a, v0.normalized()) * m);
-
- q1 = AngleAxisx(a, v0.normalized());
- q2 = AngleAxisx(a, v1.normalized());
-
- // angular distance
- Scalar refangle = ei_abs(AngleAxisx(q1.inverse()*q2).angle());
- if (refangle>Scalar(M_PI))
- refangle = Scalar(2)*Scalar(M_PI) - refangle;
-
- if((q1.coeffs()-q2.coeffs()).norm() > 10*largeEps)
- {
- VERIFY(ei_isApprox(q1.angularDistance(q2), refangle, largeEps));
- }
-
- // rotation matrix conversion
- VERIFY_IS_APPROX(q1 * v2, q1.toRotationMatrix() * v2);
- VERIFY_IS_APPROX(q1 * q2 * v2,
- q1.toRotationMatrix() * q2.toRotationMatrix() * v2);
-
- VERIFY( (q2*q1).isApprox(q1*q2, largeEps) || !(q2 * q1 * v2).isApprox(
- q1.toRotationMatrix() * q2.toRotationMatrix() * v2));
-
- q2 = q1.toRotationMatrix();
- VERIFY_IS_APPROX(q1*v1,q2*v1);
-
- matrot1 = AngleAxisx(Scalar(0.1), Vector3::UnitX())
- * AngleAxisx(Scalar(0.2), Vector3::UnitY())
- * AngleAxisx(Scalar(0.3), Vector3::UnitZ());
- VERIFY_IS_APPROX(matrot1 * v1,
- AngleAxisx(Scalar(0.1), Vector3(1,0,0)).toRotationMatrix()
- * (AngleAxisx(Scalar(0.2), Vector3(0,1,0)).toRotationMatrix()
- * (AngleAxisx(Scalar(0.3), Vector3(0,0,1)).toRotationMatrix() * v1)));
-
- // angle-axis conversion
- AngleAxisx aa = q1;
- VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
- VERIFY_IS_NOT_APPROX(q1 * v1, Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1);
-
- // from two vector creation
- VERIFY_IS_APPROX(v2.normalized(),(q2.setFromTwoVectors(v1,v2)*v1).normalized());
- VERIFY_IS_APPROX(v2.normalized(),(q2.setFromTwoVectors(v1,v2)*v1).normalized());
-
- // inverse and conjugate
- VERIFY_IS_APPROX(q1 * (q1.inverse() * v1), v1);
- VERIFY_IS_APPROX(q1 * (q1.conjugate() * v1), v1);
-
- // AngleAxis
- VERIFY_IS_APPROX(AngleAxisx(a,v1.normalized()).toRotationMatrix(),
- Quaternionx(AngleAxisx(a,v1.normalized())).toRotationMatrix());
-
- AngleAxisx aa1;
- m = q1.toRotationMatrix();
- aa1 = m;
- VERIFY_IS_APPROX(AngleAxisx(m).toRotationMatrix(),
- Quaternionx(m).toRotationMatrix());
-
- // Transform
- // TODO complete the tests !
- a = 0;
- while (ei_abs(a)<Scalar(0.1))
- a = ei_random<Scalar>(-Scalar(0.4)*Scalar(M_PI), Scalar(0.4)*Scalar(M_PI));
- q1 = AngleAxisx(a, v0.normalized());
- Transform3 t0, t1, t2;
- // first test setIdentity() and Identity()
- t0.setIdentity();
- VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
- t0.matrix().setZero();
- t0 = Transform3::Identity();
- VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
-
- t0.linear() = q1.toRotationMatrix();
- t1.setIdentity();
- t1.linear() = q1.toRotationMatrix();
-
- v0 << 50, 2, 1;//= ei_random_matrix<Vector3>().cwiseProduct(Vector3(10,2,0.5));
- t0.scale(v0);
- t1.prescale(v0);
-
- VERIFY_IS_APPROX( (t0 * Vector3(1,0,0)).norm(), v0.x());
- //VERIFY(!ei_isApprox((t1 * Vector3(1,0,0)).norm(), v0.x()));
-
- t0.setIdentity();
- t1.setIdentity();
- v1 << 1, 2, 3;
- t0.linear() = q1.toRotationMatrix();
- t0.pretranslate(v0);
- t0.scale(v1);
- t1.linear() = q1.conjugate().toRotationMatrix();
- t1.prescale(v1.cwise().inverse());
- t1.translate(-v0);
-
- VERIFY((t0.matrix() * t1.matrix()).isIdentity(test_precision<Scalar>()));
-
- t1.fromPositionOrientationScale(v0, q1, v1);
- VERIFY_IS_APPROX(t1.matrix(), t0.matrix());
- VERIFY_IS_APPROX(t1*v1, t0*v1);
-
- t0.setIdentity(); t0.scale(v0).rotate(q1.toRotationMatrix());
- t1.setIdentity(); t1.scale(v0).rotate(q1);
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- t0.setIdentity(); t0.scale(v0).rotate(AngleAxisx(q1));
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- VERIFY_IS_APPROX(t0.scale(a).matrix(), t1.scale(Vector3::Constant(a)).matrix());
- VERIFY_IS_APPROX(t0.prescale(a).matrix(), t1.prescale(Vector3::Constant(a)).matrix());
-
- // More transform constructors, operator=, operator*=
-
- Matrix3 mat3 = Matrix3::Random();
- Matrix4 mat4;
- mat4 << mat3 , Vector3::Zero() , Vector4::Zero().transpose();
- Transform3 tmat3(mat3), tmat4(mat4);
- tmat4.matrix()(3,3) = Scalar(1);
- VERIFY_IS_APPROX(tmat3.matrix(), tmat4.matrix());
-
- Scalar a3 = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
- Vector3 v3 = Vector3::Random().normalized();
- AngleAxisx aa3(a3, v3);
- Transform3 t3(aa3);
- Transform3 t4;
- t4 = aa3;
- VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
- t4.rotate(AngleAxisx(-a3,v3));
- VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
- t4 *= aa3;
- VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
-
- v3 = Vector3::Random();
- Translation3 tv3(v3);
- Transform3 t5(tv3);
- t4 = tv3;
- VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
- t4.translate(-v3);
- VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
- t4 *= tv3;
- VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
-
- Scaling3 sv3(v3);
- Transform3 t6(sv3);
- t4 = sv3;
- VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
- t4.scale(v3.cwise().inverse());
- VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
- t4 *= sv3;
- VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
-
- // matrix * transform
- VERIFY_IS_APPROX(Transform3(t3.matrix()*t4).matrix(), Transform3(t3*t4).matrix());
-
- // chained Transform product
- VERIFY_IS_APPROX(((t3*t4)*t5).matrix(), (t3*(t4*t5)).matrix());
-
- // check that Transform product doesn't have aliasing problems
- t5 = t4;
- t5 = t5*t5;
- VERIFY_IS_APPROX(t5, t4*t4);
-
- // 2D transformation
- Transform2 t20, t21;
- Vector2 v20 = Vector2::Random();
- Vector2 v21 = Vector2::Random();
- for (int k=0; k<2; ++k)
- if (ei_abs(v21[k])<Scalar(1e-3)) v21[k] = Scalar(1e-3);
- t21.setIdentity();
- t21.linear() = Rotation2D<Scalar>(a).toRotationMatrix();
- VERIFY_IS_APPROX(t20.fromPositionOrientationScale(v20,a,v21).matrix(),
- t21.pretranslate(v20).scale(v21).matrix());
-
- t21.setIdentity();
- t21.linear() = Rotation2D<Scalar>(-a).toRotationMatrix();
- VERIFY( (t20.fromPositionOrientationScale(v20,a,v21)
- * (t21.prescale(v21.cwise().inverse()).translate(-v20))).matrix().isIdentity(test_precision<Scalar>()) );
-
- // Transform - new API
- // 3D
- t0.setIdentity();
- t0.rotate(q1).scale(v0).translate(v0);
- // mat * scaling and mat * translation
- t1 = (Matrix3(q1) * Scaling3(v0)) * Translation3(v0);
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
- // mat * transformation and scaling * translation
- t1 = Matrix3(q1) * (Scaling3(v0) * Translation3(v0));
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- t0.setIdentity();
- t0.prerotate(q1).prescale(v0).pretranslate(v0);
- // translation * scaling and transformation * mat
- t1 = (Translation3(v0) * Scaling3(v0)) * Matrix3(q1);
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
- // scaling * mat and translation * mat
- t1 = Translation3(v0) * (Scaling3(v0) * Matrix3(q1));
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- t0.setIdentity();
- t0.scale(v0).translate(v0).rotate(q1);
- // translation * mat and scaling * transformation
- t1 = Scaling3(v0) * (Translation3(v0) * Matrix3(q1));
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
- // transformation * scaling
- t0.scale(v0);
- t1 = t1 * Scaling3(v0);
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
- // transformation * translation
- t0.translate(v0);
- t1 = t1 * Translation3(v0);
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
- // translation * transformation
- t0.pretranslate(v0);
- t1 = Translation3(v0) * t1;
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- // transform * quaternion
- t0.rotate(q1);
- t1 = t1 * q1;
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- // translation * quaternion
- t0.translate(v1).rotate(q1);
- t1 = t1 * (Translation3(v1) * q1);
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- // scaling * quaternion
- t0.scale(v1).rotate(q1);
- t1 = t1 * (Scaling3(v1) * q1);
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- // quaternion * transform
- t0.prerotate(q1);
- t1 = q1 * t1;
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- // quaternion * translation
- t0.rotate(q1).translate(v1);
- t1 = t1 * (q1 * Translation3(v1));
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- // quaternion * scaling
- t0.rotate(q1).scale(v1);
- t1 = t1 * (q1 * Scaling3(v1));
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- // translation * vector
- t0.setIdentity();
- t0.translate(v0);
- VERIFY_IS_APPROX(t0 * v1, Translation3(v0) * v1);
-
- // scaling * vector
- t0.setIdentity();
- t0.scale(v0);
- VERIFY_IS_APPROX(t0 * v1, Scaling3(v0) * v1);
-
- // test transform inversion
- t0.setIdentity();
- t0.translate(v0);
- t0.linear().setRandom();
- VERIFY_IS_APPROX(t0.inverse(Affine), t0.matrix().inverse());
- t0.setIdentity();
- t0.translate(v0).rotate(q1);
- VERIFY_IS_APPROX(t0.inverse(Isometry), t0.matrix().inverse());
-
- // test extract rotation and scaling
- t0.setIdentity();
- t0.translate(v0).rotate(q1).scale(v1);
- VERIFY_IS_APPROX(t0.rotation() * v1, Matrix3(q1) * v1);
-
- Matrix3 mat_rotation, mat_scaling;
- t0.setIdentity();
- t0.translate(v0).rotate(q1).scale(v1);
- t0.computeRotationScaling(&mat_rotation, &mat_scaling);
- VERIFY_IS_APPROX(t0.linear(), mat_rotation * mat_scaling);
- VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
- VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
- t0.computeScalingRotation(&mat_scaling, &mat_rotation);
- VERIFY_IS_APPROX(t0.linear(), mat_scaling * mat_rotation);
- VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
- VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
-
- // test casting
- Transform<float,3> t1f = t1.template cast<float>();
- VERIFY_IS_APPROX(t1f.template cast<Scalar>(),t1);
- Transform<double,3> t1d = t1.template cast<double>();
- VERIFY_IS_APPROX(t1d.template cast<Scalar>(),t1);
-
- Translation3 tr1(v0);
- Translation<float,3> tr1f = tr1.template cast<float>();
- VERIFY_IS_APPROX(tr1f.template cast<Scalar>(),tr1);
- Translation<double,3> tr1d = tr1.template cast<double>();
- VERIFY_IS_APPROX(tr1d.template cast<Scalar>(),tr1);
-
- Scaling3 sc1(v0);
- Scaling<float,3> sc1f = sc1.template cast<float>();
- VERIFY_IS_APPROX(sc1f.template cast<Scalar>(),sc1);
- Scaling<double,3> sc1d = sc1.template cast<double>();
- VERIFY_IS_APPROX(sc1d.template cast<Scalar>(),sc1);
-
- Quaternion<float> q1f = q1.template cast<float>();
- VERIFY_IS_APPROX(q1f.template cast<Scalar>(),q1);
- Quaternion<double> q1d = q1.template cast<double>();
- VERIFY_IS_APPROX(q1d.template cast<Scalar>(),q1);
-
- AngleAxis<float> aa1f = aa1.template cast<float>();
- VERIFY_IS_APPROX(aa1f.template cast<Scalar>(),aa1);
- AngleAxis<double> aa1d = aa1.template cast<double>();
- VERIFY_IS_APPROX(aa1d.template cast<Scalar>(),aa1);
-
- Rotation2D<Scalar> r2d1(ei_random<Scalar>());
- Rotation2D<float> r2d1f = r2d1.template cast<float>();
- VERIFY_IS_APPROX(r2d1f.template cast<Scalar>(),r2d1);
- Rotation2D<double> r2d1d = r2d1.template cast<double>();
- VERIFY_IS_APPROX(r2d1d.template cast<Scalar>(),r2d1);
-
- m = q1;
-// m.col(1) = Vector3(0,ei_random<Scalar>(),ei_random<Scalar>()).normalized();
-// m.col(0) = Vector3(-1,0,0).normalized();
-// m.col(2) = m.col(0).cross(m.col(1));
- #define VERIFY_EULER(I,J,K, X,Y,Z) { \
- Vector3 ea = m.eulerAngles(I,J,K); \
- Matrix3 m1 = Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z())); \
- VERIFY_IS_APPROX(m, m1); \
- VERIFY_IS_APPROX(m, Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z()))); \
- }
- VERIFY_EULER(0,1,2, X,Y,Z);
- VERIFY_EULER(0,1,0, X,Y,X);
- VERIFY_EULER(0,2,1, X,Z,Y);
- VERIFY_EULER(0,2,0, X,Z,X);
-
- VERIFY_EULER(1,2,0, Y,Z,X);
- VERIFY_EULER(1,2,1, Y,Z,Y);
- VERIFY_EULER(1,0,2, Y,X,Z);
- VERIFY_EULER(1,0,1, Y,X,Y);
-
- VERIFY_EULER(2,0,1, Z,X,Y);
- VERIFY_EULER(2,0,2, Z,X,Z);
- VERIFY_EULER(2,1,0, Z,Y,X);
- VERIFY_EULER(2,1,2, Z,Y,Z);
-
- // colwise/rowwise cross product
- mat3.setRandom();
- Vector3 vec3 = Vector3::Random();
- Matrix3 mcross;
- int i = ei_random<int>(0,2);
- mcross = mat3.colwise().cross(vec3);
- VERIFY_IS_APPROX(mcross.col(i), mat3.col(i).cross(vec3));
- mcross = mat3.rowwise().cross(vec3);
- VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3));
-
-
-}
-
-void test_eigen2_geometry()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( geometry<float>() );
- CALL_SUBTEST_2( geometry<double>() );
- }
-}
diff --git a/test/eigen2/eigen2_geometry_with_eigen2_prefix.cpp b/test/eigen2/eigen2_geometry_with_eigen2_prefix.cpp
deleted file mode 100644
index 12d4a71c3..000000000
--- a/test/eigen2/eigen2_geometry_with_eigen2_prefix.cpp
+++ /dev/null
@@ -1,435 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
-
-#define EIGEN2_SUPPORT_STAGE15_RESOLVE_API_CONFLICTS_WARN
-
-#include "main.h"
-#include <Eigen/Geometry>
-#include <Eigen/LU>
-#include <Eigen/SVD>
-
-template<typename Scalar> void geometry(void)
-{
- /* this test covers the following files:
- Cross.h Quaternion.h, Transform.cpp
- */
-
- typedef Matrix<Scalar,2,2> Matrix2;
- typedef Matrix<Scalar,3,3> Matrix3;
- typedef Matrix<Scalar,4,4> Matrix4;
- typedef Matrix<Scalar,2,1> Vector2;
- typedef Matrix<Scalar,3,1> Vector3;
- typedef Matrix<Scalar,4,1> Vector4;
- typedef eigen2_Quaternion<Scalar> Quaternionx;
- typedef eigen2_AngleAxis<Scalar> AngleAxisx;
- typedef eigen2_Transform<Scalar,2> Transform2;
- typedef eigen2_Transform<Scalar,3> Transform3;
- typedef eigen2_Scaling<Scalar,2> Scaling2;
- typedef eigen2_Scaling<Scalar,3> Scaling3;
- typedef eigen2_Translation<Scalar,2> Translation2;
- typedef eigen2_Translation<Scalar,3> Translation3;
-
- Scalar largeEps = test_precision<Scalar>();
- if (ei_is_same_type<Scalar,float>::ret)
- largeEps = 1e-2f;
-
- Vector3 v0 = Vector3::Random(),
- v1 = Vector3::Random(),
- v2 = Vector3::Random();
- Vector2 u0 = Vector2::Random();
- Matrix3 matrot1;
-
- Scalar a = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
-
- // cross product
- VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).eigen2_dot(v1), Scalar(1));
- Matrix3 m;
- m << v0.normalized(),
- (v0.cross(v1)).normalized(),
- (v0.cross(v1).cross(v0)).normalized();
- VERIFY(m.isUnitary());
-
- // Quaternion: Identity(), setIdentity();
- Quaternionx q1, q2;
- q2.setIdentity();
- VERIFY_IS_APPROX(Quaternionx(Quaternionx::Identity()).coeffs(), q2.coeffs());
- q1.coeffs().setRandom();
- VERIFY_IS_APPROX(q1.coeffs(), (q1*q2).coeffs());
-
- // unitOrthogonal
- VERIFY_IS_MUCH_SMALLER_THAN(u0.unitOrthogonal().eigen2_dot(u0), Scalar(1));
- VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().eigen2_dot(v0), Scalar(1));
- VERIFY_IS_APPROX(u0.unitOrthogonal().norm(), Scalar(1));
- VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), Scalar(1));
-
-
- VERIFY_IS_APPROX(v0, AngleAxisx(a, v0.normalized()) * v0);
- VERIFY_IS_APPROX(-v0, AngleAxisx(Scalar(M_PI), v0.unitOrthogonal()) * v0);
- VERIFY_IS_APPROX(ei_cos(a)*v0.squaredNorm(), v0.eigen2_dot(AngleAxisx(a, v0.unitOrthogonal()) * v0));
- m = AngleAxisx(a, v0.normalized()).toRotationMatrix().adjoint();
- VERIFY_IS_APPROX(Matrix3::Identity(), m * AngleAxisx(a, v0.normalized()));
- VERIFY_IS_APPROX(Matrix3::Identity(), AngleAxisx(a, v0.normalized()) * m);
-
- q1 = AngleAxisx(a, v0.normalized());
- q2 = AngleAxisx(a, v1.normalized());
-
- // angular distance
- Scalar refangle = ei_abs(AngleAxisx(q1.inverse()*q2).angle());
- if (refangle>Scalar(M_PI))
- refangle = Scalar(2)*Scalar(M_PI) - refangle;
-
- if((q1.coeffs()-q2.coeffs()).norm() > 10*largeEps)
- {
- VERIFY(ei_isApprox(q1.angularDistance(q2), refangle, largeEps));
- }
-
- // rotation matrix conversion
- VERIFY_IS_APPROX(q1 * v2, q1.toRotationMatrix() * v2);
- VERIFY_IS_APPROX(q1 * q2 * v2,
- q1.toRotationMatrix() * q2.toRotationMatrix() * v2);
-
- VERIFY( (q2*q1).isApprox(q1*q2, largeEps) || !(q2 * q1 * v2).isApprox(
- q1.toRotationMatrix() * q2.toRotationMatrix() * v2));
-
- q2 = q1.toRotationMatrix();
- VERIFY_IS_APPROX(q1*v1,q2*v1);
-
- matrot1 = AngleAxisx(Scalar(0.1), Vector3::UnitX())
- * AngleAxisx(Scalar(0.2), Vector3::UnitY())
- * AngleAxisx(Scalar(0.3), Vector3::UnitZ());
- VERIFY_IS_APPROX(matrot1 * v1,
- AngleAxisx(Scalar(0.1), Vector3(1,0,0)).toRotationMatrix()
- * (AngleAxisx(Scalar(0.2), Vector3(0,1,0)).toRotationMatrix()
- * (AngleAxisx(Scalar(0.3), Vector3(0,0,1)).toRotationMatrix() * v1)));
-
- // angle-axis conversion
- AngleAxisx aa = q1;
- VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
- VERIFY_IS_NOT_APPROX(q1 * v1, Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1);
-
- // from two vector creation
- VERIFY_IS_APPROX(v2.normalized(),(q2.setFromTwoVectors(v1,v2)*v1).normalized());
- VERIFY_IS_APPROX(v2.normalized(),(q2.setFromTwoVectors(v1,v2)*v1).normalized());
-
- // inverse and conjugate
- VERIFY_IS_APPROX(q1 * (q1.inverse() * v1), v1);
- VERIFY_IS_APPROX(q1 * (q1.conjugate() * v1), v1);
-
- // AngleAxis
- VERIFY_IS_APPROX(AngleAxisx(a,v1.normalized()).toRotationMatrix(),
- Quaternionx(AngleAxisx(a,v1.normalized())).toRotationMatrix());
-
- AngleAxisx aa1;
- m = q1.toRotationMatrix();
- aa1 = m;
- VERIFY_IS_APPROX(AngleAxisx(m).toRotationMatrix(),
- Quaternionx(m).toRotationMatrix());
-
- // Transform
- // TODO complete the tests !
- a = 0;
- while (ei_abs(a)<Scalar(0.1))
- a = ei_random<Scalar>(-Scalar(0.4)*Scalar(M_PI), Scalar(0.4)*Scalar(M_PI));
- q1 = AngleAxisx(a, v0.normalized());
- Transform3 t0, t1, t2;
- // first test setIdentity() and Identity()
- t0.setIdentity();
- VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
- t0.matrix().setZero();
- t0 = Transform3::Identity();
- VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
-
- t0.linear() = q1.toRotationMatrix();
- t1.setIdentity();
- t1.linear() = q1.toRotationMatrix();
-
- v0 << 50, 2, 1;//= ei_random_matrix<Vector3>().cwiseProduct(Vector3(10,2,0.5));
- t0.scale(v0);
- t1.prescale(v0);
-
- VERIFY_IS_APPROX( (t0 * Vector3(1,0,0)).norm(), v0.x());
- //VERIFY(!ei_isApprox((t1 * Vector3(1,0,0)).norm(), v0.x()));
-
- t0.setIdentity();
- t1.setIdentity();
- v1 << 1, 2, 3;
- t0.linear() = q1.toRotationMatrix();
- t0.pretranslate(v0);
- t0.scale(v1);
- t1.linear() = q1.conjugate().toRotationMatrix();
- t1.prescale(v1.cwise().inverse());
- t1.translate(-v0);
-
- VERIFY((t0.matrix() * t1.matrix()).isIdentity(test_precision<Scalar>()));
-
- t1.fromPositionOrientationScale(v0, q1, v1);
- VERIFY_IS_APPROX(t1.matrix(), t0.matrix());
- VERIFY_IS_APPROX(t1*v1, t0*v1);
-
- t0.setIdentity(); t0.scale(v0).rotate(q1.toRotationMatrix());
- t1.setIdentity(); t1.scale(v0).rotate(q1);
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- t0.setIdentity(); t0.scale(v0).rotate(AngleAxisx(q1));
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- VERIFY_IS_APPROX(t0.scale(a).matrix(), t1.scale(Vector3::Constant(a)).matrix());
- VERIFY_IS_APPROX(t0.prescale(a).matrix(), t1.prescale(Vector3::Constant(a)).matrix());
-
- // More transform constructors, operator=, operator*=
-
- Matrix3 mat3 = Matrix3::Random();
- Matrix4 mat4;
- mat4 << mat3 , Vector3::Zero() , Vector4::Zero().transpose();
- Transform3 tmat3(mat3), tmat4(mat4);
- tmat4.matrix()(3,3) = Scalar(1);
- VERIFY_IS_APPROX(tmat3.matrix(), tmat4.matrix());
-
- Scalar a3 = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
- Vector3 v3 = Vector3::Random().normalized();
- AngleAxisx aa3(a3, v3);
- Transform3 t3(aa3);
- Transform3 t4;
- t4 = aa3;
- VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
- t4.rotate(AngleAxisx(-a3,v3));
- VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
- t4 *= aa3;
- VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
-
- v3 = Vector3::Random();
- Translation3 tv3(v3);
- Transform3 t5(tv3);
- t4 = tv3;
- VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
- t4.translate(-v3);
- VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
- t4 *= tv3;
- VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
-
- Scaling3 sv3(v3);
- Transform3 t6(sv3);
- t4 = sv3;
- VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
- t4.scale(v3.cwise().inverse());
- VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
- t4 *= sv3;
- VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
-
- // matrix * transform
- VERIFY_IS_APPROX(Transform3(t3.matrix()*t4).matrix(), Transform3(t3*t4).matrix());
-
- // chained Transform product
- VERIFY_IS_APPROX(((t3*t4)*t5).matrix(), (t3*(t4*t5)).matrix());
-
- // check that Transform product doesn't have aliasing problems
- t5 = t4;
- t5 = t5*t5;
- VERIFY_IS_APPROX(t5, t4*t4);
-
- // 2D transformation
- Transform2 t20, t21;
- Vector2 v20 = Vector2::Random();
- Vector2 v21 = Vector2::Random();
- for (int k=0; k<2; ++k)
- if (ei_abs(v21[k])<Scalar(1e-3)) v21[k] = Scalar(1e-3);
- t21.setIdentity();
- t21.linear() = Rotation2D<Scalar>(a).toRotationMatrix();
- VERIFY_IS_APPROX(t20.fromPositionOrientationScale(v20,a,v21).matrix(),
- t21.pretranslate(v20).scale(v21).matrix());
-
- t21.setIdentity();
- t21.linear() = Rotation2D<Scalar>(-a).toRotationMatrix();
- VERIFY( (t20.fromPositionOrientationScale(v20,a,v21)
- * (t21.prescale(v21.cwise().inverse()).translate(-v20))).matrix().isIdentity(test_precision<Scalar>()) );
-
- // Transform - new API
- // 3D
- t0.setIdentity();
- t0.rotate(q1).scale(v0).translate(v0);
- // mat * scaling and mat * translation
- t1 = (Matrix3(q1) * Scaling3(v0)) * Translation3(v0);
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
- // mat * transformation and scaling * translation
- t1 = Matrix3(q1) * (Scaling3(v0) * Translation3(v0));
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- t0.setIdentity();
- t0.prerotate(q1).prescale(v0).pretranslate(v0);
- // translation * scaling and transformation * mat
- t1 = (Translation3(v0) * Scaling3(v0)) * Matrix3(q1);
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
- // scaling * mat and translation * mat
- t1 = Translation3(v0) * (Scaling3(v0) * Matrix3(q1));
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- t0.setIdentity();
- t0.scale(v0).translate(v0).rotate(q1);
- // translation * mat and scaling * transformation
- t1 = Scaling3(v0) * (Translation3(v0) * Matrix3(q1));
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
- // transformation * scaling
- t0.scale(v0);
- t1 = t1 * Scaling3(v0);
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
- // transformation * translation
- t0.translate(v0);
- t1 = t1 * Translation3(v0);
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
- // translation * transformation
- t0.pretranslate(v0);
- t1 = Translation3(v0) * t1;
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- // transform * quaternion
- t0.rotate(q1);
- t1 = t1 * q1;
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- // translation * quaternion
- t0.translate(v1).rotate(q1);
- t1 = t1 * (Translation3(v1) * q1);
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- // scaling * quaternion
- t0.scale(v1).rotate(q1);
- t1 = t1 * (Scaling3(v1) * q1);
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- // quaternion * transform
- t0.prerotate(q1);
- t1 = q1 * t1;
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- // quaternion * translation
- t0.rotate(q1).translate(v1);
- t1 = t1 * (q1 * Translation3(v1));
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- // quaternion * scaling
- t0.rotate(q1).scale(v1);
- t1 = t1 * (q1 * Scaling3(v1));
- VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
-
- // translation * vector
- t0.setIdentity();
- t0.translate(v0);
- VERIFY_IS_APPROX(t0 * v1, Translation3(v0) * v1);
-
- // scaling * vector
- t0.setIdentity();
- t0.scale(v0);
- VERIFY_IS_APPROX(t0 * v1, Scaling3(v0) * v1);
-
- // test transform inversion
- t0.setIdentity();
- t0.translate(v0);
- t0.linear().setRandom();
- VERIFY_IS_APPROX(t0.inverse(Affine), t0.matrix().inverse());
- t0.setIdentity();
- t0.translate(v0).rotate(q1);
- VERIFY_IS_APPROX(t0.inverse(Isometry), t0.matrix().inverse());
-
- // test extract rotation and scaling
- t0.setIdentity();
- t0.translate(v0).rotate(q1).scale(v1);
- VERIFY_IS_APPROX(t0.rotation() * v1, Matrix3(q1) * v1);
-
- Matrix3 mat_rotation, mat_scaling;
- t0.setIdentity();
- t0.translate(v0).rotate(q1).scale(v1);
- t0.computeRotationScaling(&mat_rotation, &mat_scaling);
- VERIFY_IS_APPROX(t0.linear(), mat_rotation * mat_scaling);
- VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
- VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
- t0.computeScalingRotation(&mat_scaling, &mat_rotation);
- VERIFY_IS_APPROX(t0.linear(), mat_scaling * mat_rotation);
- VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
- VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
-
- // test casting
- eigen2_Transform<float,3> t1f = t1.template cast<float>();
- VERIFY_IS_APPROX(t1f.template cast<Scalar>(),t1);
- eigen2_Transform<double,3> t1d = t1.template cast<double>();
- VERIFY_IS_APPROX(t1d.template cast<Scalar>(),t1);
-
- Translation3 tr1(v0);
- eigen2_Translation<float,3> tr1f = tr1.template cast<float>();
- VERIFY_IS_APPROX(tr1f.template cast<Scalar>(),tr1);
- eigen2_Translation<double,3> tr1d = tr1.template cast<double>();
- VERIFY_IS_APPROX(tr1d.template cast<Scalar>(),tr1);
-
- Scaling3 sc1(v0);
- eigen2_Scaling<float,3> sc1f = sc1.template cast<float>();
- VERIFY_IS_APPROX(sc1f.template cast<Scalar>(),sc1);
- eigen2_Scaling<double,3> sc1d = sc1.template cast<double>();
- VERIFY_IS_APPROX(sc1d.template cast<Scalar>(),sc1);
-
- eigen2_Quaternion<float> q1f = q1.template cast<float>();
- VERIFY_IS_APPROX(q1f.template cast<Scalar>(),q1);
- eigen2_Quaternion<double> q1d = q1.template cast<double>();
- VERIFY_IS_APPROX(q1d.template cast<Scalar>(),q1);
-
- eigen2_AngleAxis<float> aa1f = aa1.template cast<float>();
- VERIFY_IS_APPROX(aa1f.template cast<Scalar>(),aa1);
- eigen2_AngleAxis<double> aa1d = aa1.template cast<double>();
- VERIFY_IS_APPROX(aa1d.template cast<Scalar>(),aa1);
-
- eigen2_Rotation2D<Scalar> r2d1(ei_random<Scalar>());
- eigen2_Rotation2D<float> r2d1f = r2d1.template cast<float>();
- VERIFY_IS_APPROX(r2d1f.template cast<Scalar>(),r2d1);
- eigen2_Rotation2D<double> r2d1d = r2d1.template cast<double>();
- VERIFY_IS_APPROX(r2d1d.template cast<Scalar>(),r2d1);
-
- m = q1;
-// m.col(1) = Vector3(0,ei_random<Scalar>(),ei_random<Scalar>()).normalized();
-// m.col(0) = Vector3(-1,0,0).normalized();
-// m.col(2) = m.col(0).cross(m.col(1));
- #define VERIFY_EULER(I,J,K, X,Y,Z) { \
- Vector3 ea = m.eulerAngles(I,J,K); \
- Matrix3 m1 = Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z())); \
- VERIFY_IS_APPROX(m, m1); \
- VERIFY_IS_APPROX(m, Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z()))); \
- }
- VERIFY_EULER(0,1,2, X,Y,Z);
- VERIFY_EULER(0,1,0, X,Y,X);
- VERIFY_EULER(0,2,1, X,Z,Y);
- VERIFY_EULER(0,2,0, X,Z,X);
-
- VERIFY_EULER(1,2,0, Y,Z,X);
- VERIFY_EULER(1,2,1, Y,Z,Y);
- VERIFY_EULER(1,0,2, Y,X,Z);
- VERIFY_EULER(1,0,1, Y,X,Y);
-
- VERIFY_EULER(2,0,1, Z,X,Y);
- VERIFY_EULER(2,0,2, Z,X,Z);
- VERIFY_EULER(2,1,0, Z,Y,X);
- VERIFY_EULER(2,1,2, Z,Y,Z);
-
- // colwise/rowwise cross product
- mat3.setRandom();
- Vector3 vec3 = Vector3::Random();
- Matrix3 mcross;
- int i = ei_random<int>(0,2);
- mcross = mat3.colwise().cross(vec3);
- VERIFY_IS_APPROX(mcross.col(i), mat3.col(i).cross(vec3));
- mcross = mat3.rowwise().cross(vec3);
- VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3));
-
-
-}
-
-void test_eigen2_geometry_with_eigen2_prefix()
-{
- std::cout << "eigen2 support: " << EIGEN2_SUPPORT_STAGE << std::endl;
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( geometry<float>() );
- CALL_SUBTEST_2( geometry<double>() );
- }
-}
diff --git a/test/eigen2/eigen2_hyperplane.cpp b/test/eigen2/eigen2_hyperplane.cpp
deleted file mode 100644
index f3f85e14d..000000000
--- a/test/eigen2/eigen2_hyperplane.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
-// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@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/Geometry>
-#include <Eigen/LU>
-#include <Eigen/QR>
-
-template<typename HyperplaneType> void hyperplane(const HyperplaneType& _plane)
-{
- /* this test covers the following files:
- Hyperplane.h
- */
-
- const int dim = _plane.dim();
- typedef typename HyperplaneType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Matrix<Scalar, HyperplaneType::AmbientDimAtCompileTime, 1> VectorType;
- typedef Matrix<Scalar, HyperplaneType::AmbientDimAtCompileTime,
- HyperplaneType::AmbientDimAtCompileTime> MatrixType;
-
- VectorType p0 = VectorType::Random(dim);
- VectorType p1 = VectorType::Random(dim);
-
- VectorType n0 = VectorType::Random(dim).normalized();
- VectorType n1 = VectorType::Random(dim).normalized();
-
- HyperplaneType pl0(n0, p0);
- HyperplaneType pl1(n1, p1);
- HyperplaneType pl2 = pl1;
-
- Scalar s0 = ei_random<Scalar>();
- Scalar s1 = ei_random<Scalar>();
-
- VERIFY_IS_APPROX( n1.eigen2_dot(n1), Scalar(1) );
-
- VERIFY_IS_MUCH_SMALLER_THAN( pl0.absDistance(p0), Scalar(1) );
- VERIFY_IS_APPROX( pl1.signedDistance(p1 + n1 * s0), s0 );
- VERIFY_IS_MUCH_SMALLER_THAN( pl1.signedDistance(pl1.projection(p0)), Scalar(1) );
- VERIFY_IS_MUCH_SMALLER_THAN( pl1.absDistance(p1 + pl1.normal().unitOrthogonal() * s1), Scalar(1) );
-
- // transform
- if (!NumTraits<Scalar>::IsComplex)
- {
- MatrixType rot = MatrixType::Random(dim,dim).qr().matrixQ();
- Scaling<Scalar,HyperplaneType::AmbientDimAtCompileTime> scaling(VectorType::Random());
- Translation<Scalar,HyperplaneType::AmbientDimAtCompileTime> translation(VectorType::Random());
-
- pl2 = pl1;
- VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot).absDistance(rot * p1), Scalar(1) );
- pl2 = pl1;
- VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot,Isometry).absDistance(rot * p1), Scalar(1) );
- pl2 = pl1;
- VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*scaling).absDistance((rot*scaling) * p1), Scalar(1) );
- pl2 = pl1;
- VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*scaling*translation)
- .absDistance((rot*scaling*translation) * p1), Scalar(1) );
- pl2 = pl1;
- VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*translation,Isometry)
- .absDistance((rot*translation) * p1), Scalar(1) );
- }
-
- // casting
- const int Dim = HyperplaneType::AmbientDimAtCompileTime;
- typedef typename GetDifferentType<Scalar>::type OtherScalar;
- Hyperplane<OtherScalar,Dim> hp1f = pl1.template cast<OtherScalar>();
- VERIFY_IS_APPROX(hp1f.template cast<Scalar>(),pl1);
- Hyperplane<Scalar,Dim> hp1d = pl1.template cast<Scalar>();
- VERIFY_IS_APPROX(hp1d.template cast<Scalar>(),pl1);
-}
-
-template<typename Scalar> void lines()
-{
- typedef Hyperplane<Scalar, 2> HLine;
- typedef ParametrizedLine<Scalar, 2> PLine;
- typedef Matrix<Scalar,2,1> Vector;
- typedef Matrix<Scalar,3,1> CoeffsType;
-
- for(int i = 0; i < 10; i++)
- {
- Vector center = Vector::Random();
- Vector u = Vector::Random();
- Vector v = Vector::Random();
- Scalar a = ei_random<Scalar>();
- while (ei_abs(a-1) < 1e-4) a = ei_random<Scalar>();
- while (u.norm() < 1e-4) u = Vector::Random();
- while (v.norm() < 1e-4) v = Vector::Random();
-
- HLine line_u = HLine::Through(center + u, center + a*u);
- HLine line_v = HLine::Through(center + v, center + a*v);
-
- // the line equations should be normalized so that a^2+b^2=1
- VERIFY_IS_APPROX(line_u.normal().norm(), Scalar(1));
- VERIFY_IS_APPROX(line_v.normal().norm(), Scalar(1));
-
- Vector result = line_u.intersection(line_v);
-
- // the lines should intersect at the point we called "center"
- VERIFY_IS_APPROX(result, center);
-
- // check conversions between two types of lines
- PLine pl(line_u); // gcc 3.3 will commit suicide if we don't name this variable
- CoeffsType converted_coeffs(HLine(pl).coeffs());
- converted_coeffs *= line_u.coeffs()(0)/converted_coeffs(0);
- VERIFY(line_u.coeffs().isApprox(converted_coeffs));
- }
-}
-
-void test_eigen2_hyperplane()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( hyperplane(Hyperplane<float,2>()) );
- CALL_SUBTEST_2( hyperplane(Hyperplane<float,3>()) );
- CALL_SUBTEST_3( hyperplane(Hyperplane<double,4>()) );
- CALL_SUBTEST_4( hyperplane(Hyperplane<std::complex<double>,5>()) );
- CALL_SUBTEST_5( lines<float>() );
- CALL_SUBTEST_6( lines<double>() );
- }
-}
diff --git a/test/eigen2/eigen2_inverse.cpp b/test/eigen2/eigen2_inverse.cpp
deleted file mode 100644
index ccd24a194..000000000
--- a/test/eigen2/eigen2_inverse.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
-// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@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/LU>
-
-template<typename MatrixType> void inverse(const MatrixType& m)
-{
- /* this test covers the following files:
- Inverse.h
- */
- int rows = m.rows();
- int cols = m.cols();
-
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
-
- MatrixType m1 = MatrixType::Random(rows, cols),
- m2(rows, cols),
- identity = MatrixType::Identity(rows, rows);
-
- while(ei_abs(m1.determinant()) < RealScalar(0.1) && rows <= 8)
- {
- m1 = MatrixType::Random(rows, cols);
- }
-
- m2 = m1.inverse();
- VERIFY_IS_APPROX(m1, m2.inverse() );
-
- m1.computeInverse(&m2);
- VERIFY_IS_APPROX(m1, m2.inverse() );
-
- VERIFY_IS_APPROX((Scalar(2)*m2).inverse(), m2.inverse()*Scalar(0.5));
-
- VERIFY_IS_APPROX(identity, m1.inverse() * m1 );
- VERIFY_IS_APPROX(identity, m1 * m1.inverse() );
-
- VERIFY_IS_APPROX(m1, m1.inverse().inverse() );
-
- // since for the general case we implement separately row-major and col-major, test that
- VERIFY_IS_APPROX(m1.transpose().inverse(), m1.inverse().transpose());
-}
-
-void test_eigen2_inverse()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( inverse(Matrix<double,1,1>()) );
- CALL_SUBTEST_2( inverse(Matrix2d()) );
- CALL_SUBTEST_3( inverse(Matrix3f()) );
- CALL_SUBTEST_4( inverse(Matrix4f()) );
- CALL_SUBTEST_5( inverse(MatrixXf(8,8)) );
- CALL_SUBTEST_6( inverse(MatrixXcd(7,7)) );
- }
-}
diff --git a/test/eigen2/eigen2_linearstructure.cpp b/test/eigen2/eigen2_linearstructure.cpp
deleted file mode 100644
index 488f4c485..000000000
--- a/test/eigen2/eigen2_linearstructure.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@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"
-
-template<typename MatrixType> void linearStructure(const MatrixType& m)
-{
- /* this test covers the following files:
- Sum.h Difference.h Opposite.h ScalarMultiple.h
- */
-
- typedef typename MatrixType::Scalar Scalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
-
- int rows = m.rows();
- int cols = m.cols();
-
- // this test relies a lot on Random.h, and there's not much more that we can do
- // to test it, hence I consider that we will have tested Random.h
- MatrixType m1 = MatrixType::Random(rows, cols),
- m2 = MatrixType::Random(rows, cols),
- m3(rows, cols);
-
- Scalar s1 = ei_random<Scalar>();
- while (ei_abs(s1)<1e-3) s1 = ei_random<Scalar>();
-
- int r = ei_random<int>(0, rows-1),
- c = ei_random<int>(0, cols-1);
-
- VERIFY_IS_APPROX(-(-m1), m1);
- VERIFY_IS_APPROX(m1+m1, 2*m1);
- VERIFY_IS_APPROX(m1+m2-m1, m2);
- VERIFY_IS_APPROX(-m2+m1+m2, m1);
- VERIFY_IS_APPROX(m1*s1, s1*m1);
- VERIFY_IS_APPROX((m1+m2)*s1, s1*m1+s1*m2);
- VERIFY_IS_APPROX((-m1+m2)*s1, -s1*m1+s1*m2);
- m3 = m2; m3 += m1;
- VERIFY_IS_APPROX(m3, m1+m2);
- m3 = m2; m3 -= m1;
- VERIFY_IS_APPROX(m3, m2-m1);
- m3 = m2; m3 *= s1;
- VERIFY_IS_APPROX(m3, s1*m2);
- if(NumTraits<Scalar>::HasFloatingPoint)
- {
- m3 = m2; m3 /= s1;
- VERIFY_IS_APPROX(m3, m2/s1);
- }
-
- // again, test operator() to check const-qualification
- VERIFY_IS_APPROX((-m1)(r,c), -(m1(r,c)));
- VERIFY_IS_APPROX((m1-m2)(r,c), (m1(r,c))-(m2(r,c)));
- VERIFY_IS_APPROX((m1+m2)(r,c), (m1(r,c))+(m2(r,c)));
- VERIFY_IS_APPROX((s1*m1)(r,c), s1*(m1(r,c)));
- VERIFY_IS_APPROX((m1*s1)(r,c), (m1(r,c))*s1);
- if(NumTraits<Scalar>::HasFloatingPoint)
- VERIFY_IS_APPROX((m1/s1)(r,c), (m1(r,c))/s1);
-
- // use .block to disable vectorization and compare to the vectorized version
- VERIFY_IS_APPROX(m1+m1.block(0,0,rows,cols), m1+m1);
- VERIFY_IS_APPROX(m1.cwise() * m1.block(0,0,rows,cols), m1.cwise() * m1);
- VERIFY_IS_APPROX(m1 - m1.block(0,0,rows,cols), m1 - m1);
- VERIFY_IS_APPROX(m1.block(0,0,rows,cols) * s1, m1 * s1);
-}
-
-void test_eigen2_linearstructure()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( linearStructure(Matrix<float, 1, 1>()) );
- CALL_SUBTEST_2( linearStructure(Matrix2f()) );
- CALL_SUBTEST_3( linearStructure(Vector3d()) );
- CALL_SUBTEST_4( linearStructure(Matrix4d()) );
- CALL_SUBTEST_5( linearStructure(MatrixXcf(3, 3)) );
- CALL_SUBTEST_6( linearStructure(MatrixXf(8, 12)) );
- CALL_SUBTEST_7( linearStructure(MatrixXi(8, 12)) );
- CALL_SUBTEST_8( linearStructure(MatrixXcd(20, 20)) );
- }
-}
diff --git a/test/eigen2/eigen2_lu.cpp b/test/eigen2/eigen2_lu.cpp
deleted file mode 100644
index e993b1c7c..000000000
--- a/test/eigen2/eigen2_lu.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@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/LU>
-
-template<typename Derived>
-void doSomeRankPreservingOperations(Eigen::MatrixBase<Derived>& m)
-{
- typedef typename Derived::RealScalar RealScalar;
- for(int a = 0; a < 3*(m.rows()+m.cols()); a++)
- {
- RealScalar d = Eigen::ei_random<RealScalar>(-1,1);
- int i = Eigen::ei_random<int>(0,m.rows()-1); // i is a random row number
- int j;
- do {
- j = Eigen::ei_random<int>(0,m.rows()-1);
- } while (i==j); // j is another one (must be different)
- m.row(i) += d * m.row(j);
-
- i = Eigen::ei_random<int>(0,m.cols()-1); // i is a random column number
- do {
- j = Eigen::ei_random<int>(0,m.cols()-1);
- } while (i==j); // j is another one (must be different)
- m.col(i) += d * m.col(j);
- }
-}
-
-template<typename MatrixType> void lu_non_invertible()
-{
- /* this test covers the following files:
- LU.h
- */
- // NOTE there seems to be a problem with too small sizes -- could easily lie in the doSomeRankPreservingOperations function
- int rows = ei_random<int>(20,200), cols = ei_random<int>(20,200), cols2 = ei_random<int>(20,200);
- int rank = ei_random<int>(1, std::min(rows, cols)-1);
-
- MatrixType m1(rows, cols), m2(cols, cols2), m3(rows, cols2), k(1,1);
- m1 = MatrixType::Random(rows,cols);
- if(rows <= cols)
- for(int i = rank; i < rows; i++) m1.row(i).setZero();
- else
- for(int i = rank; i < cols; i++) m1.col(i).setZero();
- doSomeRankPreservingOperations(m1);
-
- LU<MatrixType> lu(m1);
- typename LU<MatrixType>::KernelResultType m1kernel = lu.kernel();
- typename LU<MatrixType>::ImageResultType m1image = lu.image();
-
- VERIFY(rank == lu.rank());
- VERIFY(cols - lu.rank() == lu.dimensionOfKernel());
- VERIFY(!lu.isInjective());
- VERIFY(!lu.isInvertible());
- VERIFY(lu.isSurjective() == (lu.rank() == rows));
- VERIFY((m1 * m1kernel).isMuchSmallerThan(m1));
- VERIFY(m1image.lu().rank() == rank);
- MatrixType sidebyside(m1.rows(), m1.cols() + m1image.cols());
- sidebyside << m1, m1image;
- VERIFY(sidebyside.lu().rank() == rank);
- m2 = MatrixType::Random(cols,cols2);
- m3 = m1*m2;
- m2 = MatrixType::Random(cols,cols2);
- lu.solve(m3, &m2);
- VERIFY_IS_APPROX(m3, m1*m2);
- /* solve now always returns true
- m3 = MatrixType::Random(rows,cols2);
- VERIFY(!lu.solve(m3, &m2));
- */
-}
-
-template<typename MatrixType> void lu_invertible()
-{
- /* this test covers the following files:
- LU.h
- */
- typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
- int size = ei_random<int>(10,200);
-
- MatrixType m1(size, size), m2(size, size), m3(size, size);
- m1 = MatrixType::Random(size,size);
-
- if (ei_is_same_type<RealScalar,float>::ret)
- {
- // let's build a matrix more stable to inverse
- MatrixType a = MatrixType::Random(size,size*2);
- m1 += a * a.adjoint();
- }
-
- LU<MatrixType> lu(m1);
- VERIFY(0 == lu.dimensionOfKernel());
- VERIFY(size == lu.rank());
- VERIFY(lu.isInjective());
- VERIFY(lu.isSurjective());
- VERIFY(lu.isInvertible());
- VERIFY(lu.image().lu().isInvertible());
- m3 = MatrixType::Random(size,size);
- lu.solve(m3, &m2);
- VERIFY_IS_APPROX(m3, m1*m2);
- VERIFY_IS_APPROX(m2, lu.inverse()*m3);
- m3 = MatrixType::Random(size,size);
- VERIFY(lu.solve(m3, &m2));
-}
-
-void test_eigen2_lu()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( lu_non_invertible<MatrixXf>() );
- CALL_SUBTEST_2( lu_non_invertible<MatrixXd>() );
- CALL_SUBTEST_3( lu_non_invertible<MatrixXcf>() );
- CALL_SUBTEST_4( lu_non_invertible<MatrixXcd>() );
- CALL_SUBTEST_1( lu_invertible<MatrixXf>() );
- CALL_SUBTEST_2( lu_invertible<MatrixXd>() );
- CALL_SUBTEST_3( lu_invertible<MatrixXcf>() );
- CALL_SUBTEST_4( lu_invertible<MatrixXcd>() );
- }
-}
diff --git a/test/eigen2/eigen2_map.cpp b/test/eigen2/eigen2_map.cpp
deleted file mode 100644
index 4a1c4e11a..000000000
--- a/test/eigen2/eigen2_map.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2007-2010 Benoit Jacob <jacob.benoit.1@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"
-
-template<typename VectorType> void map_class_vector(const VectorType& m)
-{
- typedef typename VectorType::Scalar Scalar;
-
- int size = m.size();
-
- // test Map.h
- Scalar* array1 = ei_aligned_new<Scalar>(size);
- Scalar* array2 = ei_aligned_new<Scalar>(size);
- Scalar* array3 = new Scalar[size+1];
- Scalar* array3unaligned = std::size_t(array3)%16 == 0 ? array3+1 : array3;
-
- Map<VectorType, Aligned>(array1, size) = VectorType::Random(size);
- Map<VectorType>(array2, size) = Map<VectorType>(array1, size);
- Map<VectorType>(array3unaligned, size) = Map<VectorType>((const Scalar*)array1, size); // test non-const-correctness support in eigen2
- VectorType ma1 = Map<VectorType>(array1, size);
- VectorType ma2 = Map<VectorType, Aligned>(array2, size);
- VectorType ma3 = Map<VectorType>(array3unaligned, size);
- VERIFY_IS_APPROX(ma1, ma2);
- VERIFY_IS_APPROX(ma1, ma3);
-
- ei_aligned_delete(array1, size);
- ei_aligned_delete(array2, size);
- delete[] array3;
-}
-
-template<typename MatrixType> void map_class_matrix(const MatrixType& m)
-{
- typedef typename MatrixType::Scalar Scalar;
-
- int rows = m.rows(), cols = m.cols(), size = rows*cols;
-
- // test Map.h
- Scalar* array1 = ei_aligned_new<Scalar>(size);
- for(int i = 0; i < size; i++) array1[i] = Scalar(1);
- Scalar* array2 = ei_aligned_new<Scalar>(size);
- for(int i = 0; i < size; i++) array2[i] = Scalar(1);
- Scalar* array3 = new Scalar[size+1];
- for(int i = 0; i < size+1; i++) array3[i] = Scalar(1);
- Scalar* array3unaligned = std::size_t(array3)%16 == 0 ? array3+1 : array3;
- Map<MatrixType, Aligned>(array1, rows, cols) = MatrixType::Ones(rows,cols);
- Map<MatrixType>(array2, rows, cols) = Map<MatrixType>((const Scalar*)array1, rows, cols); // test non-const-correctness support in eigen2
- Map<MatrixType>(array3unaligned, rows, cols) = Map<MatrixType>(array1, rows, cols);
- MatrixType ma1 = Map<MatrixType>(array1, rows, cols);
- MatrixType ma2 = Map<MatrixType, Aligned>(array2, rows, cols);
- VERIFY_IS_APPROX(ma1, ma2);
- MatrixType ma3 = Map<MatrixType>(array3unaligned, rows, cols);
- VERIFY_IS_APPROX(ma1, ma3);
-
- ei_aligned_delete(array1, size);
- ei_aligned_delete(array2, size);
- delete[] array3;
-}
-
-template<typename VectorType> void map_static_methods(const VectorType& m)
-{
- typedef typename VectorType::Scalar Scalar;
-
- int size = m.size();
-
- // test Map.h
- Scalar* array1 = ei_aligned_new<Scalar>(size);
- Scalar* array2 = ei_aligned_new<Scalar>(size);
- Scalar* array3 = new Scalar[size+1];
- Scalar* array3unaligned = std::size_t(array3)%16 == 0 ? array3+1 : array3;
-
- VectorType::MapAligned(array1, size) = VectorType::Random(size);
- VectorType::Map(array2, size) = VectorType::Map(array1, size);
- VectorType::Map(array3unaligned, size) = VectorType::Map(array1, size);
- VectorType ma1 = VectorType::Map(array1, size);
- VectorType ma2 = VectorType::MapAligned(array2, size);
- VectorType ma3 = VectorType::Map(array3unaligned, size);
- VERIFY_IS_APPROX(ma1, ma2);
- VERIFY_IS_APPROX(ma1, ma3);
-
- ei_aligned_delete(array1, size);
- ei_aligned_delete(array2, size);
- delete[] array3;
-}
-
-
-void test_eigen2_map()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( map_class_vector(Matrix<float, 1, 1>()) );
- CALL_SUBTEST_2( map_class_vector(Vector4d()) );
- CALL_SUBTEST_3( map_class_vector(RowVector4f()) );
- CALL_SUBTEST_4( map_class_vector(VectorXcf(8)) );
- CALL_SUBTEST_5( map_class_vector(VectorXi(12)) );
-
- CALL_SUBTEST_1( map_class_matrix(Matrix<float, 1, 1>()) );
- CALL_SUBTEST_2( map_class_matrix(Matrix4d()) );
- CALL_SUBTEST_6( map_class_matrix(Matrix<float,3,5>()) );
- CALL_SUBTEST_4( map_class_matrix(MatrixXcf(ei_random<int>(1,10),ei_random<int>(1,10))) );
- CALL_SUBTEST_5( map_class_matrix(MatrixXi(ei_random<int>(1,10),ei_random<int>(1,10))) );
-
- CALL_SUBTEST_1( map_static_methods(Matrix<double, 1, 1>()) );
- CALL_SUBTEST_2( map_static_methods(Vector3f()) );
- CALL_SUBTEST_7( map_static_methods(RowVector3d()) );
- CALL_SUBTEST_4( map_static_methods(VectorXcd(8)) );
- CALL_SUBTEST_5( map_static_methods(VectorXf(12)) );
- }
-}
diff --git a/test/eigen2/eigen2_meta.cpp b/test/eigen2/eigen2_meta.cpp
deleted file mode 100644
index 1d01bd84d..000000000
--- a/test/eigen2/eigen2_meta.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
-
-#include "main.h"
-
-void test_eigen2_meta()
-{
- typedef float & FloatRef;
- typedef const float & ConstFloatRef;
-
- VERIFY((ei_meta_if<(3<4),ei_meta_true, ei_meta_false>::ret::ret));
- VERIFY(( ei_is_same_type<float,float>::ret));
- VERIFY((!ei_is_same_type<float,double>::ret));
- VERIFY((!ei_is_same_type<float,float&>::ret));
- VERIFY((!ei_is_same_type<float,const float&>::ret));
-
- VERIFY(( ei_is_same_type<float,ei_cleantype<const float&>::type >::ret));
- VERIFY(( ei_is_same_type<float,ei_cleantype<const float*>::type >::ret));
- VERIFY(( ei_is_same_type<float,ei_cleantype<const float*&>::type >::ret));
- VERIFY(( ei_is_same_type<float,ei_cleantype<float**>::type >::ret));
- VERIFY(( ei_is_same_type<float,ei_cleantype<float**&>::type >::ret));
- VERIFY(( ei_is_same_type<float,ei_cleantype<float* const *&>::type >::ret));
- VERIFY(( ei_is_same_type<float,ei_cleantype<float* const>::type >::ret));
-
- VERIFY(( ei_is_same_type<float*,ei_unconst<const float*>::type >::ret));
- VERIFY(( ei_is_same_type<float&,ei_unconst<const float&>::type >::ret));
- VERIFY(( ei_is_same_type<float&,ei_unconst<ConstFloatRef>::type >::ret));
-
- VERIFY(( ei_is_same_type<float&,ei_unconst<float&>::type >::ret));
- VERIFY(( ei_is_same_type<float,ei_unref<float&>::type >::ret));
- VERIFY(( ei_is_same_type<const float,ei_unref<const float&>::type >::ret));
- VERIFY(( ei_is_same_type<float,ei_unpointer<float*>::type >::ret));
- VERIFY(( ei_is_same_type<const float,ei_unpointer<const float*>::type >::ret));
- VERIFY(( ei_is_same_type<float,ei_unpointer<float* const >::type >::ret));
-
- VERIFY(ei_meta_sqrt<1>::ret == 1);
- #define VERIFY_META_SQRT(X) VERIFY(ei_meta_sqrt<X>::ret == int(ei_sqrt(double(X))))
- VERIFY_META_SQRT(2);
- VERIFY_META_SQRT(3);
- VERIFY_META_SQRT(4);
- VERIFY_META_SQRT(5);
- VERIFY_META_SQRT(6);
- VERIFY_META_SQRT(8);
- VERIFY_META_SQRT(9);
- VERIFY_META_SQRT(15);
- VERIFY_META_SQRT(16);
- VERIFY_META_SQRT(17);
- VERIFY_META_SQRT(255);
- VERIFY_META_SQRT(256);
- VERIFY_META_SQRT(257);
- VERIFY_META_SQRT(1023);
- VERIFY_META_SQRT(1024);
- VERIFY_META_SQRT(1025);
-}
diff --git a/test/eigen2/eigen2_miscmatrices.cpp b/test/eigen2/eigen2_miscmatrices.cpp
deleted file mode 100644
index 8bbb20cc8..000000000
--- a/test/eigen2/eigen2_miscmatrices.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@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"
-
-template<typename MatrixType> void miscMatrices(const MatrixType& m)
-{
- /* this test covers the following files:
- DiagonalMatrix.h Ones.h
- */
-
- typedef typename MatrixType::Scalar Scalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
- typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
- int rows = m.rows();
- int cols = m.cols();
-
- int r = ei_random<int>(0, rows-1), r2 = ei_random<int>(0, rows-1), c = ei_random<int>(0, cols-1);
- VERIFY_IS_APPROX(MatrixType::Ones(rows,cols)(r,c), static_cast<Scalar>(1));
- MatrixType m1 = MatrixType::Ones(rows,cols);
- VERIFY_IS_APPROX(m1(r,c), static_cast<Scalar>(1));
- VectorType v1 = VectorType::Random(rows);
- v1[0];
- Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
- square = v1.asDiagonal();
- if(r==r2) VERIFY_IS_APPROX(square(r,r2), v1[r]);
- else VERIFY_IS_MUCH_SMALLER_THAN(square(r,r2), static_cast<Scalar>(1));
- square = MatrixType::Zero(rows, rows);
- square.diagonal() = VectorType::Ones(rows);
- VERIFY_IS_APPROX(square, MatrixType::Identity(rows, rows));
-}
-
-void test_eigen2_miscmatrices()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( miscMatrices(Matrix<float, 1, 1>()) );
- CALL_SUBTEST_2( miscMatrices(Matrix4d()) );
- CALL_SUBTEST_3( miscMatrices(MatrixXcf(3, 3)) );
- CALL_SUBTEST_4( miscMatrices(MatrixXi(8, 12)) );
- CALL_SUBTEST_5( miscMatrices(MatrixXcd(20, 20)) );
- }
-}
diff --git a/test/eigen2/eigen2_mixingtypes.cpp b/test/eigen2/eigen2_mixingtypes.cpp
deleted file mode 100644
index fb5ac5dda..000000000
--- a/test/eigen2/eigen2_mixingtypes.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
-// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@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/.
-
-#ifndef EIGEN_NO_STATIC_ASSERT
-#define EIGEN_NO_STATIC_ASSERT // turn static asserts into runtime asserts in order to check them
-#endif
-
-#ifndef EIGEN_DONT_VECTORIZE
-#define EIGEN_DONT_VECTORIZE // SSE intrinsics aren't designed to allow mixing types
-#endif
-
-#include "main.h"
-
-
-template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
-{
- typedef Matrix<float, SizeAtCompileType, SizeAtCompileType> Mat_f;
- typedef Matrix<double, SizeAtCompileType, SizeAtCompileType> Mat_d;
- typedef Matrix<std::complex<float>, SizeAtCompileType, SizeAtCompileType> Mat_cf;
- typedef Matrix<std::complex<double>, SizeAtCompileType, SizeAtCompileType> Mat_cd;
- typedef Matrix<float, SizeAtCompileType, 1> Vec_f;
- typedef Matrix<double, SizeAtCompileType, 1> Vec_d;
- typedef Matrix<std::complex<float>, SizeAtCompileType, 1> Vec_cf;
- typedef Matrix<std::complex<double>, SizeAtCompileType, 1> Vec_cd;
-
- Mat_f mf(size,size);
- Mat_d md(size,size);
- Mat_cf mcf(size,size);
- Mat_cd mcd(size,size);
- Vec_f vf(size,1);
- Vec_d vd(size,1);
- Vec_cf vcf(size,1);
- Vec_cd vcd(size,1);
-
- mf+mf;
- VERIFY_RAISES_ASSERT(mf+md);
- VERIFY_RAISES_ASSERT(mf+mcf);
- VERIFY_RAISES_ASSERT(vf=vd);
- VERIFY_RAISES_ASSERT(vf+=vd);
- VERIFY_RAISES_ASSERT(mcd=md);
-
- mf*mf;
- md*mcd;
- mcd*md;
- mf*vcf;
- mcf*vf;
- mcf *= mf;
- vcd = md*vcd;
- vcf = mcf*vf;
-#if 0
- // these are know generating hard build errors in eigen3
- VERIFY_RAISES_ASSERT(mf*md);
- VERIFY_RAISES_ASSERT(mcf*mcd);
- VERIFY_RAISES_ASSERT(mcf*vcd);
- VERIFY_RAISES_ASSERT(vcf = mf*vf);
-
- vf.eigen2_dot(vf);
- VERIFY_RAISES_ASSERT(vd.eigen2_dot(vf));
- VERIFY_RAISES_ASSERT(vcf.eigen2_dot(vf)); // yeah eventually we should allow this but i'm too lazy to make that change now in Dot.h
- // especially as that might be rewritten as cwise product .sum() which would make that automatic.
-#endif
-}
-
-void test_eigen2_mixingtypes()
-{
- // check that our operator new is indeed called:
- CALL_SUBTEST_1(mixingtypes<3>());
- CALL_SUBTEST_2(mixingtypes<4>());
- CALL_SUBTEST_3(mixingtypes<Dynamic>(20));
-}
diff --git a/test/eigen2/eigen2_nomalloc.cpp b/test/eigen2/eigen2_nomalloc.cpp
deleted file mode 100644
index d34a69999..000000000
--- a/test/eigen2/eigen2_nomalloc.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@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/.
-
-// this hack is needed to make this file compiles with -pedantic (gcc)
-#ifdef __GNUC__
-#define throw(X)
-#endif
-// discard stack allocation as that too bypasses malloc
-#define EIGEN_STACK_ALLOCATION_LIMIT 0
-// any heap allocation will raise an assert
-#define EIGEN_NO_MALLOC
-
-#include "main.h"
-
-template<typename MatrixType> void nomalloc(const MatrixType& m)
-{
- /* this test check no dynamic memory allocation are issued with fixed-size matrices
- */
-
- typedef typename MatrixType::Scalar Scalar;
-
- int rows = m.rows();
- int cols = m.cols();
-
- MatrixType m1 = MatrixType::Random(rows, cols),
- m2 = MatrixType::Random(rows, cols);
-
- Scalar s1 = ei_random<Scalar>();
-
- int r = ei_random<int>(0, rows-1),
- c = ei_random<int>(0, cols-1);
-
- VERIFY_IS_APPROX((m1+m2)*s1, s1*m1+s1*m2);
- VERIFY_IS_APPROX((m1+m2)(r,c), (m1(r,c))+(m2(r,c)));
- VERIFY_IS_APPROX(m1.cwise() * m1.block(0,0,rows,cols), m1.cwise() * m1);
- VERIFY_IS_APPROX((m1*m1.transpose())*m2, m1*(m1.transpose()*m2));
-}
-
-void test_eigen2_nomalloc()
-{
- // check that our operator new is indeed called:
- VERIFY_RAISES_ASSERT(MatrixXd dummy = MatrixXd::Random(3,3));
- CALL_SUBTEST_1( nomalloc(Matrix<float, 1, 1>()) );
- CALL_SUBTEST_2( nomalloc(Matrix4d()) );
- CALL_SUBTEST_3( nomalloc(Matrix<float,32,32>()) );
-}
diff --git a/test/eigen2/eigen2_packetmath.cpp b/test/eigen2/eigen2_packetmath.cpp
deleted file mode 100644
index b1f325fe7..000000000
--- a/test/eigen2/eigen2_packetmath.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@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"
-
-// using namespace Eigen;
-
-template<typename Scalar> bool areApprox(const Scalar* a, const Scalar* b, int size)
-{
- for (int i=0; i<size; ++i)
- if (!ei_isApprox(a[i],b[i])) return false;
- return true;
-}
-
-#define CHECK_CWISE(REFOP, POP) { \
- for (int i=0; i<PacketSize; ++i) \
- ref[i] = REFOP(data1[i], data1[i+PacketSize]); \
- ei_pstore(data2, POP(ei_pload(data1), ei_pload(data1+PacketSize))); \
- VERIFY(areApprox(ref, data2, PacketSize) && #POP); \
-}
-
-#define REF_ADD(a,b) ((a)+(b))
-#define REF_SUB(a,b) ((a)-(b))
-#define REF_MUL(a,b) ((a)*(b))
-#define REF_DIV(a,b) ((a)/(b))
-
-namespace std {
-
-template<> const complex<float>& min(const complex<float>& a, const complex<float>& b)
-{ return a.real() < b.real() ? a : b; }
-
-template<> const complex<float>& max(const complex<float>& a, const complex<float>& b)
-{ return a.real() < b.real() ? b : a; }
-
-}
-
-template<typename Scalar> void packetmath()
-{
- typedef typename ei_packet_traits<Scalar>::type Packet;
- const int PacketSize = ei_packet_traits<Scalar>::size;
-
- const int size = PacketSize*4;
- EIGEN_ALIGN_128 Scalar data1[ei_packet_traits<Scalar>::size*4];
- EIGEN_ALIGN_128 Scalar data2[ei_packet_traits<Scalar>::size*4];
- EIGEN_ALIGN_128 Packet packets[PacketSize*2];
- EIGEN_ALIGN_128 Scalar ref[ei_packet_traits<Scalar>::size*4];
- for (int i=0; i<size; ++i)
- {
- data1[i] = ei_random<Scalar>();
- data2[i] = ei_random<Scalar>();
- }
-
- ei_pstore(data2, ei_pload(data1));
- VERIFY(areApprox(data1, data2, PacketSize) && "aligned load/store");
-
- for (int offset=0; offset<PacketSize; ++offset)
- {
- ei_pstore(data2, ei_ploadu(data1+offset));
- VERIFY(areApprox(data1+offset, data2, PacketSize) && "ei_ploadu");
- }
-
- for (int offset=0; offset<PacketSize; ++offset)
- {
- ei_pstoreu(data2+offset, ei_pload(data1));
- VERIFY(areApprox(data1, data2+offset, PacketSize) && "ei_pstoreu");
- }
-
- for (int offset=0; offset<PacketSize; ++offset)
- {
- packets[0] = ei_pload(data1);
- packets[1] = ei_pload(data1+PacketSize);
- if (offset==0) ei_palign<0>(packets[0], packets[1]);
- else if (offset==1) ei_palign<1>(packets[0], packets[1]);
- else if (offset==2) ei_palign<2>(packets[0], packets[1]);
- else if (offset==3) ei_palign<3>(packets[0], packets[1]);
- ei_pstore(data2, packets[0]);
-
- for (int i=0; i<PacketSize; ++i)
- ref[i] = data1[i+offset];
-
- typedef Matrix<Scalar, PacketSize, 1> Vector;
- VERIFY(areApprox(ref, data2, PacketSize) && "ei_palign");
- }
-
- CHECK_CWISE(REF_ADD, ei_padd);
- CHECK_CWISE(REF_SUB, ei_psub);
- CHECK_CWISE(REF_MUL, ei_pmul);
- #ifndef EIGEN_VECTORIZE_ALTIVEC
- if (!ei_is_same_type<Scalar,int>::ret)
- CHECK_CWISE(REF_DIV, ei_pdiv);
- #endif
- CHECK_CWISE(std::min, ei_pmin);
- CHECK_CWISE(std::max, ei_pmax);
-
- for (int i=0; i<PacketSize; ++i)
- ref[i] = data1[0];
- ei_pstore(data2, ei_pset1(data1[0]));
- VERIFY(areApprox(ref, data2, PacketSize) && "ei_pset1");
-
- VERIFY(ei_isApprox(data1[0], ei_pfirst(ei_pload(data1))) && "ei_pfirst");
-
- ref[0] = 0;
- for (int i=0; i<PacketSize; ++i)
- ref[0] += data1[i];
- VERIFY(ei_isApprox(ref[0], ei_predux(ei_pload(data1))) && "ei_predux");
-
- for (int j=0; j<PacketSize; ++j)
- {
- ref[j] = 0;
- for (int i=0; i<PacketSize; ++i)
- ref[j] += data1[i+j*PacketSize];
- packets[j] = ei_pload(data1+j*PacketSize);
- }
- ei_pstore(data2, ei_preduxp(packets));
- VERIFY(areApprox(ref, data2, PacketSize) && "ei_preduxp");
-}
-
-void test_eigen2_packetmath()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( packetmath<float>() );
- CALL_SUBTEST_2( packetmath<double>() );
- CALL_SUBTEST_3( packetmath<int>() );
- CALL_SUBTEST_4( packetmath<std::complex<float> >() );
- }
-}
diff --git a/test/eigen2/eigen2_parametrizedline.cpp b/test/eigen2/eigen2_parametrizedline.cpp
deleted file mode 100644
index 814728870..000000000
--- a/test/eigen2/eigen2_parametrizedline.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
-// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@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/Geometry>
-#include <Eigen/LU>
-#include <Eigen/QR>
-
-template<typename LineType> void parametrizedline(const LineType& _line)
-{
- /* this test covers the following files:
- ParametrizedLine.h
- */
-
- const int dim = _line.dim();
- typedef typename LineType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Matrix<Scalar, LineType::AmbientDimAtCompileTime, 1> VectorType;
- typedef Matrix<Scalar, LineType::AmbientDimAtCompileTime,
- LineType::AmbientDimAtCompileTime> MatrixType;
-
- VectorType p0 = VectorType::Random(dim);
- VectorType p1 = VectorType::Random(dim);
-
- VectorType d0 = VectorType::Random(dim).normalized();
-
- LineType l0(p0, d0);
-
- Scalar s0 = ei_random<Scalar>();
- Scalar s1 = ei_abs(ei_random<Scalar>());
-
- VERIFY_IS_MUCH_SMALLER_THAN( l0.distance(p0), RealScalar(1) );
- VERIFY_IS_MUCH_SMALLER_THAN( l0.distance(p0+s0*d0), RealScalar(1) );
- VERIFY_IS_APPROX( (l0.projection(p1)-p1).norm(), l0.distance(p1) );
- VERIFY_IS_MUCH_SMALLER_THAN( l0.distance(l0.projection(p1)), RealScalar(1) );
- VERIFY_IS_APPROX( Scalar(l0.distance((p0+s0*d0) + d0.unitOrthogonal() * s1)), s1 );
-
- // casting
- const int Dim = LineType::AmbientDimAtCompileTime;
- typedef typename GetDifferentType<Scalar>::type OtherScalar;
- ParametrizedLine<OtherScalar,Dim> hp1f = l0.template cast<OtherScalar>();
- VERIFY_IS_APPROX(hp1f.template cast<Scalar>(),l0);
- ParametrizedLine<Scalar,Dim> hp1d = l0.template cast<Scalar>();
- VERIFY_IS_APPROX(hp1d.template cast<Scalar>(),l0);
-}
-
-void test_eigen2_parametrizedline()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( parametrizedline(ParametrizedLine<float,2>()) );
- CALL_SUBTEST_2( parametrizedline(ParametrizedLine<float,3>()) );
- CALL_SUBTEST_3( parametrizedline(ParametrizedLine<double,4>()) );
- CALL_SUBTEST_4( parametrizedline(ParametrizedLine<std::complex<double>,5>()) );
- }
-}
diff --git a/test/eigen2/eigen2_prec_inverse_4x4.cpp b/test/eigen2/eigen2_prec_inverse_4x4.cpp
deleted file mode 100644
index 8bfa55694..000000000
--- a/test/eigen2/eigen2_prec_inverse_4x4.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@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/LU>
-#include <algorithm>
-
-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>"; }
-
-#define EIGEN_DEBUG_VAR(x) std::cerr << #x << " = " << x << std::endl;
-
-template<typename T> inline typename NumTraits<T>::Real epsilon()
-{
- return std::numeric_limits<typename NumTraits<T>::Real>::epsilon();
-}
-
-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 = MatrixType::Zero();
- m(indices(0),0) = 1;
- m(indices(1),1) = 1;
- m(indices(2),2) = 1;
- m(indices(3),3) = 1;
- 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 < 10 * 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.25));
- VERIFY(error_max < (NumTraits<Scalar>::IsComplex ? 64.0 : 20.0));
-}
-
-void test_eigen2_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/eigen2/eigen2_product_large.cpp b/test/eigen2/eigen2_product_large.cpp
deleted file mode 100644
index 5149ef748..000000000
--- a/test/eigen2/eigen2_product_large.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@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 "product.h"
-
-void test_eigen2_product_large()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( product(MatrixXf(ei_random<int>(1,320), ei_random<int>(1,320))) );
- CALL_SUBTEST_2( product(MatrixXd(ei_random<int>(1,320), ei_random<int>(1,320))) );
- CALL_SUBTEST_3( product(MatrixXi(ei_random<int>(1,320), ei_random<int>(1,320))) );
- CALL_SUBTEST_4( product(MatrixXcf(ei_random<int>(1,50), ei_random<int>(1,50))) );
- CALL_SUBTEST_5( product(Matrix<float,Dynamic,Dynamic,RowMajor>(ei_random<int>(1,320), ei_random<int>(1,320))) );
- }
-
-#ifdef EIGEN_TEST_PART_6
- {
- // test a specific issue in DiagonalProduct
- int N = 1000000;
- VectorXf v = VectorXf::Ones(N);
- MatrixXf m = MatrixXf::Ones(N,3);
- m = (v+v).asDiagonal() * m;
- VERIFY_IS_APPROX(m, MatrixXf::Constant(N,3,2));
- }
-
- {
- // test deferred resizing in Matrix::operator=
- MatrixXf a = MatrixXf::Random(10,4), b = MatrixXf::Random(4,10), c = a;
- VERIFY_IS_APPROX((a = a * b), (c * b).eval());
- }
-
- {
- MatrixXf mat1(10,10); mat1.setRandom();
- MatrixXf mat2(32,10); mat2.setRandom();
- MatrixXf result = mat1.row(2)*mat2.transpose();
- VERIFY_IS_APPROX(result, (mat1.row(2)*mat2.transpose()).eval());
- }
-#endif
-}
diff --git a/test/eigen2/eigen2_product_small.cpp b/test/eigen2/eigen2_product_small.cpp
deleted file mode 100644
index 4cd8c102f..000000000
--- a/test/eigen2/eigen2_product_small.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@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/.
-
-#define EIGEN_NO_STATIC_ASSERT
-#include "product.h"
-
-void test_eigen2_product_small()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( product(Matrix<float, 3, 2>()) );
- CALL_SUBTEST_2( product(Matrix<int, 3, 5>()) );
- CALL_SUBTEST_3( product(Matrix3d()) );
- CALL_SUBTEST_4( product(Matrix4d()) );
- CALL_SUBTEST_5( product(Matrix4f()) );
- }
-}
diff --git a/test/eigen2/eigen2_qr.cpp b/test/eigen2/eigen2_qr.cpp
deleted file mode 100644
index 76977e4c1..000000000
--- a/test/eigen2/eigen2_qr.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
-
-#include "main.h"
-#include <Eigen/QR>
-
-template<typename MatrixType> void qr(const MatrixType& m)
-{
- /* this test covers the following files:
- QR.h
- */
- int rows = m.rows();
- int cols = m.cols();
-
- typedef typename MatrixType::Scalar Scalar;
- typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> SquareMatrixType;
- typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
-
- MatrixType a = MatrixType::Random(rows,cols);
- QR<MatrixType> qrOfA(a);
- VERIFY_IS_APPROX(a, qrOfA.matrixQ() * qrOfA.matrixR());
- VERIFY_IS_NOT_APPROX(a+MatrixType::Identity(rows, cols), qrOfA.matrixQ() * qrOfA.matrixR());
-
- #if 0 // eigenvalues module not yet ready
- SquareMatrixType b = a.adjoint() * a;
-
- // check tridiagonalization
- Tridiagonalization<SquareMatrixType> tridiag(b);
- VERIFY_IS_APPROX(b, tridiag.matrixQ() * tridiag.matrixT() * tridiag.matrixQ().adjoint());
-
- // check hessenberg decomposition
- HessenbergDecomposition<SquareMatrixType> hess(b);
- VERIFY_IS_APPROX(b, hess.matrixQ() * hess.matrixH() * hess.matrixQ().adjoint());
- VERIFY_IS_APPROX(tridiag.matrixT(), hess.matrixH());
- b = SquareMatrixType::Random(cols,cols);
- hess.compute(b);
- VERIFY_IS_APPROX(b, hess.matrixQ() * hess.matrixH() * hess.matrixQ().adjoint());
- #endif
-}
-
-void test_eigen2_qr()
-{
- for(int i = 0; i < 1; i++) {
- CALL_SUBTEST_1( qr(Matrix2f()) );
- CALL_SUBTEST_2( qr(Matrix4d()) );
- CALL_SUBTEST_3( qr(MatrixXf(12,8)) );
- CALL_SUBTEST_4( qr(MatrixXcd(5,5)) );
- CALL_SUBTEST_4( qr(MatrixXcd(7,3)) );
- }
-
-#ifdef EIGEN_TEST_PART_5
- // small isFullRank test
- {
- Matrix3d mat;
- mat << 1, 45, 1, 2, 2, 2, 1, 2, 3;
- VERIFY(mat.qr().isFullRank());
- mat << 1, 1, 1, 2, 2, 2, 1, 2, 3;
- //always returns true in eigen2support
- //VERIFY(!mat.qr().isFullRank());
- }
-
-#endif
-}
diff --git a/test/eigen2/eigen2_qtvector.cpp b/test/eigen2/eigen2_qtvector.cpp
deleted file mode 100644
index 6cfb58a26..000000000
--- a/test/eigen2/eigen2_qtvector.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
-// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@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/.
-
-#define EIGEN_WORK_AROUND_QT_BUG_CALLING_WRONG_OPERATOR_NEW_FIXED_IN_QT_4_5
-
-#include "main.h"
-
-#include <Eigen/Geometry>
-#include <Eigen/QtAlignedMalloc>
-
-#include <QtCore/QVector>
-
-template<typename MatrixType>
-void check_qtvector_matrix(const MatrixType& m)
-{
- int rows = m.rows();
- int cols = m.cols();
- MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
- QVector<MatrixType> v(10, MatrixType(rows,cols)), w(20, y);
- for(int i = 0; i < 20; i++)
- {
- VERIFY_IS_APPROX(w[i], 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.fill(y,22);
- VERIFY_IS_APPROX(v[21], y);
- v.push_back(x);
- VERIFY_IS_APPROX(v[22], x);
- VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(MatrixType));
-
- // do a lot of push_back such that the vector 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(int i=23; i<v.size(); ++i)
- {
- VERIFY(v[i]==w[(i-23)%w.size()]);
- }
-}
-
-template<typename TransformType>
-void check_qtvector_transform(const TransformType&)
-{
- typedef typename TransformType::MatrixType MatrixType;
- TransformType x(MatrixType::Random()), y(MatrixType::Random());
- QVector<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.fill(y,22);
- VERIFY_IS_APPROX(v[21], y);
- v.push_back(x);
- VERIFY_IS_APPROX(v[22], x);
- VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(TransformType));
-
- // do a lot of push_back such that the vector 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; int(i)<v.size(); ++i)
- {
- VERIFY(v[i].matrix()==w[(i-23)%w.size()].matrix());
- }
-}
-
-template<typename QuaternionType>
-void check_qtvector_quaternion(const QuaternionType&)
-{
- typedef typename QuaternionType::Coefficients Coefficients;
- QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
- QVector<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.fill(y,22);
- VERIFY_IS_APPROX(v[21], y);
- v.push_back(x);
- VERIFY_IS_APPROX(v[22], x);
- VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(QuaternionType));
-
- // do a lot of push_back such that the vector 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; int(i)<v.size(); ++i)
- {
- VERIFY(v[i].coeffs()==w[(i-23)%w.size()].coeffs());
- }
-}
-
-void test_eigen2_qtvector()
-{
- // some non vectorizable fixed sizes
- CALL_SUBTEST_1(check_qtvector_matrix(Vector2f()));
- CALL_SUBTEST_1(check_qtvector_matrix(Matrix3f()));
- CALL_SUBTEST_1(check_qtvector_matrix(Matrix3d()));
-
- // some vectorizable fixed sizes
- CALL_SUBTEST_2(check_qtvector_matrix(Matrix2f()));
- CALL_SUBTEST_2(check_qtvector_matrix(Vector4f()));
- CALL_SUBTEST_2(check_qtvector_matrix(Matrix4f()));
- CALL_SUBTEST_2(check_qtvector_matrix(Matrix4d()));
-
- // some dynamic sizes
- CALL_SUBTEST_3(check_qtvector_matrix(MatrixXd(1,1)));
- CALL_SUBTEST_3(check_qtvector_matrix(VectorXd(20)));
- CALL_SUBTEST_3(check_qtvector_matrix(RowVectorXf(20)));
- CALL_SUBTEST_3(check_qtvector_matrix(MatrixXcf(10,10)));
-
- // some Transform
- CALL_SUBTEST_4(check_qtvector_transform(Transform2f()));
- CALL_SUBTEST_4(check_qtvector_transform(Transform3f()));
- CALL_SUBTEST_4(check_qtvector_transform(Transform3d()));
- //CALL_SUBTEST_4(check_qtvector_transform(Transform4d()));
-
- // some Quaternion
- CALL_SUBTEST_5(check_qtvector_quaternion(Quaternionf()));
- CALL_SUBTEST_5(check_qtvector_quaternion(Quaternionf()));
-}
diff --git a/test/eigen2/eigen2_regression.cpp b/test/eigen2/eigen2_regression.cpp
deleted file mode 100644
index c68b58da8..000000000
--- a/test/eigen2/eigen2_regression.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@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/LeastSquares>
-
-template<typename VectorType,
- typename HyperplaneType>
-void makeNoisyCohyperplanarPoints(int numPoints,
- VectorType **points,
- HyperplaneType *hyperplane,
- typename VectorType::Scalar noiseAmplitude)
-{
- typedef typename VectorType::Scalar Scalar;
- const int size = points[0]->size();
- // pick a random hyperplane, store the coefficients of its equation
- hyperplane->coeffs().resize(size + 1);
- for(int j = 0; j < size + 1; j++)
- {
- do {
- hyperplane->coeffs().coeffRef(j) = ei_random<Scalar>();
- } while(ei_abs(hyperplane->coeffs().coeff(j)) < 0.5);
- }
-
- // now pick numPoints random points on this hyperplane
- for(int i = 0; i < numPoints; i++)
- {
- VectorType& cur_point = *(points[i]);
- do
- {
- cur_point = VectorType::Random(size)/*.normalized()*/;
- // project cur_point onto the hyperplane
- Scalar x = - (hyperplane->coeffs().start(size).cwise()*cur_point).sum();
- cur_point *= hyperplane->coeffs().coeff(size) / x;
- } while( cur_point.norm() < 0.5
- || cur_point.norm() > 2.0 );
- }
-
- // add some noise to these points
- for(int i = 0; i < numPoints; i++ )
- *(points[i]) += noiseAmplitude * VectorType::Random(size);
-}
-
-template<typename VectorType>
-void check_linearRegression(int numPoints,
- VectorType **points,
- const VectorType& original,
- typename VectorType::Scalar tolerance)
-{
- int size = points[0]->size();
- assert(size==2);
- VectorType result(size);
- linearRegression(numPoints, points, &result, 1);
- typename VectorType::Scalar error = (result - original).norm() / original.norm();
- VERIFY(ei_abs(error) < ei_abs(tolerance));
-}
-
-template<typename VectorType,
- typename HyperplaneType>
-void check_fitHyperplane(int numPoints,
- VectorType **points,
- const HyperplaneType& original,
- typename VectorType::Scalar tolerance)
-{
- int size = points[0]->size();
- HyperplaneType result(size);
- fitHyperplane(numPoints, points, &result);
- result.coeffs() *= original.coeffs().coeff(size)/result.coeffs().coeff(size);
- typename VectorType::Scalar error = (result.coeffs() - original.coeffs()).norm() / original.coeffs().norm();
- std::cout << ei_abs(error) << " xxx " << ei_abs(tolerance) << std::endl;
- VERIFY(ei_abs(error) < ei_abs(tolerance));
-}
-
-void test_eigen2_regression()
-{
- for(int i = 0; i < g_repeat; i++)
- {
-#ifdef EIGEN_TEST_PART_1
- {
- Vector2f points2f [1000];
- Vector2f *points2f_ptrs [1000];
- for(int i = 0; i < 1000; i++) points2f_ptrs[i] = &(points2f[i]);
- Vector2f coeffs2f;
- Hyperplane<float,2> coeffs3f;
- makeNoisyCohyperplanarPoints(1000, points2f_ptrs, &coeffs3f, 0.01f);
- coeffs2f[0] = -coeffs3f.coeffs()[0]/coeffs3f.coeffs()[1];
- coeffs2f[1] = -coeffs3f.coeffs()[2]/coeffs3f.coeffs()[1];
- CALL_SUBTEST(check_linearRegression(10, points2f_ptrs, coeffs2f, 0.05f));
- CALL_SUBTEST(check_linearRegression(100, points2f_ptrs, coeffs2f, 0.01f));
- CALL_SUBTEST(check_linearRegression(1000, points2f_ptrs, coeffs2f, 0.002f));
- }
-#endif
-#ifdef EIGEN_TEST_PART_2
- {
- Vector2f points2f [1000];
- Vector2f *points2f_ptrs [1000];
- for(int i = 0; i < 1000; i++) points2f_ptrs[i] = &(points2f[i]);
- Hyperplane<float,2> coeffs3f;
- makeNoisyCohyperplanarPoints(1000, points2f_ptrs, &coeffs3f, 0.01f);
- CALL_SUBTEST(check_fitHyperplane(10, points2f_ptrs, coeffs3f, 0.05f));
- CALL_SUBTEST(check_fitHyperplane(100, points2f_ptrs, coeffs3f, 0.01f));
- CALL_SUBTEST(check_fitHyperplane(1000, points2f_ptrs, coeffs3f, 0.002f));
- }
-#endif
-#ifdef EIGEN_TEST_PART_3
- {
- Vector4d points4d [1000];
- Vector4d *points4d_ptrs [1000];
- for(int i = 0; i < 1000; i++) points4d_ptrs[i] = &(points4d[i]);
- Hyperplane<double,4> coeffs5d;
- makeNoisyCohyperplanarPoints(1000, points4d_ptrs, &coeffs5d, 0.01);
- CALL_SUBTEST(check_fitHyperplane(10, points4d_ptrs, coeffs5d, 0.05));
- CALL_SUBTEST(check_fitHyperplane(100, points4d_ptrs, coeffs5d, 0.01));
- CALL_SUBTEST(check_fitHyperplane(1000, points4d_ptrs, coeffs5d, 0.002));
- }
-#endif
-#ifdef EIGEN_TEST_PART_4
- {
- VectorXcd *points11cd_ptrs[1000];
- for(int i = 0; i < 1000; i++) points11cd_ptrs[i] = new VectorXcd(11);
- Hyperplane<std::complex<double>,Dynamic> *coeffs12cd = new Hyperplane<std::complex<double>,Dynamic>(11);
- makeNoisyCohyperplanarPoints(1000, points11cd_ptrs, coeffs12cd, 0.01);
- CALL_SUBTEST(check_fitHyperplane(100, points11cd_ptrs, *coeffs12cd, 0.025));
- CALL_SUBTEST(check_fitHyperplane(1000, points11cd_ptrs, *coeffs12cd, 0.006));
- delete coeffs12cd;
- for(int i = 0; i < 1000; i++) delete points11cd_ptrs[i];
- }
-#endif
- }
-}
diff --git a/test/eigen2/eigen2_sizeof.cpp b/test/eigen2/eigen2_sizeof.cpp
deleted file mode 100644
index ec1af5a06..000000000
--- a/test/eigen2/eigen2_sizeof.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
-
-#include "main.h"
-
-template<typename MatrixType> void verifySizeOf(const MatrixType&)
-{
- typedef typename MatrixType::Scalar Scalar;
- if (MatrixType::RowsAtCompileTime!=Dynamic && MatrixType::ColsAtCompileTime!=Dynamic)
- VERIFY(sizeof(MatrixType)==sizeof(Scalar)*MatrixType::SizeAtCompileTime);
- else
- VERIFY(sizeof(MatrixType)==sizeof(Scalar*) + 2 * sizeof(typename MatrixType::Index));
-}
-
-void test_eigen2_sizeof()
-{
- CALL_SUBTEST( verifySizeOf(Matrix<float, 1, 1>()) );
- CALL_SUBTEST( verifySizeOf(Matrix4d()) );
- CALL_SUBTEST( verifySizeOf(Matrix<double, 4, 2>()) );
- CALL_SUBTEST( verifySizeOf(Matrix<bool, 7, 5>()) );
- CALL_SUBTEST( verifySizeOf(MatrixXcf(3, 3)) );
- CALL_SUBTEST( verifySizeOf(MatrixXi(8, 12)) );
- CALL_SUBTEST( verifySizeOf(MatrixXcd(20, 20)) );
- CALL_SUBTEST( verifySizeOf(Matrix<float, 100, 100>()) );
-}
diff --git a/test/eigen2/eigen2_smallvectors.cpp b/test/eigen2/eigen2_smallvectors.cpp
deleted file mode 100644
index 03962b17d..000000000
--- a/test/eigen2/eigen2_smallvectors.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@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"
-
-template<typename Scalar> void smallVectors()
-{
- typedef Matrix<Scalar, 1, 2> V2;
- typedef Matrix<Scalar, 3, 1> V3;
- typedef Matrix<Scalar, 1, 4> V4;
- Scalar x1 = ei_random<Scalar>(),
- x2 = ei_random<Scalar>(),
- x3 = ei_random<Scalar>(),
- x4 = ei_random<Scalar>();
- V2 v2(x1, x2);
- V3 v3(x1, x2, x3);
- V4 v4(x1, x2, x3, x4);
- VERIFY_IS_APPROX(x1, v2.x());
- VERIFY_IS_APPROX(x1, v3.x());
- VERIFY_IS_APPROX(x1, v4.x());
- VERIFY_IS_APPROX(x2, v2.y());
- VERIFY_IS_APPROX(x2, v3.y());
- VERIFY_IS_APPROX(x2, v4.y());
- VERIFY_IS_APPROX(x3, v3.z());
- VERIFY_IS_APPROX(x3, v4.z());
- VERIFY_IS_APPROX(x4, v4.w());
-}
-
-void test_eigen2_smallvectors()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST( smallVectors<int>() );
- CALL_SUBTEST( smallVectors<float>() );
- CALL_SUBTEST( smallVectors<double>() );
- }
-}
diff --git a/test/eigen2/eigen2_sparse_basic.cpp b/test/eigen2/eigen2_sparse_basic.cpp
deleted file mode 100644
index 049077670..000000000
--- a/test/eigen2/eigen2_sparse_basic.cpp
+++ /dev/null
@@ -1,317 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@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 "sparse.h"
-
-template<typename SetterType,typename DenseType, typename Scalar, int Options>
-bool test_random_setter(SparseMatrix<Scalar,Options>& sm, const DenseType& ref, const std::vector<Vector2i>& nonzeroCoords)
-{
- typedef SparseMatrix<Scalar,Options> SparseType;
- {
- sm.setZero();
- SetterType w(sm);
- std::vector<Vector2i> remaining = nonzeroCoords;
- while(!remaining.empty())
- {
- int i = ei_random<int>(0,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();
- }
- }
- return sm.isApprox(ref);
-}
-
-template<typename SetterType,typename DenseType, typename T>
-bool test_random_setter(DynamicSparseMatrix<T>& sm, const DenseType& ref, const std::vector<Vector2i>& nonzeroCoords)
-{
- sm.setZero();
- std::vector<Vector2i> remaining = nonzeroCoords;
- while(!remaining.empty())
- {
- int i = ei_random<int>(0,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();
- }
- return sm.isApprox(ref);
-}
-
-template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& ref)
-{
- const int rows = ref.rows();
- const int cols = ref.cols();
- typedef typename SparseMatrixType::Scalar Scalar;
- enum { Flags = SparseMatrixType::Flags };
-
- double density = std::max(8./(rows*cols), 0.01);
- typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
- typedef Matrix<Scalar,Dynamic,1> DenseVector;
- Scalar eps = 1e-6;
-
- SparseMatrixType m(rows, cols);
- DenseMatrix refMat = DenseMatrix::Zero(rows, cols);
- DenseVector vec1 = DenseVector::Random(rows);
- Scalar s1 = ei_random<Scalar>();
-
- std::vector<Vector2i> zeroCoords;
- std::vector<Vector2i> nonzeroCoords;
- initSparse<Scalar>(density, refMat, m, 0, &zeroCoords, &nonzeroCoords);
-
- if (zeroCoords.size()==0 || nonzeroCoords.size()==0)
- return;
-
- // test coeff and coeffRef
- for (int i=0; i<(int)zeroCoords.size(); ++i)
- {
- VERIFY_IS_MUCH_SMALLER_THAN( m.coeff(zeroCoords[i].x(),zeroCoords[i].y()), eps );
- if(ei_is_same_type<SparseMatrixType,SparseMatrix<Scalar,Flags> >::ret)
- VERIFY_RAISES_ASSERT( m.coeffRef(zeroCoords[0].x(),zeroCoords[0].y()) = 5 );
- }
- VERIFY_IS_APPROX(m, refMat);
-
- m.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
- refMat.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
-
- VERIFY_IS_APPROX(m, refMat);
- /*
- // test InnerIterators and Block expressions
- for (int t=0; t<10; ++t)
- {
- int j = ei_random<int>(0,cols-1);
- int i = ei_random<int>(0,rows-1);
- int w = ei_random<int>(1,cols-j-1);
- int h = ei_random<int>(1,rows-i-1);
-
-// VERIFY_IS_APPROX(m.block(i,j,h,w), refMat.block(i,j,h,w));
- for(int c=0; c<w; c++)
- {
- VERIFY_IS_APPROX(m.block(i,j,h,w).col(c), refMat.block(i,j,h,w).col(c));
- for(int r=0; r<h; r++)
- {
-// VERIFY_IS_APPROX(m.block(i,j,h,w).col(c).coeff(r), refMat.block(i,j,h,w).col(c).coeff(r));
- }
- }
-// for(int r=0; r<h; r++)
-// {
-// VERIFY_IS_APPROX(m.block(i,j,h,w).row(r), refMat.block(i,j,h,w).row(r));
-// for(int c=0; c<w; c++)
-// {
-// VERIFY_IS_APPROX(m.block(i,j,h,w).row(r).coeff(c), refMat.block(i,j,h,w).row(r).coeff(c));
-// }
-// }
- }
-
- for(int c=0; c<cols; c++)
- {
- VERIFY_IS_APPROX(m.col(c) + m.col(c), (m + m).col(c));
- VERIFY_IS_APPROX(m.col(c) + m.col(c), refMat.col(c) + refMat.col(c));
- }
-
- for(int r=0; r<rows; r++)
- {
- VERIFY_IS_APPROX(m.row(r) + m.row(r), (m + m).row(r));
- VERIFY_IS_APPROX(m.row(r) + m.row(r), refMat.row(r) + refMat.row(r));
- }
- */
-
- // test SparseSetters
- // coherent setter
- // TODO extend the MatrixSetter
-// {
-// m.setZero();
-// VERIFY_IS_NOT_APPROX(m, refMat);
-// SparseSetter<SparseMatrixType, FullyCoherentAccessPattern> w(m);
-// for (int i=0; i<nonzeroCoords.size(); ++i)
-// {
-// w->coeffRef(nonzeroCoords[i].x(),nonzeroCoords[i].y()) = refMat.coeff(nonzeroCoords[i].x(),nonzeroCoords[i].y());
-// }
-// }
-// VERIFY_IS_APPROX(m, refMat);
-
- // random setter
-// {
-// m.setZero();
-// VERIFY_IS_NOT_APPROX(m, refMat);
-// SparseSetter<SparseMatrixType, RandomAccessPattern> w(m);
-// std::vector<Vector2i> remaining = nonzeroCoords;
-// while(!remaining.empty())
-// {
-// int i = ei_random<int>(0,remaining.size()-1);
-// w->coeffRef(remaining[i].x(),remaining[i].y()) = refMat.coeff(remaining[i].x(),remaining[i].y());
-// remaining[i] = remaining.back();
-// remaining.pop_back();
-// }
-// }
-// VERIFY_IS_APPROX(m, refMat);
-
- VERIFY(( test_random_setter<RandomSetter<SparseMatrixType, StdMapTraits> >(m,refMat,nonzeroCoords) ));
- #ifdef EIGEN_UNORDERED_MAP_SUPPORT
- VERIFY(( test_random_setter<RandomSetter<SparseMatrixType, StdUnorderedMapTraits> >(m,refMat,nonzeroCoords) ));
- #endif
- #ifdef _DENSE_HASH_MAP_H_
- VERIFY(( test_random_setter<RandomSetter<SparseMatrixType, GoogleDenseHashMapTraits> >(m,refMat,nonzeroCoords) ));
- #endif
- #ifdef _SPARSE_HASH_MAP_H_
- VERIFY(( test_random_setter<RandomSetter<SparseMatrixType, GoogleSparseHashMapTraits> >(m,refMat,nonzeroCoords) ));
- #endif
-
- // test fillrand
- {
- DenseMatrix m1(rows,cols);
- m1.setZero();
- SparseMatrixType m2(rows,cols);
- m2.startFill();
- for (int j=0; j<cols; ++j)
- {
- for (int k=0; k<rows/2; ++k)
- {
- int i = ei_random<int>(0,rows-1);
- if (m1.coeff(i,j)==Scalar(0))
- m2.fillrand(i,j) = m1(i,j) = ei_random<Scalar>();
- }
- }
- m2.endFill();
- VERIFY_IS_APPROX(m2,m1);
- }
-
- // test RandomSetter
- /*{
- SparseMatrixType m1(rows,cols), m2(rows,cols);
- DenseMatrix refM1 = DenseMatrix::Zero(rows, rows);
- initSparse<Scalar>(density, refM1, m1);
- {
- Eigen::RandomSetter<SparseMatrixType > setter(m2);
- for (int j=0; j<m1.outerSize(); ++j)
- for (typename SparseMatrixType::InnerIterator i(m1,j); i; ++i)
- setter(i.index(), j) = i.value();
- }
- VERIFY_IS_APPROX(m1, m2);
- }*/
-// std::cerr << m.transpose() << "\n\n" << refMat.transpose() << "\n\n";
-// VERIFY_IS_APPROX(m, refMat);
-
- // test basic computations
- {
- DenseMatrix refM1 = DenseMatrix::Zero(rows, rows);
- DenseMatrix refM2 = DenseMatrix::Zero(rows, rows);
- DenseMatrix refM3 = DenseMatrix::Zero(rows, rows);
- DenseMatrix refM4 = DenseMatrix::Zero(rows, rows);
- SparseMatrixType m1(rows, rows);
- SparseMatrixType m2(rows, rows);
- SparseMatrixType m3(rows, rows);
- SparseMatrixType m4(rows, rows);
- initSparse<Scalar>(density, refM1, m1);
- initSparse<Scalar>(density, refM2, m2);
- initSparse<Scalar>(density, refM3, m3);
- initSparse<Scalar>(density, refM4, m4);
-
- VERIFY_IS_APPROX(m1+m2, refM1+refM2);
- VERIFY_IS_APPROX(m1+m2+m3, refM1+refM2+refM3);
- VERIFY_IS_APPROX(m3.cwise()*(m1+m2), refM3.cwise()*(refM1+refM2));
- VERIFY_IS_APPROX(m1*s1-m2, refM1*s1-refM2);
-
- VERIFY_IS_APPROX(m1*=s1, refM1*=s1);
- VERIFY_IS_APPROX(m1/=s1, refM1/=s1);
-
- VERIFY_IS_APPROX(m1+=m2, refM1+=refM2);
- VERIFY_IS_APPROX(m1-=m2, refM1-=refM2);
-
- VERIFY_IS_APPROX(m1.col(0).eigen2_dot(refM2.row(0)), refM1.col(0).eigen2_dot(refM2.row(0)));
-
- refM4.setRandom();
- // sparse cwise* dense
- VERIFY_IS_APPROX(m3.cwise()*refM4, refM3.cwise()*refM4);
-// VERIFY_IS_APPROX(m3.cwise()/refM4, refM3.cwise()/refM4);
- }
-
- // test innerVector()
- {
- DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
- SparseMatrixType m2(rows, rows);
- initSparse<Scalar>(density, refMat2, m2);
- int j0 = ei_random(0,rows-1);
- int j1 = ei_random(0,rows-1);
- VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.col(j0));
- VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.col(j0)+refMat2.col(j1));
- //m2.innerVector(j0) = 2*m2.innerVector(j1);
- //refMat2.col(j0) = 2*refMat2.col(j1);
- //VERIFY_IS_APPROX(m2, refMat2);
- }
-
- // test innerVectors()
- {
- DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
- SparseMatrixType m2(rows, rows);
- initSparse<Scalar>(density, refMat2, m2);
- int j0 = ei_random(0,rows-2);
- int j1 = ei_random(0,rows-2);
- int n0 = ei_random<int>(1,rows-std::max(j0,j1));
- VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(0,j0,rows,n0));
- VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0),
- refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0));
- //m2.innerVectors(j0,n0) = m2.innerVectors(j0,n0) + m2.innerVectors(j1,n0);
- //refMat2.block(0,j0,rows,n0) = refMat2.block(0,j0,rows,n0) + refMat2.block(0,j1,rows,n0);
- }
-
- // test transpose
- {
- DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
- SparseMatrixType m2(rows, rows);
- initSparse<Scalar>(density, refMat2, m2);
- VERIFY_IS_APPROX(m2.transpose().eval(), refMat2.transpose().eval());
- VERIFY_IS_APPROX(m2.transpose(), refMat2.transpose());
- }
-
- // test prune
- {
- SparseMatrixType m2(rows, rows);
- DenseMatrix refM2(rows, rows);
- refM2.setZero();
- int countFalseNonZero = 0;
- int countTrueNonZero = 0;
- m2.startFill();
- for (int j=0; j<m2.outerSize(); ++j)
- for (int i=0; i<m2.innerSize(); ++i)
- {
- float x = ei_random<float>(0,1);
- if (x<0.1)
- {
- // do nothing
- }
- else if (x<0.5)
- {
- countFalseNonZero++;
- m2.fill(i,j) = Scalar(0);
- }
- else
- {
- countTrueNonZero++;
- m2.fill(i,j) = refM2(i,j) = Scalar(1);
- }
- }
- m2.endFill();
- VERIFY(countFalseNonZero+countTrueNonZero == m2.nonZeros());
- VERIFY_IS_APPROX(m2, refM2);
- m2.prune(1);
- VERIFY(countTrueNonZero==m2.nonZeros());
- VERIFY_IS_APPROX(m2, refM2);
- }
-}
-
-void test_eigen2_sparse_basic()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( sparse_basic(SparseMatrix<double>(8, 8)) );
- CALL_SUBTEST_2( sparse_basic(SparseMatrix<std::complex<double> >(16, 16)) );
- CALL_SUBTEST_1( sparse_basic(SparseMatrix<double>(33, 33)) );
-
- CALL_SUBTEST_3( sparse_basic(DynamicSparseMatrix<double>(8, 8)) );
- }
-}
diff --git a/test/eigen2/eigen2_sparse_product.cpp b/test/eigen2/eigen2_sparse_product.cpp
deleted file mode 100644
index d28e76dff..000000000
--- a/test/eigen2/eigen2_sparse_product.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@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 "sparse.h"
-
-template<typename SparseMatrixType> void sparse_product(const SparseMatrixType& ref)
-{
- const int rows = ref.rows();
- const int cols = ref.cols();
- typedef typename SparseMatrixType::Scalar Scalar;
- enum { Flags = SparseMatrixType::Flags };
-
- double density = std::max(8./(rows*cols), 0.01);
- typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
- typedef Matrix<Scalar,Dynamic,1> DenseVector;
-
- // test matrix-matrix product
- {
- DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
- DenseMatrix refMat3 = DenseMatrix::Zero(rows, rows);
- DenseMatrix refMat4 = DenseMatrix::Zero(rows, rows);
- DenseMatrix dm4 = DenseMatrix::Zero(rows, rows);
- SparseMatrixType m2(rows, rows);
- SparseMatrixType m3(rows, rows);
- SparseMatrixType m4(rows, rows);
- initSparse<Scalar>(density, refMat2, m2);
- initSparse<Scalar>(density, refMat3, m3);
- initSparse<Scalar>(density, refMat4, m4);
- VERIFY_IS_APPROX(m4=m2*m3, refMat4=refMat2*refMat3);
- VERIFY_IS_APPROX(m4=m2.transpose()*m3, refMat4=refMat2.transpose()*refMat3);
- VERIFY_IS_APPROX(m4=m2.transpose()*m3.transpose(), refMat4=refMat2.transpose()*refMat3.transpose());
- VERIFY_IS_APPROX(m4=m2*m3.transpose(), refMat4=refMat2*refMat3.transpose());
-
- // sparse * dense
- VERIFY_IS_APPROX(dm4=m2*refMat3, refMat4=refMat2*refMat3);
- VERIFY_IS_APPROX(dm4=m2*refMat3.transpose(), refMat4=refMat2*refMat3.transpose());
- VERIFY_IS_APPROX(dm4=m2.transpose()*refMat3, refMat4=refMat2.transpose()*refMat3);
- VERIFY_IS_APPROX(dm4=m2.transpose()*refMat3.transpose(), refMat4=refMat2.transpose()*refMat3.transpose());
-
- // dense * sparse
- VERIFY_IS_APPROX(dm4=refMat2*m3, refMat4=refMat2*refMat3);
- VERIFY_IS_APPROX(dm4=refMat2*m3.transpose(), refMat4=refMat2*refMat3.transpose());
- VERIFY_IS_APPROX(dm4=refMat2.transpose()*m3, refMat4=refMat2.transpose()*refMat3);
- VERIFY_IS_APPROX(dm4=refMat2.transpose()*m3.transpose(), refMat4=refMat2.transpose()*refMat3.transpose());
-
- VERIFY_IS_APPROX(m3=m3*m3, refMat3=refMat3*refMat3);
- }
-
- // test matrix - diagonal product
- if(false) // it compiles, but the precision is terrible. probably doesn't matter in this branch....
- {
- DenseMatrix refM2 = DenseMatrix::Zero(rows, rows);
- DenseMatrix refM3 = DenseMatrix::Zero(rows, rows);
- DiagonalMatrix<DenseVector> d1(DenseVector::Random(rows));
- SparseMatrixType m2(rows, rows);
- SparseMatrixType m3(rows, rows);
- initSparse<Scalar>(density, refM2, m2);
- initSparse<Scalar>(density, refM3, m3);
- VERIFY_IS_APPROX(m3=m2*d1, refM3=refM2*d1);
- VERIFY_IS_APPROX(m3=m2.transpose()*d1, refM3=refM2.transpose()*d1);
- VERIFY_IS_APPROX(m3=d1*m2, refM3=d1*refM2);
- VERIFY_IS_APPROX(m3=d1*m2.transpose(), refM3=d1 * refM2.transpose());
- }
-
- // test self adjoint products
- {
- DenseMatrix b = DenseMatrix::Random(rows, rows);
- DenseMatrix x = DenseMatrix::Random(rows, rows);
- DenseMatrix refX = DenseMatrix::Random(rows, rows);
- DenseMatrix refUp = DenseMatrix::Zero(rows, rows);
- DenseMatrix refLo = DenseMatrix::Zero(rows, rows);
- DenseMatrix refS = DenseMatrix::Zero(rows, rows);
- SparseMatrixType mUp(rows, rows);
- SparseMatrixType mLo(rows, rows);
- SparseMatrixType mS(rows, rows);
- do {
- initSparse<Scalar>(density, refUp, mUp, ForceRealDiag|/*ForceNonZeroDiag|*/MakeUpperTriangular);
- } while (refUp.isZero());
- refLo = refUp.transpose().conjugate();
- mLo = mUp.transpose().conjugate();
- refS = refUp + refLo;
- refS.diagonal() *= 0.5;
- mS = mUp + mLo;
- for (int k=0; k<mS.outerSize(); ++k)
- for (typename SparseMatrixType::InnerIterator it(mS,k); it; ++it)
- if (it.index() == k)
- it.valueRef() *= 0.5;
-
- VERIFY_IS_APPROX(refS.adjoint(), refS);
- VERIFY_IS_APPROX(mS.transpose().conjugate(), mS);
- VERIFY_IS_APPROX(mS, refS);
- VERIFY_IS_APPROX(x=mS*b, refX=refS*b);
- VERIFY_IS_APPROX(x=mUp.template marked<UpperTriangular|SelfAdjoint>()*b, refX=refS*b);
- VERIFY_IS_APPROX(x=mLo.template marked<LowerTriangular|SelfAdjoint>()*b, refX=refS*b);
- VERIFY_IS_APPROX(x=mS.template marked<SelfAdjoint>()*b, refX=refS*b);
- }
-
-}
-
-void test_eigen2_sparse_product()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( sparse_product(SparseMatrix<double>(8, 8)) );
- CALL_SUBTEST_2( sparse_product(SparseMatrix<std::complex<double> >(16, 16)) );
- CALL_SUBTEST_1( sparse_product(SparseMatrix<double>(33, 33)) );
-
- CALL_SUBTEST_3( sparse_product(DynamicSparseMatrix<double>(8, 8)) );
- }
-}
diff --git a/test/eigen2/eigen2_sparse_solvers.cpp b/test/eigen2/eigen2_sparse_solvers.cpp
deleted file mode 100644
index 3aef27ab4..000000000
--- a/test/eigen2/eigen2_sparse_solvers.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@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 "sparse.h"
-
-template<typename Scalar> void
-initSPD(double density,
- Matrix<Scalar,Dynamic,Dynamic>& refMat,
- SparseMatrix<Scalar>& sparseMat)
-{
- Matrix<Scalar,Dynamic,Dynamic> aux(refMat.rows(),refMat.cols());
- initSparse(density,refMat,sparseMat);
- refMat = refMat * refMat.adjoint();
- for (int k=0; k<2; ++k)
- {
- initSparse(density,aux,sparseMat,ForceNonZeroDiag);
- refMat += aux * aux.adjoint();
- }
- sparseMat.startFill();
- for (int j=0 ; j<sparseMat.cols(); ++j)
- for (int i=j ; i<sparseMat.rows(); ++i)
- if (refMat(i,j)!=Scalar(0))
- sparseMat.fill(i,j) = refMat(i,j);
- sparseMat.endFill();
-}
-
-template<typename Scalar> void sparse_solvers(int rows, int cols)
-{
- double density = std::max(8./(rows*cols), 0.01);
- typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
- typedef Matrix<Scalar,Dynamic,1> DenseVector;
- // Scalar eps = 1e-6;
-
- DenseVector vec1 = DenseVector::Random(rows);
-
- std::vector<Vector2i> zeroCoords;
- std::vector<Vector2i> nonzeroCoords;
-
- // test triangular solver
- {
- DenseVector vec2 = vec1, vec3 = vec1;
- SparseMatrix<Scalar> m2(rows, cols);
- DenseMatrix refMat2 = DenseMatrix::Zero(rows, cols);
-
- // lower
- initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeLowerTriangular, &zeroCoords, &nonzeroCoords);
- VERIFY_IS_APPROX(refMat2.template marked<LowerTriangular>().solveTriangular(vec2),
- m2.template marked<LowerTriangular>().solveTriangular(vec3));
-
- // lower - transpose
- initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeLowerTriangular, &zeroCoords, &nonzeroCoords);
- VERIFY_IS_APPROX(refMat2.template marked<LowerTriangular>().transpose().solveTriangular(vec2),
- m2.template marked<LowerTriangular>().transpose().solveTriangular(vec3));
-
- // upper
- initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeUpperTriangular, &zeroCoords, &nonzeroCoords);
- VERIFY_IS_APPROX(refMat2.template marked<UpperTriangular>().solveTriangular(vec2),
- m2.template marked<UpperTriangular>().solveTriangular(vec3));
-
- // upper - transpose
- initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeUpperTriangular, &zeroCoords, &nonzeroCoords);
- VERIFY_IS_APPROX(refMat2.template marked<UpperTriangular>().transpose().solveTriangular(vec2),
- m2.template marked<UpperTriangular>().transpose().solveTriangular(vec3));
- }
-
- // test LLT
- {
- // TODO fix the issue with complex (see SparseLLT::solveInPlace)
- SparseMatrix<Scalar> m2(rows, cols);
- DenseMatrix refMat2(rows, cols);
-
- DenseVector b = DenseVector::Random(cols);
- DenseVector refX(cols), x(cols);
-
- initSPD(density, refMat2, m2);
-
- refMat2.llt().solve(b, &refX);
- typedef SparseMatrix<Scalar,LowerTriangular|SelfAdjoint> SparseSelfAdjointMatrix;
- if (!NumTraits<Scalar>::IsComplex)
- {
- x = b;
- SparseLLT<SparseSelfAdjointMatrix> (m2).solveInPlace(x);
- VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LLT: default");
- }
- #ifdef EIGEN_CHOLMOD_SUPPORT
- x = b;
- SparseLLT<SparseSelfAdjointMatrix,Cholmod>(m2).solveInPlace(x);
- VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LLT: cholmod");
- #endif
- if (!NumTraits<Scalar>::IsComplex)
- {
- #ifdef EIGEN_TAUCS_SUPPORT
- x = b;
- SparseLLT<SparseSelfAdjointMatrix,Taucs>(m2,IncompleteFactorization).solveInPlace(x);
- VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LLT: taucs (IncompleteFactorization)");
- x = b;
- SparseLLT<SparseSelfAdjointMatrix,Taucs>(m2,SupernodalMultifrontal).solveInPlace(x);
- VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LLT: taucs (SupernodalMultifrontal)");
- x = b;
- SparseLLT<SparseSelfAdjointMatrix,Taucs>(m2,SupernodalLeftLooking).solveInPlace(x);
- VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LLT: taucs (SupernodalLeftLooking)");
- #endif
- }
- }
-
- // test LDLT
- if (!NumTraits<Scalar>::IsComplex)
- {
- // TODO fix the issue with complex (see SparseLDLT::solveInPlace)
- SparseMatrix<Scalar> m2(rows, cols);
- DenseMatrix refMat2(rows, cols);
-
- DenseVector b = DenseVector::Random(cols);
- DenseVector refX(cols), x(cols);
-
- //initSPD(density, refMat2, m2);
- initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeUpperTriangular, 0, 0);
- refMat2 += refMat2.adjoint();
- refMat2.diagonal() *= 0.5;
-
- refMat2.ldlt().solve(b, &refX);
- typedef SparseMatrix<Scalar,UpperTriangular|SelfAdjoint> SparseSelfAdjointMatrix;
- x = b;
- SparseLDLT<SparseSelfAdjointMatrix> ldlt(m2);
- if (ldlt.succeeded())
- ldlt.solveInPlace(x);
- VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LDLT: default");
- }
-
- // test LU
- {
- static int count = 0;
- SparseMatrix<Scalar> m2(rows, cols);
- DenseMatrix refMat2(rows, cols);
-
- DenseVector b = DenseVector::Random(cols);
- DenseVector refX(cols), x(cols);
-
- initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag, &zeroCoords, &nonzeroCoords);
-
- LU<DenseMatrix> refLu(refMat2);
- refLu.solve(b, &refX);
- #if defined(EIGEN_SUPERLU_SUPPORT) || defined(EIGEN_UMFPACK_SUPPORT)
- Scalar refDet = refLu.determinant();
- #endif
- x.setZero();
- // // SparseLU<SparseMatrix<Scalar> > (m2).solve(b,&x);
- // // VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LU: default");
- #ifdef EIGEN_SUPERLU_SUPPORT
- {
- x.setZero();
- SparseLU<SparseMatrix<Scalar>,SuperLU> slu(m2);
- if (slu.succeeded())
- {
- if (slu.solve(b,&x)) {
- VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LU: SuperLU");
- }
- // std::cerr << refDet << " == " << slu.determinant() << "\n";
- if (count==0) {
- VERIFY_IS_APPROX(refDet,slu.determinant()); // FIXME det is not very stable for complex
- }
- }
- }
- #endif
- #ifdef EIGEN_UMFPACK_SUPPORT
- {
- // check solve
- x.setZero();
- SparseLU<SparseMatrix<Scalar>,UmfPack> slu(m2);
- if (slu.succeeded()) {
- if (slu.solve(b,&x)) {
- if (count==0) {
- VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LU: umfpack"); // FIXME solve is not very stable for complex
- }
- }
- VERIFY_IS_APPROX(refDet,slu.determinant());
- // TODO check the extracted data
- //std::cerr << slu.matrixL() << "\n";
- }
- }
- #endif
- count++;
- }
-
-}
-
-void test_eigen2_sparse_solvers()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( sparse_solvers<double>(8, 8) );
- CALL_SUBTEST_2( sparse_solvers<std::complex<double> >(16, 16) );
- CALL_SUBTEST_1( sparse_solvers<double>(101, 101) );
- }
-}
diff --git a/test/eigen2/eigen2_sparse_vector.cpp b/test/eigen2/eigen2_sparse_vector.cpp
deleted file mode 100644
index e6d2d77a1..000000000
--- a/test/eigen2/eigen2_sparse_vector.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@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 "sparse.h"
-
-template<typename Scalar> 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> SparseVectorType;
- typedef SparseMatrix<Scalar> SparseMatrixType;
- Scalar eps = 1e-6;
-
- SparseMatrixType m1(rows,cols);
- SparseVectorType v1(rows), v2(rows), v3(rows);
- DenseMatrix refM1 = DenseMatrix::Zero(rows, cols);
- DenseVector refV1 = DenseVector::Random(rows),
- refV2 = DenseVector::Random(rows),
- refV3 = DenseVector::Random(rows);
-
- std::vector<int> zerocoords, nonzerocoords;
- initSparse<Scalar>(densityVec, refV1, v1, &zerocoords, &nonzerocoords);
- initSparse<Scalar>(densityMat, refM1, m1);
-
- initSparse<Scalar>(densityVec, refV2, v2);
- initSparse<Scalar>(densityVec, refV3, v3);
-
- Scalar s1 = ei_random<Scalar>();
-
- // test coeff and coeffRef
- for (unsigned int i=0; i<zerocoords.size(); ++i)
- {
- VERIFY_IS_MUCH_SMALLER_THAN( v1.coeff(zerocoords[i]), eps );
- //VERIFY_RAISES_ASSERT( v1.coeffRef(zerocoords[i]) = 5 );
- }
- {
- VERIFY(int(nonzerocoords.size()) == v1.nonZeros());
- int j=0;
- for (typename SparseVectorType::InnerIterator it(v1); it; ++it,++j)
- {
- VERIFY(nonzerocoords[j]==it.index());
- VERIFY(it.value()==v1.coeff(it.index()));
- VERIFY(it.value()==refV1.coeff(it.index()));
- }
- }
- VERIFY_IS_APPROX(v1, refV1);
-
- v1.coeffRef(nonzerocoords[0]) = Scalar(5);
- refV1.coeffRef(nonzerocoords[0]) = Scalar(5);
- VERIFY_IS_APPROX(v1, refV1);
-
- VERIFY_IS_APPROX(v1+v2, refV1+refV2);
- VERIFY_IS_APPROX(v1+v2+v3, refV1+refV2+refV3);
-
- VERIFY_IS_APPROX(v1*s1-v2, refV1*s1-refV2);
-
- VERIFY_IS_APPROX(v1*=s1, refV1*=s1);
- VERIFY_IS_APPROX(v1/=s1, refV1/=s1);
-
- VERIFY_IS_APPROX(v1+=v2, refV1+=refV2);
- VERIFY_IS_APPROX(v1-=v2, refV1-=refV2);
-
- VERIFY_IS_APPROX(v1.eigen2_dot(v2), refV1.eigen2_dot(refV2));
- VERIFY_IS_APPROX(v1.eigen2_dot(refV2), refV1.eigen2_dot(refV2));
-
-}
-
-void test_eigen2_sparse_vector()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( sparse_vector<double>(8, 8) );
- CALL_SUBTEST_2( sparse_vector<std::complex<double> >(16, 16) );
- CALL_SUBTEST_1( sparse_vector<double>(299, 535) );
- }
-}
-
diff --git a/test/eigen2/eigen2_stdvector.cpp b/test/eigen2/eigen2_stdvector.cpp
deleted file mode 100644
index 6ab05c20a..000000000
--- a/test/eigen2/eigen2_stdvector.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@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 <Eigen/StdVector>
-#include "main.h"
-#include <Eigen/Geometry>
-
-template<typename MatrixType>
-void check_stdvector_matrix(const MatrixType& m)
-{
- int rows = m.rows();
- int cols = m.cols();
- MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
- std::vector<MatrixType, aligned_allocator<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);
- VERIFY((std::size_t)&(v[22]) == (std::size_t)&(v[21]) + sizeof(MatrixType));
-
- // do a lot of push_back such that the vector 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_stdvector_transform(const TransformType&)
-{
- typedef typename TransformType::MatrixType MatrixType;
- TransformType x(MatrixType::Random()), y(MatrixType::Random());
- std::vector<TransformType, aligned_allocator<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);
- VERIFY((std::size_t)&(v[22]) == (std::size_t)&(v[21]) + sizeof(TransformType));
-
- // do a lot of push_back such that the vector 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_stdvector_quaternion(const QuaternionType&)
-{
- typedef typename QuaternionType::Coefficients Coefficients;
- QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
- std::vector<QuaternionType, aligned_allocator<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);
- VERIFY((std::size_t)&(v[22]) == (std::size_t)&(v[21]) + sizeof(QuaternionType));
-
- // do a lot of push_back such that the vector 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_eigen2_stdvector()
-{
- // some non vectorizable fixed sizes
- CALL_SUBTEST_1(check_stdvector_matrix(Vector2f()));
- CALL_SUBTEST_1(check_stdvector_matrix(Matrix3f()));
- CALL_SUBTEST_1(check_stdvector_matrix(Matrix3d()));
-
- // some vectorizable fixed sizes
- CALL_SUBTEST_2(check_stdvector_matrix(Matrix2f()));
- CALL_SUBTEST_2(check_stdvector_matrix(Vector4f()));
- CALL_SUBTEST_2(check_stdvector_matrix(Matrix4f()));
- CALL_SUBTEST_2(check_stdvector_matrix(Matrix4d()));
-
- // some dynamic sizes
- CALL_SUBTEST_3(check_stdvector_matrix(MatrixXd(1,1)));
- CALL_SUBTEST_3(check_stdvector_matrix(VectorXd(20)));
- CALL_SUBTEST_3(check_stdvector_matrix(RowVectorXf(20)));
- CALL_SUBTEST_3(check_stdvector_matrix(MatrixXcf(10,10)));
-
- // some Transform
- CALL_SUBTEST_4(check_stdvector_transform(Transform2f()));
- CALL_SUBTEST_4(check_stdvector_transform(Transform3f()));
- CALL_SUBTEST_4(check_stdvector_transform(Transform3d()));
- //CALL_SUBTEST_4(check_stdvector_transform(Transform4d()));
-
- // some Quaternion
- CALL_SUBTEST_5(check_stdvector_quaternion(Quaternionf()));
- CALL_SUBTEST_5(check_stdvector_quaternion(Quaternionf()));
-}
diff --git a/test/eigen2/eigen2_submatrices.cpp b/test/eigen2/eigen2_submatrices.cpp
deleted file mode 100644
index dee970b63..000000000
--- a/test/eigen2/eigen2_submatrices.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@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"
-
-// check minor separately in order to avoid the possible creation of a zero-sized
-// array. Comes from a compilation error with gcc-3.4 or gcc-4 with -ansi -pedantic.
-// Another solution would be to declare the array like this: T m_data[Size==0?1:Size]; in ei_matrix_storage
-// but this is probably not bad to raise such an error at compile time...
-template<typename Scalar, int _Rows, int _Cols> struct CheckMinor
-{
- typedef Matrix<Scalar, _Rows, _Cols> MatrixType;
- CheckMinor(MatrixType& m1, int r1, int c1)
- {
- int rows = m1.rows();
- int cols = m1.cols();
-
- Matrix<Scalar, Dynamic, Dynamic> mi = m1.minor(0,0).eval();
- VERIFY_IS_APPROX(mi, m1.block(1,1,rows-1,cols-1));
- mi = m1.minor(r1,c1);
- VERIFY_IS_APPROX(mi.transpose(), m1.transpose().minor(c1,r1));
- //check operator(), both constant and non-constant, on minor()
- m1.minor(r1,c1)(0,0) = m1.minor(0,0)(0,0);
- }
-};
-
-template<typename Scalar> struct CheckMinor<Scalar,1,1>
-{
- typedef Matrix<Scalar, 1, 1> MatrixType;
- CheckMinor(MatrixType&, int, int) {}
-};
-
-template<typename MatrixType> void submatrices(const MatrixType& m)
-{
- /* this test covers the following files:
- Row.h Column.h Block.h Minor.h DiagonalCoeffs.h
- */
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::RealScalar RealScalar;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
- typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
- int rows = m.rows();
- int cols = m.cols();
-
- MatrixType m1 = MatrixType::Random(rows, cols),
- m2 = MatrixType::Random(rows, cols),
- m3(rows, cols),
- ones = MatrixType::Ones(rows, cols),
- square = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
- ::Random(rows, rows);
- VectorType v1 = VectorType::Random(rows);
-
- Scalar s1 = ei_random<Scalar>();
-
- int r1 = ei_random<int>(0,rows-1);
- int r2 = ei_random<int>(r1,rows-1);
- int c1 = ei_random<int>(0,cols-1);
- int c2 = ei_random<int>(c1,cols-1);
-
- //check row() and col()
- VERIFY_IS_APPROX(m1.col(c1).transpose(), m1.transpose().row(c1));
- VERIFY_IS_APPROX(square.row(r1).eigen2_dot(m1.col(c1)), (square.lazy() * m1.conjugate())(r1,c1));
- //check operator(), both constant and non-constant, on row() and col()
- m1.row(r1) += s1 * m1.row(r2);
- m1.col(c1) += s1 * m1.col(c2);
-
- //check block()
- Matrix<Scalar,Dynamic,Dynamic> b1(1,1); b1(0,0) = m1(r1,c1);
- RowVectorType br1(m1.block(r1,0,1,cols));
- VectorType bc1(m1.block(0,c1,rows,1));
- VERIFY_IS_APPROX(b1, m1.block(r1,c1,1,1));
- VERIFY_IS_APPROX(m1.row(r1), br1);
- VERIFY_IS_APPROX(m1.col(c1), bc1);
- //check operator(), both constant and non-constant, on block()
- m1.block(r1,c1,r2-r1+1,c2-c1+1) = s1 * m2.block(0, 0, r2-r1+1,c2-c1+1);
- m1.block(r1,c1,r2-r1+1,c2-c1+1)(r2-r1,c2-c1) = m2.block(0, 0, r2-r1+1,c2-c1+1)(0,0);
-
- //check minor()
- CheckMinor<Scalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime> checkminor(m1,r1,c1);
-
- //check diagonal()
- VERIFY_IS_APPROX(m1.diagonal(), m1.transpose().diagonal());
- m2.diagonal() = 2 * m1.diagonal();
- m2.diagonal()[0] *= 3;
- VERIFY_IS_APPROX(m2.diagonal()[0], static_cast<Scalar>(6) * m1.diagonal()[0]);
-
- enum {
- BlockRows = EIGEN_SIZE_MIN_PREFER_FIXED(MatrixType::RowsAtCompileTime,2),
- BlockCols = EIGEN_SIZE_MIN_PREFER_FIXED(MatrixType::ColsAtCompileTime,5)
- };
- if (rows>=5 && cols>=8)
- {
- // test fixed block() as lvalue
- m1.template block<BlockRows,BlockCols>(1,1) *= s1;
- // test operator() on fixed block() both as constant and non-constant
- m1.template block<BlockRows,BlockCols>(1,1)(0, 3) = m1.template block<2,5>(1,1)(1,2);
- // check that fixed block() and block() agree
- Matrix<Scalar,Dynamic,Dynamic> b = m1.template block<BlockRows,BlockCols>(3,3);
- VERIFY_IS_APPROX(b, m1.block(3,3,BlockRows,BlockCols));
- }
-
- if (rows>2)
- {
- // test sub vectors
- VERIFY_IS_APPROX(v1.template start<2>(), v1.block(0,0,2,1));
- VERIFY_IS_APPROX(v1.template start<2>(), v1.start(2));
- VERIFY_IS_APPROX(v1.template start<2>(), v1.segment(0,2));
- VERIFY_IS_APPROX(v1.template start<2>(), v1.template segment<2>(0));
- int i = rows-2;
- VERIFY_IS_APPROX(v1.template end<2>(), v1.block(i,0,2,1));
- VERIFY_IS_APPROX(v1.template end<2>(), v1.end(2));
- VERIFY_IS_APPROX(v1.template end<2>(), v1.segment(i,2));
- VERIFY_IS_APPROX(v1.template end<2>(), v1.template segment<2>(i));
- i = ei_random(0,rows-2);
- VERIFY_IS_APPROX(v1.segment(i,2), v1.template segment<2>(i));
- }
-
- // stress some basic stuffs with block matrices
- VERIFY(ei_real(ones.col(c1).sum()) == RealScalar(rows));
- VERIFY(ei_real(ones.row(r1).sum()) == RealScalar(cols));
-
- VERIFY(ei_real(ones.col(c1).eigen2_dot(ones.col(c2))) == RealScalar(rows));
- VERIFY(ei_real(ones.row(r1).eigen2_dot(ones.row(r2))) == RealScalar(cols));
-}
-
-void test_eigen2_submatrices()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( submatrices(Matrix<float, 1, 1>()) );
- CALL_SUBTEST_2( submatrices(Matrix4d()) );
- CALL_SUBTEST_3( submatrices(MatrixXcf(3, 3)) );
- CALL_SUBTEST_4( submatrices(MatrixXi(8, 12)) );
- CALL_SUBTEST_5( submatrices(MatrixXcd(20, 20)) );
- CALL_SUBTEST_6( submatrices(MatrixXf(20, 20)) );
- }
-}
diff --git a/test/eigen2/eigen2_sum.cpp b/test/eigen2/eigen2_sum.cpp
deleted file mode 100644
index b47057caa..000000000
--- a/test/eigen2/eigen2_sum.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@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"
-
-template<typename MatrixType> void matrixSum(const MatrixType& m)
-{
- typedef typename MatrixType::Scalar Scalar;
-
- int rows = m.rows();
- int cols = m.cols();
-
- MatrixType m1 = MatrixType::Random(rows, cols);
-
- VERIFY_IS_MUCH_SMALLER_THAN(MatrixType::Zero(rows, cols).sum(), Scalar(1));
- VERIFY_IS_APPROX(MatrixType::Ones(rows, cols).sum(), Scalar(float(rows*cols))); // the float() here to shut up excessive MSVC warning about int->complex conversion being lossy
- Scalar x = Scalar(0);
- for(int i = 0; i < rows; i++) for(int j = 0; j < cols; j++) x += m1(i,j);
- VERIFY_IS_APPROX(m1.sum(), x);
-}
-
-template<typename VectorType> void vectorSum(const VectorType& w)
-{
- typedef typename VectorType::Scalar Scalar;
- int size = w.size();
-
- VectorType v = VectorType::Random(size);
- for(int i = 1; i < size; i++)
- {
- Scalar s = Scalar(0);
- for(int j = 0; j < i; j++) s += v[j];
- VERIFY_IS_APPROX(s, v.start(i).sum());
- }
-
- for(int i = 0; i < size-1; i++)
- {
- Scalar s = Scalar(0);
- for(int j = i; j < size; j++) s += v[j];
- VERIFY_IS_APPROX(s, v.end(size-i).sum());
- }
-
- for(int i = 0; i < size/2; i++)
- {
- Scalar s = Scalar(0);
- for(int j = i; j < size-i; j++) s += v[j];
- VERIFY_IS_APPROX(s, v.segment(i, size-2*i).sum());
- }
-}
-
-void test_eigen2_sum()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( matrixSum(Matrix<float, 1, 1>()) );
- CALL_SUBTEST_2( matrixSum(Matrix2f()) );
- CALL_SUBTEST_3( matrixSum(Matrix4d()) );
- CALL_SUBTEST_4( matrixSum(MatrixXcf(3, 3)) );
- CALL_SUBTEST_5( matrixSum(MatrixXf(8, 12)) );
- CALL_SUBTEST_6( matrixSum(MatrixXi(8, 12)) );
- }
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_5( vectorSum(VectorXf(5)) );
- CALL_SUBTEST_7( vectorSum(VectorXd(10)) );
- CALL_SUBTEST_5( vectorSum(VectorXf(33)) );
- }
-}
diff --git a/test/eigen2/eigen2_svd.cpp b/test/eigen2/eigen2_svd.cpp
deleted file mode 100644
index d4689a56f..000000000
--- a/test/eigen2/eigen2_svd.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
-
-#include "main.h"
-#include <Eigen/SVD>
-
-template<typename MatrixType> void svd(const MatrixType& m)
-{
- /* this test covers the following files:
- SVD.h
- */
- int rows = m.rows();
- int cols = m.cols();
-
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- MatrixType a = MatrixType::Random(rows,cols);
- Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> b =
- Matrix<Scalar, MatrixType::RowsAtCompileTime, 1>::Random(rows,1);
- Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> x(cols,1), x2(cols,1);
-
- RealScalar largerEps = test_precision<RealScalar>();
- if (ei_is_same_type<RealScalar,float>::ret)
- largerEps = 1e-3f;
-
- {
- SVD<MatrixType> svd(a);
- MatrixType sigma = MatrixType::Zero(rows,cols);
- MatrixType matU = MatrixType::Zero(rows,rows);
- sigma.block(0,0,cols,cols) = svd.singularValues().asDiagonal();
- matU.block(0,0,rows,cols) = svd.matrixU();
- VERIFY_IS_APPROX(a, matU * sigma * svd.matrixV().transpose());
- }
-
-
- if (rows==cols)
- {
- if (ei_is_same_type<RealScalar,float>::ret)
- {
- MatrixType a1 = MatrixType::Random(rows,cols);
- a += a * a.adjoint() + a1 * a1.adjoint();
- }
- SVD<MatrixType> svd(a);
- svd.solve(b, &x);
- VERIFY_IS_APPROX(a * x,b);
- }
-
-
- if(rows==cols)
- {
- SVD<MatrixType> svd(a);
- MatrixType unitary, positive;
- svd.computeUnitaryPositive(&unitary, &positive);
- VERIFY_IS_APPROX(unitary * unitary.adjoint(), MatrixType::Identity(unitary.rows(),unitary.rows()));
- VERIFY_IS_APPROX(positive, positive.adjoint());
- for(int i = 0; i < rows; i++) VERIFY(positive.diagonal()[i] >= 0); // cheap necessary (not sufficient) condition for positivity
- VERIFY_IS_APPROX(unitary*positive, a);
-
- svd.computePositiveUnitary(&positive, &unitary);
- VERIFY_IS_APPROX(unitary * unitary.adjoint(), MatrixType::Identity(unitary.rows(),unitary.rows()));
- VERIFY_IS_APPROX(positive, positive.adjoint());
- for(int i = 0; i < rows; i++) VERIFY(positive.diagonal()[i] >= 0); // cheap necessary (not sufficient) condition for positivity
- VERIFY_IS_APPROX(positive*unitary, a);
- }
-}
-
-void test_eigen2_svd()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( svd(Matrix3f()) );
- CALL_SUBTEST_2( svd(Matrix4d()) );
- CALL_SUBTEST_3( svd(MatrixXf(7,7)) );
- CALL_SUBTEST_4( svd(MatrixXd(14,7)) );
- // complex are not implemented yet
-// CALL_SUBTEST( svd(MatrixXcd(6,6)) );
-// CALL_SUBTEST( svd(MatrixXcf(3,3)) );
- SVD<MatrixXf> s;
- MatrixXf m = MatrixXf::Random(10,1);
- s.compute(m);
- }
-}
diff --git a/test/eigen2/eigen2_swap.cpp b/test/eigen2/eigen2_swap.cpp
deleted file mode 100644
index f3a8846d9..000000000
--- a/test/eigen2/eigen2_swap.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@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/.
-
-#define EIGEN_NO_STATIC_ASSERT
-#include "main.h"
-
-template<typename T>
-struct other_matrix_type
-{
- typedef int type;
-};
-
-template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
-struct other_matrix_type<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
-{
- typedef Matrix<_Scalar, _Rows, _Cols, _Options^RowMajor, _MaxRows, _MaxCols> type;
-};
-
-template<typename MatrixType> void swap(const MatrixType& m)
-{
- typedef typename other_matrix_type<MatrixType>::type OtherMatrixType;
- typedef typename MatrixType::Scalar Scalar;
-
- ei_assert((!ei_is_same_type<MatrixType,OtherMatrixType>::ret));
- int rows = m.rows();
- int cols = m.cols();
-
- // construct 3 matrix guaranteed to be distinct
- MatrixType m1 = MatrixType::Random(rows,cols);
- MatrixType m2 = MatrixType::Random(rows,cols) + Scalar(100) * MatrixType::Identity(rows,cols);
- OtherMatrixType m3 = OtherMatrixType::Random(rows,cols) + Scalar(200) * OtherMatrixType::Identity(rows,cols);
-
- MatrixType m1_copy = m1;
- MatrixType m2_copy = m2;
- OtherMatrixType m3_copy = m3;
-
- // test swapping 2 matrices of same type
- m1.swap(m2);
- VERIFY_IS_APPROX(m1,m2_copy);
- VERIFY_IS_APPROX(m2,m1_copy);
- m1 = m1_copy;
- m2 = m2_copy;
-
- // test swapping 2 matrices of different types
- m1.swap(m3);
- VERIFY_IS_APPROX(m1,m3_copy);
- VERIFY_IS_APPROX(m3,m1_copy);
- m1 = m1_copy;
- m3 = m3_copy;
-
- // test swapping matrix with expression
- m1.swap(m2.block(0,0,rows,cols));
- VERIFY_IS_APPROX(m1,m2_copy);
- VERIFY_IS_APPROX(m2,m1_copy);
- m1 = m1_copy;
- m2 = m2_copy;
-
- // test swapping two expressions of different types
- m1.transpose().swap(m3.transpose());
- VERIFY_IS_APPROX(m1,m3_copy);
- VERIFY_IS_APPROX(m3,m1_copy);
- m1 = m1_copy;
- m3 = m3_copy;
-
- // test assertion on mismatching size -- matrix case
- VERIFY_RAISES_ASSERT(m1.swap(m1.row(0)));
- // test assertion on mismatching size -- xpr case
- VERIFY_RAISES_ASSERT(m1.row(0).swap(m1));
-}
-
-void test_eigen2_swap()
-{
- CALL_SUBTEST_1( swap(Matrix3f()) ); // fixed size, no vectorization
- CALL_SUBTEST_1( swap(Matrix4d()) ); // fixed size, possible vectorization
- CALL_SUBTEST_1( swap(MatrixXd(3,3)) ); // dyn size, no vectorization
- CALL_SUBTEST_1( swap(MatrixXf(30,30)) ); // dyn size, possible vectorization
-}
diff --git a/test/eigen2/eigen2_triangular.cpp b/test/eigen2/eigen2_triangular.cpp
deleted file mode 100644
index 6f17b7dff..000000000
--- a/test/eigen2/eigen2_triangular.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@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"
-
-template<typename MatrixType> void triangular(const MatrixType& m)
-{
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
-
- RealScalar largerEps = 10*test_precision<RealScalar>();
-
- 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);
-
- MatrixType m1up = m1.template part<Eigen::UpperTriangular>();
- MatrixType m2up = m2.template part<Eigen::UpperTriangular>();
-
- if (rows*cols>1)
- {
- VERIFY(m1up.isUpperTriangular());
- VERIFY(m2up.transpose().isLowerTriangular());
- VERIFY(!m2.isLowerTriangular());
- }
-
-// VERIFY_IS_APPROX(m1up.transpose() * m2, m1.upper().transpose().lower() * m2);
-
- // test overloaded operator+=
- r1.setZero();
- r2.setZero();
- r1.template part<Eigen::UpperTriangular>() += m1;
- r2 += m1up;
- VERIFY_IS_APPROX(r1,r2);
-
- // test overloaded operator=
- m1.setZero();
- m1.template part<Eigen::UpperTriangular>() = (m2.transpose() * m2).lazy();
- m3 = m2.transpose() * m2;
- VERIFY_IS_APPROX(m3.template part<Eigen::LowerTriangular>().transpose(), m1);
-
- // test overloaded operator=
- m1.setZero();
- m1.template part<Eigen::LowerTriangular>() = (m2.transpose() * m2).lazy();
- VERIFY_IS_APPROX(m3.template part<Eigen::LowerTriangular>(), m1);
-
- VERIFY_IS_APPROX(m3.template part<Diagonal>(), m3.diagonal().asDiagonal());
-
- 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>();
-
- Transpose<MatrixType> trm4(m4);
- // test back and forward subsitution
- m3 = m1.template part<Eigen::LowerTriangular>();
- VERIFY(m3.template marked<Eigen::LowerTriangular>().solveTriangular(m3).cwise().abs().isIdentity(test_precision<RealScalar>()));
- VERIFY(m3.transpose().template marked<Eigen::UpperTriangular>()
- .solveTriangular(m3.transpose()).cwise().abs().isIdentity(test_precision<RealScalar>()));
- // check M * inv(L) using in place API
- m4 = m3;
- m3.transpose().template marked<Eigen::UpperTriangular>().solveTriangularInPlace(trm4);
- VERIFY(m4.cwise().abs().isIdentity(test_precision<RealScalar>()));
-
- m3 = m1.template part<Eigen::UpperTriangular>();
- VERIFY(m3.template marked<Eigen::UpperTriangular>().solveTriangular(m3).cwise().abs().isIdentity(test_precision<RealScalar>()));
- VERIFY(m3.transpose().template marked<Eigen::LowerTriangular>()
- .solveTriangular(m3.transpose()).cwise().abs().isIdentity(test_precision<RealScalar>()));
- // check M * inv(U) using in place API
- m4 = m3;
- m3.transpose().template marked<Eigen::LowerTriangular>().solveTriangularInPlace(trm4);
- VERIFY(m4.cwise().abs().isIdentity(test_precision<RealScalar>()));
-
- m3 = m1.template part<Eigen::UpperTriangular>();
- VERIFY(m2.isApprox(m3 * (m3.template marked<Eigen::UpperTriangular>().solveTriangular(m2)), largerEps));
- m3 = m1.template part<Eigen::LowerTriangular>();
- VERIFY(m2.isApprox(m3 * (m3.template marked<Eigen::LowerTriangular>().solveTriangular(m2)), largerEps));
-
- VERIFY((m1.template part<Eigen::UpperTriangular>() * m2.template part<Eigen::UpperTriangular>()).isUpperTriangular());
-
- // test swap
- m1.setOnes();
- m2.setZero();
- m2.template part<Eigen::UpperTriangular>().swap(m1);
- m3.setZero();
- m3.template part<Eigen::UpperTriangular>().setOnes();
- VERIFY_IS_APPROX(m2,m3);
-
-}
-
-void selfadjoint()
-{
- Matrix2i m;
- m << 1, 2,
- 3, 4;
-
- Matrix2i m1 = Matrix2i::Zero();
- m1.part<SelfAdjoint>() = m;
- Matrix2i ref1;
- ref1 << 1, 2,
- 2, 4;
- VERIFY(m1 == ref1);
-
- Matrix2i m2 = Matrix2i::Zero();
- m2.part<SelfAdjoint>() = m.part<UpperTriangular>();
- Matrix2i ref2;
- ref2 << 1, 2,
- 2, 4;
- VERIFY(m2 == ref2);
-
- Matrix2i m3 = Matrix2i::Zero();
- m3.part<SelfAdjoint>() = m.part<LowerTriangular>();
- Matrix2i ref3;
- ref3 << 1, 0,
- 0, 4;
- VERIFY(m3 == ref3);
-
- // example inspired from bug 159
- int array[] = {1, 2, 3, 4};
- Matrix2i::Map(array).part<SelfAdjoint>() = Matrix2i::Random().part<LowerTriangular>();
-
- std::cout << "hello\n" << array << std::endl;
-}
-
-void test_eigen2_triangular()
-{
- CALL_SUBTEST_8( selfadjoint() );
- 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(MatrixXd(17,17)) );
- CALL_SUBTEST_7( triangular(Matrix<float,Dynamic,Dynamic,RowMajor>(5, 5)) );
- }
-}
diff --git a/test/eigen2/eigen2_unalignedassert.cpp b/test/eigen2/eigen2_unalignedassert.cpp
deleted file mode 100644
index d10b6f538..000000000
--- a/test/eigen2/eigen2_unalignedassert.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@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"
-
-struct Good1
-{
- MatrixXd m; // good: m will allocate its own array, taking care of alignment.
- Good1() : m(20,20) {}
-};
-
-struct Good2
-{
- Matrix3d m; // good: m's size isn't a multiple of 16 bytes, so m doesn't have to be aligned
-};
-
-struct Good3
-{
- Vector2f m; // good: same reason
-};
-
-struct Bad4
-{
- Vector2d m; // bad: sizeof(m)%16==0 so alignment is required
-};
-
-struct Bad5
-{
- Matrix<float, 2, 6> m; // bad: same reason
-};
-
-struct Bad6
-{
- Matrix<double, 3, 4> m; // bad: same reason
-};
-
-struct Good7
-{
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW
- Vector2d m;
- float f; // make the struct have sizeof%16!=0 to make it a little more tricky when we allow an array of 2 such objects
-};
-
-struct Good8
-{
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW
- float f; // try the f at first -- the EIGEN_ALIGN_128 attribute of m should make that still work
- Matrix4f m;
-};
-
-struct Good9
-{
- Matrix<float,2,2,DontAlign> m; // good: no alignment requested
- float f;
-};
-
-template<bool Align> struct Depends
-{
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(Align)
- Vector2d m;
- float f;
-};
-
-template<typename T>
-void check_unalignedassert_good()
-{
- T *x, *y;
- x = new T;
- delete x;
- y = new T[2];
- delete[] y;
-}
-
-#if EIGEN_ARCH_WANTS_ALIGNMENT
-template<typename T>
-void check_unalignedassert_bad()
-{
- float buf[sizeof(T)+16];
- float *unaligned = buf;
- while((reinterpret_cast<std::size_t>(unaligned)&0xf)==0) ++unaligned; // make sure unaligned is really unaligned
- T *x = ::new(static_cast<void*>(unaligned)) T;
- x->~T();
-}
-#endif
-
-void unalignedassert()
-{
- check_unalignedassert_good<Good1>();
- check_unalignedassert_good<Good2>();
- check_unalignedassert_good<Good3>();
-#if EIGEN_ARCH_WANTS_ALIGNMENT
- VERIFY_RAISES_ASSERT(check_unalignedassert_bad<Bad4>());
- VERIFY_RAISES_ASSERT(check_unalignedassert_bad<Bad5>());
- VERIFY_RAISES_ASSERT(check_unalignedassert_bad<Bad6>());
-#endif
-
- check_unalignedassert_good<Good7>();
- check_unalignedassert_good<Good8>();
- check_unalignedassert_good<Good9>();
- check_unalignedassert_good<Depends<true> >();
-
-#if EIGEN_ARCH_WANTS_ALIGNMENT
- VERIFY_RAISES_ASSERT(check_unalignedassert_bad<Depends<false> >());
-#endif
-}
-
-void test_eigen2_unalignedassert()
-{
- CALL_SUBTEST(unalignedassert());
-}
diff --git a/test/eigen2/eigen2_visitor.cpp b/test/eigen2/eigen2_visitor.cpp
deleted file mode 100644
index 4781991de..000000000
--- a/test/eigen2/eigen2_visitor.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@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"
-
-template<typename MatrixType> void matrixVisitor(const MatrixType& p)
-{
- typedef typename MatrixType::Scalar Scalar;
-
- int rows = p.rows();
- int cols = p.cols();
-
- // construct a random matrix where all coefficients are different
- MatrixType m;
- m = MatrixType::Random(rows, cols);
- for(int i = 0; i < m.size(); i++)
- for(int i2 = 0; i2 < i; i2++)
- while(m(i) == m(i2)) // yes, ==
- m(i) = ei_random<Scalar>();
-
- Scalar minc = Scalar(1000), maxc = Scalar(-1000);
- int minrow=0,mincol=0,maxrow=0,maxcol=0;
- for(int j = 0; j < cols; j++)
- for(int i = 0; i < rows; i++)
- {
- if(m(i,j) < minc)
- {
- minc = m(i,j);
- minrow = i;
- mincol = j;
- }
- if(m(i,j) > maxc)
- {
- maxc = m(i,j);
- maxrow = i;
- maxcol = j;
- }
- }
- int eigen_minrow, eigen_mincol, eigen_maxrow, eigen_maxcol;
- Scalar eigen_minc, eigen_maxc;
- eigen_minc = m.minCoeff(&eigen_minrow,&eigen_mincol);
- eigen_maxc = m.maxCoeff(&eigen_maxrow,&eigen_maxcol);
- VERIFY(minrow == eigen_minrow);
- VERIFY(maxrow == eigen_maxrow);
- VERIFY(mincol == eigen_mincol);
- VERIFY(maxcol == eigen_maxcol);
- VERIFY_IS_APPROX(minc, eigen_minc);
- VERIFY_IS_APPROX(maxc, eigen_maxc);
- VERIFY_IS_APPROX(minc, m.minCoeff());
- VERIFY_IS_APPROX(maxc, m.maxCoeff());
-}
-
-template<typename VectorType> void vectorVisitor(const VectorType& w)
-{
- typedef typename VectorType::Scalar Scalar;
-
- int size = w.size();
-
- // construct a random vector where all coefficients are different
- VectorType v;
- v = VectorType::Random(size);
- for(int i = 0; i < size; i++)
- for(int i2 = 0; i2 < i; i2++)
- while(v(i) == v(i2)) // yes, ==
- v(i) = ei_random<Scalar>();
-
- Scalar minc = Scalar(1000), maxc = Scalar(-1000);
- int minidx=0,maxidx=0;
- for(int i = 0; i < size; i++)
- {
- if(v(i) < minc)
- {
- minc = v(i);
- minidx = i;
- }
- if(v(i) > maxc)
- {
- maxc = v(i);
- maxidx = i;
- }
- }
- int eigen_minidx, eigen_maxidx;
- Scalar eigen_minc, eigen_maxc;
- eigen_minc = v.minCoeff(&eigen_minidx);
- eigen_maxc = v.maxCoeff(&eigen_maxidx);
- VERIFY(minidx == eigen_minidx);
- VERIFY(maxidx == eigen_maxidx);
- VERIFY_IS_APPROX(minc, eigen_minc);
- VERIFY_IS_APPROX(maxc, eigen_maxc);
- VERIFY_IS_APPROX(minc, v.minCoeff());
- VERIFY_IS_APPROX(maxc, v.maxCoeff());
-}
-
-void test_eigen2_visitor()
-{
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_1( matrixVisitor(Matrix<float, 1, 1>()) );
- CALL_SUBTEST_2( matrixVisitor(Matrix2f()) );
- CALL_SUBTEST_3( matrixVisitor(Matrix4d()) );
- CALL_SUBTEST_4( matrixVisitor(MatrixXd(8, 12)) );
- CALL_SUBTEST_5( matrixVisitor(Matrix<double,Dynamic,Dynamic,RowMajor>(20, 20)) );
- CALL_SUBTEST_6( matrixVisitor(MatrixXi(8, 12)) );
- }
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_7( vectorVisitor(Vector4f()) );
- CALL_SUBTEST_4( vectorVisitor(VectorXd(10)) );
- CALL_SUBTEST_4( vectorVisitor(RowVectorXd(10)) );
- CALL_SUBTEST_8( vectorVisitor(VectorXf(33)) );
- }
-}
diff --git a/test/eigen2/gsl_helper.h b/test/eigen2/gsl_helper.h
deleted file mode 100644
index d1d854533..000000000
--- a/test/eigen2/gsl_helper.h
+++ /dev/null
@@ -1,175 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
-
-#ifndef EIGEN_GSL_HELPER
-#define EIGEN_GSL_HELPER
-
-#include <Eigen/Core>
-
-#include <gsl/gsl_blas.h>
-#include <gsl/gsl_multifit.h>
-#include <gsl/gsl_eigen.h>
-#include <gsl/gsl_linalg.h>
-#include <gsl/gsl_complex.h>
-#include <gsl/gsl_complex_math.h>
-
-namespace Eigen {
-
-template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex> struct GslTraits
-{
- typedef gsl_matrix* Matrix;
- typedef gsl_vector* Vector;
- static Matrix createMatrix(int rows, int cols) { return gsl_matrix_alloc(rows,cols); }
- static Vector createVector(int size) { return gsl_vector_alloc(size); }
- static void free(Matrix& m) { gsl_matrix_free(m); m=0; }
- static void free(Vector& m) { gsl_vector_free(m); m=0; }
- static void prod(const Matrix& m, const Vector& v, Vector& x) { gsl_blas_dgemv(CblasNoTrans,1,m,v,0,x); }
- static void cholesky(Matrix& m) { gsl_linalg_cholesky_decomp(m); }
- static void cholesky_solve(const Matrix& m, const Vector& b, Vector& x) { gsl_linalg_cholesky_solve(m,b,x); }
- static void eigen_symm(const Matrix& m, Vector& eval, Matrix& evec)
- {
- gsl_eigen_symmv_workspace * w = gsl_eigen_symmv_alloc(m->size1);
- Matrix a = createMatrix(m->size1, m->size2);
- gsl_matrix_memcpy(a, m);
- gsl_eigen_symmv(a,eval,evec,w);
- gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_VAL_ASC);
- gsl_eigen_symmv_free(w);
- free(a);
- }
- static void eigen_symm_gen(const Matrix& m, const Matrix& _b, Vector& eval, Matrix& evec)
- {
- gsl_eigen_gensymmv_workspace * w = gsl_eigen_gensymmv_alloc(m->size1);
- Matrix a = createMatrix(m->size1, m->size2);
- Matrix b = createMatrix(_b->size1, _b->size2);
- gsl_matrix_memcpy(a, m);
- gsl_matrix_memcpy(b, _b);
- gsl_eigen_gensymmv(a,b,eval,evec,w);
- gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_VAL_ASC);
- gsl_eigen_gensymmv_free(w);
- free(a);
- }
-};
-
-template<typename Scalar> struct GslTraits<Scalar,true>
-{
- typedef gsl_matrix_complex* Matrix;
- typedef gsl_vector_complex* Vector;
- static Matrix createMatrix(int rows, int cols) { return gsl_matrix_complex_alloc(rows,cols); }
- static Vector createVector(int size) { return gsl_vector_complex_alloc(size); }
- static void free(Matrix& m) { gsl_matrix_complex_free(m); m=0; }
- static void free(Vector& m) { gsl_vector_complex_free(m); m=0; }
- static void cholesky(Matrix& m) { gsl_linalg_complex_cholesky_decomp(m); }
- static void cholesky_solve(const Matrix& m, const Vector& b, Vector& x) { gsl_linalg_complex_cholesky_solve(m,b,x); }
- static void prod(const Matrix& m, const Vector& v, Vector& x)
- { gsl_blas_zgemv(CblasNoTrans,gsl_complex_rect(1,0),m,v,gsl_complex_rect(0,0),x); }
- static void eigen_symm(const Matrix& m, gsl_vector* &eval, Matrix& evec)
- {
- gsl_eigen_hermv_workspace * w = gsl_eigen_hermv_alloc(m->size1);
- Matrix a = createMatrix(m->size1, m->size2);
- gsl_matrix_complex_memcpy(a, m);
- gsl_eigen_hermv(a,eval,evec,w);
- gsl_eigen_hermv_sort(eval, evec, GSL_EIGEN_SORT_VAL_ASC);
- gsl_eigen_hermv_free(w);
- free(a);
- }
- static void eigen_symm_gen(const Matrix& m, const Matrix& _b, gsl_vector* &eval, Matrix& evec)
- {
- gsl_eigen_genhermv_workspace * w = gsl_eigen_genhermv_alloc(m->size1);
- Matrix a = createMatrix(m->size1, m->size2);
- Matrix b = createMatrix(_b->size1, _b->size2);
- gsl_matrix_complex_memcpy(a, m);
- gsl_matrix_complex_memcpy(b, _b);
- gsl_eigen_genhermv(a,b,eval,evec,w);
- gsl_eigen_hermv_sort(eval, evec, GSL_EIGEN_SORT_VAL_ASC);
- gsl_eigen_genhermv_free(w);
- free(a);
- }
-};
-
-template<typename MatrixType>
-void convert(const MatrixType& m, gsl_matrix* &res)
-{
-// if (res)
-// gsl_matrix_free(res);
- res = gsl_matrix_alloc(m.rows(), m.cols());
- for (int i=0 ; i<m.rows() ; ++i)
- for (int j=0 ; j<m.cols(); ++j)
- gsl_matrix_set(res, i, j, m(i,j));
-}
-
-template<typename MatrixType>
-void convert(const gsl_matrix* m, MatrixType& res)
-{
- res.resize(int(m->size1), int(m->size2));
- for (int i=0 ; i<res.rows() ; ++i)
- for (int j=0 ; j<res.cols(); ++j)
- res(i,j) = gsl_matrix_get(m,i,j);
-}
-
-template<typename VectorType>
-void convert(const VectorType& m, gsl_vector* &res)
-{
- if (res) gsl_vector_free(res);
- res = gsl_vector_alloc(m.size());
- for (int i=0 ; i<m.size() ; ++i)
- gsl_vector_set(res, i, m[i]);
-}
-
-template<typename VectorType>
-void convert(const gsl_vector* m, VectorType& res)
-{
- res.resize (m->size);
- for (int i=0 ; i<res.rows() ; ++i)
- res[i] = gsl_vector_get(m, i);
-}
-
-template<typename MatrixType>
-void convert(const MatrixType& m, gsl_matrix_complex* &res)
-{
- res = gsl_matrix_complex_alloc(m.rows(), m.cols());
- for (int i=0 ; i<m.rows() ; ++i)
- for (int j=0 ; j<m.cols(); ++j)
- {
- gsl_matrix_complex_set(res, i, j,
- gsl_complex_rect(m(i,j).real(), m(i,j).imag()));
- }
-}
-
-template<typename MatrixType>
-void convert(const gsl_matrix_complex* m, MatrixType& res)
-{
- res.resize(int(m->size1), int(m->size2));
- for (int i=0 ; i<res.rows() ; ++i)
- for (int j=0 ; j<res.cols(); ++j)
- res(i,j) = typename MatrixType::Scalar(
- GSL_REAL(gsl_matrix_complex_get(m,i,j)),
- GSL_IMAG(gsl_matrix_complex_get(m,i,j)));
-}
-
-template<typename VectorType>
-void convert(const VectorType& m, gsl_vector_complex* &res)
-{
- res = gsl_vector_complex_alloc(m.size());
- for (int i=0 ; i<m.size() ; ++i)
- gsl_vector_complex_set(res, i, gsl_complex_rect(m[i].real(), m[i].imag()));
-}
-
-template<typename VectorType>
-void convert(const gsl_vector_complex* m, VectorType& res)
-{
- res.resize(m->size);
- for (int i=0 ; i<res.rows() ; ++i)
- res[i] = typename VectorType::Scalar(
- GSL_REAL(gsl_vector_complex_get(m, i)),
- GSL_IMAG(gsl_vector_complex_get(m, i)));
-}
-
-}
-
-#endif // EIGEN_GSL_HELPER
diff --git a/test/eigen2/main.h b/test/eigen2/main.h
deleted file mode 100644
index ad2ba1994..000000000
--- a/test/eigen2/main.h
+++ /dev/null
@@ -1,399 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
-
-#include <cstdlib>
-#include <ctime>
-#include <iostream>
-#include <string>
-#include <vector>
-
-#ifndef EIGEN_TEST_FUNC
-#error EIGEN_TEST_FUNC must be defined
-#endif
-
-#define DEFAULT_REPEAT 10
-
-namespace Eigen
-{
- static std::vector<std::string> g_test_stack;
- static int g_repeat;
-}
-
-#define EI_PP_MAKE_STRING2(S) #S
-#define EI_PP_MAKE_STRING(S) EI_PP_MAKE_STRING2(S)
-
-#define EI_PP_CAT2(a,b) a ## b
-#define EI_PP_CAT(a,b) EI_PP_CAT2(a,b)
-
-#ifndef EIGEN_NO_ASSERTION_CHECKING
-
- namespace Eigen
- {
- static const bool should_raise_an_assert = false;
-
- // Used to avoid to raise two exceptions at a time in which
- // case the exception is not properly caught.
- // This may happen when a second exceptions is raise in a destructor.
- static bool no_more_assert = false;
-
- struct eigen_assert_exception
- {
- eigen_assert_exception(void) {}
- ~eigen_assert_exception() { Eigen::no_more_assert = false; }
- };
- }
-
- // If EIGEN_DEBUG_ASSERTS is defined and if no assertion is raised while
- // one should have been, then the list of excecuted assertions is printed out.
- //
- // EIGEN_DEBUG_ASSERTS is not enabled by default as it
- // significantly increases the compilation time
- // and might even introduce side effects that would hide
- // some memory errors.
- #ifdef EIGEN_DEBUG_ASSERTS
-
- namespace Eigen
- {
- static bool ei_push_assert = false;
- static std::vector<std::string> eigen_assert_list;
- }
-
- #define eigen_assert(a) \
- if( (!(a)) && (!no_more_assert) ) \
- { \
- Eigen::no_more_assert = true; \
- throw Eigen::eigen_assert_exception(); \
- } \
- else if (Eigen::ei_push_assert) \
- { \
- eigen_assert_list.push_back(std::string(EI_PP_MAKE_STRING(__FILE__)" ("EI_PP_MAKE_STRING(__LINE__)") : "#a) ); \
- }
-
- #define VERIFY_RAISES_ASSERT(a) \
- { \
- Eigen::no_more_assert = false; \
- try { \
- Eigen::eigen_assert_list.clear(); \
- Eigen::ei_push_assert = true; \
- a; \
- Eigen::ei_push_assert = false; \
- std::cerr << "One of the following asserts should have been raised:\n"; \
- for (uint ai=0 ; ai<eigen_assert_list.size() ; ++ai) \
- std::cerr << " " << eigen_assert_list[ai] << "\n"; \
- VERIFY(Eigen::should_raise_an_assert && # a); \
- } catch (Eigen::eigen_assert_exception e) { \
- Eigen::ei_push_assert = false; VERIFY(true); \
- } \
- }
-
- #else // EIGEN_DEBUG_ASSERTS
-
- #undef eigen_assert
-
- // see bug 89. The copy_bool here is working around a bug in gcc <= 4.3
- #define eigen_assert(a) \
- if( (!Eigen::internal::copy_bool(a)) && (!no_more_assert) ) \
- { \
- Eigen::no_more_assert = true; \
- throw Eigen::eigen_assert_exception(); \
- }
-
- #define VERIFY_RAISES_ASSERT(a) { \
- Eigen::no_more_assert = false; \
- try { a; VERIFY(Eigen::should_raise_an_assert && # a); } \
- catch (Eigen::eigen_assert_exception e) { VERIFY(true); } \
- }
-
- #endif // EIGEN_DEBUG_ASSERTS
-
- #define EIGEN_USE_CUSTOM_ASSERT
-
-#else // EIGEN_NO_ASSERTION_CHECKING
-
- #define VERIFY_RAISES_ASSERT(a) {}
-
-#endif // EIGEN_NO_ASSERTION_CHECKING
-
-
-#define EIGEN_INTERNAL_DEBUGGING
-#define EIGEN_NICE_RANDOM
-#include <Eigen/Array>
-
-
-#define VERIFY(a) do { if (!(a)) { \
- std::cerr << "Test " << g_test_stack.back() << " failed in "EI_PP_MAKE_STRING(__FILE__) << " (" << EI_PP_MAKE_STRING(__LINE__) << ")" \
- << std::endl << " " << EI_PP_MAKE_STRING(a) << std::endl << std::endl; \
- abort(); \
- } } while (0)
-
-#define VERIFY_IS_APPROX(a, b) VERIFY(test_ei_isApprox(a, b))
-#define VERIFY_IS_NOT_APPROX(a, b) VERIFY(!test_ei_isApprox(a, b))
-#define VERIFY_IS_MUCH_SMALLER_THAN(a, b) VERIFY(test_ei_isMuchSmallerThan(a, b))
-#define VERIFY_IS_NOT_MUCH_SMALLER_THAN(a, b) VERIFY(!test_ei_isMuchSmallerThan(a, b))
-#define VERIFY_IS_APPROX_OR_LESS_THAN(a, b) VERIFY(test_ei_isApproxOrLessThan(a, b))
-#define VERIFY_IS_NOT_APPROX_OR_LESS_THAN(a, b) VERIFY(!test_ei_isApproxOrLessThan(a, b))
-
-#define CALL_SUBTEST(FUNC) do { \
- g_test_stack.push_back(EI_PP_MAKE_STRING(FUNC)); \
- FUNC; \
- g_test_stack.pop_back(); \
- } while (0)
-
-namespace Eigen {
-
-template<typename T> inline typename NumTraits<T>::Real test_precision();
-template<> inline int test_precision<int>() { return 0; }
-template<> inline float test_precision<float>() { return 1e-3f; }
-template<> inline double test_precision<double>() { return 1e-6; }
-template<> inline float test_precision<std::complex<float> >() { return test_precision<float>(); }
-template<> inline double test_precision<std::complex<double> >() { return test_precision<double>(); }
-template<> inline long double test_precision<long double>() { return 1e-6; }
-
-inline bool test_ei_isApprox(const int& a, const int& b)
-{ return ei_isApprox(a, b, test_precision<int>()); }
-inline bool test_ei_isMuchSmallerThan(const int& a, const int& b)
-{ return ei_isMuchSmallerThan(a, b, test_precision<int>()); }
-inline bool test_ei_isApproxOrLessThan(const int& a, const int& b)
-{ return ei_isApproxOrLessThan(a, b, test_precision<int>()); }
-
-inline bool test_ei_isApprox(const float& a, const float& b)
-{ return ei_isApprox(a, b, test_precision<float>()); }
-inline bool test_ei_isMuchSmallerThan(const float& a, const float& b)
-{ return ei_isMuchSmallerThan(a, b, test_precision<float>()); }
-inline bool test_ei_isApproxOrLessThan(const float& a, const float& b)
-{ return ei_isApproxOrLessThan(a, b, test_precision<float>()); }
-
-inline bool test_ei_isApprox(const double& a, const double& b)
-{ return ei_isApprox(a, b, test_precision<double>()); }
-inline bool test_ei_isMuchSmallerThan(const double& a, const double& b)
-{ return ei_isMuchSmallerThan(a, b, test_precision<double>()); }
-inline bool test_ei_isApproxOrLessThan(const double& a, const double& b)
-{ return ei_isApproxOrLessThan(a, b, test_precision<double>()); }
-
-inline bool test_ei_isApprox(const std::complex<float>& a, const std::complex<float>& b)
-{ return ei_isApprox(a, b, test_precision<std::complex<float> >()); }
-inline bool test_ei_isMuchSmallerThan(const std::complex<float>& a, const std::complex<float>& b)
-{ return ei_isMuchSmallerThan(a, b, test_precision<std::complex<float> >()); }
-
-inline bool test_ei_isApprox(const std::complex<double>& a, const std::complex<double>& b)
-{ return ei_isApprox(a, b, test_precision<std::complex<double> >()); }
-inline bool test_ei_isMuchSmallerThan(const std::complex<double>& a, const std::complex<double>& b)
-{ return ei_isMuchSmallerThan(a, b, test_precision<std::complex<double> >()); }
-
-inline bool test_ei_isApprox(const long double& a, const long double& b)
-{ return ei_isApprox(a, b, test_precision<long double>()); }
-inline bool test_ei_isMuchSmallerThan(const long double& a, const long double& b)
-{ return ei_isMuchSmallerThan(a, b, test_precision<long double>()); }
-inline bool test_ei_isApproxOrLessThan(const long double& a, const long double& b)
-{ return ei_isApproxOrLessThan(a, b, test_precision<long double>()); }
-
-template<typename Type1, typename Type2>
-inline bool test_ei_isApprox(const Type1& a, const Type2& b)
-{
- return a.isApprox(b, test_precision<typename Type1::Scalar>());
-}
-
-template<typename Derived1, typename Derived2>
-inline bool test_ei_isMuchSmallerThan(const MatrixBase<Derived1>& m1,
- const MatrixBase<Derived2>& m2)
-{
- return m1.isMuchSmallerThan(m2, test_precision<typename ei_traits<Derived1>::Scalar>());
-}
-
-template<typename Derived>
-inline bool test_ei_isMuchSmallerThan(const MatrixBase<Derived>& m,
- const typename NumTraits<typename ei_traits<Derived>::Scalar>::Real& s)
-{
- return m.isMuchSmallerThan(s, test_precision<typename ei_traits<Derived>::Scalar>());
-}
-
-} // end namespace Eigen
-
-template<typename T> struct GetDifferentType;
-
-template<> struct GetDifferentType<float> { typedef double type; };
-template<> struct GetDifferentType<double> { typedef float type; };
-template<typename T> struct GetDifferentType<std::complex<T> >
-{ typedef std::complex<typename GetDifferentType<T>::type> type; };
-
-// forward declaration of the main test function
-void EI_PP_CAT(test_,EIGEN_TEST_FUNC)();
-
-using namespace Eigen;
-
-#ifdef EIGEN_TEST_PART_1
-#define CALL_SUBTEST_1(FUNC) CALL_SUBTEST(FUNC)
-#else
-#define CALL_SUBTEST_1(FUNC)
-#endif
-
-#ifdef EIGEN_TEST_PART_2
-#define CALL_SUBTEST_2(FUNC) CALL_SUBTEST(FUNC)
-#else
-#define CALL_SUBTEST_2(FUNC)
-#endif
-
-#ifdef EIGEN_TEST_PART_3
-#define CALL_SUBTEST_3(FUNC) CALL_SUBTEST(FUNC)
-#else
-#define CALL_SUBTEST_3(FUNC)
-#endif
-
-#ifdef EIGEN_TEST_PART_4
-#define CALL_SUBTEST_4(FUNC) CALL_SUBTEST(FUNC)
-#else
-#define CALL_SUBTEST_4(FUNC)
-#endif
-
-#ifdef EIGEN_TEST_PART_5
-#define CALL_SUBTEST_5(FUNC) CALL_SUBTEST(FUNC)
-#else
-#define CALL_SUBTEST_5(FUNC)
-#endif
-
-#ifdef EIGEN_TEST_PART_6
-#define CALL_SUBTEST_6(FUNC) CALL_SUBTEST(FUNC)
-#else
-#define CALL_SUBTEST_6(FUNC)
-#endif
-
-#ifdef EIGEN_TEST_PART_7
-#define CALL_SUBTEST_7(FUNC) CALL_SUBTEST(FUNC)
-#else
-#define CALL_SUBTEST_7(FUNC)
-#endif
-
-#ifdef EIGEN_TEST_PART_8
-#define CALL_SUBTEST_8(FUNC) CALL_SUBTEST(FUNC)
-#else
-#define CALL_SUBTEST_8(FUNC)
-#endif
-
-#ifdef EIGEN_TEST_PART_9
-#define CALL_SUBTEST_9(FUNC) CALL_SUBTEST(FUNC)
-#else
-#define CALL_SUBTEST_9(FUNC)
-#endif
-
-#ifdef EIGEN_TEST_PART_10
-#define CALL_SUBTEST_10(FUNC) CALL_SUBTEST(FUNC)
-#else
-#define CALL_SUBTEST_10(FUNC)
-#endif
-
-#ifdef EIGEN_TEST_PART_11
-#define CALL_SUBTEST_11(FUNC) CALL_SUBTEST(FUNC)
-#else
-#define CALL_SUBTEST_11(FUNC)
-#endif
-
-#ifdef EIGEN_TEST_PART_12
-#define CALL_SUBTEST_12(FUNC) CALL_SUBTEST(FUNC)
-#else
-#define CALL_SUBTEST_12(FUNC)
-#endif
-
-#ifdef EIGEN_TEST_PART_13
-#define CALL_SUBTEST_13(FUNC) CALL_SUBTEST(FUNC)
-#else
-#define CALL_SUBTEST_13(FUNC)
-#endif
-
-#ifdef EIGEN_TEST_PART_14
-#define CALL_SUBTEST_14(FUNC) CALL_SUBTEST(FUNC)
-#else
-#define CALL_SUBTEST_14(FUNC)
-#endif
-
-#ifdef EIGEN_TEST_PART_15
-#define CALL_SUBTEST_15(FUNC) CALL_SUBTEST(FUNC)
-#else
-#define CALL_SUBTEST_15(FUNC)
-#endif
-
-#ifdef EIGEN_TEST_PART_16
-#define CALL_SUBTEST_16(FUNC) CALL_SUBTEST(FUNC)
-#else
-#define CALL_SUBTEST_16(FUNC)
-#endif
-
-
-
-int main(int argc, char *argv[])
-{
- bool has_set_repeat = false;
- bool 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)
- {
- std::cout << "Argument " << argv[i] << " conflicting with a former argument" << std::endl;
- return 1;
- }
- repeat = std::atoi(argv[i]+1);
- has_set_repeat = true;
- if(repeat <= 0)
- {
- std::cout << "Invalid \'repeat\' value " << argv[i]+1 << std::endl;
- return 1;
- }
- }
- else if(argv[i][0] == 's')
- {
- if(has_set_seed)
- {
- std::cout << "Argument " << argv[i] << " conflicting with a former argument" << std::endl;
- return 1;
- }
- seed = int(std::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;
- }
- }
- else
- {
- need_help = true;
- }
- }
-
- if(need_help)
- {
- 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;
- return 1;
- }
-
- if(!has_set_seed) seed = (unsigned int) std::time(NULL);
- if(!has_set_repeat) repeat = DEFAULT_REPEAT;
-
- std::cout << "Initializing random number generator with seed " << seed << std::endl;
- std::srand(seed);
- std::cout << "Repeating each test " << repeat << " times" << std::endl;
-
- Eigen::g_repeat = repeat;
- Eigen::g_test_stack.push_back(EI_PP_MAKE_STRING(EIGEN_TEST_FUNC));
-
- EI_PP_CAT(test_,EIGEN_TEST_FUNC)();
- return 0;
-}
-
-
-
diff --git a/test/eigen2/product.h b/test/eigen2/product.h
deleted file mode 100644
index ae1b4bae4..000000000
--- a/test/eigen2/product.h
+++ /dev/null
@@ -1,129 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@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/Array>
-#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>())
-{
- return !((m1-m2).cwise().abs2().maxCoeff() < epsilon * epsilon
- * std::max(m1.cwise().abs2().maxCoeff(), m2.cwise().abs2().maxCoeff()));
-}
-
-template<typename MatrixType> void product(const MatrixType& m)
-{
- /* this test covers the following files:
- Identity.h Product.h
- */
-
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::FloatingPoint FloatingPoint;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> RowVectorType;
- typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> ColVectorType;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> RowSquareMatrixType;
- typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> ColSquareMatrixType;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime,
- MatrixType::Options^RowMajor> OtherMajorMatrixType;
-
- int rows = m.rows();
- int cols = m.cols();
-
- // this test relies a lot on Random.h, and there's not much more that we can do
- // to test it, hence I consider that we will have tested Random.h
- MatrixType m1 = MatrixType::Random(rows, cols),
- m2 = MatrixType::Random(rows, cols),
- m3(rows, cols);
- RowSquareMatrixType
- identity = RowSquareMatrixType::Identity(rows, rows),
- square = RowSquareMatrixType::Random(rows, rows),
- res = RowSquareMatrixType::Random(rows, rows);
- ColSquareMatrixType
- square2 = ColSquareMatrixType::Random(cols, cols),
- res2 = ColSquareMatrixType::Random(cols, cols);
- RowVectorType v1 = RowVectorType::Random(rows);
- ColVectorType vc2 = ColVectorType::Random(cols), vcres(cols);
- OtherMajorMatrixType tm1 = m1;
-
- Scalar s1 = ei_random<Scalar>();
-
- int r = ei_random<int>(0, rows-1),
- c = ei_random<int>(0, cols-1);
-
- // begin testing Product.h: only associativity for now
- // (we use Transpose.h but this doesn't count as a test for it)
-
- VERIFY_IS_APPROX((m1*m1.transpose())*m2, m1*(m1.transpose()*m2));
- m3 = m1;
- m3 *= m1.transpose() * m2;
- VERIFY_IS_APPROX(m3, m1 * (m1.transpose()*m2));
- VERIFY_IS_APPROX(m3, m1.lazy() * (m1.transpose()*m2));
-
- // continue testing Product.h: distributivity
- VERIFY_IS_APPROX(square*(m1 + m2), square*m1+square*m2);
- VERIFY_IS_APPROX(square*(m1 - m2), square*m1-square*m2);
-
- // continue testing Product.h: compatibility with ScalarMultiple.h
- VERIFY_IS_APPROX(s1*(square*m1), (s1*square)*m1);
- VERIFY_IS_APPROX(s1*(square*m1), square*(m1*s1));
-
- // again, test operator() to check const-qualification
- s1 += (square.lazy() * m1)(r,c);
-
- // test Product.h together with Identity.h
- VERIFY_IS_APPROX(v1, identity*v1);
- VERIFY_IS_APPROX(v1.transpose(), v1.transpose() * identity);
- // again, test operator() to check const-qualification
- VERIFY_IS_APPROX(MatrixType::Identity(rows, cols)(r,c), static_cast<Scalar>(r==c));
-
- if (rows!=cols)
- VERIFY_RAISES_ASSERT(m3 = m1*m1);
-
- // test the previous tests were not screwed up because operator* returns 0
- // (we use the more accurate default epsilon)
- if (NumTraits<Scalar>::HasFloatingPoint && std::min(rows,cols)>1)
- {
- VERIFY(areNotApprox(m1.transpose()*m2,m2.transpose()*m1));
- }
-
- // test optimized operator+= path
- res = square;
- res += (m1 * m2.transpose()).lazy();
- VERIFY_IS_APPROX(res, square + m1 * m2.transpose());
- if (NumTraits<Scalar>::HasFloatingPoint && std::min(rows,cols)>1)
- {
- VERIFY(areNotApprox(res,square + m2 * m1.transpose()));
- }
- vcres = vc2;
- vcres += (m1.transpose() * v1).lazy();
- VERIFY_IS_APPROX(vcres, vc2 + m1.transpose() * v1);
- tm1 = m1;
- VERIFY_IS_APPROX(tm1.transpose() * v1, m1.transpose() * v1);
- VERIFY_IS_APPROX(v1.transpose() * tm1, v1.transpose() * m1);
-
- // test submatrix and matrix/vector product
- for (int i=0; i<rows; ++i)
- res.row(i) = m1.row(i) * m2.transpose();
- VERIFY_IS_APPROX(res, m1 * m2.transpose());
- // the other way round:
- for (int i=0; i<rows; ++i)
- res.col(i) = m1 * m2.transpose().col(i);
- VERIFY_IS_APPROX(res, m1 * m2.transpose());
-
- res2 = square2;
- res2 += (m1.transpose() * m2).lazy();
- VERIFY_IS_APPROX(res2, square2 + m1.transpose() * m2);
-
- if (NumTraits<Scalar>::HasFloatingPoint && std::min(rows,cols)>1)
- {
- VERIFY(areNotApprox(res2,square2 + m2.transpose() * m1));
- }
-}
-
diff --git a/test/eigen2/runtest.sh b/test/eigen2/runtest.sh
deleted file mode 100755
index bc693af13..000000000
--- a/test/eigen2/runtest.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/bash
-
-black='\E[30m'
-red='\E[31m'
-green='\E[32m'
-yellow='\E[33m'
-blue='\E[34m'
-magenta='\E[35m'
-cyan='\E[36m'
-white='\E[37m'
-
-if make test_$1 > /dev/null 2> .runtest.log ; then
- if ! ./test_$1 r20 > /dev/null 2> .runtest.log ; then
- echo -e $red Test $1 failed: $black
- echo -e $blue
- cat .runtest.log
- echo -e $black
- exit 1
- else
- echo -e $green Test $1 passed$black
- fi
-else
- echo -e $red Build of target $1 failed: $black
- echo -e $blue
- cat .runtest.log
- echo -e $black
- exit 1
-fi
diff --git a/test/eigen2/sparse.h b/test/eigen2/sparse.h
deleted file mode 100644
index e12f89990..000000000
--- a/test/eigen2/sparse.h
+++ /dev/null
@@ -1,154 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra. Eigen itself is part of the KDE project.
-//
-// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@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/.
-
-#ifndef EIGEN_TESTSPARSE_H
-
-#include "main.h"
-
-#if EIGEN_GNUC_AT_LEAST(4,0) && !defined __ICC
-#include <tr1/unordered_map>
-#define EIGEN_UNORDERED_MAP_SUPPORT
-namespace std {
- using std::tr1::unordered_map;
-}
-#endif
-
-#ifdef EIGEN_GOOGLEHASH_SUPPORT
- #include <google/sparse_hash_map>
-#endif
-
-#include <Eigen/Cholesky>
-#include <Eigen/LU>
-#include <Eigen/Sparse>
-
-enum {
- ForceNonZeroDiag = 1,
- MakeLowerTriangular = 2,
- MakeUpperTriangular = 4,
- ForceRealDiag = 8
-};
-
-/* Initializes both a sparse and dense matrix with same random values,
- * and a ratio of \a density non zero entries.
- * \param flags is a union of ForceNonZeroDiag, MakeLowerTriangular and MakeUpperTriangular
- * allowing to control the shape of the matrix.
- * \param zeroCoords and nonzeroCoords allows to get the coordinate lists of the non zero,
- * and zero coefficients respectively.
- */
-template<typename Scalar> void
-initSparse(double density,
- Matrix<Scalar,Dynamic,Dynamic>& refMat,
- SparseMatrix<Scalar>& sparseMat,
- int flags = 0,
- std::vector<Vector2i>* zeroCoords = 0,
- std::vector<Vector2i>* nonzeroCoords = 0)
-{
- sparseMat.startFill(int(refMat.rows()*refMat.cols()*density));
- for(int j=0; j<refMat.cols(); j++)
- {
- for(int i=0; i<refMat.rows(); i++)
- {
- Scalar v = (ei_random<double>(0,1) < density) ? ei_random<Scalar>() : Scalar(0);
- if ((flags&ForceNonZeroDiag) && (i==j))
- {
- v = ei_random<Scalar>()*Scalar(3.);
- v = v*v + Scalar(5.);
- }
- if ((flags & MakeLowerTriangular) && j>i)
- v = Scalar(0);
- else if ((flags & MakeUpperTriangular) && j<i)
- v = Scalar(0);
-
- if ((flags&ForceRealDiag) && (i==j))
- v = ei_real(v);
-
- if (v!=Scalar(0))
- {
- sparseMat.fill(i,j) = v;
- if (nonzeroCoords)
- nonzeroCoords->push_back(Vector2i(i,j));
- }
- else if (zeroCoords)
- {
- zeroCoords->push_back(Vector2i(i,j));
- }
- refMat(i,j) = v;
- }
- }
- sparseMat.endFill();
-}
-
-template<typename Scalar> void
-initSparse(double density,
- Matrix<Scalar,Dynamic,Dynamic>& refMat,
- DynamicSparseMatrix<Scalar>& sparseMat,
- int flags = 0,
- std::vector<Vector2i>* zeroCoords = 0,
- std::vector<Vector2i>* nonzeroCoords = 0)
-{
- sparseMat.startFill(int(refMat.rows()*refMat.cols()*density));
- for(int j=0; j<refMat.cols(); j++)
- {
- for(int i=0; i<refMat.rows(); i++)
- {
- Scalar v = (ei_random<double>(0,1) < density) ? ei_random<Scalar>() : Scalar(0);
- if ((flags&ForceNonZeroDiag) && (i==j))
- {
- v = ei_random<Scalar>()*Scalar(3.);
- v = v*v + Scalar(5.);
- }
- if ((flags & MakeLowerTriangular) && j>i)
- v = Scalar(0);
- else if ((flags & MakeUpperTriangular) && j<i)
- v = Scalar(0);
-
- if ((flags&ForceRealDiag) && (i==j))
- v = ei_real(v);
-
- if (v!=Scalar(0))
- {
- sparseMat.fill(i,j) = v;
- if (nonzeroCoords)
- nonzeroCoords->push_back(Vector2i(i,j));
- }
- else if (zeroCoords)
- {
- zeroCoords->push_back(Vector2i(i,j));
- }
- refMat(i,j) = v;
- }
- }
- sparseMat.endFill();
-}
-
-template<typename Scalar> void
-initSparse(double density,
- Matrix<Scalar,Dynamic,1>& refVec,
- SparseVector<Scalar>& sparseVec,
- std::vector<int>* zeroCoords = 0,
- std::vector<int>* nonzeroCoords = 0)
-{
- sparseVec.reserve(int(refVec.size()*density));
- sparseVec.setZero();
- for(int i=0; i<refVec.size(); i++)
- {
- Scalar v = (ei_random<double>(0,1) < density) ? ei_random<Scalar>() : Scalar(0);
- if (v!=Scalar(0))
- {
- sparseVec.fill(i) = v;
- if (nonzeroCoords)
- nonzeroCoords->push_back(i);
- }
- else if (zeroCoords)
- zeroCoords->push_back(i);
- refVec[i] = v;
- }
-}
-
-#endif // EIGEN_TESTSPARSE_H
diff --git a/test/eigen2/testsuite.cmake b/test/eigen2/testsuite.cmake
deleted file mode 100644
index 12b6bfa2e..000000000
--- a/test/eigen2/testsuite.cmake
+++ /dev/null
@@ -1,197 +0,0 @@
-
-####################################################################
-#
-# 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]]
-#
-# Options:
-# - EIGEN_CXX: compiler, eg.: g++-4.2
-# default: default c++ compiler
-# - EIGEN_SITE: eg, INRIA-Bdx_pc-gael, or the name of the contributor, etc.
-# default: hostname
-# - EIGEN_BUILD_STRING: a string which identify the system/compiler. It should be formed like that:
-# <OS_name>-<OS_version>-<arch>-<compiler-version>
-# with:
-# <OS_name> = opensuse, debian, osx, windows, cygwin, freebsd, solaris, etc.
-# <OS_version> = 11.1, XP, vista, leopard, etc.
-# <arch> = i386, x86_64, ia64, powerpc, etc.
-# <compiler-version> = gcc-4.3.2, icc-11.0, MSVC-2008, etc.
-# - EIGEN_EXPLICIT_VECTORIZATION: novec, SSE2, Altivec
-# default: SSE2 for x86_64 systems, novec otherwise
-# Its value is automatically appended to EIGEN_BUILD_STRING
-# - EIGEN_CMAKE_DIR: path to cmake executable
-# - EIGEN_MODE: dashboard model, can be Experimental, Nightly, or Continuous
-# default: Nightly
-# - EIGEN_WORK_DIR: directory used to download the source files and make the builds
-# default: folder which contains this script
-# - EIGEN_CMAKE_ARGS: additional arguments passed to cmake
-# - CTEST_SOURCE_DIRECTORY: path to eigen's src (use a new and empty folder, not the one you are working on)
-# default: <EIGEN_WORK_DIR>/src
-# - CTEST_BINARY_DIRECTORY: build directory
-# default: <EIGEN_WORK_DIR>/nightly-<EIGEN_CXX>
-#
-# Here is an example running several compilers on a linux system:
-# #!/bin/bash
-# ARCH=`uname -m`
-# SITE=`hostname`
-# VERSION=opensuse-11.1
-# WORK_DIR=/home/gael/Coding/eigen2/cdash
-# # get the last version of the script
-# 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
-# $COMMON-gcc-4.3.2,EIGEN_CXX=g++-4.3,EIGEN_EXPLICIT_VECTORIZATION=novec
-# $COMMON-gcc-4.3.2,EIGEN_CXX=g++-4.3,EIGEN_EXPLICIT_VECTORIZATION=SSE2
-# $COMMON-icc-11.0,EIGEN_CXX=icpc
-#
-####################################################################
-
-# process the arguments
-
-set(ARGLIST ${CTEST_SCRIPT_ARG})
-while(${ARGLIST} MATCHES ".+.*")
-
- # pick first
- string(REGEX MATCH "([^,]*)(,.*)?" DUMMY ${ARGLIST})
- SET(TOP ${CMAKE_MATCH_1})
-
- # remove first
- string(REGEX MATCHALL "[^,]*,(.*)" DUMMY ${ARGLIST})
- SET(ARGLIST ${CMAKE_MATCH_1})
-
- # decompose as a pair key=value
- string(REGEX MATCH "([^=]*)(=.*)?" DUMMY ${TOP})
- SET(KEY ${CMAKE_MATCH_1})
-
- string(REGEX MATCH "[^=]*=(.*)" DUMMY ${TOP})
- SET(VALUE ${CMAKE_MATCH_1})
-
- # set the variable to the specified value
- if(VALUE)
- SET(${KEY} ${VALUE})
- else(VALUE)
- SET(${KEY} ON)
- endif(VALUE)
-
-endwhile(${ARGLIST} MATCHES ".+.*")
-
-####################################################################
-# Automatically set some user variables if they have not been defined manually
-####################################################################
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
-
-if(NOT EIGEN_SITE)
- site_name(EIGEN_SITE)
-endif(NOT EIGEN_SITE)
-
-if(NOT EIGEN_CMAKE_DIR)
- SET(EIGEN_CMAKE_DIR "")
-endif(NOT EIGEN_CMAKE_DIR)
-
-if(NOT EIGEN_BUILD_STRING)
-
- # let's try to find all information we need to make the build string ourself
-
- # OS
- build_name(EIGEN_OS_VERSION)
-
- # arch
- set(EIGEN_ARCH ${CMAKE_SYSTEM_PROCESSOR})
- if(WIN32)
- set(EIGEN_ARCH $ENV{PROCESSOR_ARCHITECTURE})
- else(WIN32)
- execute_process(COMMAND uname -m OUTPUT_VARIABLE EIGEN_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
- endif(WIN32)
-
- set(EIGEN_BUILD_STRING ${EIGEN_OS_VERSION}${EIGEN_ARCH}-${EIGEN_CXX})
-
-endif(NOT EIGEN_BUILD_STRING)
-
-if(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
- set(EIGEN_BUILD_STRING ${EIGEN_BUILD_STRING}-${EIGEN_EXPLICIT_VECTORIZATION})
-endif(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
-
-if(NOT EIGEN_WORK_DIR)
- set(EIGEN_WORK_DIR ${CTEST_SCRIPT_DIRECTORY})
-endif(NOT EIGEN_WORK_DIR)
-
-if(NOT CTEST_SOURCE_DIRECTORY)
- SET (CTEST_SOURCE_DIRECTORY "${EIGEN_WORK_DIR}/src")
-endif(NOT CTEST_SOURCE_DIRECTORY)
-
-if(NOT CTEST_BINARY_DIRECTORY)
- SET (CTEST_BINARY_DIRECTORY "${EIGEN_WORK_DIR}/nightly_${EIGEN_CXX}")
-endif(NOT CTEST_BINARY_DIRECTORY)
-
-if(NOT EIGEN_MODE)
- set(EIGEN_MODE Nightly)
-endif(NOT EIGEN_MODE)
-
-## mandatory variables (the default should be ok in most cases):
-
-SET (CTEST_CVS_COMMAND "hg")
-SET (CTEST_CVS_CHECKOUT "${CTEST_CVS_COMMAND} clone -r 2.0 http://bitbucket.org/eigen/eigen \"${CTEST_SOURCE_DIRECTORY}\"")
-
-# which ctest command to use for running the dashboard
-SET (CTEST_COMMAND "${EIGEN_CMAKE_DIR}ctest -D ${EIGEN_MODE}")
-
-# what cmake command to use for configuring this dashboard
-SET (CTEST_CMAKE_COMMAND "${EIGEN_CMAKE_DIR}cmake -DEIGEN_BUILD_TESTS=on ")
-
-####################################################################
-# The values in this section are optional you can either
-# have them or leave them commented out
-####################################################################
-
-# this make sure we get consistent outputs
-SET($ENV{LC_MESSAGES} "en_EN")
-
-# should ctest wipe the binary tree before running
-SET(CTEST_START_WITH_EMPTY_BINARY_DIRECTORY TRUE)
-SET(CTEST_BACKUP_AND_RESTORE TRUE)
-
-# this is the initial cache to use for the binary tree, be careful to escape
-# any quotes inside of this string if you use it
-if(WIN32 AND NOT UNIX)
- #message(SEND_ERROR "win32")
- set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -G \"NMake Makefiles\" -DCMAKE_MAKE_PROGRAM=nmake")
- SET (CTEST_INITIAL_CACHE "
- MAKECOMMAND:STRING=nmake -i
- CMAKE_MAKE_PROGRAM:FILEPATH=nmake
- CMAKE_GENERATOR:INTERNAL=NMake Makefiles
- BUILDNAME:STRING=${EIGEN_BUILD_STRING}
- SITE:STRING=${EIGEN_SITE}
- ")
-else(WIN32 AND NOT UNIX)
- SET (CTEST_INITIAL_CACHE "
- BUILDNAME:STRING=${EIGEN_BUILD_STRING}
- SITE:STRING=${EIGEN_SITE}
- ")
-endif(WIN32 AND NOT UNIX)
-
-# set any extra environment variables to use during the execution of the script here:
-
-if(EIGEN_CXX)
- set(CTEST_ENVIRONMENT "CXX=${EIGEN_CXX}")
-endif(EIGEN_CXX)
-
-if(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
- if(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE2)
- set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_SSE2=ON")
- elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE3)
- set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_SSE2=ON -DEIGEN_TEST_SSE3=ON")
- elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES Altivec)
- set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_ALTIVEC=ON")
- elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES novec)
- set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_NO_EXPLICIT_VECTORIZATION=ON")
- else(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE2)
- message(FATAL_ERROR "Invalid value for EIGEN_EXPLICIT_VECTORIZATION (${EIGEN_EXPLICIT_VECTORIZATION}), must be: novec, SSE2, SSE3, Altivec")
- endif(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE2)
-endif(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
-
-if(DEFINED EIGEN_CMAKE_ARGS)
- set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} ${EIGEN_CMAKE_ARGS}")
-endif(DEFINED EIGEN_CMAKE_ARGS)
diff --git a/test/eigen2support.cpp b/test/eigen2support.cpp
index 1fa49a8c8..ad1d98091 100644
--- a/test/eigen2support.cpp
+++ b/test/eigen2support.cpp
@@ -8,7 +8,6 @@
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#define EIGEN2_SUPPORT
-#define EIGEN_NO_EIGEN2_DEPRECATED_WARNING
#include "main.h"
diff --git a/test/eigensolver_complex.cpp b/test/eigensolver_complex.cpp
index c9d8c0877..293b1b265 100644
--- a/test/eigensolver_complex.cpp
+++ b/test/eigensolver_complex.cpp
@@ -13,20 +13,59 @@
#include <Eigen/Eigenvalues>
#include <Eigen/LU>
-/* Check that two column vectors are approximately equal upto permutations,
- by checking that the k-th power sums are equal for k = 1, ..., vec1.rows() */
+template<typename MatrixType> bool find_pivot(typename MatrixType::Scalar tol, MatrixType &diffs, Index col=0)
+{
+ bool match = diffs.diagonal().sum() <= tol;
+ if(match || col==diffs.cols())
+ {
+ return match;
+ }
+ else
+ {
+ Index n = diffs.cols();
+ std::vector<std::pair<Index,Index> > transpositions;
+ for(Index i=col; i<n; ++i)
+ {
+ Index best_index(0);
+ if(diffs.col(col).segment(col,n-i).minCoeff(&best_index) > tol)
+ break;
+
+ best_index += col;
+
+ diffs.row(col).swap(diffs.row(best_index));
+ if(find_pivot(tol,diffs,col+1)) return true;
+ diffs.row(col).swap(diffs.row(best_index));
+
+ // move current pivot to the end
+ diffs.row(n-(i-col)-1).swap(diffs.row(best_index));
+ transpositions.push_back(std::pair<Index,Index>(n-(i-col)-1,best_index));
+ }
+ // restore
+ for(Index k=transpositions.size()-1; k>=0; --k)
+ diffs.row(transpositions[k].first).swap(diffs.row(transpositions[k].second));
+ }
+ return false;
+}
+
+/* Check that two column vectors are approximately equal upto permutations.
+ * Initially, this method checked that the k-th power sums are equal for all k = 1, ..., vec1.rows(),
+ * however this strategy is numerically inacurate because of numerical cancellation issues.
+ */
template<typename VectorType>
void verify_is_approx_upto_permutation(const VectorType& vec1, const VectorType& vec2)
{
- typedef typename NumTraits<typename VectorType::Scalar>::Real RealScalar;
+ typedef typename VectorType::Scalar Scalar;
+ typedef typename NumTraits<Scalar>::Real RealScalar;
VERIFY(vec1.cols() == 1);
VERIFY(vec2.cols() == 1);
VERIFY(vec1.rows() == vec2.rows());
- for (int k = 1; k <= vec1.rows(); ++k)
- {
- VERIFY_IS_APPROX(vec1.array().pow(RealScalar(k)).sum(), vec2.array().pow(RealScalar(k)).sum());
- }
+
+ Index n = vec1.rows();
+ RealScalar tol = test_precision<RealScalar>()*test_precision<RealScalar>()*numext::maxi(vec1.squaredNorm(),vec2.squaredNorm());
+ Matrix<RealScalar,Dynamic,Dynamic> diffs = (vec1.rowwise().replicate(n) - vec2.rowwise().replicate(n).transpose()).cwiseAbs2();
+
+ VERIFY( find_pivot(tol, diffs) );
}
@@ -79,13 +118,28 @@ template<typename MatrixType> void eigensolver(const MatrixType& m)
MatrixType id = MatrixType::Identity(rows, cols);
VERIFY_IS_APPROX(id.operatorNorm(), RealScalar(1));
- if (rows > 1)
+ if (rows > 1 && rows < 20)
{
// Test matrix with NaN
a(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
ComplexEigenSolver<MatrixType> eiNaN(a);
VERIFY_IS_EQUAL(eiNaN.info(), NoConvergence);
}
+
+ // regression test for bug 1098
+ {
+ ComplexEigenSolver<MatrixType> eig(a.adjoint() * a);
+ eig.compute(a.adjoint() * a);
+ }
+
+ // regression test for bug 478
+ {
+ a.setZero();
+ ComplexEigenSolver<MatrixType> ei3(a);
+ VERIFY_IS_EQUAL(ei3.info(), Success);
+ VERIFY_IS_MUCH_SMALLER_THAN(ei3.eigenvalues().norm(),RealScalar(1));
+ VERIFY((ei3.eigenvectors().transpose()*ei3.eigenvectors().transpose()).eval().isIdentity());
+ }
}
template<typename MatrixType> void eigensolver_verify_assert(const MatrixType& m)
@@ -108,6 +162,7 @@ void test_eigensolver_complex()
CALL_SUBTEST_2( eigensolver(MatrixXcd(s,s)) );
CALL_SUBTEST_3( eigensolver(Matrix<std::complex<float>, 1, 1>()) );
CALL_SUBTEST_4( eigensolver(Matrix3f()) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
}
CALL_SUBTEST_1( eigensolver_verify_assert(Matrix4cf()) );
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
diff --git a/test/eigensolver_generalized_real.cpp b/test/eigensolver_generalized_real.cpp
index 566a4bdc6..9c0838ba4 100644
--- a/test/eigensolver_generalized_real.cpp
+++ b/test/eigensolver_generalized_real.cpp
@@ -1,15 +1,17 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
-// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2012-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
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#define EIGEN_RUNTIME_NO_MALLOC
#include "main.h"
#include <limits>
#include <Eigen/Eigenvalues>
+#include <Eigen/LU>
template<typename MatrixType> void generalized_eigensolver_real(const MatrixType& m)
{
@@ -21,6 +23,7 @@ template<typename MatrixType> void generalized_eigensolver_real(const MatrixType
Index cols = m.cols();
typedef typename MatrixType::Scalar Scalar;
+ typedef std::complex<Scalar> ComplexScalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
MatrixType a = MatrixType::Random(rows,cols);
@@ -31,14 +34,49 @@ template<typename MatrixType> void generalized_eigensolver_real(const MatrixType
MatrixType spdB = b.adjoint() * b + b1.adjoint() * b1;
// lets compare to GeneralizedSelfAdjointEigenSolver
- GeneralizedSelfAdjointEigenSolver<MatrixType> symmEig(spdA, spdB);
- GeneralizedEigenSolver<MatrixType> eig(spdA, spdB);
+ {
+ GeneralizedSelfAdjointEigenSolver<MatrixType> symmEig(spdA, spdB);
+ GeneralizedEigenSolver<MatrixType> eig(spdA, spdB);
- VERIFY_IS_EQUAL(eig.eigenvalues().imag().cwiseAbs().maxCoeff(), 0);
+ VERIFY_IS_EQUAL(eig.eigenvalues().imag().cwiseAbs().maxCoeff(), 0);
- VectorType realEigenvalues = eig.eigenvalues().real();
- std::sort(realEigenvalues.data(), realEigenvalues.data()+realEigenvalues.size());
- VERIFY_IS_APPROX(realEigenvalues, symmEig.eigenvalues());
+ VectorType realEigenvalues = eig.eigenvalues().real();
+ std::sort(realEigenvalues.data(), realEigenvalues.data()+realEigenvalues.size());
+ VERIFY_IS_APPROX(realEigenvalues, symmEig.eigenvalues());
+
+ // check eigenvectors
+ typename GeneralizedEigenSolver<MatrixType>::EigenvectorsType D = eig.eigenvalues().asDiagonal();
+ typename GeneralizedEigenSolver<MatrixType>::EigenvectorsType V = eig.eigenvectors();
+ VERIFY_IS_APPROX(spdA*V, spdB*V*D);
+ }
+
+ // non symmetric case:
+ {
+ GeneralizedEigenSolver<MatrixType> eig(rows);
+ // TODO enable full-prealocation of required memory, this probably requires an in-place mode for HessenbergDecomposition
+ //Eigen::internal::set_is_malloc_allowed(false);
+ eig.compute(a,b);
+ //Eigen::internal::set_is_malloc_allowed(true);
+ for(Index k=0; k<cols; ++k)
+ {
+ Matrix<ComplexScalar,Dynamic,Dynamic> tmp = (eig.betas()(k)*a).template cast<ComplexScalar>() - eig.alphas()(k)*b;
+ if(tmp.size()>1 && tmp.norm()>(std::numeric_limits<Scalar>::min)())
+ tmp /= tmp.norm();
+ VERIFY_IS_MUCH_SMALLER_THAN( std::abs(tmp.determinant()), Scalar(1) );
+ }
+ // check eigenvectors
+ typename GeneralizedEigenSolver<MatrixType>::EigenvectorsType D = eig.eigenvalues().asDiagonal();
+ typename GeneralizedEigenSolver<MatrixType>::EigenvectorsType V = eig.eigenvectors();
+ VERIFY_IS_APPROX(a*V, b*V*D);
+ }
+
+ // regression test for bug 1098
+ {
+ GeneralizedSelfAdjointEigenSolver<MatrixType> eig1(a.adjoint() * a,b.adjoint() * b);
+ eig1.compute(a.adjoint() * a,b.adjoint() * b);
+ GeneralizedEigenSolver<MatrixType> eig2(a.adjoint() * a,b.adjoint() * b);
+ eig2.compute(a.adjoint() * a,b.adjoint() * b);
+ }
}
void test_eigensolver_generalized_real()
@@ -49,7 +87,7 @@ void test_eigensolver_generalized_real()
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
CALL_SUBTEST_2( generalized_eigensolver_real(MatrixXd(s,s)) );
- // some trivial but implementation-wise tricky cases
+ // some trivial but implementation-wise special cases
CALL_SUBTEST_2( generalized_eigensolver_real(MatrixXd(1,1)) );
CALL_SUBTEST_2( generalized_eigensolver_real(MatrixXd(2,2)) );
CALL_SUBTEST_3( generalized_eigensolver_real(Matrix<double,1,1>()) );
diff --git a/test/eigensolver_generic.cpp b/test/eigensolver_generic.cpp
index 005af81eb..d0e644d4b 100644
--- a/test/eigensolver_generic.cpp
+++ b/test/eigensolver_generic.cpp
@@ -63,13 +63,28 @@ template<typename MatrixType> void eigensolver(const MatrixType& m)
MatrixType id = MatrixType::Identity(rows, cols);
VERIFY_IS_APPROX(id.operatorNorm(), RealScalar(1));
- if (rows > 2)
+ if (rows > 2 && rows < 20)
{
// Test matrix with NaN
a(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
EigenSolver<MatrixType> eiNaN(a);
VERIFY_IS_EQUAL(eiNaN.info(), NoConvergence);
}
+
+ // regression test for bug 1098
+ {
+ EigenSolver<MatrixType> eig(a.adjoint() * a);
+ eig.compute(a.adjoint() * a);
+ }
+
+ // regression test for bug 478
+ {
+ a.setZero();
+ EigenSolver<MatrixType> ei3(a);
+ VERIFY_IS_EQUAL(ei3.info(), Success);
+ VERIFY_IS_MUCH_SMALLER_THAN(ei3.eigenvalues().norm(),RealScalar(1));
+ VERIFY((ei3.eigenvectors().transpose()*ei3.eigenvectors().transpose()).eval().isIdentity());
+ }
}
template<typename MatrixType> void eigensolver_verify_assert(const MatrixType& m)
@@ -93,6 +108,7 @@ void test_eigensolver_generic()
CALL_SUBTEST_1( eigensolver(Matrix4f()) );
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
CALL_SUBTEST_2( eigensolver(MatrixXd(s,s)) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
// some trivial but implementation-wise tricky cases
CALL_SUBTEST_2( eigensolver(MatrixXd(1,1)) );
@@ -114,12 +130,37 @@ void test_eigensolver_generic()
CALL_SUBTEST_2(
{
MatrixXd A(1,1);
- A(0,0) = std::sqrt(-1.);
+ A(0,0) = std::sqrt(-1.); // is Not-a-Number
Eigen::EigenSolver<MatrixXd> solver(A);
- MatrixXd V(1, 1);
- V(0,0) = solver.eigenvectors()(0,0).real();
+ VERIFY_IS_EQUAL(solver.info(), NumericalIssue);
}
);
+#ifdef EIGEN_TEST_PART_2
+ {
+ // regression test for bug 793
+ MatrixXd a(3,3);
+ a << 0, 0, 1,
+ 1, 1, 1,
+ 1, 1e+200, 1;
+ Eigen::EigenSolver<MatrixXd> eig(a);
+ double scale = 1e-200; // scale to avoid overflow during the comparisons
+ VERIFY_IS_APPROX(a * eig.pseudoEigenvectors()*scale, eig.pseudoEigenvectors() * eig.pseudoEigenvalueMatrix()*scale);
+ VERIFY_IS_APPROX(a * eig.eigenvectors()*scale, eig.eigenvectors() * eig.eigenvalues().asDiagonal()*scale);
+ }
+ {
+ // check a case where all eigenvalues are null.
+ MatrixXd a(2,2);
+ a << 1, 1,
+ -1, -1;
+ Eigen::EigenSolver<MatrixXd> eig(a);
+ VERIFY_IS_APPROX(eig.pseudoEigenvectors().squaredNorm(), 2.);
+ VERIFY_IS_APPROX((a * eig.pseudoEigenvectors()).norm()+1., 1.);
+ VERIFY_IS_APPROX((eig.pseudoEigenvectors() * eig.pseudoEigenvalueMatrix()).norm()+1., 1.);
+ VERIFY_IS_APPROX((a * eig.eigenvectors()).norm()+1., 1.);
+ VERIFY_IS_APPROX((eig.eigenvectors() * eig.eigenvalues().asDiagonal()).norm()+1., 1.);
+ }
+#endif
+
TEST_SET_BUT_UNUSED_VARIABLE(s)
}
diff --git a/test/eigensolver_selfadjoint.cpp b/test/eigensolver_selfadjoint.cpp
index 38689cfbf..39ad4130e 100644
--- a/test/eigensolver_selfadjoint.cpp
+++ b/test/eigensolver_selfadjoint.cpp
@@ -9,8 +9,62 @@
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "main.h"
+#include "svd_fill.h"
#include <limits>
#include <Eigen/Eigenvalues>
+#include <Eigen/SparseCore>
+
+
+template<typename MatrixType> void selfadjointeigensolver_essential_check(const MatrixType& m)
+{
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+ RealScalar eival_eps = numext::mini<RealScalar>(test_precision<RealScalar>(), NumTraits<Scalar>::dummy_precision()*20000);
+
+ SelfAdjointEigenSolver<MatrixType> eiSymm(m);
+ VERIFY_IS_EQUAL(eiSymm.info(), Success);
+
+ RealScalar scaling = m.cwiseAbs().maxCoeff();
+
+ if(scaling<(std::numeric_limits<RealScalar>::min)())
+ {
+ VERIFY(eiSymm.eigenvalues().cwiseAbs().maxCoeff() <= (std::numeric_limits<RealScalar>::min)());
+ }
+ else
+ {
+ VERIFY_IS_APPROX((m.template selfadjointView<Lower>() * eiSymm.eigenvectors())/scaling,
+ (eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal())/scaling);
+ }
+ VERIFY_IS_APPROX(m.template selfadjointView<Lower>().eigenvalues(), eiSymm.eigenvalues());
+ VERIFY_IS_UNITARY(eiSymm.eigenvectors());
+
+ if(m.cols()<=4)
+ {
+ SelfAdjointEigenSolver<MatrixType> eiDirect;
+ eiDirect.computeDirect(m);
+ VERIFY_IS_EQUAL(eiDirect.info(), Success);
+ if(! eiSymm.eigenvalues().isApprox(eiDirect.eigenvalues(), eival_eps) )
+ {
+ std::cerr << "reference eigenvalues: " << eiSymm.eigenvalues().transpose() << "\n"
+ << "obtained eigenvalues: " << eiDirect.eigenvalues().transpose() << "\n"
+ << "diff: " << (eiSymm.eigenvalues()-eiDirect.eigenvalues()).transpose() << "\n"
+ << "error (eps): " << (eiSymm.eigenvalues()-eiDirect.eigenvalues()).norm() / eiSymm.eigenvalues().norm() << " (" << eival_eps << ")\n";
+ }
+ if(scaling<(std::numeric_limits<RealScalar>::min)())
+ {
+ VERIFY(eiDirect.eigenvalues().cwiseAbs().maxCoeff() <= (std::numeric_limits<RealScalar>::min)());
+ }
+ else
+ {
+ VERIFY_IS_APPROX(eiSymm.eigenvalues()/scaling, eiDirect.eigenvalues()/scaling);
+ VERIFY_IS_APPROX((m.template selfadjointView<Lower>() * eiDirect.eigenvectors())/scaling,
+ (eiDirect.eigenvectors() * eiDirect.eigenvalues().asDiagonal())/scaling);
+ VERIFY_IS_APPROX(m.template selfadjointView<Lower>().eigenvalues()/scaling, eiDirect.eigenvalues()/scaling);
+ }
+
+ VERIFY_IS_UNITARY(eiDirect.eigenvectors());
+ }
+}
template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m)
{
@@ -31,17 +85,8 @@ template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m)
MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1;
MatrixType symmC = symmA;
- // randomly nullify some rows/columns
- {
- Index count = 1;//internal::random<Index>(-cols,cols);
- for(Index k=0; k<count; ++k)
- {
- Index i = internal::random<Index>(0,cols-1);
- symmA.row(i).setZero();
- symmA.col(i).setZero();
- }
- }
-
+ svd_fill_random(symmA,Symmetric);
+
symmA.template triangularView<StrictlyUpper>().setZero();
symmC.template triangularView<StrictlyUpper>().setZero();
@@ -49,23 +94,13 @@ template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m)
MatrixType b1 = MatrixType::Random(rows,cols);
MatrixType symmB = b.adjoint() * b + b1.adjoint() * b1;
symmB.template triangularView<StrictlyUpper>().setZero();
+
+ CALL_SUBTEST( selfadjointeigensolver_essential_check(symmA) );
SelfAdjointEigenSolver<MatrixType> eiSymm(symmA);
- SelfAdjointEigenSolver<MatrixType> eiDirect;
- eiDirect.computeDirect(symmA);
// generalized eigen pb
GeneralizedSelfAdjointEigenSolver<MatrixType> eiSymmGen(symmC, symmB);
- VERIFY_IS_EQUAL(eiSymm.info(), Success);
- VERIFY((symmA.template selfadjointView<Lower>() * eiSymm.eigenvectors()).isApprox(
- eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal(), largerEps));
- VERIFY_IS_APPROX(symmA.template selfadjointView<Lower>().eigenvalues(), eiSymm.eigenvalues());
-
- VERIFY_IS_EQUAL(eiDirect.info(), Success);
- VERIFY((symmA.template selfadjointView<Lower>() * eiDirect.eigenvectors()).isApprox(
- eiDirect.eigenvectors() * eiDirect.eigenvalues().asDiagonal(), largerEps));
- VERIFY_IS_APPROX(symmA.template selfadjointView<Lower>().eigenvalues(), eiDirect.eigenvalues());
-
SelfAdjointEigenSolver<MatrixType> eiSymmNoEivecs(symmA, false);
VERIFY_IS_EQUAL(eiSymmNoEivecs.info(), Success);
VERIFY_IS_APPROX(eiSymm.eigenvalues(), eiSymmNoEivecs.eigenvalues());
@@ -111,37 +146,111 @@ template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m)
// test Tridiagonalization's methods
Tridiagonalization<MatrixType> tridiag(symmC);
- // FIXME tridiag.matrixQ().adjoint() does not work
+ VERIFY_IS_APPROX(tridiag.diagonal(), tridiag.matrixT().diagonal());
+ VERIFY_IS_APPROX(tridiag.subDiagonal(), tridiag.matrixT().template diagonal<-1>());
+ Matrix<RealScalar,Dynamic,Dynamic> T = tridiag.matrixT();
+ if(rows>1 && cols>1) {
+ // FIXME check that upper and lower part are 0:
+ //VERIFY(T.topRightCorner(rows-2, cols-2).template triangularView<Upper>().isZero());
+ }
+ VERIFY_IS_APPROX(tridiag.diagonal(), T.diagonal());
+ VERIFY_IS_APPROX(tridiag.subDiagonal(), T.template diagonal<1>());
VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()), tridiag.matrixQ() * tridiag.matrixT().eval() * MatrixType(tridiag.matrixQ()).adjoint());
+ VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()), tridiag.matrixQ() * tridiag.matrixT() * tridiag.matrixQ().adjoint());
- if (rows > 1)
+ // Test computation of eigenvalues from tridiagonal matrix
+ if(rows > 1)
+ {
+ SelfAdjointEigenSolver<MatrixType> eiSymmTridiag;
+ eiSymmTridiag.computeFromTridiagonal(tridiag.matrixT().diagonal(), tridiag.matrixT().diagonal(-1), ComputeEigenvectors);
+ VERIFY_IS_APPROX(eiSymm.eigenvalues(), eiSymmTridiag.eigenvalues());
+ VERIFY_IS_APPROX(tridiag.matrixT(), eiSymmTridiag.eigenvectors().real() * eiSymmTridiag.eigenvalues().asDiagonal() * eiSymmTridiag.eigenvectors().real().transpose());
+ }
+
+ if (rows > 1 && rows < 20)
{
// Test matrix with NaN
symmC(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
SelfAdjointEigenSolver<MatrixType> eiSymmNaN(symmC);
VERIFY_IS_EQUAL(eiSymmNaN.info(), NoConvergence);
}
+
+ // regression test for bug 1098
+ {
+ SelfAdjointEigenSolver<MatrixType> eig(a.adjoint() * a);
+ eig.compute(a.adjoint() * a);
+ }
+
+ // regression test for bug 478
+ {
+ a.setZero();
+ SelfAdjointEigenSolver<MatrixType> ei3(a);
+ VERIFY_IS_EQUAL(ei3.info(), Success);
+ VERIFY_IS_MUCH_SMALLER_THAN(ei3.eigenvalues().norm(),RealScalar(1));
+ VERIFY((ei3.eigenvectors().transpose()*ei3.eigenvectors().transpose()).eval().isIdentity());
+ }
+}
+
+template<int>
+void bug_854()
+{
+ Matrix3d m;
+ m << 850.961, 51.966, 0,
+ 51.966, 254.841, 0,
+ 0, 0, 0;
+ selfadjointeigensolver_essential_check(m);
+}
+
+template<int>
+void bug_1014()
+{
+ Matrix3d m;
+ m << 0.11111111111111114658, 0, 0,
+ 0, 0.11111111111111109107, 0,
+ 0, 0, 0.11111111111111107719;
+ selfadjointeigensolver_essential_check(m);
+}
+
+template<int>
+void bug_1225()
+{
+ Matrix3d m1, m2;
+ m1.setRandom();
+ m1 = m1*m1.transpose();
+ m2 = m1.triangularView<Upper>();
+ SelfAdjointEigenSolver<Matrix3d> eig1(m1);
+ SelfAdjointEigenSolver<Matrix3d> eig2(m2.selfadjointView<Upper>());
+ VERIFY_IS_APPROX(eig1.eigenvalues(), eig2.eigenvalues());
+}
+
+template<int>
+void bug_1204()
+{
+ SparseMatrix<double> A(2,2);
+ A.setIdentity();
+ SelfAdjointEigenSolver<Eigen::SparseMatrix<double> > eig(A);
}
void test_eigensolver_selfadjoint()
{
int s = 0;
for(int i = 0; i < g_repeat; i++) {
+ // trivial test for 1x1 matrices:
+ CALL_SUBTEST_1( selfadjointeigensolver(Matrix<float, 1, 1>()));
+ CALL_SUBTEST_1( selfadjointeigensolver(Matrix<double, 1, 1>()));
// very important to test 3x3 and 2x2 matrices since we provide special paths for them
- CALL_SUBTEST_1( selfadjointeigensolver(Matrix2f()) );
- CALL_SUBTEST_1( selfadjointeigensolver(Matrix2d()) );
- CALL_SUBTEST_1( selfadjointeigensolver(Matrix3f()) );
- CALL_SUBTEST_1( selfadjointeigensolver(Matrix3d()) );
+ CALL_SUBTEST_12( selfadjointeigensolver(Matrix2f()) );
+ CALL_SUBTEST_12( selfadjointeigensolver(Matrix2d()) );
+ CALL_SUBTEST_13( selfadjointeigensolver(Matrix3f()) );
+ CALL_SUBTEST_13( selfadjointeigensolver(Matrix3d()) );
CALL_SUBTEST_2( selfadjointeigensolver(Matrix4d()) );
+
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
CALL_SUBTEST_3( selfadjointeigensolver(MatrixXf(s,s)) );
- s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
CALL_SUBTEST_4( selfadjointeigensolver(MatrixXd(s,s)) );
- s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
CALL_SUBTEST_5( selfadjointeigensolver(MatrixXcd(s,s)) );
-
- s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
CALL_SUBTEST_9( selfadjointeigensolver(Matrix<std::complex<double>,Dynamic,Dynamic,RowMajor>(s,s)) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
// some trivial but implementation-wise tricky cases
CALL_SUBTEST_4( selfadjointeigensolver(MatrixXd(1,1)) );
@@ -149,6 +258,11 @@ void test_eigensolver_selfadjoint()
CALL_SUBTEST_6( selfadjointeigensolver(Matrix<double,1,1>()) );
CALL_SUBTEST_7( selfadjointeigensolver(Matrix<double,2,2>()) );
}
+
+ CALL_SUBTEST_13( bug_854<0>() );
+ CALL_SUBTEST_13( bug_1014<0>() );
+ CALL_SUBTEST_13( bug_1204<0>() );
+ CALL_SUBTEST_13( bug_1225<0>() );
// Test problem size constructors
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
diff --git a/test/evaluator_common.h b/test/evaluator_common.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/test/evaluator_common.h
diff --git a/test/evaluators.cpp b/test/evaluators.cpp
new file mode 100644
index 000000000..aed5a05a7
--- /dev/null
+++ b/test/evaluators.cpp
@@ -0,0 +1,499 @@
+
+#include "main.h"
+
+namespace Eigen {
+
+ template<typename Lhs,typename Rhs>
+ const Product<Lhs,Rhs>
+ prod(const Lhs& lhs, const Rhs& rhs)
+ {
+ return Product<Lhs,Rhs>(lhs,rhs);
+ }
+
+ template<typename Lhs,typename Rhs>
+ const Product<Lhs,Rhs,LazyProduct>
+ lazyprod(const Lhs& lhs, const Rhs& rhs)
+ {
+ return Product<Lhs,Rhs,LazyProduct>(lhs,rhs);
+ }
+
+ template<typename DstXprType, typename SrcXprType>
+ EIGEN_STRONG_INLINE
+ DstXprType& copy_using_evaluator(const EigenBase<DstXprType> &dst, const SrcXprType &src)
+ {
+ call_assignment(dst.const_cast_derived(), src.derived(), internal::assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar>());
+ return dst.const_cast_derived();
+ }
+
+ template<typename DstXprType, template <typename> class StorageBase, typename SrcXprType>
+ EIGEN_STRONG_INLINE
+ const DstXprType& copy_using_evaluator(const NoAlias<DstXprType, StorageBase>& dst, const SrcXprType &src)
+ {
+ call_assignment(dst, src.derived(), internal::assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar>());
+ return dst.expression();
+ }
+
+ template<typename DstXprType, typename SrcXprType>
+ EIGEN_STRONG_INLINE
+ DstXprType& copy_using_evaluator(const PlainObjectBase<DstXprType> &dst, const SrcXprType &src)
+ {
+ #ifdef EIGEN_NO_AUTOMATIC_RESIZING
+ eigen_assert((dst.size()==0 || (IsVectorAtCompileTime ? (dst.size() == src.size())
+ : (dst.rows() == src.rows() && dst.cols() == src.cols())))
+ && "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined");
+ #else
+ dst.const_cast_derived().resizeLike(src.derived());
+ #endif
+
+ call_assignment(dst.const_cast_derived(), src.derived(), internal::assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar>());
+ return dst.const_cast_derived();
+ }
+
+ template<typename DstXprType, typename SrcXprType>
+ void add_assign_using_evaluator(const DstXprType& dst, const SrcXprType& src)
+ {
+ typedef typename DstXprType::Scalar Scalar;
+ call_assignment(const_cast<DstXprType&>(dst), src.derived(), internal::add_assign_op<Scalar,typename SrcXprType::Scalar>());
+ }
+
+ template<typename DstXprType, typename SrcXprType>
+ void subtract_assign_using_evaluator(const DstXprType& dst, const SrcXprType& src)
+ {
+ typedef typename DstXprType::Scalar Scalar;
+ call_assignment(const_cast<DstXprType&>(dst), src.derived(), internal::sub_assign_op<Scalar,typename SrcXprType::Scalar>());
+ }
+
+ template<typename DstXprType, typename SrcXprType>
+ void multiply_assign_using_evaluator(const DstXprType& dst, const SrcXprType& src)
+ {
+ typedef typename DstXprType::Scalar Scalar;
+ call_assignment(dst.const_cast_derived(), src.derived(), internal::mul_assign_op<Scalar,typename SrcXprType::Scalar>());
+ }
+
+ template<typename DstXprType, typename SrcXprType>
+ void divide_assign_using_evaluator(const DstXprType& dst, const SrcXprType& src)
+ {
+ typedef typename DstXprType::Scalar Scalar;
+ call_assignment(dst.const_cast_derived(), src.derived(), internal::div_assign_op<Scalar,typename SrcXprType::Scalar>());
+ }
+
+ template<typename DstXprType, typename SrcXprType>
+ void swap_using_evaluator(const DstXprType& dst, const SrcXprType& src)
+ {
+ typedef typename DstXprType::Scalar Scalar;
+ call_assignment(dst.const_cast_derived(), src.const_cast_derived(), internal::swap_assign_op<Scalar>());
+ }
+
+ namespace internal {
+ template<typename Dst, template <typename> class StorageBase, typename Src, typename Func>
+ EIGEN_DEVICE_FUNC void call_assignment(const NoAlias<Dst,StorageBase>& dst, const Src& src, const Func& func)
+ {
+ call_assignment_no_alias(dst.expression(), src, func);
+ }
+ }
+
+}
+
+template<typename XprType> long get_cost(const XprType& ) { return Eigen::internal::evaluator<XprType>::CoeffReadCost; }
+
+using namespace std;
+
+#define VERIFY_IS_APPROX_EVALUATOR(DEST,EXPR) VERIFY_IS_APPROX(copy_using_evaluator(DEST,(EXPR)), (EXPR).eval());
+#define VERIFY_IS_APPROX_EVALUATOR2(DEST,EXPR,REF) VERIFY_IS_APPROX(copy_using_evaluator(DEST,(EXPR)), (REF).eval());
+
+void test_evaluators()
+{
+ // Testing Matrix evaluator and Transpose
+ Vector2d v = Vector2d::Random();
+ const Vector2d v_const(v);
+ Vector2d v2;
+ RowVector2d w;
+
+ VERIFY_IS_APPROX_EVALUATOR(v2, v);
+ VERIFY_IS_APPROX_EVALUATOR(v2, v_const);
+
+ // Testing Transpose
+ VERIFY_IS_APPROX_EVALUATOR(w, v.transpose()); // Transpose as rvalue
+ VERIFY_IS_APPROX_EVALUATOR(w, v_const.transpose());
+
+ copy_using_evaluator(w.transpose(), v); // Transpose as lvalue
+ VERIFY_IS_APPROX(w,v.transpose().eval());
+
+ copy_using_evaluator(w.transpose(), v_const);
+ VERIFY_IS_APPROX(w,v_const.transpose().eval());
+
+ // Testing Array evaluator
+ {
+ ArrayXXf a(2,3);
+ ArrayXXf b(3,2);
+ a << 1,2,3, 4,5,6;
+ const ArrayXXf a_const(a);
+
+ VERIFY_IS_APPROX_EVALUATOR(b, a.transpose());
+
+ VERIFY_IS_APPROX_EVALUATOR(b, a_const.transpose());
+
+ // Testing CwiseNullaryOp evaluator
+ copy_using_evaluator(w, RowVector2d::Random());
+ VERIFY((w.array() >= -1).all() && (w.array() <= 1).all()); // not easy to test ...
+
+ VERIFY_IS_APPROX_EVALUATOR(w, RowVector2d::Zero());
+
+ VERIFY_IS_APPROX_EVALUATOR(w, RowVector2d::Constant(3));
+
+ // mix CwiseNullaryOp and transpose
+ VERIFY_IS_APPROX_EVALUATOR(w, Vector2d::Zero().transpose());
+ }
+
+ {
+ // test product expressions
+ int s = internal::random<int>(1,100);
+ MatrixXf a(s,s), b(s,s), c(s,s), d(s,s);
+ a.setRandom();
+ b.setRandom();
+ c.setRandom();
+ d.setRandom();
+ VERIFY_IS_APPROX_EVALUATOR(d, (a + b));
+ VERIFY_IS_APPROX_EVALUATOR(d, (a + b).transpose());
+ VERIFY_IS_APPROX_EVALUATOR2(d, prod(a,b), a*b);
+ VERIFY_IS_APPROX_EVALUATOR2(d.noalias(), prod(a,b), a*b);
+ VERIFY_IS_APPROX_EVALUATOR2(d, prod(a,b) + c, a*b + c);
+ VERIFY_IS_APPROX_EVALUATOR2(d, s * prod(a,b), s * a*b);
+ VERIFY_IS_APPROX_EVALUATOR2(d, prod(a,b).transpose(), (a*b).transpose());
+ VERIFY_IS_APPROX_EVALUATOR2(d, prod(a,b) + prod(b,c), a*b + b*c);
+
+ // check that prod works even with aliasing present
+ c = a*a;
+ copy_using_evaluator(a, prod(a,a));
+ VERIFY_IS_APPROX(a,c);
+
+ // check compound assignment of products
+ d = c;
+ add_assign_using_evaluator(c.noalias(), prod(a,b));
+ d.noalias() += a*b;
+ VERIFY_IS_APPROX(c, d);
+
+ d = c;
+ subtract_assign_using_evaluator(c.noalias(), prod(a,b));
+ d.noalias() -= a*b;
+ VERIFY_IS_APPROX(c, d);
+ }
+
+ {
+ // test product with all possible sizes
+ int s = internal::random<int>(1,100);
+ Matrix<float, 1, 1> m11, res11; m11.setRandom(1,1);
+ Matrix<float, 1, 4> m14, res14; m14.setRandom(1,4);
+ Matrix<float, 1,Dynamic> m1X, res1X; m1X.setRandom(1,s);
+ Matrix<float, 4, 1> m41, res41; m41.setRandom(4,1);
+ Matrix<float, 4, 4> m44, res44; m44.setRandom(4,4);
+ Matrix<float, 4,Dynamic> m4X, res4X; m4X.setRandom(4,s);
+ Matrix<float,Dynamic, 1> mX1, resX1; mX1.setRandom(s,1);
+ Matrix<float,Dynamic, 4> mX4, resX4; mX4.setRandom(s,4);
+ Matrix<float,Dynamic,Dynamic> mXX, resXX; mXX.setRandom(s,s);
+
+ VERIFY_IS_APPROX_EVALUATOR2(res11, prod(m11,m11), m11*m11);
+ VERIFY_IS_APPROX_EVALUATOR2(res11, prod(m14,m41), m14*m41);
+ VERIFY_IS_APPROX_EVALUATOR2(res11, prod(m1X,mX1), m1X*mX1);
+ VERIFY_IS_APPROX_EVALUATOR2(res14, prod(m11,m14), m11*m14);
+ VERIFY_IS_APPROX_EVALUATOR2(res14, prod(m14,m44), m14*m44);
+ VERIFY_IS_APPROX_EVALUATOR2(res14, prod(m1X,mX4), m1X*mX4);
+ VERIFY_IS_APPROX_EVALUATOR2(res1X, prod(m11,m1X), m11*m1X);
+ VERIFY_IS_APPROX_EVALUATOR2(res1X, prod(m14,m4X), m14*m4X);
+ VERIFY_IS_APPROX_EVALUATOR2(res1X, prod(m1X,mXX), m1X*mXX);
+ VERIFY_IS_APPROX_EVALUATOR2(res41, prod(m41,m11), m41*m11);
+ VERIFY_IS_APPROX_EVALUATOR2(res41, prod(m44,m41), m44*m41);
+ VERIFY_IS_APPROX_EVALUATOR2(res41, prod(m4X,mX1), m4X*mX1);
+ VERIFY_IS_APPROX_EVALUATOR2(res44, prod(m41,m14), m41*m14);
+ VERIFY_IS_APPROX_EVALUATOR2(res44, prod(m44,m44), m44*m44);
+ VERIFY_IS_APPROX_EVALUATOR2(res44, prod(m4X,mX4), m4X*mX4);
+ VERIFY_IS_APPROX_EVALUATOR2(res4X, prod(m41,m1X), m41*m1X);
+ VERIFY_IS_APPROX_EVALUATOR2(res4X, prod(m44,m4X), m44*m4X);
+ VERIFY_IS_APPROX_EVALUATOR2(res4X, prod(m4X,mXX), m4X*mXX);
+ VERIFY_IS_APPROX_EVALUATOR2(resX1, prod(mX1,m11), mX1*m11);
+ VERIFY_IS_APPROX_EVALUATOR2(resX1, prod(mX4,m41), mX4*m41);
+ VERIFY_IS_APPROX_EVALUATOR2(resX1, prod(mXX,mX1), mXX*mX1);
+ VERIFY_IS_APPROX_EVALUATOR2(resX4, prod(mX1,m14), mX1*m14);
+ VERIFY_IS_APPROX_EVALUATOR2(resX4, prod(mX4,m44), mX4*m44);
+ VERIFY_IS_APPROX_EVALUATOR2(resX4, prod(mXX,mX4), mXX*mX4);
+ VERIFY_IS_APPROX_EVALUATOR2(resXX, prod(mX1,m1X), mX1*m1X);
+ VERIFY_IS_APPROX_EVALUATOR2(resXX, prod(mX4,m4X), mX4*m4X);
+ VERIFY_IS_APPROX_EVALUATOR2(resXX, prod(mXX,mXX), mXX*mXX);
+ }
+
+ {
+ ArrayXXf a(2,3);
+ ArrayXXf b(3,2);
+ a << 1,2,3, 4,5,6;
+ const ArrayXXf a_const(a);
+
+ // this does not work because Random is eval-before-nested:
+ // copy_using_evaluator(w, Vector2d::Random().transpose());
+
+ // test CwiseUnaryOp
+ VERIFY_IS_APPROX_EVALUATOR(v2, 3 * v);
+ VERIFY_IS_APPROX_EVALUATOR(w, (3 * v).transpose());
+ VERIFY_IS_APPROX_EVALUATOR(b, (a + 3).transpose());
+ VERIFY_IS_APPROX_EVALUATOR(b, (2 * a_const + 3).transpose());
+
+ // test CwiseBinaryOp
+ VERIFY_IS_APPROX_EVALUATOR(v2, v + Vector2d::Ones());
+ VERIFY_IS_APPROX_EVALUATOR(w, (v + Vector2d::Ones()).transpose().cwiseProduct(RowVector2d::Constant(3)));
+
+ // dynamic matrices and arrays
+ MatrixXd mat1(6,6), mat2(6,6);
+ VERIFY_IS_APPROX_EVALUATOR(mat1, MatrixXd::Identity(6,6));
+ VERIFY_IS_APPROX_EVALUATOR(mat2, mat1);
+ copy_using_evaluator(mat2.transpose(), mat1);
+ VERIFY_IS_APPROX(mat2.transpose(), mat1);
+
+ ArrayXXd arr1(6,6), arr2(6,6);
+ VERIFY_IS_APPROX_EVALUATOR(arr1, ArrayXXd::Constant(6,6, 3.0));
+ VERIFY_IS_APPROX_EVALUATOR(arr2, arr1);
+
+ // test automatic resizing
+ mat2.resize(3,3);
+ VERIFY_IS_APPROX_EVALUATOR(mat2, mat1);
+ arr2.resize(9,9);
+ VERIFY_IS_APPROX_EVALUATOR(arr2, arr1);
+
+ // test direct traversal
+ Matrix3f m3;
+ Array33f a3;
+ VERIFY_IS_APPROX_EVALUATOR(m3, Matrix3f::Identity()); // matrix, nullary
+ // TODO: find a way to test direct traversal with array
+ VERIFY_IS_APPROX_EVALUATOR(m3.transpose(), Matrix3f::Identity().transpose()); // transpose
+ VERIFY_IS_APPROX_EVALUATOR(m3, 2 * Matrix3f::Identity()); // unary
+ VERIFY_IS_APPROX_EVALUATOR(m3, Matrix3f::Identity() + Matrix3f::Zero()); // binary
+ VERIFY_IS_APPROX_EVALUATOR(m3.block(0,0,2,2), Matrix3f::Identity().block(1,1,2,2)); // block
+
+ // test linear traversal
+ VERIFY_IS_APPROX_EVALUATOR(m3, Matrix3f::Zero()); // matrix, nullary
+ VERIFY_IS_APPROX_EVALUATOR(a3, Array33f::Zero()); // array
+ VERIFY_IS_APPROX_EVALUATOR(m3.transpose(), Matrix3f::Zero().transpose()); // transpose
+ VERIFY_IS_APPROX_EVALUATOR(m3, 2 * Matrix3f::Zero()); // unary
+ VERIFY_IS_APPROX_EVALUATOR(m3, Matrix3f::Zero() + m3); // binary
+
+ // test inner vectorization
+ Matrix4f m4, m4src = Matrix4f::Random();
+ Array44f a4, a4src = Matrix4f::Random();
+ VERIFY_IS_APPROX_EVALUATOR(m4, m4src); // matrix
+ VERIFY_IS_APPROX_EVALUATOR(a4, a4src); // array
+ VERIFY_IS_APPROX_EVALUATOR(m4.transpose(), m4src.transpose()); // transpose
+ // TODO: find out why Matrix4f::Zero() does not allow inner vectorization
+ VERIFY_IS_APPROX_EVALUATOR(m4, 2 * m4src); // unary
+ VERIFY_IS_APPROX_EVALUATOR(m4, m4src + m4src); // binary
+
+ // test linear vectorization
+ MatrixXf mX(6,6), mXsrc = MatrixXf::Random(6,6);
+ ArrayXXf aX(6,6), aXsrc = ArrayXXf::Random(6,6);
+ VERIFY_IS_APPROX_EVALUATOR(mX, mXsrc); // matrix
+ VERIFY_IS_APPROX_EVALUATOR(aX, aXsrc); // array
+ VERIFY_IS_APPROX_EVALUATOR(mX.transpose(), mXsrc.transpose()); // transpose
+ VERIFY_IS_APPROX_EVALUATOR(mX, MatrixXf::Zero(6,6)); // nullary
+ VERIFY_IS_APPROX_EVALUATOR(mX, 2 * mXsrc); // unary
+ VERIFY_IS_APPROX_EVALUATOR(mX, mXsrc + mXsrc); // binary
+
+ // test blocks and slice vectorization
+ VERIFY_IS_APPROX_EVALUATOR(m4, (mXsrc.block<4,4>(1,0)));
+ VERIFY_IS_APPROX_EVALUATOR(aX, ArrayXXf::Constant(10, 10, 3.0).block(2, 3, 6, 6));
+
+ Matrix4f m4ref = m4;
+ copy_using_evaluator(m4.block(1, 1, 2, 3), m3.bottomRows(2));
+ m4ref.block(1, 1, 2, 3) = m3.bottomRows(2);
+ VERIFY_IS_APPROX(m4, m4ref);
+
+ mX.setIdentity(20,20);
+ MatrixXf mXref = MatrixXf::Identity(20,20);
+ mXsrc = MatrixXf::Random(9,12);
+ copy_using_evaluator(mX.block(4, 4, 9, 12), mXsrc);
+ mXref.block(4, 4, 9, 12) = mXsrc;
+ VERIFY_IS_APPROX(mX, mXref);
+
+ // test Map
+ const float raw[3] = {1,2,3};
+ float buffer[3] = {0,0,0};
+ Vector3f v3;
+ Array3f a3f;
+ VERIFY_IS_APPROX_EVALUATOR(v3, Map<const Vector3f>(raw));
+ VERIFY_IS_APPROX_EVALUATOR(a3f, Map<const Array3f>(raw));
+ Vector3f::Map(buffer) = 2*v3;
+ VERIFY(buffer[0] == 2);
+ VERIFY(buffer[1] == 4);
+ VERIFY(buffer[2] == 6);
+
+ // test CwiseUnaryView
+ mat1.setRandom();
+ mat2.setIdentity();
+ MatrixXcd matXcd(6,6), matXcd_ref(6,6);
+ copy_using_evaluator(matXcd.real(), mat1);
+ copy_using_evaluator(matXcd.imag(), mat2);
+ matXcd_ref.real() = mat1;
+ matXcd_ref.imag() = mat2;
+ VERIFY_IS_APPROX(matXcd, matXcd_ref);
+
+ // test Select
+ VERIFY_IS_APPROX_EVALUATOR(aX, (aXsrc > 0).select(aXsrc, -aXsrc));
+
+ // test Replicate
+ mXsrc = MatrixXf::Random(6, 6);
+ VectorXf vX = VectorXf::Random(6);
+ mX.resize(6, 6);
+ VERIFY_IS_APPROX_EVALUATOR(mX, mXsrc.colwise() + vX);
+ matXcd.resize(12, 12);
+ VERIFY_IS_APPROX_EVALUATOR(matXcd, matXcd_ref.replicate(2,2));
+ VERIFY_IS_APPROX_EVALUATOR(matXcd, (matXcd_ref.replicate<2,2>()));
+
+ // test partial reductions
+ VectorXd vec1(6);
+ VERIFY_IS_APPROX_EVALUATOR(vec1, mat1.rowwise().sum());
+ VERIFY_IS_APPROX_EVALUATOR(vec1, mat1.colwise().sum().transpose());
+
+ // test MatrixWrapper and ArrayWrapper
+ mat1.setRandom(6,6);
+ arr1.setRandom(6,6);
+ VERIFY_IS_APPROX_EVALUATOR(mat2, arr1.matrix());
+ VERIFY_IS_APPROX_EVALUATOR(arr2, mat1.array());
+ VERIFY_IS_APPROX_EVALUATOR(mat2, (arr1 + 2).matrix());
+ VERIFY_IS_APPROX_EVALUATOR(arr2, mat1.array() + 2);
+ mat2.array() = arr1 * arr1;
+ VERIFY_IS_APPROX(mat2, (arr1 * arr1).matrix());
+ arr2.matrix() = MatrixXd::Identity(6,6);
+ VERIFY_IS_APPROX(arr2, MatrixXd::Identity(6,6).array());
+
+ // test Reverse
+ VERIFY_IS_APPROX_EVALUATOR(arr2, arr1.reverse());
+ VERIFY_IS_APPROX_EVALUATOR(arr2, arr1.colwise().reverse());
+ VERIFY_IS_APPROX_EVALUATOR(arr2, arr1.rowwise().reverse());
+ arr2.reverse() = arr1;
+ VERIFY_IS_APPROX(arr2, arr1.reverse());
+ mat2.array() = mat1.array().reverse();
+ VERIFY_IS_APPROX(mat2.array(), mat1.array().reverse());
+
+ // test Diagonal
+ VERIFY_IS_APPROX_EVALUATOR(vec1, mat1.diagonal());
+ vec1.resize(5);
+ VERIFY_IS_APPROX_EVALUATOR(vec1, mat1.diagonal(1));
+ VERIFY_IS_APPROX_EVALUATOR(vec1, mat1.diagonal<-1>());
+ vec1.setRandom();
+
+ mat2 = mat1;
+ copy_using_evaluator(mat1.diagonal(1), vec1);
+ mat2.diagonal(1) = vec1;
+ VERIFY_IS_APPROX(mat1, mat2);
+
+ copy_using_evaluator(mat1.diagonal<-1>(), mat1.diagonal(1));
+ mat2.diagonal<-1>() = mat2.diagonal(1);
+ VERIFY_IS_APPROX(mat1, mat2);
+ }
+
+ {
+ // test swapping
+ MatrixXd mat1, mat2, mat1ref, mat2ref;
+ mat1ref = mat1 = MatrixXd::Random(6, 6);
+ mat2ref = mat2 = 2 * mat1 + MatrixXd::Identity(6, 6);
+ swap_using_evaluator(mat1, mat2);
+ mat1ref.swap(mat2ref);
+ VERIFY_IS_APPROX(mat1, mat1ref);
+ VERIFY_IS_APPROX(mat2, mat2ref);
+
+ swap_using_evaluator(mat1.block(0, 0, 3, 3), mat2.block(3, 3, 3, 3));
+ mat1ref.block(0, 0, 3, 3).swap(mat2ref.block(3, 3, 3, 3));
+ VERIFY_IS_APPROX(mat1, mat1ref);
+ VERIFY_IS_APPROX(mat2, mat2ref);
+
+ swap_using_evaluator(mat1.row(2), mat2.col(3).transpose());
+ mat1.row(2).swap(mat2.col(3).transpose());
+ VERIFY_IS_APPROX(mat1, mat1ref);
+ VERIFY_IS_APPROX(mat2, mat2ref);
+ }
+
+ {
+ // test compound assignment
+ const Matrix4d mat_const = Matrix4d::Random();
+ Matrix4d mat, mat_ref;
+ mat = mat_ref = Matrix4d::Identity();
+ add_assign_using_evaluator(mat, mat_const);
+ mat_ref += mat_const;
+ VERIFY_IS_APPROX(mat, mat_ref);
+
+ subtract_assign_using_evaluator(mat.row(1), 2*mat.row(2));
+ mat_ref.row(1) -= 2*mat_ref.row(2);
+ VERIFY_IS_APPROX(mat, mat_ref);
+
+ const ArrayXXf arr_const = ArrayXXf::Random(5,3);
+ ArrayXXf arr, arr_ref;
+ arr = arr_ref = ArrayXXf::Constant(5, 3, 0.5);
+ multiply_assign_using_evaluator(arr, arr_const);
+ arr_ref *= arr_const;
+ VERIFY_IS_APPROX(arr, arr_ref);
+
+ divide_assign_using_evaluator(arr.row(1), arr.row(2) + 1);
+ arr_ref.row(1) /= (arr_ref.row(2) + 1);
+ VERIFY_IS_APPROX(arr, arr_ref);
+ }
+
+ {
+ // test triangular shapes
+ MatrixXd A = MatrixXd::Random(6,6), B(6,6), C(6,6), D(6,6);
+ A.setRandom();B.setRandom();
+ VERIFY_IS_APPROX_EVALUATOR2(B, A.triangularView<Upper>(), MatrixXd(A.triangularView<Upper>()));
+
+ A.setRandom();B.setRandom();
+ VERIFY_IS_APPROX_EVALUATOR2(B, A.triangularView<UnitLower>(), MatrixXd(A.triangularView<UnitLower>()));
+
+ A.setRandom();B.setRandom();
+ VERIFY_IS_APPROX_EVALUATOR2(B, A.triangularView<UnitUpper>(), MatrixXd(A.triangularView<UnitUpper>()));
+
+ A.setRandom();B.setRandom();
+ C = B; C.triangularView<Upper>() = A;
+ copy_using_evaluator(B.triangularView<Upper>(), A);
+ VERIFY(B.isApprox(C) && "copy_using_evaluator(B.triangularView<Upper>(), A)");
+
+ A.setRandom();B.setRandom();
+ C = B; C.triangularView<Lower>() = A.triangularView<Lower>();
+ copy_using_evaluator(B.triangularView<Lower>(), A.triangularView<Lower>());
+ VERIFY(B.isApprox(C) && "copy_using_evaluator(B.triangularView<Lower>(), A.triangularView<Lower>())");
+
+
+ A.setRandom();B.setRandom();
+ C = B; C.triangularView<Lower>() = A.triangularView<Upper>().transpose();
+ copy_using_evaluator(B.triangularView<Lower>(), A.triangularView<Upper>().transpose());
+ VERIFY(B.isApprox(C) && "copy_using_evaluator(B.triangularView<Lower>(), A.triangularView<Lower>().transpose())");
+
+
+ A.setRandom();B.setRandom(); C = B; D = A;
+ C.triangularView<Upper>().swap(D.triangularView<Upper>());
+ swap_using_evaluator(B.triangularView<Upper>(), A.triangularView<Upper>());
+ VERIFY(B.isApprox(C) && "swap_using_evaluator(B.triangularView<Upper>(), A.triangularView<Upper>())");
+
+
+ VERIFY_IS_APPROX_EVALUATOR2(B, prod(A.triangularView<Upper>(),A), MatrixXd(A.triangularView<Upper>()*A));
+
+ VERIFY_IS_APPROX_EVALUATOR2(B, prod(A.selfadjointView<Upper>(),A), MatrixXd(A.selfadjointView<Upper>()*A));
+ }
+
+ {
+ // test diagonal shapes
+ VectorXd d = VectorXd::Random(6);
+ MatrixXd A = MatrixXd::Random(6,6), B(6,6);
+ A.setRandom();B.setRandom();
+
+ VERIFY_IS_APPROX_EVALUATOR2(B, lazyprod(d.asDiagonal(),A), MatrixXd(d.asDiagonal()*A));
+ VERIFY_IS_APPROX_EVALUATOR2(B, lazyprod(A,d.asDiagonal()), MatrixXd(A*d.asDiagonal()));
+ }
+
+ {
+ // test CoeffReadCost
+ Matrix4d a, b;
+ VERIFY_IS_EQUAL( get_cost(a), 1 );
+ VERIFY_IS_EQUAL( get_cost(a+b), 3);
+ VERIFY_IS_EQUAL( get_cost(2*a+b), 4);
+ VERIFY_IS_EQUAL( get_cost(a*b), 1);
+ VERIFY_IS_EQUAL( get_cost(a.lazyProduct(b)), 15);
+ VERIFY_IS_EQUAL( get_cost(a*(a*b)), 1);
+ VERIFY_IS_EQUAL( get_cost(a.lazyProduct(a*b)), 15);
+ VERIFY_IS_EQUAL( get_cost(a*(a+b)), 1);
+ VERIFY_IS_EQUAL( get_cost(a.lazyProduct(a+b)), 15);
+ }
+}
diff --git a/test/fastmath.cpp b/test/fastmath.cpp
new file mode 100644
index 000000000..cc5db0746
--- /dev/null
+++ b/test/fastmath.cpp
@@ -0,0 +1,99 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// 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/.
+
+#include "main.h"
+
+void check(bool b, bool ref)
+{
+ std::cout << b;
+ if(b==ref)
+ std::cout << " OK ";
+ else
+ std::cout << " BAD ";
+}
+
+#if EIGEN_COMP_MSVC && EIGEN_COMP_MSVC < 1800
+namespace std {
+ template<typename T> bool (isfinite)(T x) { return _finite(x); }
+ template<typename T> bool (isnan)(T x) { return _isnan(x); }
+ template<typename T> bool (isinf)(T x) { return _fpclass(x)==_FPCLASS_NINF || _fpclass(x)==_FPCLASS_PINF; }
+}
+#endif
+
+template<typename T>
+void check_inf_nan(bool dryrun) {
+ Matrix<T,Dynamic,1> m(10);
+ m.setRandom();
+ m(3) = std::numeric_limits<T>::quiet_NaN();
+
+ if(dryrun)
+ {
+ std::cout << "std::isfinite(" << m(3) << ") = "; check((std::isfinite)(m(3)),false); std::cout << " ; numext::isfinite = "; check((numext::isfinite)(m(3)), false); std::cout << "\n";
+ std::cout << "std::isinf(" << m(3) << ") = "; check((std::isinf)(m(3)),false); std::cout << " ; numext::isinf = "; check((numext::isinf)(m(3)), false); std::cout << "\n";
+ std::cout << "std::isnan(" << m(3) << ") = "; check((std::isnan)(m(3)),true); std::cout << " ; numext::isnan = "; check((numext::isnan)(m(3)), true); std::cout << "\n";
+ std::cout << "allFinite: "; check(m.allFinite(), 0); std::cout << "\n";
+ std::cout << "hasNaN: "; check(m.hasNaN(), 1); std::cout << "\n";
+ std::cout << "\n";
+ }
+ else
+ {
+ VERIFY( !(numext::isfinite)(m(3)) );
+ VERIFY( !(numext::isinf)(m(3)) );
+ VERIFY( (numext::isnan)(m(3)) );
+ VERIFY( !m.allFinite() );
+ VERIFY( m.hasNaN() );
+ }
+ T hidden_zero = (std::numeric_limits<T>::min)()*(std::numeric_limits<T>::min)();
+ m(4) /= hidden_zero;
+ if(dryrun)
+ {
+ std::cout << "std::isfinite(" << m(4) << ") = "; check((std::isfinite)(m(4)),false); std::cout << " ; numext::isfinite = "; check((numext::isfinite)(m(4)), false); std::cout << "\n";
+ std::cout << "std::isinf(" << m(4) << ") = "; check((std::isinf)(m(4)),true); std::cout << " ; numext::isinf = "; check((numext::isinf)(m(4)), true); std::cout << "\n";
+ std::cout << "std::isnan(" << m(4) << ") = "; check((std::isnan)(m(4)),false); std::cout << " ; numext::isnan = "; check((numext::isnan)(m(4)), false); std::cout << "\n";
+ std::cout << "allFinite: "; check(m.allFinite(), 0); std::cout << "\n";
+ std::cout << "hasNaN: "; check(m.hasNaN(), 1); std::cout << "\n";
+ std::cout << "\n";
+ }
+ else
+ {
+ VERIFY( !(numext::isfinite)(m(4)) );
+ VERIFY( (numext::isinf)(m(4)) );
+ VERIFY( !(numext::isnan)(m(4)) );
+ VERIFY( !m.allFinite() );
+ VERIFY( m.hasNaN() );
+ }
+ m(3) = 0;
+ if(dryrun)
+ {
+ std::cout << "std::isfinite(" << m(3) << ") = "; check((std::isfinite)(m(3)),true); std::cout << " ; numext::isfinite = "; check((numext::isfinite)(m(3)), true); std::cout << "\n";
+ std::cout << "std::isinf(" << m(3) << ") = "; check((std::isinf)(m(3)),false); std::cout << " ; numext::isinf = "; check((numext::isinf)(m(3)), false); std::cout << "\n";
+ std::cout << "std::isnan(" << m(3) << ") = "; check((std::isnan)(m(3)),false); std::cout << " ; numext::isnan = "; check((numext::isnan)(m(3)), false); std::cout << "\n";
+ std::cout << "allFinite: "; check(m.allFinite(), 0); std::cout << "\n";
+ std::cout << "hasNaN: "; check(m.hasNaN(), 0); std::cout << "\n";
+ std::cout << "\n\n";
+ }
+ else
+ {
+ VERIFY( (numext::isfinite)(m(3)) );
+ VERIFY( !(numext::isinf)(m(3)) );
+ VERIFY( !(numext::isnan)(m(3)) );
+ VERIFY( !m.allFinite() );
+ VERIFY( !m.hasNaN() );
+ }
+}
+
+void test_fastmath() {
+ std::cout << "*** float *** \n\n"; check_inf_nan<float>(true);
+ std::cout << "*** double ***\n\n"; check_inf_nan<double>(true);
+ std::cout << "*** long double *** \n\n"; check_inf_nan<long double>(true);
+
+ check_inf_nan<float>(false);
+ check_inf_nan<double>(false);
+ check_inf_nan<long double>(false);
+}
diff --git a/test/first_aligned.cpp b/test/first_aligned.cpp
index 467f94510..ae2d4bc42 100644
--- a/test/first_aligned.cpp
+++ b/test/first_aligned.cpp
@@ -13,7 +13,7 @@ template<typename Scalar>
void test_first_aligned_helper(Scalar *array, int size)
{
const int packet_size = sizeof(Scalar) * internal::packet_traits<Scalar>::size;
- VERIFY(((size_t(array) + sizeof(Scalar) * internal::first_aligned(array, size)) % packet_size) == 0);
+ VERIFY(((size_t(array) + sizeof(Scalar) * internal::first_default_aligned(array, size)) % packet_size) == 0);
}
template<typename Scalar>
@@ -21,7 +21,7 @@ void test_none_aligned_helper(Scalar *array, int size)
{
EIGEN_UNUSED_VARIABLE(array);
EIGEN_UNUSED_VARIABLE(size);
- VERIFY(internal::packet_traits<Scalar>::size == 1 || internal::first_aligned(array, size) == size);
+ VERIFY(internal::packet_traits<Scalar>::size == 1 || internal::first_default_aligned(array, size) == size);
}
struct some_non_vectorizable_type { float x; };
@@ -41,7 +41,7 @@ void test_first_aligned()
test_first_aligned_helper(array_double+1, 50);
test_first_aligned_helper(array_double+2, 50);
- double *array_double_plus_4_bytes = (double*)(size_t(array_double)+4);
+ double *array_double_plus_4_bytes = (double*)(internal::UIntPtr(array_double)+4);
test_none_aligned_helper(array_double_plus_4_bytes, 50);
test_none_aligned_helper(array_double_plus_4_bytes+1, 50);
diff --git a/test/geo_alignedbox.cpp b/test/geo_alignedbox.cpp
index 8e36adbe3..d2339a651 100644
--- a/test/geo_alignedbox.cpp
+++ b/test/geo_alignedbox.cpp
@@ -16,7 +16,7 @@
using namespace std;
template<typename T> EIGEN_DONT_INLINE
-void kill_extra_precision(T& x) { eigen_assert(&x != 0); }
+void kill_extra_precision(T& x) { eigen_assert((void*)(&x) != (void*)0); }
template<typename BoxType> void alignedbox(const BoxType& _box)
@@ -48,12 +48,21 @@ template<typename BoxType> void alignedbox(const BoxType& _box)
b0.extend(p0);
b0.extend(p1);
VERIFY(b0.contains(p0*s1+(Scalar(1)-s1)*p1));
+ VERIFY(b0.contains(b0.center()));
+ VERIFY_IS_APPROX(b0.center(),(p0+p1)/Scalar(2));
(b2 = b0).extend(b1);
VERIFY(b2.contains(b0));
VERIFY(b2.contains(b1));
VERIFY_IS_APPROX(b2.clamp(b0), b0);
+ // intersection
+ BoxType box1(VectorType::Random(dim));
+ box1.extend(VectorType::Random(dim));
+ BoxType box2(VectorType::Random(dim));
+ box2.extend(VectorType::Random(dim));
+
+ VERIFY(box1.intersects(box2) == !box1.intersection(box2).isEmpty());
// alignment -- make sure there is no memory alignment assertion
BoxType *bp0 = new BoxType(dim);
@@ -172,6 +181,8 @@ void test_geo_alignedbox()
CALL_SUBTEST_9( alignedbox(AlignedBox1i()) );
CALL_SUBTEST_10( alignedbox(AlignedBox2i()) );
CALL_SUBTEST_11( alignedbox(AlignedBox3i()) );
+
+ CALL_SUBTEST_14( alignedbox(AlignedBox<double,Dynamic>(4)) );
}
CALL_SUBTEST_12( specificTest1() );
CALL_SUBTEST_13( specificTest2() );
diff --git a/test/geo_eulerangles.cpp b/test/geo_eulerangles.cpp
index b4830bd41..932ebe773 100644
--- a/test/geo_eulerangles.cpp
+++ b/test/geo_eulerangles.cpp
@@ -26,16 +26,16 @@ void verify_euler(const Matrix<Scalar,3,1>& ea, int i, int j, int k)
VERIFY_IS_APPROX(m, mbis);
/* If I==K, and ea[1]==0, then there no unique solution. */
/* The remark apply in the case where I!=K, and |ea[1]| is close to pi/2. */
- if( (i!=k || ea[1]!=0) && (i==k || !internal::isApprox(abs(ea[1]),Scalar(M_PI/2),test_precision<Scalar>())) )
+ if( (i!=k || ea[1]!=0) && (i==k || !internal::isApprox(abs(ea[1]),Scalar(EIGEN_PI/2),test_precision<Scalar>())) )
VERIFY((ea-eabis).norm() <= test_precision<Scalar>());
// approx_or_less_than does not work for 0
VERIFY(0 < eabis[0] || test_isMuchSmallerThan(eabis[0], Scalar(1)));
- VERIFY_IS_APPROX_OR_LESS_THAN(eabis[0], Scalar(M_PI));
- VERIFY_IS_APPROX_OR_LESS_THAN(-Scalar(M_PI), eabis[1]);
- VERIFY_IS_APPROX_OR_LESS_THAN(eabis[1], Scalar(M_PI));
- VERIFY_IS_APPROX_OR_LESS_THAN(-Scalar(M_PI), eabis[2]);
- VERIFY_IS_APPROX_OR_LESS_THAN(eabis[2], Scalar(M_PI));
+ VERIFY_IS_APPROX_OR_LESS_THAN(eabis[0], Scalar(EIGEN_PI));
+ VERIFY_IS_APPROX_OR_LESS_THAN(-Scalar(EIGEN_PI), eabis[1]);
+ VERIFY_IS_APPROX_OR_LESS_THAN(eabis[1], Scalar(EIGEN_PI));
+ VERIFY_IS_APPROX_OR_LESS_THAN(-Scalar(EIGEN_PI), eabis[2]);
+ VERIFY_IS_APPROX_OR_LESS_THAN(eabis[2], Scalar(EIGEN_PI));
}
template<typename Scalar> void check_all_var(const Matrix<Scalar,3,1>& ea)
@@ -64,7 +64,7 @@ template<typename Scalar> void eulerangles()
typedef Quaternion<Scalar> Quaternionx;
typedef AngleAxis<Scalar> AngleAxisx;
- Scalar a = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
+ Scalar a = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_PI));
Quaternionx q1;
q1 = AngleAxisx(a, Vector3::Random().normalized());
Matrix3 m;
@@ -84,13 +84,13 @@ template<typename Scalar> void eulerangles()
check_all_var(ea);
// Check with random angles in range [0:pi]x[-pi:pi]x[-pi:pi].
- ea = (Array3::Random() + Array3(1,0,0))*Scalar(M_PI)*Array3(0.5,1,1);
+ ea = (Array3::Random() + Array3(1,0,0))*Scalar(EIGEN_PI)*Array3(0.5,1,1);
check_all_var(ea);
- ea[2] = ea[0] = internal::random<Scalar>(0,Scalar(M_PI));
+ ea[2] = ea[0] = internal::random<Scalar>(0,Scalar(EIGEN_PI));
check_all_var(ea);
- ea[0] = ea[1] = internal::random<Scalar>(0,Scalar(M_PI));
+ ea[0] = ea[1] = internal::random<Scalar>(0,Scalar(EIGEN_PI));
check_all_var(ea);
ea[1] = 0;
diff --git a/test/geo_homogeneous.cpp b/test/geo_homogeneous.cpp
index c91bde819..2187c7bf9 100644
--- a/test/geo_homogeneous.cpp
+++ b/test/geo_homogeneous.cpp
@@ -38,6 +38,10 @@ template<typename Scalar,int Size> void homogeneous(void)
hv0 << v0, 1;
VERIFY_IS_APPROX(v0.homogeneous(), hv0);
VERIFY_IS_APPROX(v0, hv0.hnormalized());
+
+ VERIFY_IS_APPROX(v0.homogeneous().sum(), hv0.sum());
+ VERIFY_IS_APPROX(v0.homogeneous().minCoeff(), hv0.minCoeff());
+ VERIFY_IS_APPROX(v0.homogeneous().maxCoeff(), hv0.maxCoeff());
hm0 << m0, ones.transpose();
VERIFY_IS_APPROX(m0.colwise().homogeneous(), hm0);
@@ -54,10 +58,11 @@ template<typename Scalar,int Size> void homogeneous(void)
T2MatrixType t2 = T2MatrixType::Random();
VERIFY_IS_APPROX(t2 * (v0.homogeneous().eval()), t2 * v0.homogeneous());
VERIFY_IS_APPROX(t2 * (m0.colwise().homogeneous().eval()), t2 * m0.colwise().homogeneous());
+ VERIFY_IS_APPROX(t2 * (v0.homogeneous().asDiagonal()), t2 * hv0.asDiagonal());
+ VERIFY_IS_APPROX((v0.homogeneous().asDiagonal()) * t2, hv0.asDiagonal() * t2);
VERIFY_IS_APPROX((v0.transpose().rowwise().homogeneous().eval()) * t2,
v0.transpose().rowwise().homogeneous() * t2);
- m0.transpose().rowwise().homogeneous().eval();
VERIFY_IS_APPROX((m0.transpose().rowwise().homogeneous().eval()) * t2,
m0.transpose().rowwise().homogeneous() * t2);
@@ -82,7 +87,7 @@ template<typename Scalar,int Size> void homogeneous(void)
VERIFY_IS_APPROX(aff * pts.colwise().homogeneous(), (aff * pts1).colwise().hnormalized());
VERIFY_IS_APPROX(caff * pts.colwise().homogeneous(), (caff * pts1).colwise().hnormalized());
VERIFY_IS_APPROX(proj * pts.colwise().homogeneous(), (proj * pts1));
-
+
VERIFY_IS_APPROX((aff * pts1).colwise().hnormalized(), aff * pts);
VERIFY_IS_APPROX((caff * pts1).colwise().hnormalized(), caff * pts);
@@ -91,6 +96,23 @@ template<typename Scalar,int Size> void homogeneous(void)
VERIFY_IS_APPROX((aff * pts2).colwise().hnormalized(), aff * pts2.colwise().hnormalized());
VERIFY_IS_APPROX((caff * pts2).colwise().hnormalized(), caff * pts2.colwise().hnormalized());
VERIFY_IS_APPROX((proj * pts2).colwise().hnormalized(), (proj * pts2.colwise().hnormalized().colwise().homogeneous()).colwise().hnormalized());
+
+ // Test combination of homogeneous
+
+ VERIFY_IS_APPROX( (t2 * v0.homogeneous()).hnormalized(),
+ (t2.template topLeftCorner<Size,Size>() * v0 + t2.template topRightCorner<Size,1>())
+ / ((t2.template bottomLeftCorner<1,Size>()*v0).value() + t2(Size,Size)) );
+
+ VERIFY_IS_APPROX( (t2 * pts.colwise().homogeneous()).colwise().hnormalized(),
+ (Matrix<Scalar, Size+1, Dynamic>(t2 * pts1).colwise().hnormalized()) );
+
+ VERIFY_IS_APPROX( (t2 .lazyProduct( v0.homogeneous() )).hnormalized(), (t2 * v0.homogeneous()).hnormalized() );
+ VERIFY_IS_APPROX( (t2 .lazyProduct ( pts.colwise().homogeneous() )).colwise().hnormalized(), (t2 * pts1).colwise().hnormalized() );
+
+ VERIFY_IS_APPROX( (v0.transpose().homogeneous() .lazyProduct( t2 )).hnormalized(), (v0.transpose().homogeneous()*t2).hnormalized() );
+ VERIFY_IS_APPROX( (pts.transpose().rowwise().homogeneous() .lazyProduct( t2 )).rowwise().hnormalized(), (pts1.transpose()*t2).rowwise().hnormalized() );
+
+ VERIFY_IS_APPROX( (t2.template triangularView<Lower>() * v0.homogeneous()).eval(), (t2.template triangularView<Lower>()*hv0) );
}
void test_geo_homogeneous()
diff --git a/test/geo_hyperplane.cpp b/test/geo_hyperplane.cpp
index 327537801..27892850d 100644
--- a/test/geo_hyperplane.cpp
+++ b/test/geo_hyperplane.cpp
@@ -18,10 +18,12 @@ template<typename HyperplaneType> void hyperplane(const HyperplaneType& _plane)
/* this test covers the following files:
Hyperplane.h
*/
+ using std::abs;
typedef typename HyperplaneType::Index Index;
const Index dim = _plane.dim();
enum { Options = HyperplaneType::Options };
typedef typename HyperplaneType::Scalar Scalar;
+ typedef typename HyperplaneType::RealScalar RealScalar;
typedef Matrix<Scalar, HyperplaneType::AmbientDimAtCompileTime, 1> VectorType;
typedef Matrix<Scalar, HyperplaneType::AmbientDimAtCompileTime,
HyperplaneType::AmbientDimAtCompileTime> MatrixType;
@@ -42,7 +44,10 @@ template<typename HyperplaneType> void hyperplane(const HyperplaneType& _plane)
VERIFY_IS_APPROX( n1.dot(n1), Scalar(1) );
VERIFY_IS_MUCH_SMALLER_THAN( pl0.absDistance(p0), Scalar(1) );
- VERIFY_IS_APPROX( pl1.signedDistance(p1 + n1 * s0), s0 );
+ if(numext::abs2(s0)>RealScalar(1e-6))
+ VERIFY_IS_APPROX( pl1.signedDistance(p1 + n1 * s0), s0);
+ else
+ VERIFY_IS_MUCH_SMALLER_THAN( abs(pl1.signedDistance(p1 + n1 * s0) - s0), Scalar(1) );
VERIFY_IS_MUCH_SMALLER_THAN( pl1.signedDistance(pl1.projection(p0)), Scalar(1) );
VERIFY_IS_MUCH_SMALLER_THAN( pl1.absDistance(p1 + pl1.normal().unitOrthogonal() * s1), Scalar(1) );
@@ -52,6 +57,8 @@ template<typename HyperplaneType> void hyperplane(const HyperplaneType& _plane)
MatrixType rot = MatrixType::Random(dim,dim).householderQr().householderQ();
DiagonalMatrix<Scalar,HyperplaneType::AmbientDimAtCompileTime> scaling(VectorType::Random());
Translation<Scalar,HyperplaneType::AmbientDimAtCompileTime> translation(VectorType::Random());
+
+ while(scaling.diagonal().cwiseAbs().minCoeff()<RealScalar(1e-4)) scaling.diagonal() = VectorType::Random();
pl2 = pl1;
VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot).absDistance(rot * p1), Scalar(1) );
@@ -59,12 +66,15 @@ template<typename HyperplaneType> void hyperplane(const HyperplaneType& _plane)
VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot,Isometry).absDistance(rot * p1), Scalar(1) );
pl2 = pl1;
VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*scaling).absDistance((rot*scaling) * p1), Scalar(1) );
+ VERIFY_IS_APPROX( pl2.normal().norm(), RealScalar(1) );
pl2 = pl1;
VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*scaling*translation)
- .absDistance((rot*scaling*translation) * p1), Scalar(1) );
+ .absDistance((rot*scaling*translation) * p1), Scalar(1) );
+ VERIFY_IS_APPROX( pl2.normal().norm(), RealScalar(1) );
pl2 = pl1;
VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*translation,Isometry)
.absDistance((rot*translation) * p1), Scalar(1) );
+ VERIFY_IS_APPROX( pl2.normal().norm(), RealScalar(1) );
}
// casting
@@ -90,9 +100,9 @@ template<typename Scalar> void lines()
Vector u = Vector::Random();
Vector v = Vector::Random();
Scalar a = internal::random<Scalar>();
- while (abs(a-1) < 1e-4) a = internal::random<Scalar>();
- while (u.norm() < 1e-4) u = Vector::Random();
- while (v.norm() < 1e-4) v = Vector::Random();
+ while (abs(a-1) < Scalar(1e-4)) a = internal::random<Scalar>();
+ while (u.norm() < Scalar(1e-4)) u = Vector::Random();
+ while (v.norm() < Scalar(1e-4)) v = Vector::Random();
HLine line_u = HLine::Through(center + u, center + a*u);
HLine line_v = HLine::Through(center + v, center + a*v);
@@ -104,12 +114,15 @@ template<typename Scalar> void lines()
Vector result = line_u.intersection(line_v);
// the lines should intersect at the point we called "center"
- VERIFY_IS_APPROX(result, center);
+ if(abs(a-1) > Scalar(1e-2) && abs(v.normalized().dot(u.normalized()))<Scalar(0.9))
+ VERIFY_IS_APPROX(result, center);
// check conversions between two types of lines
PLine pl(line_u); // gcc 3.3 will commit suicide if we don't name this variable
- CoeffsType converted_coeffs = HLine(pl).coeffs();
- converted_coeffs *= (line_u.coeffs()[0])/(converted_coeffs[0]);
+ HLine line_u2(pl);
+ CoeffsType converted_coeffs = line_u2.coeffs();
+ if(line_u2.normal().dot(line_u.normal())<Scalar(0))
+ converted_coeffs = -line_u2.coeffs();
VERIFY(line_u.coeffs().isApprox(converted_coeffs));
}
}
@@ -145,9 +158,9 @@ template<typename Scalar> void hyperplane_alignment()
typedef Hyperplane<Scalar,3,AutoAlign> Plane3a;
typedef Hyperplane<Scalar,3,DontAlign> Plane3u;
- EIGEN_ALIGN16 Scalar array1[4];
- EIGEN_ALIGN16 Scalar array2[4];
- EIGEN_ALIGN16 Scalar array3[4+1];
+ EIGEN_ALIGN_MAX Scalar array1[4];
+ EIGEN_ALIGN_MAX Scalar array2[4];
+ EIGEN_ALIGN_MAX Scalar array3[4+1];
Scalar* array3u = array3+1;
Plane3a *p1 = ::new(reinterpret_cast<void*>(array1)) Plane3a;
@@ -161,8 +174,8 @@ template<typename Scalar> void hyperplane_alignment()
VERIFY_IS_APPROX(p1->coeffs(), p2->coeffs());
VERIFY_IS_APPROX(p1->coeffs(), p3->coeffs());
- #if defined(EIGEN_VECTORIZE) && EIGEN_ALIGN_STATICALLY
- if(internal::packet_traits<Scalar>::Vectorizable)
+ #if defined(EIGEN_VECTORIZE) && EIGEN_MAX_STATIC_ALIGN_BYTES > 0
+ if(internal::packet_traits<Scalar>::Vectorizable && internal::packet_traits<Scalar>::size<=4)
VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Plane3a));
#endif
}
diff --git a/test/geo_orthomethods.cpp b/test/geo_orthomethods.cpp
index c836dae40..e178df257 100644
--- a/test/geo_orthomethods.cpp
+++ b/test/geo_orthomethods.cpp
@@ -33,12 +33,16 @@ template<typename Scalar> void orthomethods_3()
VERIFY_IS_MUCH_SMALLER_THAN(v1.dot(v1.cross(v2)), Scalar(1));
VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).dot(v2), Scalar(1));
VERIFY_IS_MUCH_SMALLER_THAN(v2.dot(v1.cross(v2)), Scalar(1));
+ VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(Vector3::Random()).dot(v1), Scalar(1));
Matrix3 mat3;
mat3 << v0.normalized(),
(v0.cross(v1)).normalized(),
(v0.cross(v1).cross(v0)).normalized();
VERIFY(mat3.isUnitary());
-
+
+ mat3.setRandom();
+ VERIFY_IS_APPROX(v0.cross(mat3*v1), -(mat3*v1).cross(v0));
+ VERIFY_IS_APPROX(v0.cross(mat3.lazyProduct(v1)), -(mat3.lazyProduct(v1)).cross(v0));
// colwise/rowwise cross product
mat3.setRandom();
@@ -47,6 +51,13 @@ template<typename Scalar> void orthomethods_3()
int i = internal::random<int>(0,2);
mcross = mat3.colwise().cross(vec3);
VERIFY_IS_APPROX(mcross.col(i), mat3.col(i).cross(vec3));
+
+ VERIFY_IS_MUCH_SMALLER_THAN((mat3.adjoint() * mat3.colwise().cross(vec3)).diagonal().cwiseAbs().sum(), Scalar(1));
+ VERIFY_IS_MUCH_SMALLER_THAN((mat3.adjoint() * mat3.colwise().cross(Vector3::Random())).diagonal().cwiseAbs().sum(), Scalar(1));
+
+ VERIFY_IS_MUCH_SMALLER_THAN((vec3.adjoint() * mat3.colwise().cross(vec3)).cwiseAbs().sum(), Scalar(1));
+ VERIFY_IS_MUCH_SMALLER_THAN((vec3.adjoint() * Matrix3::Random().colwise().cross(vec3)).cwiseAbs().sum(), Scalar(1));
+
mcross = mat3.rowwise().cross(vec3);
VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3));
@@ -57,6 +68,7 @@ template<typename Scalar> void orthomethods_3()
v40.w() = v41.w() = v42.w() = 0;
v42.template head<3>() = v40.template head<3>().cross(v41.template head<3>());
VERIFY_IS_APPROX(v40.cross3(v41), v42);
+ VERIFY_IS_MUCH_SMALLER_THAN(v40.cross3(Vector4::Random()).dot(v40), Scalar(1));
// check mixed product
typedef Matrix<RealScalar, 3, 1> RealVector3;
diff --git a/test/geo_parametrizedline.cpp b/test/geo_parametrizedline.cpp
index f0462d40a..9bf5f3c1d 100644
--- a/test/geo_parametrizedline.cpp
+++ b/test/geo_parametrizedline.cpp
@@ -66,9 +66,9 @@ template<typename Scalar> void parametrizedline_alignment()
typedef ParametrizedLine<Scalar,4,AutoAlign> Line4a;
typedef ParametrizedLine<Scalar,4,DontAlign> Line4u;
- EIGEN_ALIGN16 Scalar array1[8];
- EIGEN_ALIGN16 Scalar array2[8];
- EIGEN_ALIGN16 Scalar array3[8+1];
+ EIGEN_ALIGN_MAX Scalar array1[16];
+ EIGEN_ALIGN_MAX Scalar array2[16];
+ EIGEN_ALIGN_MAX Scalar array3[16+1];
Scalar* array3u = array3+1;
Line4a *p1 = ::new(reinterpret_cast<void*>(array1)) Line4a;
@@ -85,8 +85,8 @@ template<typename Scalar> void parametrizedline_alignment()
VERIFY_IS_APPROX(p1->direction(), p2->direction());
VERIFY_IS_APPROX(p1->direction(), p3->direction());
- #if defined(EIGEN_VECTORIZE) && EIGEN_ALIGN_STATICALLY
- if(internal::packet_traits<Scalar>::Vectorizable)
+ #if defined(EIGEN_VECTORIZE) && EIGEN_MAX_STATIC_ALIGN_BYTES>0
+ if(internal::packet_traits<Scalar>::Vectorizable && internal::packet_traits<Scalar>::size<=4)
VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Line4a));
#endif
}
diff --git a/test/geo_quaternion.cpp b/test/geo_quaternion.cpp
index 1694b32c7..96889e722 100644
--- a/test/geo_quaternion.cpp
+++ b/test/geo_quaternion.cpp
@@ -30,8 +30,8 @@ template<typename QuatType> void check_slerp(const QuatType& q0, const QuatType&
Scalar largeEps = test_precision<Scalar>();
Scalar theta_tot = AA(q1*q0.inverse()).angle();
- if(theta_tot>M_PI)
- theta_tot = Scalar(2.*M_PI)-theta_tot;
+ if(theta_tot>Scalar(EIGEN_PI))
+ theta_tot = Scalar(2.)*Scalar(EIGEN_PI)-theta_tot;
for(Scalar t=0; t<=Scalar(1.001); t+=Scalar(0.1))
{
QuatType q = q0.slerp(t,q1);
@@ -49,13 +49,13 @@ template<typename Scalar, int Options> void quaternion(void)
*/
using std::abs;
typedef Matrix<Scalar,3,1> Vector3;
- typedef Matrix<Scalar,4,1> Vector4;
+ typedef Matrix<Scalar,3,3> Matrix3;
typedef Quaternion<Scalar,Options> Quaternionx;
typedef AngleAxis<Scalar> AngleAxisx;
Scalar largeEps = test_precision<Scalar>();
if (internal::is_same<Scalar,float>::value)
- largeEps = 1e-3f;
+ largeEps = Scalar(1e-3);
Scalar eps = internal::random<Scalar>() * Scalar(1e-2);
@@ -64,8 +64,8 @@ template<typename Scalar, int Options> void quaternion(void)
v2 = Vector3::Random(),
v3 = Vector3::Random();
- Scalar a = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI)),
- b = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
+ Scalar a = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_PI)),
+ b = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_PI));
// Quaternion: Identity(), setIdentity();
Quaternionx q1, q2;
@@ -82,8 +82,8 @@ template<typename Scalar, int Options> void quaternion(void)
// angular distance
Scalar refangle = abs(AngleAxisx(q1.inverse()*q2).angle());
- if (refangle>Scalar(M_PI))
- refangle = Scalar(2)*Scalar(M_PI) - refangle;
+ if (refangle>Scalar(EIGEN_PI))
+ refangle = Scalar(2)*Scalar(EIGEN_PI) - refangle;
if((q1.coeffs()-q2.coeffs()).norm() > 10*largeEps)
{
@@ -101,6 +101,11 @@ template<typename Scalar, int Options> void quaternion(void)
q2 = q1.toRotationMatrix();
VERIFY_IS_APPROX(q1*v1,q2*v1);
+ Matrix3 rot1(q1);
+ VERIFY_IS_APPROX(q1*v1,rot1*v1);
+ Quaternionx q3(rot1.transpose()*rot1);
+ VERIFY_IS_APPROX(q3*v1,v1);
+
// angle-axis conversion
AngleAxisx aa = AngleAxisx(q1);
@@ -109,8 +114,8 @@ template<typename Scalar, int Options> void quaternion(void)
// Do not execute the test if the rotation angle is almost zero, or
// the rotation axis and v1 are almost parallel.
if (abs(aa.angle()) > 5*test_precision<Scalar>()
- && (aa.axis() - v1.normalized()).norm() < 1.99
- && (aa.axis() + v1.normalized()).norm() < 1.99)
+ && (aa.axis() - v1.normalized()).norm() < Scalar(1.99)
+ && (aa.axis() + v1.normalized()).norm() < Scalar(1.99))
{
VERIFY_IS_NOT_APPROX(q1 * v1, Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1);
}
@@ -151,19 +156,19 @@ template<typename Scalar, int Options> void quaternion(void)
Quaternionx *q = new Quaternionx;
delete q;
- q1 = AngleAxisx(a, v0.normalized());
- q2 = AngleAxisx(b, v1.normalized());
+ q1 = Quaternionx::UnitRandom();
+ q2 = Quaternionx::UnitRandom();
check_slerp(q1,q2);
q1 = AngleAxisx(b, v1.normalized());
- q2 = AngleAxisx(b+Scalar(M_PI), v1.normalized());
+ q2 = AngleAxisx(b+Scalar(EIGEN_PI), v1.normalized());
check_slerp(q1,q2);
q1 = AngleAxisx(b, v1.normalized());
q2 = AngleAxisx(-b, -v1.normalized());
check_slerp(q1,q2);
- q1.coeffs() = Vector4::Random().normalized();
+ q1 = Quaternionx::UnitRandom();
q2.coeffs() = -q1.coeffs();
check_slerp(q1,q2);
}
@@ -179,11 +184,11 @@ template<typename Scalar> void mapQuaternion(void){
Vector3 v0 = Vector3::Random(),
v1 = Vector3::Random();
- Scalar a = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
+ Scalar a = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_PI));
- EIGEN_ALIGN16 Scalar array1[4];
- EIGEN_ALIGN16 Scalar array2[4];
- EIGEN_ALIGN16 Scalar array3[4+1];
+ EIGEN_ALIGN_MAX Scalar array1[4];
+ EIGEN_ALIGN_MAX Scalar array2[4];
+ EIGEN_ALIGN_MAX Scalar array3[4+1];
Scalar* array3unaligned = array3+1;
MQuaternionA mq1(array1);
@@ -232,9 +237,9 @@ template<typename Scalar> void quaternionAlignment(void){
typedef Quaternion<Scalar,AutoAlign> QuaternionA;
typedef Quaternion<Scalar,DontAlign> QuaternionUA;
- EIGEN_ALIGN16 Scalar array1[4];
- EIGEN_ALIGN16 Scalar array2[4];
- EIGEN_ALIGN16 Scalar array3[4+1];
+ EIGEN_ALIGN_MAX Scalar array1[4];
+ EIGEN_ALIGN_MAX Scalar array2[4];
+ EIGEN_ALIGN_MAX Scalar array3[4+1];
Scalar* arrayunaligned = array3+1;
QuaternionA *q1 = ::new(reinterpret_cast<void*>(array1)) QuaternionA;
@@ -247,8 +252,8 @@ template<typename Scalar> void quaternionAlignment(void){
VERIFY_IS_APPROX(q1->coeffs(), q2->coeffs());
VERIFY_IS_APPROX(q1->coeffs(), q3->coeffs());
- #if defined(EIGEN_VECTORIZE) && EIGEN_ALIGN_STATICALLY
- if(internal::packet_traits<Scalar>::Vectorizable)
+ #if defined(EIGEN_VECTORIZE) && EIGEN_MAX_STATIC_ALIGN_BYTES>0
+ if(internal::packet_traits<Scalar>::Vectorizable && internal::packet_traits<Scalar>::size<=4)
VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(arrayunaligned)) QuaternionA));
#endif
}
diff --git a/test/geo_transformations.cpp b/test/geo_transformations.cpp
index 4ad3793d8..278e527c2 100644..100755
--- a/test/geo_transformations.cpp
+++ b/test/geo_transformations.cpp
@@ -12,6 +12,17 @@
#include <Eigen/LU>
#include <Eigen/SVD>
+template<typename T>
+Matrix<T,2,1> angleToVec(T a)
+{
+ return Matrix<T,2,1>(std::cos(a), std::sin(a));
+}
+
+// This permits to workaround a bug in clang/llvm code generation.
+template<typename T>
+EIGEN_DONT_INLINE
+void dont_over_optimize(T& x) { volatile typename T::Scalar tmp = x(0); x(0) = tmp; }
+
template<typename Scalar, int Mode, int Options> void non_projective_only()
{
/* this test covers the following files:
@@ -29,7 +40,7 @@ template<typename Scalar, int Mode, int Options> void non_projective_only()
Transform3 t0, t1, t2;
- Scalar a = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
+ Scalar a = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_PI));
Quaternionx q1, q2;
@@ -97,16 +108,14 @@ template<typename Scalar, int Mode, int Options> void transformations()
v1 = Vector3::Random();
Matrix3 matrot1, m;
- Scalar a = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
- Scalar s0 = internal::random<Scalar>(),
- s1 = internal::random<Scalar>();
+ Scalar a = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_PI));
+ Scalar s0 = internal::random<Scalar>(), s1 = internal::random<Scalar>();
while(v0.norm() < test_precision<Scalar>()) v0 = Vector3::Random();
while(v1.norm() < test_precision<Scalar>()) v1 = Vector3::Random();
-
VERIFY_IS_APPROX(v0, AngleAxisx(a, v0.normalized()) * v0);
- VERIFY_IS_APPROX(-v0, AngleAxisx(Scalar(M_PI), v0.unitOrthogonal()) * v0);
+ VERIFY_IS_APPROX(-v0, AngleAxisx(Scalar(EIGEN_PI), v0.unitOrthogonal()) * v0);
if(abs(cos(a)) > test_precision<Scalar>())
{
VERIFY_IS_APPROX(cos(a)*v0.squaredNorm(), v0.dot(AngleAxisx(a, v0.unitOrthogonal()) * v0));
@@ -132,14 +141,16 @@ template<typename Scalar, int Mode, int Options> void transformations()
AngleAxisx aa = AngleAxisx(q1);
VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
- if(abs(aa.angle()) > NumTraits<Scalar>::dummy_precision())
+ // The following test is stable only if 2*angle != angle and v1 is not colinear with axis
+ if( (abs(aa.angle()) > test_precision<Scalar>()) && (abs(aa.axis().dot(v1.normalized()))<(Scalar(1)-Scalar(4)*test_precision<Scalar>())) )
{
VERIFY( !(q1 * v1).isApprox(Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1) );
}
aa.fromRotationMatrix(aa.toRotationMatrix());
VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
- if(abs(aa.angle()) > NumTraits<Scalar>::dummy_precision())
+ // The following test is stable only if 2*angle != angle and v1 is not colinear with axis
+ if( (abs(aa.angle()) > test_precision<Scalar>()) && (abs(aa.axis().dot(v1.normalized()))<(Scalar(1)-Scalar(4)*test_precision<Scalar>())) )
{
VERIFY( !(q1 * v1).isApprox(Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1) );
}
@@ -158,7 +169,7 @@ template<typename Scalar, int Mode, int Options> void transformations()
// TODO complete the tests !
a = 0;
while (abs(a)<Scalar(0.1))
- a = internal::random<Scalar>(-Scalar(0.4)*Scalar(M_PI), Scalar(0.4)*Scalar(M_PI));
+ a = internal::random<Scalar>(-Scalar(0.4)*Scalar(EIGEN_PI), Scalar(0.4)*Scalar(EIGEN_PI));
q1 = AngleAxisx(a, v0.normalized());
Transform3 t0, t1, t2;
@@ -204,7 +215,7 @@ template<typename Scalar, int Mode, int Options> void transformations()
tmat4.matrix()(3,3) = Scalar(1);
VERIFY_IS_APPROX(tmat3.matrix(), tmat4.matrix());
- Scalar a3 = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
+ Scalar a3 = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_PI));
Vector3 v3 = Vector3::Random().normalized();
AngleAxisx aa3(a3, v3);
Transform3 t3(aa3);
@@ -216,12 +227,15 @@ template<typename Scalar, int Mode, int Options> void transformations()
t4 *= aa3;
VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
- v3 = Vector3::Random();
+ do {
+ v3 = Vector3::Random();
+ dont_over_optimize(v3);
+ } while (v3.cwiseAbs().minCoeff()<NumTraits<Scalar>::epsilon());
Translation3 tv3(v3);
Transform3 t5(tv3);
t4 = tv3;
VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
- t4.translate(-v3);
+ t4.translate((-v3).eval());
VERIFY_IS_APPROX(t4.matrix(), MatrixType::Identity());
t4 *= tv3;
VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
@@ -413,12 +427,28 @@ template<typename Scalar, int Mode, int Options> void transformations()
VERIFY_IS_APPROX(r2d1f.template cast<Scalar>(),r2d1);
Rotation2D<double> r2d1d = r2d1.template cast<double>();
VERIFY_IS_APPROX(r2d1d.template cast<Scalar>(),r2d1);
-
- t20 = Translation2(v20) * (Rotation2D<Scalar>(s0) * Eigen::Scaling(s0));
- t21 = Translation2(v20) * Rotation2D<Scalar>(s0) * Eigen::Scaling(s0);
- VERIFY_IS_APPROX(t20,t21);
+ for(int k=0; k<100; ++k)
+ {
+ Scalar angle = internal::random<Scalar>(-100,100);
+ Rotation2D<Scalar> rot2(angle);
+ VERIFY( rot2.smallestPositiveAngle() >= 0 );
+ VERIFY( rot2.smallestPositiveAngle() <= Scalar(2)*Scalar(EIGEN_PI) );
+ VERIFY_IS_APPROX( angleToVec(rot2.smallestPositiveAngle()), angleToVec(rot2.angle()) );
+
+ VERIFY( rot2.smallestAngle() >= -Scalar(EIGEN_PI) );
+ VERIFY( rot2.smallestAngle() <= Scalar(EIGEN_PI) );
+ VERIFY_IS_APPROX( angleToVec(rot2.smallestAngle()), angleToVec(rot2.angle()) );
+
+ Matrix<Scalar,2,2> rot2_as_mat(rot2);
+ Rotation2D<Scalar> rot3(rot2_as_mat);
+ VERIFY_IS_APPROX( angleToVec(rot2.smallestAngle()), angleToVec(rot3.angle()) );
+ }
+
+ s0 = internal::random<Scalar>(-100,100);
+ s1 = internal::random<Scalar>(-100,100);
Rotation2D<Scalar> R0(s0), R1(s1);
+
t20 = Translation2(v20) * (R0 * Eigen::Scaling(s0));
t21 = Translation2(v20) * R0 * Eigen::Scaling(s0);
VERIFY_IS_APPROX(t20,t21);
@@ -428,9 +458,24 @@ template<typename Scalar, int Mode, int Options> void transformations()
VERIFY_IS_APPROX(t20,t21);
VERIFY_IS_APPROX(s0, (R0.slerp(0, R1)).angle());
- VERIFY_IS_APPROX(s1, (R0.slerp(1, R1)).angle());
- VERIFY_IS_APPROX(s0, (R0.slerp(0.5, R0)).angle());
- VERIFY_IS_APPROX(Scalar(0), (R0.slerp(0.5, R0.inverse())).angle());
+ VERIFY_IS_APPROX( angleToVec(R1.smallestPositiveAngle()), angleToVec((R0.slerp(1, R1)).smallestPositiveAngle()) );
+ VERIFY_IS_APPROX(R0.smallestPositiveAngle(), (R0.slerp(0.5, R0)).smallestPositiveAngle());
+
+ if(std::cos(s0)>0)
+ VERIFY_IS_MUCH_SMALLER_THAN((R0.slerp(0.5, R0.inverse())).smallestAngle(), Scalar(1));
+ else
+ VERIFY_IS_APPROX(Scalar(EIGEN_PI), (R0.slerp(0.5, R0.inverse())).smallestPositiveAngle());
+
+ // Check path length
+ Scalar l = 0;
+ int path_steps = 100;
+ for(int k=0; k<path_steps; ++k)
+ {
+ Scalar a1 = R0.slerp(Scalar(k)/Scalar(path_steps), R1).angle();
+ Scalar a2 = R0.slerp(Scalar(k+1)/Scalar(path_steps), R1).angle();
+ l += std::abs(a2-a1);
+ }
+ VERIFY(l<=Scalar(EIGEN_PI)*(Scalar(1)+NumTraits<Scalar>::epsilon()*Scalar(path_steps/2)));
// check basic features
{
@@ -520,9 +565,9 @@ template<typename Scalar> void transform_alignment()
typedef Transform<Scalar,3,Projective,AutoAlign> Projective3a;
typedef Transform<Scalar,3,Projective,DontAlign> Projective3u;
- EIGEN_ALIGN16 Scalar array1[16];
- EIGEN_ALIGN16 Scalar array2[16];
- EIGEN_ALIGN16 Scalar array3[16+1];
+ EIGEN_ALIGN_MAX Scalar array1[16];
+ EIGEN_ALIGN_MAX Scalar array2[16];
+ EIGEN_ALIGN_MAX Scalar array3[16+1];
Scalar* array3u = array3+1;
Projective3a *p1 = ::new(reinterpret_cast<void*>(array1)) Projective3a;
@@ -538,7 +583,7 @@ template<typename Scalar> void transform_alignment()
VERIFY_IS_APPROX( (*p1) * (*p1), (*p2)*(*p3));
- #if defined(EIGEN_VECTORIZE) && EIGEN_ALIGN_STATICALLY
+ #if defined(EIGEN_VECTORIZE) && EIGEN_MAX_STATIC_ALIGN_BYTES>0
if(internal::packet_traits<Scalar>::Vectorizable)
VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Projective3a));
#endif
diff --git a/test/half_float.cpp b/test/half_float.cpp
new file mode 100644
index 000000000..f8d438e2f
--- /dev/null
+++ b/test/half_float.cpp
@@ -0,0 +1,252 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// 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 <sstream>
+
+#include "main.h"
+
+#include <Eigen/src/Core/arch/CUDA/Half.h>
+
+// Make sure it's possible to forward declare Eigen::half
+namespace Eigen {
+struct half;
+}
+
+using Eigen::half;
+
+void test_conversion()
+{
+ using Eigen::half_impl::__half;
+
+ // Conversion from float.
+ VERIFY_IS_EQUAL(half(1.0f).x, 0x3c00);
+ VERIFY_IS_EQUAL(half(0.5f).x, 0x3800);
+ VERIFY_IS_EQUAL(half(0.33333f).x, 0x3555);
+ VERIFY_IS_EQUAL(half(0.0f).x, 0x0000);
+ VERIFY_IS_EQUAL(half(-0.0f).x, 0x8000);
+ VERIFY_IS_EQUAL(half(65504.0f).x, 0x7bff);
+ VERIFY_IS_EQUAL(half(65536.0f).x, 0x7c00); // Becomes infinity.
+
+ // Denormals.
+ VERIFY_IS_EQUAL(half(-5.96046e-08f).x, 0x8001);
+ VERIFY_IS_EQUAL(half(5.96046e-08f).x, 0x0001);
+ VERIFY_IS_EQUAL(half(1.19209e-07f).x, 0x0002);
+
+ // Verify round-to-nearest-even behavior.
+ float val1 = float(half(__half(0x3c00)));
+ float val2 = float(half(__half(0x3c01)));
+ float val3 = float(half(__half(0x3c02)));
+ VERIFY_IS_EQUAL(half(0.5f * (val1 + val2)).x, 0x3c00);
+ VERIFY_IS_EQUAL(half(0.5f * (val2 + val3)).x, 0x3c02);
+
+ // Conversion from int.
+ VERIFY_IS_EQUAL(half(-1).x, 0xbc00);
+ VERIFY_IS_EQUAL(half(0).x, 0x0000);
+ VERIFY_IS_EQUAL(half(1).x, 0x3c00);
+ VERIFY_IS_EQUAL(half(2).x, 0x4000);
+ VERIFY_IS_EQUAL(half(3).x, 0x4200);
+
+ // Conversion from bool.
+ VERIFY_IS_EQUAL(half(false).x, 0x0000);
+ VERIFY_IS_EQUAL(half(true).x, 0x3c00);
+
+ // Conversion to float.
+ VERIFY_IS_EQUAL(float(half(__half(0x0000))), 0.0f);
+ VERIFY_IS_EQUAL(float(half(__half(0x3c00))), 1.0f);
+
+ // Denormals.
+ VERIFY_IS_APPROX(float(half(__half(0x8001))), -5.96046e-08f);
+ VERIFY_IS_APPROX(float(half(__half(0x0001))), 5.96046e-08f);
+ VERIFY_IS_APPROX(float(half(__half(0x0002))), 1.19209e-07f);
+
+ // NaNs and infinities.
+ VERIFY(!(numext::isinf)(float(half(65504.0f)))); // Largest finite number.
+ VERIFY(!(numext::isnan)(float(half(0.0f))));
+ VERIFY((numext::isinf)(float(half(__half(0xfc00)))));
+ VERIFY((numext::isnan)(float(half(__half(0xfc01)))));
+ VERIFY((numext::isinf)(float(half(__half(0x7c00)))));
+ VERIFY((numext::isnan)(float(half(__half(0x7c01)))));
+
+#if !EIGEN_COMP_MSVC
+ // Visual Studio errors out on divisions by 0
+ VERIFY((numext::isnan)(float(half(0.0 / 0.0))));
+ VERIFY((numext::isinf)(float(half(1.0 / 0.0))));
+ VERIFY((numext::isinf)(float(half(-1.0 / 0.0))));
+#endif
+
+ // Exactly same checks as above, just directly on the half representation.
+ VERIFY(!(numext::isinf)(half(__half(0x7bff))));
+ VERIFY(!(numext::isnan)(half(__half(0x0000))));
+ VERIFY((numext::isinf)(half(__half(0xfc00))));
+ VERIFY((numext::isnan)(half(__half(0xfc01))));
+ VERIFY((numext::isinf)(half(__half(0x7c00))));
+ VERIFY((numext::isnan)(half(__half(0x7c01))));
+
+#if !EIGEN_COMP_MSVC
+ // Visual Studio errors out on divisions by 0
+ VERIFY((numext::isnan)(half(0.0 / 0.0)));
+ VERIFY((numext::isinf)(half(1.0 / 0.0)));
+ VERIFY((numext::isinf)(half(-1.0 / 0.0)));
+#endif
+}
+
+void test_numtraits()
+{
+ std::cout << "epsilon = " << NumTraits<half>::epsilon() << std::endl;
+ std::cout << "highest = " << NumTraits<half>::highest() << std::endl;
+ std::cout << "lowest = " << NumTraits<half>::lowest() << std::endl;
+ std::cout << "inifinty = " << NumTraits<half>::infinity() << std::endl;
+ std::cout << "nan = " << NumTraits<half>::quiet_NaN() << std::endl;
+
+}
+
+void test_arithmetic()
+{
+ VERIFY_IS_EQUAL(float(half(2) + half(2)), 4);
+ VERIFY_IS_EQUAL(float(half(2) + half(-2)), 0);
+ VERIFY_IS_APPROX(float(half(0.33333f) + half(0.66667f)), 1.0f);
+ VERIFY_IS_EQUAL(float(half(2.0f) * half(-5.5f)), -11.0f);
+ VERIFY_IS_APPROX(float(half(1.0f) / half(3.0f)), 0.33333f);
+ VERIFY_IS_EQUAL(float(-half(4096.0f)), -4096.0f);
+ VERIFY_IS_EQUAL(float(-half(-4096.0f)), 4096.0f);
+}
+
+void test_comparison()
+{
+ VERIFY(half(1.0f) > half(0.5f));
+ VERIFY(half(0.5f) < half(1.0f));
+ VERIFY(!(half(1.0f) < half(0.5f)));
+ VERIFY(!(half(0.5f) > half(1.0f)));
+
+ VERIFY(!(half(4.0f) > half(4.0f)));
+ VERIFY(!(half(4.0f) < half(4.0f)));
+
+ VERIFY(!(half(0.0f) < half(-0.0f)));
+ VERIFY(!(half(-0.0f) < half(0.0f)));
+ VERIFY(!(half(0.0f) > half(-0.0f)));
+ VERIFY(!(half(-0.0f) > half(0.0f)));
+
+ VERIFY(half(0.2f) > half(-1.0f));
+ VERIFY(half(-1.0f) < half(0.2f));
+ VERIFY(half(-16.0f) < half(-15.0f));
+
+ VERIFY(half(1.0f) == half(1.0f));
+ VERIFY(half(1.0f) != half(2.0f));
+
+ // Comparisons with NaNs and infinities.
+#if !EIGEN_COMP_MSVC
+ // Visual Studio errors out on divisions by 0
+ VERIFY(!(half(0.0 / 0.0) == half(0.0 / 0.0)));
+ VERIFY(half(0.0 / 0.0) != half(0.0 / 0.0));
+
+ VERIFY(!(half(1.0) == half(0.0 / 0.0)));
+ VERIFY(!(half(1.0) < half(0.0 / 0.0)));
+ VERIFY(!(half(1.0) > half(0.0 / 0.0)));
+ VERIFY(half(1.0) != half(0.0 / 0.0));
+
+ VERIFY(half(1.0) < half(1.0 / 0.0));
+ VERIFY(half(1.0) > half(-1.0 / 0.0));
+#endif
+}
+
+void test_basic_functions()
+{
+ VERIFY_IS_EQUAL(float(numext::abs(half(3.5f))), 3.5f);
+ VERIFY_IS_EQUAL(float(abs(half(3.5f))), 3.5f);
+ VERIFY_IS_EQUAL(float(numext::abs(half(-3.5f))), 3.5f);
+ VERIFY_IS_EQUAL(float(abs(half(-3.5f))), 3.5f);
+
+ VERIFY_IS_EQUAL(float(numext::floor(half(3.5f))), 3.0f);
+ VERIFY_IS_EQUAL(float(floor(half(3.5f))), 3.0f);
+ VERIFY_IS_EQUAL(float(numext::floor(half(-3.5f))), -4.0f);
+ VERIFY_IS_EQUAL(float(floor(half(-3.5f))), -4.0f);
+
+ VERIFY_IS_EQUAL(float(numext::ceil(half(3.5f))), 4.0f);
+ VERIFY_IS_EQUAL(float(ceil(half(3.5f))), 4.0f);
+ VERIFY_IS_EQUAL(float(numext::ceil(half(-3.5f))), -3.0f);
+ VERIFY_IS_EQUAL(float(ceil(half(-3.5f))), -3.0f);
+
+ VERIFY_IS_APPROX(float(numext::sqrt(half(0.0f))), 0.0f);
+ VERIFY_IS_APPROX(float(sqrt(half(0.0f))), 0.0f);
+ VERIFY_IS_APPROX(float(numext::sqrt(half(4.0f))), 2.0f);
+ VERIFY_IS_APPROX(float(sqrt(half(4.0f))), 2.0f);
+
+ VERIFY_IS_APPROX(float(numext::pow(half(0.0f), half(1.0f))), 0.0f);
+ VERIFY_IS_APPROX(float(pow(half(0.0f), half(1.0f))), 0.0f);
+ VERIFY_IS_APPROX(float(numext::pow(half(2.0f), half(2.0f))), 4.0f);
+ VERIFY_IS_APPROX(float(pow(half(2.0f), half(2.0f))), 4.0f);
+
+ VERIFY_IS_EQUAL(float(numext::exp(half(0.0f))), 1.0f);
+ VERIFY_IS_EQUAL(float(exp(half(0.0f))), 1.0f);
+ VERIFY_IS_APPROX(float(numext::exp(half(EIGEN_PI))), 20.f + float(EIGEN_PI));
+ VERIFY_IS_APPROX(float(exp(half(EIGEN_PI))), 20.f + float(EIGEN_PI));
+
+ VERIFY_IS_EQUAL(float(numext::log(half(1.0f))), 0.0f);
+ VERIFY_IS_EQUAL(float(log(half(1.0f))), 0.0f);
+ VERIFY_IS_APPROX(float(numext::log(half(10.0f))), 2.30273f);
+ VERIFY_IS_APPROX(float(log(half(10.0f))), 2.30273f);
+
+ VERIFY_IS_EQUAL(float(numext::log1p(half(0.0f))), 0.0f);
+ VERIFY_IS_EQUAL(float(log1p(half(0.0f))), 0.0f);
+ VERIFY_IS_APPROX(float(numext::log1p(half(10.0f))), 2.3978953f);
+ VERIFY_IS_APPROX(float(log1p(half(10.0f))), 2.3978953f);
+}
+
+void test_trigonometric_functions()
+{
+ VERIFY_IS_APPROX(numext::cos(half(0.0f)), half(cosf(0.0f)));
+ VERIFY_IS_APPROX(cos(half(0.0f)), half(cosf(0.0f)));
+ VERIFY_IS_APPROX(numext::cos(half(EIGEN_PI)), half(cosf(EIGEN_PI)));
+ //VERIFY_IS_APPROX(numext::cos(half(EIGEN_PI/2)), half(cosf(EIGEN_PI/2)));
+ //VERIFY_IS_APPROX(numext::cos(half(3*EIGEN_PI/2)), half(cosf(3*EIGEN_PI/2)));
+ VERIFY_IS_APPROX(numext::cos(half(3.5f)), half(cosf(3.5f)));
+
+ VERIFY_IS_APPROX(numext::sin(half(0.0f)), half(sinf(0.0f)));
+ VERIFY_IS_APPROX(sin(half(0.0f)), half(sinf(0.0f)));
+ // VERIFY_IS_APPROX(numext::sin(half(EIGEN_PI)), half(sinf(EIGEN_PI)));
+ VERIFY_IS_APPROX(numext::sin(half(EIGEN_PI/2)), half(sinf(EIGEN_PI/2)));
+ VERIFY_IS_APPROX(numext::sin(half(3*EIGEN_PI/2)), half(sinf(3*EIGEN_PI/2)));
+ VERIFY_IS_APPROX(numext::sin(half(3.5f)), half(sinf(3.5f)));
+
+ VERIFY_IS_APPROX(numext::tan(half(0.0f)), half(tanf(0.0f)));
+ VERIFY_IS_APPROX(tan(half(0.0f)), half(tanf(0.0f)));
+ // VERIFY_IS_APPROX(numext::tan(half(EIGEN_PI)), half(tanf(EIGEN_PI)));
+ // VERIFY_IS_APPROX(numext::tan(half(EIGEN_PI/2)), half(tanf(EIGEN_PI/2)));
+ //VERIFY_IS_APPROX(numext::tan(half(3*EIGEN_PI/2)), half(tanf(3*EIGEN_PI/2)));
+ VERIFY_IS_APPROX(numext::tan(half(3.5f)), half(tanf(3.5f)));
+}
+
+void test_array()
+{
+ typedef Array<half,1,Dynamic> ArrayXh;
+ Index size = internal::random<Index>(1,10);
+ Index i = internal::random<Index>(0,size-1);
+ ArrayXh a1 = ArrayXh::Random(size), a2 = ArrayXh::Random(size);
+ VERIFY_IS_APPROX( a1+a1, half(2)*a1 );
+ VERIFY( (a1.abs() >= half(0)).all() );
+ VERIFY_IS_APPROX( (a1*a1).sqrt(), a1.abs() );
+
+ VERIFY( ((a1.min)(a2) <= (a1.max)(a2)).all() );
+ a1(i) = half(-10.);
+ VERIFY_IS_EQUAL( a1.minCoeff(), half(-10.) );
+ a1(i) = half(10.);
+ VERIFY_IS_EQUAL( a1.maxCoeff(), half(10.) );
+
+ std::stringstream ss;
+ ss << a1;
+}
+
+void test_half_float()
+{
+ CALL_SUBTEST(test_conversion());
+ CALL_SUBTEST(test_numtraits());
+ CALL_SUBTEST(test_arithmetic());
+ CALL_SUBTEST(test_comparison());
+ CALL_SUBTEST(test_basic_functions());
+ CALL_SUBTEST(test_trigonometric_functions());
+ CALL_SUBTEST(test_array());
+}
diff --git a/test/incomplete_cholesky.cpp b/test/incomplete_cholesky.cpp
new file mode 100644
index 000000000..59ffe9259
--- /dev/null
+++ b/test/incomplete_cholesky.cpp
@@ -0,0 +1,65 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// 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
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// #define EIGEN_DONT_VECTORIZE
+// #define EIGEN_MAX_ALIGN_BYTES 0
+#include "sparse_solver.h"
+#include <Eigen/IterativeLinearSolvers>
+#include <unsupported/Eigen/IterativeSolvers>
+
+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, 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()
+{
+ 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/inplace_decomposition.cpp b/test/inplace_decomposition.cpp
new file mode 100644
index 000000000..92d0d91b6
--- /dev/null
+++ b/test/inplace_decomposition.cpp
@@ -0,0 +1,110 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 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
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/LU>
+#include <Eigen/Cholesky>
+#include <Eigen/QR>
+
+// This file test inplace decomposition through Ref<>, as supported by Cholesky, LU, and QR decompositions.
+
+template<typename DecType,typename MatrixType> void inplace(bool square = false, bool SPD = false)
+{
+ typedef typename MatrixType::Scalar Scalar;
+ typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> RhsType;
+ typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> ResType;
+
+ Index rows = MatrixType::RowsAtCompileTime==Dynamic ? internal::random<Index>(2,EIGEN_TEST_MAX_SIZE/2) : Index(MatrixType::RowsAtCompileTime);
+ Index cols = MatrixType::ColsAtCompileTime==Dynamic ? (square?rows:internal::random<Index>(2,rows)) : Index(MatrixType::ColsAtCompileTime);
+
+ MatrixType A = MatrixType::Random(rows,cols);
+ RhsType b = RhsType::Random(rows);
+ ResType x(cols);
+
+ if(SPD)
+ {
+ assert(square);
+ A.topRows(cols) = A.topRows(cols).adjoint() * A.topRows(cols);
+ A.diagonal().array() += 1e-3;
+ }
+
+ MatrixType A0 = A;
+ MatrixType A1 = A;
+
+ DecType dec(A);
+
+ // Check that the content of A has been modified
+ VERIFY_IS_NOT_APPROX( A, A0 );
+
+ // Check that the decomposition is correct:
+ if(rows==cols)
+ {
+ VERIFY_IS_APPROX( A0 * (x = dec.solve(b)), b );
+ }
+ else
+ {
+ VERIFY_IS_APPROX( A0.transpose() * A0 * (x = dec.solve(b)), A0.transpose() * b );
+ }
+
+ // Check that modifying A breaks the current dec:
+ A.setRandom();
+ if(rows==cols)
+ {
+ VERIFY_IS_NOT_APPROX( A0 * (x = dec.solve(b)), b );
+ }
+ else
+ {
+ VERIFY_IS_NOT_APPROX( A0.transpose() * A0 * (x = dec.solve(b)), A0.transpose() * b );
+ }
+
+ // Check that calling compute(A1) does not modify A1:
+ A = A0;
+ dec.compute(A1);
+ VERIFY_IS_EQUAL(A0,A1);
+ VERIFY_IS_NOT_APPROX( A, A0 );
+ if(rows==cols)
+ {
+ VERIFY_IS_APPROX( A0 * (x = dec.solve(b)), b );
+ }
+ else
+ {
+ VERIFY_IS_APPROX( A0.transpose() * A0 * (x = dec.solve(b)), A0.transpose() * b );
+ }
+}
+
+
+void test_inplace_decomposition()
+{
+ EIGEN_UNUSED typedef Matrix<double,4,3> Matrix43d;
+ for(int i = 0; i < g_repeat; i++) {
+ CALL_SUBTEST_1(( inplace<LLT<Ref<MatrixXd> >, MatrixXd>(true,true) ));
+ CALL_SUBTEST_1(( inplace<LLT<Ref<Matrix4d> >, Matrix4d>(true,true) ));
+
+ CALL_SUBTEST_2(( inplace<LDLT<Ref<MatrixXd> >, MatrixXd>(true,true) ));
+ CALL_SUBTEST_2(( inplace<LDLT<Ref<Matrix4d> >, Matrix4d>(true,true) ));
+
+ CALL_SUBTEST_3(( inplace<PartialPivLU<Ref<MatrixXd> >, MatrixXd>(true,false) ));
+ CALL_SUBTEST_3(( inplace<PartialPivLU<Ref<Matrix4d> >, Matrix4d>(true,false) ));
+
+ CALL_SUBTEST_4(( inplace<FullPivLU<Ref<MatrixXd> >, MatrixXd>(true,false) ));
+ CALL_SUBTEST_4(( inplace<FullPivLU<Ref<Matrix4d> >, Matrix4d>(true,false) ));
+
+ CALL_SUBTEST_5(( inplace<HouseholderQR<Ref<MatrixXd> >, MatrixXd>(false,false) ));
+ CALL_SUBTEST_5(( inplace<HouseholderQR<Ref<Matrix43d> >, Matrix43d>(false,false) ));
+
+ CALL_SUBTEST_6(( inplace<ColPivHouseholderQR<Ref<MatrixXd> >, MatrixXd>(false,false) ));
+ CALL_SUBTEST_6(( inplace<ColPivHouseholderQR<Ref<Matrix43d> >, Matrix43d>(false,false) ));
+
+ CALL_SUBTEST_7(( inplace<FullPivHouseholderQR<Ref<MatrixXd> >, MatrixXd>(false,false) ));
+ CALL_SUBTEST_7(( inplace<FullPivHouseholderQR<Ref<Matrix43d> >, Matrix43d>(false,false) ));
+
+ CALL_SUBTEST_8(( inplace<CompleteOrthogonalDecomposition<Ref<MatrixXd> >, MatrixXd>(false,false) ));
+ CALL_SUBTEST_8(( inplace<CompleteOrthogonalDecomposition<Ref<Matrix43d> >, Matrix43d>(false,false) ));
+ }
+}
diff --git a/test/integer_types.cpp b/test/integer_types.cpp
index 950f8e9be..a21f73a81 100644
--- a/test/integer_types.cpp
+++ b/test/integer_types.cpp
@@ -158,4 +158,12 @@ void test_integer_types()
CALL_SUBTEST_8( integer_type_tests(Matrix<unsigned long long, Dynamic, 5>(1, 5)) );
}
+#ifdef EIGEN_TEST_PART_9
+ VERIFY_IS_EQUAL(internal::scalar_div_cost<int>::value, 8);
+ VERIFY_IS_EQUAL(internal::scalar_div_cost<unsigned int>::value, 8);
+ if(sizeof(long)>sizeof(int)) {
+ VERIFY(internal::scalar_div_cost<long>::value > internal::scalar_div_cost<int>::value);
+ VERIFY(internal::scalar_div_cost<unsigned long>::value > internal::scalar_div_cost<int>::value);
+ }
+#endif
}
diff --git a/test/inverse.cpp b/test/inverse.cpp
index 8187b088d..5c6777a18 100644
--- a/test/inverse.cpp
+++ b/test/inverse.cpp
@@ -68,6 +68,15 @@ template<typename MatrixType> void inverse(const MatrixType& m)
VERIFY_IS_MUCH_SMALLER_THAN(abs(det-m3.determinant()), RealScalar(1));
m3.computeInverseWithCheck(m4, invertible);
VERIFY( rows==1 ? invertible : !invertible );
+
+ // check with submatrices
+ {
+ Matrix<Scalar, MatrixType::RowsAtCompileTime+1, MatrixType::RowsAtCompileTime+1, MatrixType::Options> m5;
+ m5.setRandom();
+ m5.topLeftCorner(rows,rows) = m1;
+ m2 = m5.template topLeftCorner<MatrixType::RowsAtCompileTime,MatrixType::ColsAtCompileTime>().inverse();
+ VERIFY_IS_APPROX( (m5.template topLeftCorner<MatrixType::RowsAtCompileTime,MatrixType::ColsAtCompileTime>()), m2.inverse() );
+ }
#endif
// check in-place inversion
@@ -93,12 +102,16 @@ void test_inverse()
CALL_SUBTEST_3( inverse(Matrix3f()) );
CALL_SUBTEST_4( inverse(Matrix4f()) );
CALL_SUBTEST_4( inverse(Matrix<float,4,4,DontAlign>()) );
+
s = internal::random<int>(50,320);
CALL_SUBTEST_5( inverse(MatrixXf(s,s)) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
+
s = internal::random<int>(25,100);
CALL_SUBTEST_6( inverse(MatrixXcd(s,s)) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
+
CALL_SUBTEST_7( inverse(Matrix4d()) );
CALL_SUBTEST_7( inverse(Matrix<double,4,4,DontAlign>()) );
}
- TEST_SET_BUT_UNUSED_VARIABLE(s)
}
diff --git a/test/is_same_dense.cpp b/test/is_same_dense.cpp
new file mode 100644
index 000000000..2c7838ce9
--- /dev/null
+++ b/test/is_same_dense.cpp
@@ -0,0 +1,33 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// 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/.
+
+#include "main.h"
+
+using internal::is_same_dense;
+
+void test_is_same_dense()
+{
+ 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));
+ VERIFY(is_same_dense(const_ref_m1,ref_m1));
+
+ 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 ColMatrixXd> const_ref_m1_row(m1.row(1));
+ VERIFY(!is_same_dense(m1.row(1),const_ref_m1_row));
+
+ 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/jacobisvd.cpp b/test/jacobisvd.cpp
index 12c556e59..7f5f71562 100644
--- a/test/jacobisvd.cpp
+++ b/test/jacobisvd.cpp
@@ -1,7 +1,7 @@
// 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) 2008-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
@@ -14,279 +14,47 @@
#include "main.h"
#include <Eigen/SVD>
-template<typename MatrixType, int QRPreconditioner>
-void jacobisvd_check_full(const MatrixType& m, const JacobiSVD<MatrixType, QRPreconditioner>& svd)
-{
- typedef typename MatrixType::Index Index;
- Index rows = m.rows();
- Index cols = m.cols();
-
- enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime
- };
-
- typedef typename MatrixType::Scalar Scalar;
- typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime> MatrixUType;
- typedef Matrix<Scalar, ColsAtCompileTime, ColsAtCompileTime> MatrixVType;
-
- MatrixType sigma = MatrixType::Zero(rows,cols);
- sigma.diagonal() = svd.singularValues().template cast<Scalar>();
- MatrixUType u = svd.matrixU();
- MatrixVType v = svd.matrixV();
-
- VERIFY_IS_APPROX(m, u * sigma * v.adjoint());
- VERIFY_IS_UNITARY(u);
- VERIFY_IS_UNITARY(v);
-}
-
-template<typename MatrixType, int QRPreconditioner>
-void jacobisvd_compare_to_full(const MatrixType& m,
- unsigned int computationOptions,
- const JacobiSVD<MatrixType, QRPreconditioner>& referenceSvd)
-{
- typedef typename MatrixType::Index Index;
- Index rows = m.rows();
- Index cols = m.cols();
- Index diagSize = (std::min)(rows, cols);
-
- JacobiSVD<MatrixType, QRPreconditioner> svd(m, computationOptions);
-
- VERIFY_IS_APPROX(svd.singularValues(), referenceSvd.singularValues());
- if(computationOptions & ComputeFullU)
- VERIFY_IS_APPROX(svd.matrixU(), referenceSvd.matrixU());
- if(computationOptions & ComputeThinU)
- VERIFY_IS_APPROX(svd.matrixU(), referenceSvd.matrixU().leftCols(diagSize));
- if(computationOptions & ComputeFullV)
- VERIFY_IS_APPROX(svd.matrixV(), referenceSvd.matrixV());
- if(computationOptions & ComputeThinV)
- VERIFY_IS_APPROX(svd.matrixV(), referenceSvd.matrixV().leftCols(diagSize));
-}
-
-template<typename MatrixType, int QRPreconditioner>
-void jacobisvd_solve(const MatrixType& m, unsigned int computationOptions)
-{
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::RealScalar RealScalar;
- typedef typename MatrixType::Index Index;
- Index rows = m.rows();
- Index cols = m.cols();
-
- enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime
- };
-
- typedef Matrix<Scalar, RowsAtCompileTime, Dynamic> RhsType;
- typedef Matrix<Scalar, ColsAtCompileTime, Dynamic> SolutionType;
-
- RhsType rhs = RhsType::Random(rows, internal::random<Index>(1, cols));
- JacobiSVD<MatrixType, QRPreconditioner> svd(m, computationOptions);
-
- if(internal::is_same<RealScalar,double>::value) svd.setThreshold(1e-8);
- else if(internal::is_same<RealScalar,float>::value) svd.setThreshold(1e-4);
-
- SolutionType x = svd.solve(rhs);
-
- RealScalar residual = (m*x-rhs).norm();
- // Check that there is no significantly better solution in the neighborhood of x
- if(!test_isMuchSmallerThan(residual,rhs.norm()))
- {
- // If the residual is very small, then we have an exact solution, so we are already good.
- for(int k=0;k<x.rows();++k)
- {
- SolutionType y(x);
- y.row(k).array() += 2*NumTraits<RealScalar>::epsilon();
- RealScalar residual_y = (m*y-rhs).norm();
- VERIFY( test_isApprox(residual_y,residual) || residual < residual_y );
-
- y.row(k) = x.row(k).array() - 2*NumTraits<RealScalar>::epsilon();
- residual_y = (m*y-rhs).norm();
- VERIFY( test_isApprox(residual_y,residual) || residual < residual_y );
- }
- }
-
- // evaluate normal equation which works also for least-squares solutions
- if(internal::is_same<RealScalar,double>::value)
- {
- // This test is not stable with single precision.
- // This is probably because squaring m signicantly affects the precision.
- VERIFY_IS_APPROX(m.adjoint()*m*x,m.adjoint()*rhs);
- }
-
- // check minimal norm solutions
- {
- // generate a full-rank m x n problem with m<n
- enum {
- RankAtCompileTime2 = ColsAtCompileTime==Dynamic ? Dynamic : (ColsAtCompileTime)/2+1,
- RowsAtCompileTime3 = ColsAtCompileTime==Dynamic ? Dynamic : ColsAtCompileTime+1
- };
- typedef Matrix<Scalar, RankAtCompileTime2, ColsAtCompileTime> MatrixType2;
- typedef Matrix<Scalar, RankAtCompileTime2, 1> RhsType2;
- typedef Matrix<Scalar, ColsAtCompileTime, RankAtCompileTime2> MatrixType2T;
- Index rank = RankAtCompileTime2==Dynamic ? internal::random<Index>(1,cols) : Index(RankAtCompileTime2);
- MatrixType2 m2(rank,cols);
- int guard = 0;
- do {
- m2.setRandom();
- } while(m2.jacobiSvd().setThreshold(test_precision<Scalar>()).rank()!=rank && (++guard)<10);
- VERIFY(guard<10);
- RhsType2 rhs2 = RhsType2::Random(rank);
- // use QR to find a reference minimal norm solution
- HouseholderQR<MatrixType2T> qr(m2.adjoint());
- Matrix<Scalar,Dynamic,1> tmp = qr.matrixQR().topLeftCorner(rank,rank).template triangularView<Upper>().adjoint().solve(rhs2);
- tmp.conservativeResize(cols);
- tmp.tail(cols-rank).setZero();
- SolutionType x21 = qr.householderQ() * tmp;
- // now check with SVD
- JacobiSVD<MatrixType2, ColPivHouseholderQRPreconditioner> svd2(m2, computationOptions);
- SolutionType x22 = svd2.solve(rhs2);
- VERIFY_IS_APPROX(m2*x21, rhs2);
- VERIFY_IS_APPROX(m2*x22, rhs2);
- VERIFY_IS_APPROX(x21, x22);
-
- // Now check with a rank deficient matrix
- typedef Matrix<Scalar, RowsAtCompileTime3, ColsAtCompileTime> MatrixType3;
- typedef Matrix<Scalar, RowsAtCompileTime3, 1> RhsType3;
- Index rows3 = RowsAtCompileTime3==Dynamic ? internal::random<Index>(rank+1,2*cols) : Index(RowsAtCompileTime3);
- Matrix<Scalar,RowsAtCompileTime3,Dynamic> C = Matrix<Scalar,RowsAtCompileTime3,Dynamic>::Random(rows3,rank);
- MatrixType3 m3 = C * m2;
- RhsType3 rhs3 = C * rhs2;
- JacobiSVD<MatrixType3, ColPivHouseholderQRPreconditioner> svd3(m3, computationOptions);
- SolutionType x3 = svd3.solve(rhs3);
- if(svd3.rank()!=rank) {
- std::cout << m3 << "\n\n";
- std::cout << svd3.singularValues().transpose() << "\n";
- std::cout << svd3.rank() << " == " << rank << "\n";
- std::cout << x21.norm() << " == " << x3.norm() << "\n";
- }
-// VERIFY_IS_APPROX(m3*x3, rhs3);
- VERIFY_IS_APPROX(m3*x21, rhs3);
- VERIFY_IS_APPROX(m2*x3, rhs2);
-
- VERIFY_IS_APPROX(x21, x3);
- }
-}
-
-template<typename MatrixType, int QRPreconditioner>
-void jacobisvd_test_all_computation_options(const MatrixType& m)
-{
- if (QRPreconditioner == NoQRPreconditioner && m.rows() != m.cols())
- return;
- JacobiSVD<MatrixType, QRPreconditioner> fullSvd(m, ComputeFullU|ComputeFullV);
- CALL_SUBTEST(( jacobisvd_check_full(m, fullSvd) ));
- CALL_SUBTEST(( jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeFullU | ComputeFullV) ));
-
- #if defined __INTEL_COMPILER
- // remark #111: statement is unreachable
- #pragma warning disable 111
- #endif
- if(QRPreconditioner == FullPivHouseholderQRPreconditioner)
- return;
-
- CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeFullU, fullSvd) ));
- CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeFullV, fullSvd) ));
- CALL_SUBTEST(( jacobisvd_compare_to_full(m, 0, fullSvd) ));
-
- if (MatrixType::ColsAtCompileTime == Dynamic) {
- // thin U/V are only available with dynamic number of columns
- CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeFullU|ComputeThinV, fullSvd) ));
- CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeThinV, fullSvd) ));
- CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeThinU|ComputeFullV, fullSvd) ));
- CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeThinU , fullSvd) ));
- CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeThinU|ComputeThinV, fullSvd) ));
- CALL_SUBTEST(( jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeFullU | ComputeThinV) ));
- CALL_SUBTEST(( jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeThinU | ComputeFullV) ));
- CALL_SUBTEST(( jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeThinU | ComputeThinV) ));
-
- // test reconstruction
- typedef typename MatrixType::Index Index;
- Index diagSize = (std::min)(m.rows(), m.cols());
- JacobiSVD<MatrixType, QRPreconditioner> svd(m, ComputeThinU | ComputeThinV);
- VERIFY_IS_APPROX(m, svd.matrixU().leftCols(diagSize) * svd.singularValues().asDiagonal() * svd.matrixV().leftCols(diagSize).adjoint());
- }
-}
+#define SVD_DEFAULT(M) JacobiSVD<M>
+#define SVD_FOR_MIN_NORM(M) JacobiSVD<M,ColPivHouseholderQRPreconditioner>
+#include "svd_common.h"
+// Check all variants of JacobiSVD
template<typename MatrixType>
void jacobisvd(const MatrixType& a = MatrixType(), bool pickrandom = true)
{
MatrixType m = a;
if(pickrandom)
- {
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::RealScalar RealScalar;
- typedef typename MatrixType::Index Index;
- Index diagSize = (std::min)(a.rows(), a.cols());
- RealScalar s = std::numeric_limits<RealScalar>::max_exponent10/4;
- s = internal::random<RealScalar>(1,s);
- Matrix<RealScalar,Dynamic,1> d = Matrix<RealScalar,Dynamic,1>::Random(diagSize);
- for(Index k=0; k<diagSize; ++k)
- d(k) = d(k)*std::pow(RealScalar(10),internal::random<RealScalar>(-s,s));
- m = Matrix<Scalar,Dynamic,Dynamic>::Random(a.rows(),diagSize) * d.asDiagonal() * Matrix<Scalar,Dynamic,Dynamic>::Random(diagSize,a.cols());
- // cancel some coeffs
- Index n = internal::random<Index>(0,m.size()-1);
- for(Index i=0; i<n; ++i)
- m(internal::random<Index>(0,m.rows()-1), internal::random<Index>(0,m.cols()-1)) = Scalar(0);
- }
+ svd_fill_random(m);
- CALL_SUBTEST(( jacobisvd_test_all_computation_options<MatrixType, FullPivHouseholderQRPreconditioner>(m) ));
- CALL_SUBTEST(( jacobisvd_test_all_computation_options<MatrixType, ColPivHouseholderQRPreconditioner>(m) ));
- CALL_SUBTEST(( jacobisvd_test_all_computation_options<MatrixType, HouseholderQRPreconditioner>(m) ));
- CALL_SUBTEST(( jacobisvd_test_all_computation_options<MatrixType, NoQRPreconditioner>(m) ));
+ CALL_SUBTEST(( svd_test_all_computation_options<JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner> >(m, true) )); // check full only
+ CALL_SUBTEST(( svd_test_all_computation_options<JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner> >(m, false) ));
+ CALL_SUBTEST(( svd_test_all_computation_options<JacobiSVD<MatrixType, HouseholderQRPreconditioner> >(m, false) ));
+ if(m.rows()==m.cols())
+ CALL_SUBTEST(( svd_test_all_computation_options<JacobiSVD<MatrixType, NoQRPreconditioner> >(m, false) ));
}
template<typename MatrixType> void jacobisvd_verify_assert(const MatrixType& m)
{
- typedef typename MatrixType::Scalar Scalar;
+ svd_verify_assert<JacobiSVD<MatrixType> >(m);
typedef typename MatrixType::Index Index;
Index rows = m.rows();
Index cols = m.cols();
enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
ColsAtCompileTime = MatrixType::ColsAtCompileTime
};
- typedef Matrix<Scalar, RowsAtCompileTime, 1> RhsType;
-
- RhsType rhs(rows);
-
- JacobiSVD<MatrixType> svd;
- VERIFY_RAISES_ASSERT(svd.matrixU())
- VERIFY_RAISES_ASSERT(svd.singularValues())
- VERIFY_RAISES_ASSERT(svd.matrixV())
- VERIFY_RAISES_ASSERT(svd.solve(rhs))
MatrixType a = MatrixType::Zero(rows, cols);
a.setZero();
- svd.compute(a, 0);
- VERIFY_RAISES_ASSERT(svd.matrixU())
- VERIFY_RAISES_ASSERT(svd.matrixV())
- svd.singularValues();
- VERIFY_RAISES_ASSERT(svd.solve(rhs))
if (ColsAtCompileTime == Dynamic)
{
- svd.compute(a, ComputeThinU);
- svd.matrixU();
- VERIFY_RAISES_ASSERT(svd.matrixV())
- VERIFY_RAISES_ASSERT(svd.solve(rhs))
-
- svd.compute(a, ComputeThinV);
- svd.matrixV();
- VERIFY_RAISES_ASSERT(svd.matrixU())
- VERIFY_RAISES_ASSERT(svd.solve(rhs))
-
JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner> svd_fullqr;
VERIFY_RAISES_ASSERT(svd_fullqr.compute(a, ComputeFullU|ComputeThinV))
VERIFY_RAISES_ASSERT(svd_fullqr.compute(a, ComputeThinU|ComputeThinV))
VERIFY_RAISES_ASSERT(svd_fullqr.compute(a, ComputeThinU|ComputeFullV))
}
- else
- {
- VERIFY_RAISES_ASSERT(svd.compute(a, ComputeThinU))
- VERIFY_RAISES_ASSERT(svd.compute(a, ComputeThinV))
- }
}
template<typename MatrixType>
@@ -302,126 +70,17 @@ void jacobisvd_method()
VERIFY_IS_APPROX(m.jacobiSvd(ComputeFullU|ComputeFullV).solve(m), m);
}
-// work around stupid msvc error when constructing at compile time an expression that involves
-// a division by zero, even if the numeric type has floating point
-template<typename Scalar>
-EIGEN_DONT_INLINE Scalar zero() { return Scalar(0); }
-
-// workaround aggressive optimization in ICC
-template<typename T> EIGEN_DONT_INLINE T sub(T a, T b) { return a - b; }
-
-template<typename MatrixType>
-void jacobisvd_inf_nan()
-{
- // all this function does is verify we don't iterate infinitely on nan/inf values
-
- JacobiSVD<MatrixType> svd;
- typedef typename MatrixType::Scalar Scalar;
- Scalar some_inf = Scalar(1) / zero<Scalar>();
- VERIFY(sub(some_inf, some_inf) != sub(some_inf, some_inf));
- svd.compute(MatrixType::Constant(10,10,some_inf), ComputeFullU | ComputeFullV);
-
- Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
- VERIFY(nan != nan);
- svd.compute(MatrixType::Constant(10,10,nan), ComputeFullU | ComputeFullV);
-
- MatrixType m = MatrixType::Zero(10,10);
- m(internal::random<int>(0,9), internal::random<int>(0,9)) = some_inf;
- svd.compute(m, ComputeFullU | ComputeFullV);
-
- m = MatrixType::Zero(10,10);
- m(internal::random<int>(0,9), internal::random<int>(0,9)) = nan;
- svd.compute(m, ComputeFullU | ComputeFullV);
-
- // regression test for bug 791
- m.resize(3,3);
- m << 0, 2*NumTraits<Scalar>::epsilon(), 0.5,
- 0, -0.5, 0,
- nan, 0, 0;
- svd.compute(m, ComputeFullU | ComputeFullV);
-}
-
-// Regression test for bug 286: JacobiSVD loops indefinitely with some
-// matrices containing denormal numbers.
-void jacobisvd_bug286()
-{
-#if defined __INTEL_COMPILER
-// shut up warning #239: floating point underflow
-#pragma warning push
-#pragma warning disable 239
-#endif
- Matrix2d M;
- M << -7.90884e-313, -4.94e-324,
- 0, 5.60844e-313;
-#if defined __INTEL_COMPILER
-#pragma warning pop
-#endif
- JacobiSVD<Matrix2d> svd;
- svd.compute(M); // just check we don't loop indefinitely
-}
-
-void jacobisvd_preallocate()
-{
- Vector3f v(3.f, 2.f, 1.f);
- MatrixXf m = v.asDiagonal();
-
- internal::set_is_malloc_allowed(false);
- VERIFY_RAISES_ASSERT(VectorXf tmp(10);)
- JacobiSVD<MatrixXf> svd;
- internal::set_is_malloc_allowed(true);
- svd.compute(m);
- VERIFY_IS_APPROX(svd.singularValues(), v);
-
- JacobiSVD<MatrixXf> svd2(3,3);
- internal::set_is_malloc_allowed(false);
- svd2.compute(m);
- internal::set_is_malloc_allowed(true);
- VERIFY_IS_APPROX(svd2.singularValues(), v);
- VERIFY_RAISES_ASSERT(svd2.matrixU());
- VERIFY_RAISES_ASSERT(svd2.matrixV());
- svd2.compute(m, ComputeFullU | ComputeFullV);
- VERIFY_IS_APPROX(svd2.matrixU(), Matrix3f::Identity());
- VERIFY_IS_APPROX(svd2.matrixV(), Matrix3f::Identity());
- internal::set_is_malloc_allowed(false);
- svd2.compute(m);
- internal::set_is_malloc_allowed(true);
-
- JacobiSVD<MatrixXf> svd3(3,3,ComputeFullU|ComputeFullV);
- internal::set_is_malloc_allowed(false);
- svd2.compute(m);
- internal::set_is_malloc_allowed(true);
- VERIFY_IS_APPROX(svd2.singularValues(), v);
- VERIFY_IS_APPROX(svd2.matrixU(), Matrix3f::Identity());
- VERIFY_IS_APPROX(svd2.matrixV(), Matrix3f::Identity());
- internal::set_is_malloc_allowed(false);
- svd2.compute(m, ComputeFullU|ComputeFullV);
- internal::set_is_malloc_allowed(true);
-}
-
void test_jacobisvd()
{
CALL_SUBTEST_3(( jacobisvd_verify_assert(Matrix3f()) ));
CALL_SUBTEST_4(( jacobisvd_verify_assert(Matrix4d()) ));
CALL_SUBTEST_7(( jacobisvd_verify_assert(MatrixXf(10,12)) ));
CALL_SUBTEST_8(( jacobisvd_verify_assert(MatrixXcd(7,5)) ));
+
+ CALL_SUBTEST_11(svd_all_trivial_2x2(jacobisvd<Matrix2cd>));
+ CALL_SUBTEST_12(svd_all_trivial_2x2(jacobisvd<Matrix2d>));
for(int i = 0; i < g_repeat; i++) {
- Matrix2cd m;
- m << 0, 1,
- 0, 1;
- CALL_SUBTEST_1(( jacobisvd(m, false) ));
- m << 1, 0,
- 1, 0;
- CALL_SUBTEST_1(( jacobisvd(m, false) ));
-
- Matrix2d n;
- n << 0, 0,
- 0, 0;
- CALL_SUBTEST_2(( jacobisvd(n, false) ));
- n << 0, 0,
- 0, 1;
- CALL_SUBTEST_2(( jacobisvd(n, false) ));
-
CALL_SUBTEST_3(( jacobisvd<Matrix3f>() ));
CALL_SUBTEST_4(( jacobisvd<Matrix4d>() ));
CALL_SUBTEST_5(( jacobisvd<Matrix<float,3,5> >() ));
@@ -440,8 +99,14 @@ void test_jacobisvd()
(void) c;
// Test on inf/nan matrix
- CALL_SUBTEST_7( jacobisvd_inf_nan<MatrixXf>() );
- CALL_SUBTEST_10( jacobisvd_inf_nan<MatrixXd>() );
+ CALL_SUBTEST_7( (svd_inf_nan<JacobiSVD<MatrixXf>, MatrixXf>()) );
+ CALL_SUBTEST_10( (svd_inf_nan<JacobiSVD<MatrixXd>, MatrixXd>()) );
+
+ // bug1395 test compile-time vectors as input
+ CALL_SUBTEST_13(( jacobisvd_verify_assert(Matrix<double,6,1>()) ));
+ CALL_SUBTEST_13(( jacobisvd_verify_assert(Matrix<double,1,6>()) ));
+ CALL_SUBTEST_13(( jacobisvd_verify_assert(Matrix<double,Dynamic,1>(r)) ));
+ CALL_SUBTEST_13(( jacobisvd_verify_assert(Matrix<double,1,Dynamic>(c)) ));
}
CALL_SUBTEST_7(( jacobisvd<MatrixXf>(MatrixXf(internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/2), internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/2))) ));
@@ -455,8 +120,7 @@ void test_jacobisvd()
CALL_SUBTEST_7( JacobiSVD<MatrixXf>(10,10) );
// Check that preallocation avoids subsequent mallocs
- CALL_SUBTEST_9( jacobisvd_preallocate() );
+ CALL_SUBTEST_9( svd_preallocate<void>() );
- // Regression check for bug 286
- CALL_SUBTEST_2( jacobisvd_bug286() );
+ CALL_SUBTEST_2( svd_underoverflow<void>() );
}
diff --git a/test/linearstructure.cpp b/test/linearstructure.cpp
index 618984d5c..17474af10 100644
--- a/test/linearstructure.cpp
+++ b/test/linearstructure.cpp
@@ -2,11 +2,15 @@
// for linear algebra.
//
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2014 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/.
+static bool g_called;
+#define EIGEN_SCALAR_BINARY_OP_PLUGIN { g_called |= (!internal::is_same<LhsScalar,RhsScalar>::value); }
+
#include "main.h"
template<typename MatrixType> void linearStructure(const MatrixType& m)
@@ -17,6 +21,7 @@ template<typename MatrixType> void linearStructure(const MatrixType& m)
*/
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
Index rows = m.rows();
Index cols = m.cols();
@@ -28,7 +33,7 @@ template<typename MatrixType> void linearStructure(const MatrixType& m)
m3(rows, cols);
Scalar s1 = internal::random<Scalar>();
- while (abs(s1)<1e-3) s1 = internal::random<Scalar>();
+ while (abs(s1)<RealScalar(1e-3)) s1 = internal::random<Scalar>();
Index r = internal::random<Index>(0, rows-1),
c = internal::random<Index>(0, cols-1);
@@ -68,8 +73,48 @@ template<typename MatrixType> void linearStructure(const MatrixType& m)
VERIFY_IS_APPROX(m1.block(0,0,rows,cols) * s1, m1 * s1);
}
+// Make sure that complex * real and real * complex are properly optimized
+template<typename MatrixType> void real_complex(DenseIndex rows = MatrixType::RowsAtCompileTime, DenseIndex cols = MatrixType::ColsAtCompileTime)
+{
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
+
+ RealScalar s = internal::random<RealScalar>();
+ MatrixType m1 = MatrixType::Random(rows, cols);
+
+ g_called = false;
+ VERIFY_IS_APPROX(s*m1, Scalar(s)*m1);
+ VERIFY(g_called && "real * matrix<complex> not properly optimized");
+
+ g_called = false;
+ VERIFY_IS_APPROX(m1*s, m1*Scalar(s));
+ VERIFY(g_called && "matrix<complex> * real not properly optimized");
+
+ g_called = false;
+ VERIFY_IS_APPROX(m1/s, m1/Scalar(s));
+ VERIFY(g_called && "matrix<complex> / real not properly optimized");
+
+ g_called = false;
+ VERIFY_IS_APPROX(s+m1.array(), Scalar(s)+m1.array());
+ VERIFY(g_called && "real + matrix<complex> not properly optimized");
+
+ g_called = false;
+ VERIFY_IS_APPROX(m1.array()+s, m1.array()+Scalar(s));
+ VERIFY(g_called && "matrix<complex> + real not properly optimized");
+
+ g_called = false;
+ VERIFY_IS_APPROX(s-m1.array(), Scalar(s)-m1.array());
+ VERIFY(g_called && "real - matrix<complex> not properly optimized");
+
+ g_called = false;
+ VERIFY_IS_APPROX(m1.array()-s, m1.array()-Scalar(s));
+ VERIFY(g_called && "matrix<complex> - real not properly optimized");
+}
+
void test_linearstructure()
{
+ g_called = true;
+ VERIFY(g_called); // avoid `unneeded-internal-declaration` warning.
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_1( linearStructure(Matrix<float, 1, 1>()) );
CALL_SUBTEST_2( linearStructure(Matrix2f()) );
@@ -80,5 +125,25 @@ void test_linearstructure()
CALL_SUBTEST_7( linearStructure(MatrixXi (internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
CALL_SUBTEST_8( linearStructure(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
CALL_SUBTEST_9( linearStructure(ArrayXXf (internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+ CALL_SUBTEST_10( linearStructure(ArrayXXcf (internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+
+ CALL_SUBTEST_11( real_complex<Matrix4cd>() );
+ CALL_SUBTEST_11( real_complex<MatrixXcf>(10,10) );
+ CALL_SUBTEST_11( real_complex<ArrayXXcf>(10,10) );
+ }
+
+#ifdef EIGEN_TEST_PART_4
+ {
+ // make sure that /=scalar and /scalar do not overflow
+ // rational: 1.0/4.94e-320 overflow, but m/4.94e-320 should not
+ Matrix4d m2, m3;
+ m3 = m2 = Matrix4d::Random()*1e-20;
+ m2 = m2 / 4.9e-320;
+ VERIFY_IS_APPROX(m2.cwiseQuotient(m2), Matrix4d::Ones());
+ m3 /= 4.9e-320;
+ VERIFY_IS_APPROX(m3.cwiseQuotient(m3), Matrix4d::Ones());
+
+
}
+#endif
}
diff --git a/test/lscg.cpp b/test/lscg.cpp
new file mode 100644
index 000000000..daa62a954
--- /dev/null
+++ b/test/lscg.cpp
@@ -0,0 +1,29 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Gael Guennebaud <g.gael@free.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/.
+
+#include "sparse_solver.h"
+#include <Eigen/IterativeLinearSolvers>
+
+template<typename T> void test_lscg_T()
+{
+ LeastSquaresConjugateGradient<SparseMatrix<T> > lscg_colmajor_diag;
+ LeastSquaresConjugateGradient<SparseMatrix<T>, IdentityPreconditioner> lscg_colmajor_I;
+
+ CALL_SUBTEST( check_sparse_square_solving(lscg_colmajor_diag) );
+ CALL_SUBTEST( check_sparse_square_solving(lscg_colmajor_I) );
+
+ CALL_SUBTEST( check_sparse_leastsquare_solving(lscg_colmajor_diag) );
+ CALL_SUBTEST( check_sparse_leastsquare_solving(lscg_colmajor_I) );
+}
+
+void test_lscg()
+{
+ CALL_SUBTEST_1(test_lscg_T<double>());
+ CALL_SUBTEST_2(test_lscg_T<std::complex<double> >());
+}
diff --git a/test/lu.cpp b/test/lu.cpp
index 374652694..9787f4d86 100644
--- a/test/lu.cpp
+++ b/test/lu.cpp
@@ -11,6 +11,11 @@
#include <Eigen/LU>
using namespace std;
+template<typename MatrixType>
+typename MatrixType::RealScalar matrix_l1_norm(const MatrixType& m) {
+ return m.cwiseAbs().colwise().sum().maxCoeff();
+}
+
template<typename MatrixType> void lu_non_invertible()
{
typedef typename MatrixType::Index Index;
@@ -92,6 +97,26 @@ template<typename MatrixType> void lu_non_invertible()
// test that the code, which does resize(), may be applied to an xpr
m2.block(0,0,m2.rows(),m2.cols()) = lu.solve(m3);
VERIFY_IS_APPROX(m3, m1*m2);
+
+ // test solve with transposed
+ m3 = MatrixType::Random(rows,cols2);
+ m2 = m1.transpose()*m3;
+ m3 = MatrixType::Random(rows,cols2);
+ lu.template _solve_impl_transposed<false>(m2, m3);
+ VERIFY_IS_APPROX(m2, m1.transpose()*m3);
+ m3 = MatrixType::Random(rows,cols2);
+ m3 = lu.transpose().solve(m2);
+ VERIFY_IS_APPROX(m2, m1.transpose()*m3);
+
+ // test solve with conjugate transposed
+ m3 = MatrixType::Random(rows,cols2);
+ m2 = m1.adjoint()*m3;
+ m3 = MatrixType::Random(rows,cols2);
+ lu.template _solve_impl_transposed<true>(m2, m3);
+ VERIFY_IS_APPROX(m2, m1.adjoint()*m3);
+ m3 = MatrixType::Random(rows,cols2);
+ m3 = lu.adjoint().solve(m2);
+ VERIFY_IS_APPROX(m2, m1.adjoint()*m3);
}
template<typename MatrixType> void lu_invertible()
@@ -100,9 +125,9 @@ template<typename MatrixType> void lu_invertible()
LU.h
*/
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
- DenseIndex size = MatrixType::RowsAtCompileTime;
+ Index size = MatrixType::RowsAtCompileTime;
if( size==Dynamic)
- size = internal::random<DenseIndex>(1,EIGEN_TEST_MAX_SIZE);
+ size = internal::random<Index>(1,EIGEN_TEST_MAX_SIZE);
MatrixType m1(size, size), m2(size, size), m3(size, size);
FullPivLU<MatrixType> lu;
@@ -123,7 +148,28 @@ template<typename MatrixType> void lu_invertible()
m3 = MatrixType::Random(size,size);
m2 = lu.solve(m3);
VERIFY_IS_APPROX(m3, m1*m2);
- VERIFY_IS_APPROX(m2, lu.inverse()*m3);
+ MatrixType m1_inverse = lu.inverse();
+ VERIFY_IS_APPROX(m2, m1_inverse*m3);
+
+ RealScalar rcond = (RealScalar(1) / matrix_l1_norm(m1)) / matrix_l1_norm(m1_inverse);
+ const RealScalar rcond_est = lu.rcond();
+ // Verify that the estimated condition number is within a factor of 10 of the
+ // truth.
+ VERIFY(rcond_est > rcond / 10 && rcond_est < rcond * 10);
+
+ // test solve with transposed
+ lu.template _solve_impl_transposed<false>(m3, m2);
+ VERIFY_IS_APPROX(m3, m1.transpose()*m2);
+ m3 = MatrixType::Random(size,size);
+ m3 = lu.transpose().solve(m2);
+ VERIFY_IS_APPROX(m2, m1.transpose()*m3);
+
+ // test solve with conjugate transposed
+ lu.template _solve_impl_transposed<true>(m3, m2);
+ VERIFY_IS_APPROX(m3, m1.adjoint()*m2);
+ m3 = MatrixType::Random(size,size);
+ m3 = lu.adjoint().solve(m2);
+ VERIFY_IS_APPROX(m2, m1.adjoint()*m3);
// Regression test for Bug 302
MatrixType m4 = MatrixType::Random(size,size);
@@ -136,14 +182,39 @@ template<typename MatrixType> void lu_partial_piv()
PartialPivLU.h
*/
typedef typename MatrixType::Index Index;
- Index rows = internal::random<Index>(1,4);
- Index cols = rows;
+ typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
+ Index size = internal::random<Index>(1,4);
- MatrixType m1(cols, rows);
+ MatrixType m1(size, size), m2(size, size), m3(size, size);
m1.setRandom();
PartialPivLU<MatrixType> plu(m1);
VERIFY_IS_APPROX(m1, plu.reconstructedMatrix());
+
+ m3 = MatrixType::Random(size,size);
+ m2 = plu.solve(m3);
+ VERIFY_IS_APPROX(m3, m1*m2);
+ MatrixType m1_inverse = plu.inverse();
+ VERIFY_IS_APPROX(m2, m1_inverse*m3);
+
+ RealScalar rcond = (RealScalar(1) / matrix_l1_norm(m1)) / matrix_l1_norm(m1_inverse);
+ const RealScalar rcond_est = plu.rcond();
+ // Verify that the estimate is within a factor of 10 of the truth.
+ VERIFY(rcond_est > rcond / 10 && rcond_est < rcond * 10);
+
+ // test solve with transposed
+ plu.template _solve_impl_transposed<false>(m3, m2);
+ VERIFY_IS_APPROX(m3, m1.transpose()*m2);
+ m3 = MatrixType::Random(size,size);
+ m3 = plu.transpose().solve(m2);
+ VERIFY_IS_APPROX(m2, m1.transpose()*m3);
+
+ // test solve with conjugate transposed
+ plu.template _solve_impl_transposed<true>(m3, m2);
+ VERIFY_IS_APPROX(m3, m1.adjoint()*m2);
+ m3 = MatrixType::Random(size,size);
+ m3 = plu.adjoint().solve(m2);
+ VERIFY_IS_APPROX(m2, m1.adjoint()*m3);
}
template<typename MatrixType> void lu_verify_assert()
diff --git a/test/main.h b/test/main.h
index 664204866..25d2dcf43 100644
--- a/test/main.h
+++ b/test/main.h
@@ -41,7 +41,14 @@
#include <complex>
#include <deque>
#include <queue>
+#include <cassert>
#include <list>
+#if __cplusplus >= 201103L
+#include <random>
+#ifdef EIGEN_USE_THREADS
+#include <future>
+#endif
+#endif
// To test that all calls from Eigen code to std::min() and std::max() are
// protected by parenthesis against macro expansion, the min()/max() macros
@@ -49,14 +56,48 @@
// compiler error.
#define min(A,B) please_protect_your_min_with_parentheses
#define max(A,B) please_protect_your_max_with_parentheses
+#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
#define B0 FORBIDDEN_IDENTIFIER
+// Unit tests calling Eigen's blas library must preserve the default blocking size
+// to avoid troubles.
+#ifndef EIGEN_NO_DEBUG_SMALL_PRODUCT_BLOCKS
+#define EIGEN_DEBUG_SMALL_PRODUCT_BLOCKS
+#endif
// shuts down ICC's remark #593: variable "XXX" was set but never used
-#define TEST_SET_BUT_UNUSED_VARIABLE(X) X = X + 0;
+#define TEST_SET_BUT_UNUSED_VARIABLE(X) EIGEN_UNUSED_VARIABLE(X)
+
+#ifdef TEST_ENABLE_TEMPORARY_TRACKING
+
+static long int nb_temporaries;
+static long int nb_temporaries_on_assert = -1;
+
+inline void on_temporary_creation(long int size) {
+ // here's a great place to set a breakpoint when debugging failures in this test!
+ if(size!=0) nb_temporaries++;
+ if(nb_temporaries_on_assert>0) assert(nb_temporaries<nb_temporaries_on_assert);
+}
+
+#define EIGEN_DENSE_STORAGE_CTOR_PLUGIN { on_temporary_creation(size); }
+
+#define VERIFY_EVALUATION_COUNT(XPR,N) {\
+ nb_temporaries = 0; \
+ XPR; \
+ if(nb_temporaries!=N) { std::cerr << "nb_temporaries == " << nb_temporaries << "\n"; }\
+ VERIFY( (#XPR) && nb_temporaries==N ); \
+ }
+
+#endif
// the following file is automatically generated by cmake
#include "split_test_helper.h"
@@ -71,7 +112,7 @@
#endif
// bounds integer values for AltiVec
-#ifdef __ALTIVEC__
+#if defined(__ALTIVEC__) || defined(__VSX__)
#define EIGEN_MAKING_DOCS
#endif
@@ -84,16 +125,26 @@
namespace Eigen
{
static std::vector<std::string> g_test_stack;
+ // level == 0 <=> abort if test fail
+ // level >= 1 <=> warning message to std::cerr if test fail
+ static int g_test_level = 0;
static int g_repeat;
static unsigned int g_seed;
static bool g_has_set_repeat, g_has_set_seed;
}
+#define TRACK std::cerr << __FILE__ << " " << __LINE__ << std::endl
+// #define TRACK while()
+
#define EI_PP_MAKE_STRING2(S) #S
#define EI_PP_MAKE_STRING(S) EI_PP_MAKE_STRING2(S)
#define EIGEN_DEFAULT_IO_FORMAT IOFormat(4, 0, " ", "\n", "", "", "", "")
+#if (defined(_CPPUNWIND) || defined(__EXCEPTIONS)) && !defined(__CUDA_ARCH__)
+ #define EIGEN_EXCEPTIONS
+#endif
+
#ifndef EIGEN_NO_ASSERTION_CHECKING
namespace Eigen
@@ -135,33 +186,35 @@ namespace Eigen
if(report_on_cerr_on_assert_failure) \
std::cerr << #a << " " __FILE__ << "(" << __LINE__ << ")\n"; \
Eigen::no_more_assert = true; \
- throw Eigen::eigen_assert_exception(); \
+ EIGEN_THROW_X(Eigen::eigen_assert_exception()); \
} \
else if (Eigen::internal::push_assert) \
{ \
eigen_assert_list.push_back(std::string(EI_PP_MAKE_STRING(__FILE__) " (" EI_PP_MAKE_STRING(__LINE__) ") : " #a) ); \
}
+ #ifdef EIGEN_EXCEPTIONS
#define VERIFY_RAISES_ASSERT(a) \
{ \
Eigen::no_more_assert = false; \
- Eigen::eigen_assert_list.clear(); \
- Eigen::internal::push_assert = true; \
+ Eigen::eigen_assert_list.clear(); \
+ Eigen::internal::push_assert = true; \
Eigen::report_on_cerr_on_assert_failure = false; \
try { \
a; \
std::cerr << "One of the following asserts should have been triggered:\n"; \
- for (uint ai=0 ; ai<eigen_assert_list.size() ; ++ai) \
- std::cerr << " " << eigen_assert_list[ai] << "\n"; \
+ for (uint ai=0 ; ai<eigen_assert_list.size() ; ++ai) \
+ std::cerr << " " << eigen_assert_list[ai] << "\n"; \
VERIFY(Eigen::should_raise_an_assert && # a); \
- } catch (Eigen::eigen_assert_exception) { \
- Eigen::internal::push_assert = false; VERIFY(true); \
+ } catch (Eigen::eigen_assert_exception) { \
+ Eigen::internal::push_assert = false; VERIFY(true); \
} \
Eigen::report_on_cerr_on_assert_failure = true; \
- Eigen::internal::push_assert = false; \
+ Eigen::internal::push_assert = false; \
}
+ #endif //EIGEN_EXCEPTIONS
- #else // EIGEN_DEBUG_ASSERTS
+ #elif !defined(__CUDACC__) // EIGEN_DEBUG_ASSERTS
// see bug 89. The copy_bool here is working around a bug in gcc <= 4.3
#define eigen_assert(a) \
if( (!Eigen::internal::copy_bool(a)) && (!no_more_assert) )\
@@ -170,22 +223,30 @@ namespace Eigen
if(report_on_cerr_on_assert_failure) \
eigen_plain_assert(a); \
else \
- throw Eigen::eigen_assert_exception(); \
+ EIGEN_THROW_X(Eigen::eigen_assert_exception()); \
}
- #define VERIFY_RAISES_ASSERT(a) { \
+ #ifdef EIGEN_EXCEPTIONS
+ #define VERIFY_RAISES_ASSERT(a) { \
Eigen::no_more_assert = false; \
Eigen::report_on_cerr_on_assert_failure = false; \
try { \
a; \
VERIFY(Eigen::should_raise_an_assert && # a); \
} \
- catch (Eigen::eigen_assert_exception&) { VERIFY(true); } \
+ catch (Eigen::eigen_assert_exception&) { VERIFY(true); } \
Eigen::report_on_cerr_on_assert_failure = true; \
}
-
+ #endif //EIGEN_EXCEPTIONS
#endif // EIGEN_DEBUG_ASSERTS
+#ifndef VERIFY_RAISES_ASSERT
+ #define VERIFY_RAISES_ASSERT(a) \
+ std::cout << "Can't VERIFY_RAISES_ASSERT( " #a " ) with exceptions disabled\n";
+#endif
+
+ #if !defined(__CUDACC__)
#define EIGEN_USE_CUSTOM_ASSERT
+ #endif
#else // EIGEN_NO_ASSERTION_CHECKING
@@ -201,6 +262,8 @@ inline void verify_impl(bool condition, const char *testname, const char *file,
{
if (!condition)
{
+ if(Eigen::g_test_level>0)
+ std::cerr << "WARNING: ";
std::cerr << "Test " << testname << " failed in " << file << " (" << line << ")"
<< std::endl << " " << condition_as_string << std::endl;
std::cerr << "Stack:\n";
@@ -208,14 +271,20 @@ inline void verify_impl(bool condition, const char *testname, const char *file,
for(int i=test_stack_size-1; i>=0; --i)
std::cerr << " - " << Eigen::g_test_stack[i] << "\n";
std::cerr << "\n";
- abort();
+ if(Eigen::g_test_level==0)
+ abort();
}
}
#define VERIFY(a) ::verify_impl(a, g_test_stack.back().c_str(), __FILE__, __LINE__, EI_PP_MAKE_STRING(a))
-#define VERIFY_IS_EQUAL(a, b) VERIFY(test_is_equal(a, b))
-#define VERIFY_IS_APPROX(a, b) VERIFY(test_isApprox(a, b))
+#define VERIFY_GE(a, b) ::verify_impl(a >= b, g_test_stack.back().c_str(), __FILE__, __LINE__, EI_PP_MAKE_STRING(a >= b))
+#define VERIFY_LE(a, b) ::verify_impl(a <= b, g_test_stack.back().c_str(), __FILE__, __LINE__, EI_PP_MAKE_STRING(a <= b))
+
+
+#define VERIFY_IS_EQUAL(a, b) VERIFY(test_is_equal(a, b, true))
+#define VERIFY_IS_NOT_EQUAL(a, b) VERIFY(test_is_equal(a, b, false))
+#define VERIFY_IS_APPROX(a, b) VERIFY(verifyIsApprox(a, b))
#define VERIFY_IS_NOT_APPROX(a, b) VERIFY(!test_isApprox(a, b))
#define VERIFY_IS_MUCH_SMALLER_THAN(a, b) VERIFY(test_isMuchSmallerThan(a, b))
#define VERIFY_IS_NOT_MUCH_SMALLER_THAN(a, b) VERIFY(!test_isMuchSmallerThan(a, b))
@@ -236,9 +305,10 @@ namespace Eigen {
template<typename T> inline typename NumTraits<T>::Real test_precision() { return NumTraits<T>::dummy_precision(); }
template<> inline float test_precision<float>() { return 1e-3f; }
template<> inline double test_precision<double>() { return 1e-6; }
+template<> inline long double test_precision<long double>() { return 1e-6l; }
template<> inline float test_precision<std::complex<float> >() { return test_precision<float>(); }
template<> inline double test_precision<std::complex<double> >() { return test_precision<double>(); }
-template<> inline long double test_precision<long double>() { return 1e-6; }
+template<> inline long double test_precision<std::complex<long double> >() { return test_precision<long double>(); }
inline bool test_isApprox(const int& a, const int& b)
{ return internal::isApprox(a, b, test_precision<int>()); }
@@ -253,14 +323,15 @@ inline bool test_isMuchSmallerThan(const float& a, const float& b)
{ return internal::isMuchSmallerThan(a, b, test_precision<float>()); }
inline bool test_isApproxOrLessThan(const float& a, const float& b)
{ return internal::isApproxOrLessThan(a, b, test_precision<float>()); }
+
inline bool test_isApprox(const double& a, const double& b)
{ return internal::isApprox(a, b, test_precision<double>()); }
-
inline bool test_isMuchSmallerThan(const double& a, const double& b)
{ return internal::isMuchSmallerThan(a, b, test_precision<double>()); }
inline bool test_isApproxOrLessThan(const double& a, const double& b)
{ return internal::isApproxOrLessThan(a, b, test_precision<double>()); }
+#ifndef EIGEN_TEST_NO_COMPLEX
inline bool test_isApprox(const std::complex<float>& a, const std::complex<float>& b)
{ return internal::isApprox(a, b, test_precision<std::complex<float> >()); }
inline bool test_isMuchSmallerThan(const std::complex<float>& a, const std::complex<float>& b)
@@ -271,6 +342,15 @@ 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)
{
bool ret = internal::isApprox(a, b, test_precision<long double>());
@@ -284,13 +364,127 @@ inline bool test_isMuchSmallerThan(const long double& a, const long double& b)
{ return internal::isMuchSmallerThan(a, b, test_precision<long double>()); }
inline bool test_isApproxOrLessThan(const long double& a, const long double& b)
{ return internal::isApproxOrLessThan(a, b, test_precision<long double>()); }
+#endif // EIGEN_TEST_NO_LONGDOUBLE
+
+inline bool test_isApprox(const half& a, const half& b)
+{ return internal::isApprox(a, b, test_precision<half>()); }
+inline bool test_isMuchSmallerThan(const half& a, const half& b)
+{ return internal::isMuchSmallerThan(a, b, test_precision<half>()); }
+inline bool test_isApproxOrLessThan(const half& a, const half& b)
+{ return internal::isApproxOrLessThan(a, b, test_precision<half>()); }
+
+// test_relative_error returns the relative difference between a and b as a real scalar as used in isApprox.
+template<typename T1,typename T2>
+typename NumTraits<typename T1::RealScalar>::NonInteger test_relative_error(const EigenBase<T1> &a, const EigenBase<T2> &b)
+{
+ using std::sqrt;
+ typedef typename NumTraits<typename T1::RealScalar>::NonInteger RealScalar;
+ typename internal::nested_eval<T1,2>::type ea(a.derived());
+ typename internal::nested_eval<T2,2>::type eb(b.derived());
+ return sqrt(RealScalar((ea-eb).cwiseAbs2().sum()) / RealScalar((std::min)(eb.cwiseAbs2().sum(),ea.cwiseAbs2().sum())));
+}
+
+template<typename T1,typename T2>
+typename T1::RealScalar test_relative_error(const T1 &a, const T2 &b, const typename T1::Coefficients* = 0)
+{
+ return test_relative_error(a.coeffs(), b.coeffs());
+}
+
+template<typename T1,typename T2>
+typename T1::Scalar test_relative_error(const T1 &a, const T2 &b, const typename T1::MatrixType* = 0)
+{
+ return test_relative_error(a.matrix(), b.matrix());
+}
+
+template<typename S, int D>
+S test_relative_error(const Translation<S,D> &a, const Translation<S,D> &b)
+{
+ return test_relative_error(a.vector(), b.vector());
+}
+
+template <typename S, int D, int O>
+S test_relative_error(const ParametrizedLine<S,D,O> &a, const ParametrizedLine<S,D,O> &b)
+{
+ return (std::max)(test_relative_error(a.origin(), b.origin()), test_relative_error(a.origin(), b.origin()));
+}
+
+template <typename S, int D>
+S test_relative_error(const AlignedBox<S,D> &a, const AlignedBox<S,D> &b)
+{
+ return (std::max)(test_relative_error((a.min)(), (b.min)()), test_relative_error((a.max)(), (b.max)()));
+}
+
+template<typename Derived> class SparseMatrixBase;
+template<typename T1,typename T2>
+typename T1::RealScalar test_relative_error(const MatrixBase<T1> &a, const SparseMatrixBase<T2> &b)
+{
+ return test_relative_error(a,b.toDense());
+}
+
+template<typename Derived> class SparseMatrixBase;
+template<typename T1,typename T2>
+typename T1::RealScalar test_relative_error(const SparseMatrixBase<T1> &a, const MatrixBase<T2> &b)
+{
+ return test_relative_error(a.toDense(),b);
+}
+
+template<typename Derived> class SparseMatrixBase;
+template<typename T1,typename T2>
+typename T1::RealScalar test_relative_error(const SparseMatrixBase<T1> &a, const SparseMatrixBase<T2> &b)
+{
+ return test_relative_error(a.toDense(),b.toDense());
+}
+
+template<typename T1,typename T2>
+typename NumTraits<typename NumTraits<T1>::Real>::NonInteger test_relative_error(const T1 &a, const T2 &b, typename internal::enable_if<internal::is_arithmetic<typename NumTraits<T1>::Real>::value, T1>::type* = 0)
+{
+ typedef typename NumTraits<typename NumTraits<T1>::Real>::NonInteger RealScalar;
+ return numext::sqrt(RealScalar(numext::abs2(a-b))/RealScalar((numext::mini)(numext::abs2(a),numext::abs2(b))));
+}
+
+template<typename T>
+T test_relative_error(const Rotation2D<T> &a, const Rotation2D<T> &b)
+{
+ return test_relative_error(a.angle(), b.angle());
+}
+
+template<typename T>
+T test_relative_error(const AngleAxis<T> &a, const AngleAxis<T> &b)
+{
+ return (std::max)(test_relative_error(a.angle(), b.angle()), test_relative_error(a.axis(), b.axis()));
+}
template<typename Type1, typename Type2>
-inline bool test_isApprox(const Type1& a, const Type2& b)
+inline bool test_isApprox(const Type1& a, const Type2& b, typename Type1::Scalar* = 0) // Enabled for Eigen's type only
{
return a.isApprox(b, test_precision<typename Type1::Scalar>());
}
+// get_test_precision is a small wrapper to test_precision allowing to return the scalar precision for either scalars or expressions
+template<typename T>
+typename NumTraits<typename T::Scalar>::Real get_test_precision(const T&, const typename T::Scalar* = 0)
+{
+ return test_precision<typename NumTraits<typename T::Scalar>::Real>();
+}
+
+template<typename T>
+typename NumTraits<T>::Real get_test_precision(const T&,typename internal::enable_if<internal::is_arithmetic<typename NumTraits<T>::Real>::value, T>::type* = 0)
+{
+ return test_precision<typename NumTraits<T>::Real>();
+}
+
+// verifyIsApprox is a wrapper to test_isApprox that outputs the relative difference magnitude if the test fails.
+template<typename Type1, typename Type2>
+inline bool verifyIsApprox(const Type1& a, const Type2& b)
+{
+ bool ret = test_isApprox(a,b);
+ if(!ret)
+ {
+ std::cerr << "Difference too large wrt tolerance " << get_test_precision(a) << ", relative error is: " << test_relative_error(a,b) << std::endl;
+ }
+ return ret;
+}
+
// The idea behind this function is to compare the two scalars a and b where
// the scalar ref is a hint about the expected order of magnitude of a and b.
// WARNING: the scalar a and b must be positive
@@ -326,17 +520,17 @@ inline bool test_isUnitary(const MatrixBase<Derived>& m)
// Forward declaration to avoid ICC warning
template<typename T, typename U>
-bool test_is_equal(const T& actual, const U& expected);
+bool test_is_equal(const T& actual, const U& expected, bool expect_equal=true);
template<typename T, typename U>
-bool test_is_equal(const T& actual, const U& expected)
+bool test_is_equal(const T& actual, const U& expected, bool expect_equal)
{
- if (actual==expected)
+ if ((actual==expected) == expect_equal)
return true;
// false:
std::cerr
- << std::endl << " actual = " << actual
- << std::endl << " expected = " << expected << std::endl << std::endl;
+ << "\n actual = " << actual
+ << "\n expected " << (expect_equal ? "= " : "!=") << expected << "\n\n";
return false;
}
@@ -347,11 +541,10 @@ bool test_is_equal(const T& actual, const U& expected)
*/
// Forward declaration to avoid ICC warning
template<typename MatrixType>
-void createRandomPIMatrixOfRank(typename MatrixType::Index desired_rank, typename MatrixType::Index rows, typename MatrixType::Index cols, MatrixType& m);
+void createRandomPIMatrixOfRank(Index desired_rank, Index rows, Index cols, MatrixType& m);
template<typename MatrixType>
-void createRandomPIMatrixOfRank(typename MatrixType::Index desired_rank, typename MatrixType::Index rows, typename MatrixType::Index cols, MatrixType& m)
+void createRandomPIMatrixOfRank(Index desired_rank, Index rows, Index cols, MatrixType& m)
{
- typedef typename internal::traits<MatrixType>::Index Index;
typedef typename internal::traits<MatrixType>::Scalar Scalar;
enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
@@ -388,11 +581,10 @@ void createRandomPIMatrixOfRank(typename MatrixType::Index desired_rank, typenam
// Forward declaration to avoid ICC warning
template<typename PermutationVectorType>
-void randomPermutationVector(PermutationVectorType& v, typename PermutationVectorType::Index size);
+void randomPermutationVector(PermutationVectorType& v, Index size);
template<typename PermutationVectorType>
-void randomPermutationVector(PermutationVectorType& v, typename PermutationVectorType::Index size)
+void randomPermutationVector(PermutationVectorType& v, Index size)
{
- typedef typename PermutationVectorType::Index Index;
typedef typename PermutationVectorType::Scalar Scalar;
v.resize(size);
for(Index i = 0; i < size; ++i) v(i) = Scalar(i);
@@ -411,12 +603,7 @@ template<typename T> bool isNotNaN(const T& x)
return x==x;
}
-template<typename T> bool isNaN(const T& x)
-{
- return x!=x;
-}
-
-template<typename T> bool isInf(const T& x)
+template<typename T> bool isPlusInf(const T& x)
{
return x > NumTraits<T>::highest();
}
@@ -437,13 +624,15 @@ template<typename T> struct GetDifferentType<std::complex<T> >
// Forward declaration to avoid ICC warning
template<typename T> std::string type_name();
-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>"; }
+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<long double>() { return "long 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<long double> >() { return "complex<long 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)();
@@ -550,3 +739,8 @@ int main(int argc, char *argv[])
// remark #1572: floating-point equality and inequality comparisons are unreliable
#pragma warning disable 279 383 1418 1572
#endif
+
+#ifdef _MSC_VER
+ // 4503 - decorated name length exceeded, name was truncated
+ #pragma warning( disable : 4503)
+#endif
diff --git a/test/mapped_matrix.cpp b/test/mapped_matrix.cpp
index 58904fa37..6a84c5897 100644
--- a/test/mapped_matrix.cpp
+++ b/test/mapped_matrix.cpp
@@ -13,6 +13,8 @@
#include "main.h"
+#define EIGEN_TESTMAP_MAX_SIZE 256
+
template<typename VectorType> void map_class_vector(const VectorType& m)
{
typedef typename VectorType::Index Index;
@@ -20,23 +22,26 @@ template<typename VectorType> void map_class_vector(const VectorType& m)
Index size = m.size();
- // test Map.h
Scalar* array1 = internal::aligned_new<Scalar>(size);
Scalar* array2 = internal::aligned_new<Scalar>(size);
Scalar* array3 = new Scalar[size+1];
- Scalar* array3unaligned = size_t(array3)%16 == 0 ? array3+1 : array3;
+ Scalar* array3unaligned = (internal::UIntPtr(array3)%EIGEN_MAX_ALIGN_BYTES) == 0 ? array3+1 : array3;
+ Scalar array4[EIGEN_TESTMAP_MAX_SIZE];
- Map<VectorType, Aligned>(array1, size) = VectorType::Random(size);
- Map<VectorType, Aligned>(array2, size) = Map<VectorType,Aligned>(array1, size);
+ Map<VectorType, AlignedMax>(array1, size) = VectorType::Random(size);
+ Map<VectorType, AlignedMax>(array2, size) = Map<VectorType,AlignedMax>(array1, size);
Map<VectorType>(array3unaligned, size) = Map<VectorType>(array1, size);
- VectorType ma1 = Map<VectorType, Aligned>(array1, size);
- VectorType ma2 = Map<VectorType, Aligned>(array2, size);
+ Map<VectorType>(array4, size) = Map<VectorType,AlignedMax>(array1, size);
+ VectorType ma1 = Map<VectorType, AlignedMax>(array1, size);
+ VectorType ma2 = Map<VectorType, AlignedMax>(array2, size);
VectorType ma3 = Map<VectorType>(array3unaligned, size);
+ VectorType ma4 = Map<VectorType>(array4, size);
VERIFY_IS_EQUAL(ma1, ma2);
VERIFY_IS_EQUAL(ma1, ma3);
+ VERIFY_IS_EQUAL(ma1, ma4);
#ifdef EIGEN_VECTORIZE
- if(internal::packet_traits<Scalar>::Vectorizable)
- VERIFY_RAISES_ASSERT((Map<VectorType,Aligned>(array3unaligned, size)))
+ if(internal::packet_traits<Scalar>::Vectorizable && size>=AlignedMax)
+ VERIFY_RAISES_ASSERT((Map<VectorType,AlignedMax>(array3unaligned, size)))
#endif
internal::aligned_delete(array1, size);
@@ -50,23 +55,64 @@ template<typename MatrixType> void map_class_matrix(const MatrixType& m)
typedef typename MatrixType::Scalar Scalar;
Index rows = m.rows(), cols = m.cols(), size = rows*cols;
+ Scalar s1 = internal::random<Scalar>();
- // test Map.h
+ // array1 and array2 -> aligned heap allocation
Scalar* array1 = internal::aligned_new<Scalar>(size);
for(int i = 0; i < size; i++) array1[i] = Scalar(1);
Scalar* array2 = internal::aligned_new<Scalar>(size);
for(int i = 0; i < size; i++) array2[i] = Scalar(1);
+ // array3unaligned -> unaligned pointer to heap
Scalar* array3 = new Scalar[size+1];
for(int i = 0; i < size+1; i++) array3[i] = Scalar(1);
- Scalar* array3unaligned = size_t(array3)%16 == 0 ? array3+1 : array3;
- Map<MatrixType, Aligned>(array1, rows, cols) = MatrixType::Ones(rows,cols);
- Map<MatrixType>(array2, rows, cols) = Map<MatrixType>(array1, rows, cols);
- Map<MatrixType>(array3unaligned, rows, cols) = Map<MatrixType>(array1, rows, cols);
- MatrixType ma1 = Map<MatrixType>(array1, rows, cols);
- MatrixType ma2 = Map<MatrixType, Aligned>(array2, rows, cols);
+ Scalar* array3unaligned = internal::UIntPtr(array3)%EIGEN_MAX_ALIGN_BYTES == 0 ? array3+1 : array3;
+ Scalar array4[256];
+ if(size<=256)
+ for(int i = 0; i < size; i++) array4[i] = Scalar(1);
+
+ Map<MatrixType> map1(array1, rows, cols);
+ Map<MatrixType, AlignedMax> map2(array2, rows, cols);
+ Map<MatrixType> map3(array3unaligned, rows, cols);
+ Map<MatrixType> map4(array4, rows, cols);
+
+ VERIFY_IS_EQUAL(map1, MatrixType::Ones(rows,cols));
+ VERIFY_IS_EQUAL(map2, MatrixType::Ones(rows,cols));
+ VERIFY_IS_EQUAL(map3, MatrixType::Ones(rows,cols));
+ map1 = MatrixType::Random(rows,cols);
+ map2 = map1;
+ map3 = map1;
+ MatrixType ma1 = map1;
+ MatrixType ma2 = map2;
+ MatrixType ma3 = map3;
+ VERIFY_IS_EQUAL(map1, map2);
+ VERIFY_IS_EQUAL(map1, map3);
VERIFY_IS_EQUAL(ma1, ma2);
- MatrixType ma3 = Map<MatrixType>(array3unaligned, rows, cols);
VERIFY_IS_EQUAL(ma1, ma3);
+ VERIFY_IS_EQUAL(ma1, map3);
+
+ VERIFY_IS_APPROX(s1*map1, s1*map2);
+ VERIFY_IS_APPROX(s1*ma1, s1*ma2);
+ VERIFY_IS_EQUAL(s1*ma1, s1*ma3);
+ VERIFY_IS_APPROX(s1*map1, s1*map3);
+
+ map2 *= s1;
+ map3 *= s1;
+ VERIFY_IS_APPROX(s1*map1, map2);
+ VERIFY_IS_APPROX(s1*map1, map3);
+
+ if(size<=256)
+ {
+ VERIFY_IS_EQUAL(map4, MatrixType::Ones(rows,cols));
+ map4 = map1;
+ MatrixType ma4 = map4;
+ VERIFY_IS_EQUAL(map1, map4);
+ VERIFY_IS_EQUAL(ma1, map4);
+ VERIFY_IS_EQUAL(ma1, ma4);
+ VERIFY_IS_APPROX(s1*map1, s1*map4);
+
+ map4 *= s1;
+ VERIFY_IS_APPROX(s1*map1, map4);
+ }
internal::aligned_delete(array1, size);
internal::aligned_delete(array2, size);
@@ -80,11 +126,10 @@ template<typename VectorType> void map_static_methods(const VectorType& m)
Index size = m.size();
- // test Map.h
Scalar* array1 = internal::aligned_new<Scalar>(size);
Scalar* array2 = internal::aligned_new<Scalar>(size);
Scalar* array3 = new Scalar[size+1];
- Scalar* array3unaligned = size_t(array3)%16 == 0 ? array3+1 : array3;
+ Scalar* array3unaligned = internal::UIntPtr(array3)%EIGEN_MAX_ALIGN_BYTES == 0 ? array3+1 : array3;
VectorType::MapAligned(array1, size) = VectorType::Random(size);
VectorType::Map(array2, size) = VectorType::Map(array1, size);
@@ -109,9 +154,9 @@ template<typename PlainObjectType> void check_const_correctness(const PlainObjec
// verify that map-to-const don't have LvalueBit
typedef typename internal::add_const<PlainObjectType>::type ConstPlainObjectType;
VERIFY( !(internal::traits<Map<ConstPlainObjectType> >::Flags & LvalueBit) );
- VERIFY( !(internal::traits<Map<ConstPlainObjectType, Aligned> >::Flags & LvalueBit) );
+ VERIFY( !(internal::traits<Map<ConstPlainObjectType, AlignedMax> >::Flags & LvalueBit) );
VERIFY( !(Map<ConstPlainObjectType>::Flags & LvalueBit) );
- VERIFY( !(Map<ConstPlainObjectType, Aligned>::Flags & LvalueBit) );
+ VERIFY( !(Map<ConstPlainObjectType, AlignedMax>::Flags & LvalueBit) );
}
template<typename Scalar>
@@ -142,6 +187,7 @@ void test_mapped_matrix()
CALL_SUBTEST_1( map_class_vector(Matrix<float, 1, 1>()) );
CALL_SUBTEST_1( check_const_correctness(Matrix<float, 1, 1>()) );
CALL_SUBTEST_2( map_class_vector(Vector4d()) );
+ CALL_SUBTEST_2( map_class_vector(VectorXd(13)) );
CALL_SUBTEST_2( check_const_correctness(Matrix4d()) );
CALL_SUBTEST_3( map_class_vector(RowVector4f()) );
CALL_SUBTEST_4( map_class_vector(VectorXcf(8)) );
diff --git a/test/mapstaticmethods.cpp b/test/mapstaticmethods.cpp
index 5b512bde4..06272d106 100644
--- a/test/mapstaticmethods.cpp
+++ b/test/mapstaticmethods.cpp
@@ -69,7 +69,8 @@ struct mapstaticmethods_impl<PlainObjectType, true, false>
{
static void run(const PlainObjectType& m)
{
- int rows = m.rows(), cols = m.cols();
+ typedef typename PlainObjectType::Index Index;
+ Index rows = m.rows(), cols = m.cols();
int i = internal::random<int>(2,5), j = internal::random<int>(2,5);
@@ -115,7 +116,8 @@ struct mapstaticmethods_impl<PlainObjectType, true, true>
{
static void run(const PlainObjectType& v)
{
- int size = v.size();
+ typedef typename PlainObjectType::Index Index;
+ Index size = v.size();
int i = internal::random<int>(2,5);
diff --git a/test/mapstride.cpp b/test/mapstride.cpp
index b1dc9de2a..4858f8fea 100644
--- a/test/mapstride.cpp
+++ b/test/mapstride.cpp
@@ -23,7 +23,7 @@ template<int Alignment,typename VectorType> void map_class_vector(const VectorTy
Scalar* a_array = internal::aligned_new<Scalar>(arraysize+1);
Scalar* array = a_array;
if(Alignment!=Aligned)
- array = (Scalar*)(ptrdiff_t(a_array) + (internal::packet_traits<Scalar>::AlignedOnScalar?sizeof(Scalar):sizeof(typename NumTraits<Scalar>::Real)));
+ array = (Scalar*)(internal::IntPtr(a_array) + (internal::packet_traits<Scalar>::AlignedOnScalar?sizeof(Scalar):sizeof(typename NumTraits<Scalar>::Real)));
{
Map<VectorType, Alignment, InnerStride<3> > map(array, size);
@@ -56,16 +56,30 @@ template<int Alignment,typename MatrixType> void map_class_matrix(const MatrixTy
Index rows = _m.rows(), cols = _m.cols();
MatrixType m = MatrixType::Random(rows,cols);
+ Scalar s1 = internal::random<Scalar>();
Index arraysize = 2*(rows+4)*(cols+4);
- Scalar* a_array = internal::aligned_new<Scalar>(arraysize+1);
- Scalar* array = a_array;
+ Scalar* a_array1 = internal::aligned_new<Scalar>(arraysize+1);
+ Scalar* array1 = a_array1;
if(Alignment!=Aligned)
- array = (Scalar*)(ptrdiff_t(a_array) + (internal::packet_traits<Scalar>::AlignedOnScalar?sizeof(Scalar):sizeof(typename NumTraits<Scalar>::Real)));
+ array1 = (Scalar*)(internal::IntPtr(a_array1) + (internal::packet_traits<Scalar>::AlignedOnScalar?sizeof(Scalar):sizeof(typename NumTraits<Scalar>::Real)));
+ Scalar a_array2[256];
+ Scalar* array2 = a_array2;
+ if(Alignment!=Aligned)
+ array2 = (Scalar*)(internal::IntPtr(a_array2) + (internal::packet_traits<Scalar>::AlignedOnScalar?sizeof(Scalar):sizeof(typename NumTraits<Scalar>::Real)));
+ else
+ array2 = (Scalar*)(((internal::UIntPtr(a_array2)+EIGEN_MAX_ALIGN_BYTES-1)/EIGEN_MAX_ALIGN_BYTES)*EIGEN_MAX_ALIGN_BYTES);
+ Index maxsize2 = a_array2 - array2 + 256;
+
// test no inner stride and some dynamic outer stride
+ for(int k=0; k<2; ++k)
{
+ if(k==1 && (m.innerSize()+1)*m.outerSize() > maxsize2)
+ break;
+ Scalar* array = (k==0 ? array1 : array2);
+
Map<MatrixType, Alignment, OuterStride<Dynamic> > map(array, rows, cols, OuterStride<Dynamic>(m.innerSize()+1));
map = m;
VERIFY(map.outerStride() == map.innerSize()+1);
@@ -75,11 +89,19 @@ template<int Alignment,typename MatrixType> void map_class_matrix(const MatrixTy
VERIFY(array[map.outerStride()*i+j] == m.coeffByOuterInner(i,j));
VERIFY(map.coeffByOuterInner(i,j) == m.coeffByOuterInner(i,j));
}
+ VERIFY_IS_APPROX(s1*map,s1*m);
+ map *= s1;
+ VERIFY_IS_APPROX(map,s1*m);
}
// test no inner stride and an outer stride of +4. This is quite important as for fixed-size matrices,
// this allows to hit the special case where it's vectorizable.
+ for(int k=0; k<2; ++k)
{
+ if(k==1 && (m.innerSize()+4)*m.outerSize() > maxsize2)
+ break;
+ Scalar* array = (k==0 ? array1 : array2);
+
enum {
InnerSize = MatrixType::InnerSizeAtCompileTime,
OuterStrideAtCompileTime = InnerSize==Dynamic ? Dynamic : InnerSize+4
@@ -94,10 +116,18 @@ template<int Alignment,typename MatrixType> void map_class_matrix(const MatrixTy
VERIFY(array[map.outerStride()*i+j] == m.coeffByOuterInner(i,j));
VERIFY(map.coeffByOuterInner(i,j) == m.coeffByOuterInner(i,j));
}
+ VERIFY_IS_APPROX(s1*map,s1*m);
+ map *= s1;
+ VERIFY_IS_APPROX(map,s1*m);
}
// test both inner stride and outer stride
+ for(int k=0; k<2; ++k)
{
+ if(k==1 && (2*m.innerSize()+1)*(m.outerSize()*2) > maxsize2)
+ break;
+ Scalar* array = (k==0 ? array1 : array2);
+
Map<MatrixType, Alignment, Stride<Dynamic,Dynamic> > map(array, rows, cols, Stride<Dynamic,Dynamic>(2*m.innerSize()+1, 2));
map = m;
VERIFY(map.outerStride() == 2*map.innerSize()+1);
@@ -108,9 +138,12 @@ template<int Alignment,typename MatrixType> void map_class_matrix(const MatrixTy
VERIFY(array[map.outerStride()*i+map.innerStride()*j] == m.coeffByOuterInner(i,j));
VERIFY(map.coeffByOuterInner(i,j) == m.coeffByOuterInner(i,j));
}
+ VERIFY_IS_APPROX(s1*map,s1*m);
+ map *= s1;
+ VERIFY_IS_APPROX(map,s1*m);
}
- internal::aligned_delete(a_array, arraysize+1);
+ internal::aligned_delete(a_array1, arraysize+1);
}
void test_mapstride()
diff --git a/test/meta.cpp b/test/meta.cpp
index 3302c5887..b8dea68e8 100644
--- a/test/meta.cpp
+++ b/test/meta.cpp
@@ -9,6 +9,12 @@
#include "main.h"
+template<typename From, typename To>
+bool check_is_convertible(const From&, const To&)
+{
+ return internal::is_convertible<From,To>::value;
+}
+
void test_meta()
{
VERIFY((internal::conditional<(3<4),internal::true_type, internal::false_type>::type::value));
@@ -52,6 +58,24 @@ void test_meta()
VERIFY(( internal::is_same<const float,internal::remove_pointer<const float*>::type >::value));
VERIFY(( internal::is_same<float,internal::remove_pointer<float* const >::type >::value));
+ VERIFY(( internal::is_convertible<float,double>::value ));
+ VERIFY(( internal::is_convertible<int,double>::value ));
+ VERIFY(( internal::is_convertible<double,int>::value ));
+ VERIFY((!internal::is_convertible<std::complex<double>,double>::value ));
+ VERIFY(( internal::is_convertible<Array33f,Matrix3f>::value ));
+// VERIFY((!internal::is_convertible<Matrix3f,Matrix3d>::value )); //does not work because the conversion is prevented by a static assertion
+ VERIFY((!internal::is_convertible<Array33f,int>::value ));
+ VERIFY((!internal::is_convertible<MatrixXf,float>::value ));
+ {
+ float f;
+ MatrixXf A, B;
+ VectorXf a, b;
+ VERIFY(( check_is_convertible(a.dot(b), f) ));
+ VERIFY(( check_is_convertible(a.transpose()*b, f) ));
+ VERIFY((!check_is_convertible(A*B, f) ));
+ VERIFY(( check_is_convertible(A*B, A) ));
+ }
+
VERIFY(internal::meta_sqrt<1>::ret == 1);
#define VERIFY_META_SQRT(X) VERIFY(internal::meta_sqrt<X>::ret == int(std::sqrt(double(X))))
VERIFY_META_SQRT(2);
diff --git a/test/metis_support.cpp b/test/metis_support.cpp
index 932b04074..d87c56a13 100644
--- a/test/metis_support.cpp
+++ b/test/metis_support.cpp
@@ -3,24 +3,10 @@
//
// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
//
-// 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/>.
+// 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 "sparse_solver.h"
#include <Eigen/SparseLU>
#include <Eigen/MetisSupport>
diff --git a/test/mixingtypes.cpp b/test/mixingtypes.cpp
index 6c2f74875..ad9c2c652 100644
--- a/test/mixingtypes.cpp
+++ b/test/mixingtypes.cpp
@@ -1,7 +1,7 @@
// 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) 2008-2015 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
@@ -15,14 +15,26 @@
#define EIGEN_NO_STATIC_ASSERT // turn static asserts into runtime asserts in order to check them
#endif
-// #ifndef EIGEN_DONT_VECTORIZE
-// #define EIGEN_DONT_VECTORIZE // SSE intrinsics aren't designed to allow mixing types
-// #endif
+#if defined(EIGEN_TEST_PART_1) || defined(EIGEN_TEST_PART_2) || defined(EIGEN_TEST_PART_3)
+
+#ifndef EIGEN_DONT_VECTORIZE
+#define EIGEN_DONT_VECTORIZE
+#endif
+
+#endif
+
+static bool g_called;
+#define EIGEN_SCALAR_BINARY_OP_PLUGIN { g_called |= (!internal::is_same<LhsScalar,RhsScalar>::value); }
#include "main.h"
using namespace std;
+#define VERIFY_MIX_SCALAR(XPR,REF) \
+ g_called = false; \
+ VERIFY_IS_APPROX(XPR,REF); \
+ VERIFY( g_called && #XPR" not properly optimized");
+
template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
{
typedef std::complex<float> CF;
@@ -38,8 +50,10 @@ template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
Mat_f mf = Mat_f::Random(size,size);
Mat_d md = mf.template cast<double>();
+ //Mat_d rd = md;
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);
@@ -49,19 +63,59 @@ template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
complex<float> scf = internal::random<complex<float> >();
complex<double> scd = internal::random<complex<double> >();
-
mf+mf;
- VERIFY_RAISES_ASSERT(mf+md);
- VERIFY_RAISES_ASSERT(mf+mcf);
+
+ float epsf = std::sqrt(std::numeric_limits<float> ::min EIGEN_EMPTY ());
+ double epsd = std::sqrt(std::numeric_limits<double>::min EIGEN_EMPTY ());
+
+ while(std::abs(sf )<epsf) sf = internal::random<float>();
+ while(std::abs(sd )<epsd) sf = internal::random<double>();
+ while(std::abs(scf)<epsf) scf = internal::random<CF>();
+ while(std::abs(scd)<epsd) scd = internal::random<CD>();
+
+// VERIFY_RAISES_ASSERT(mf+md); // does not even compile
+
+#ifdef EIGEN_DONT_VECTORIZE
VERIFY_RAISES_ASSERT(vf=vd);
VERIFY_RAISES_ASSERT(vf+=vd);
- VERIFY_RAISES_ASSERT(mcd=md);
-
+#endif
+
// check scalar products
- VERIFY_IS_APPROX(vcf * sf , vcf * complex<float>(sf));
- VERIFY_IS_APPROX(sd * vcd, complex<double>(sd) * vcd);
- VERIFY_IS_APPROX(vf * scf , vf.template cast<complex<float> >() * scf);
- VERIFY_IS_APPROX(scd * vd, scd * vd.template cast<complex<double> >());
+ VERIFY_MIX_SCALAR(vcf * sf , vcf * complex<float>(sf));
+ VERIFY_MIX_SCALAR(sd * vcd , complex<double>(sd) * vcd);
+ VERIFY_MIX_SCALAR(vf * scf , vf.template cast<complex<float> >() * scf);
+ VERIFY_MIX_SCALAR(scd * vd , scd * vd.template cast<complex<double> >());
+
+ VERIFY_MIX_SCALAR(vcf * 2 , vcf * complex<float>(2));
+ VERIFY_MIX_SCALAR(vcf * 2.1 , vcf * complex<float>(2.1));
+ VERIFY_MIX_SCALAR(2 * vcf, vcf * complex<float>(2));
+ VERIFY_MIX_SCALAR(2.1 * vcf , vcf * complex<float>(2.1));
+
+ // check scalar quotients
+ VERIFY_MIX_SCALAR(vcf / sf , vcf / complex<float>(sf));
+ VERIFY_MIX_SCALAR(vf / scf , vf.template cast<complex<float> >() / scf);
+ VERIFY_MIX_SCALAR(vf.array() / scf, vf.template cast<complex<float> >().array() / scf);
+ VERIFY_MIX_SCALAR(scd / vd.array() , scd / vd.template cast<complex<double> >().array());
+
+ // check scalar increment
+ VERIFY_MIX_SCALAR(vcf.array() + sf , vcf.array() + complex<float>(sf));
+ VERIFY_MIX_SCALAR(sd + vcd.array(), complex<double>(sd) + vcd.array());
+ VERIFY_MIX_SCALAR(vf.array() + scf, vf.template cast<complex<float> >().array() + scf);
+ VERIFY_MIX_SCALAR(scd + vd.array() , scd + vd.template cast<complex<double> >().array());
+
+ // check scalar subtractions
+ VERIFY_MIX_SCALAR(vcf.array() - sf , vcf.array() - complex<float>(sf));
+ VERIFY_MIX_SCALAR(sd - vcd.array(), complex<double>(sd) - vcd.array());
+ VERIFY_MIX_SCALAR(vf.array() - scf, vf.template cast<complex<float> >().array() - scf);
+ VERIFY_MIX_SCALAR(scd - vd.array() , scd - vd.template cast<complex<double> >().array());
+
+ // check scalar powers
+ VERIFY_MIX_SCALAR( pow(vcf.array(), sf), Eigen::pow(vcf.array(), complex<float>(sf)) );
+ VERIFY_MIX_SCALAR( vcf.array().pow(sf) , Eigen::pow(vcf.array(), complex<float>(sf)) );
+ VERIFY_MIX_SCALAR( pow(sd, vcd.array()), Eigen::pow(complex<double>(sd), vcd.array()) );
+ VERIFY_MIX_SCALAR( Eigen::pow(vf.array(), scf), Eigen::pow(vf.template cast<complex<float> >().array(), scf) );
+ VERIFY_MIX_SCALAR( vf.array().pow(scf) , Eigen::pow(vf.template cast<complex<float> >().array(), scf) );
+ VERIFY_MIX_SCALAR( Eigen::pow(scd, vd.array()), Eigen::pow(scd, vd.template cast<complex<double> >().array()) );
// check dot product
vf.dot(vf);
@@ -75,6 +129,7 @@ template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
VERIFY_IS_APPROX(vcd.asDiagonal() * md, vcd.asDiagonal() * md.template cast<complex<double> >());
VERIFY_IS_APPROX(mcf * vf.asDiagonal(), mcf * vf.template cast<complex<float> >().asDiagonal());
VERIFY_IS_APPROX(md * vcd.asDiagonal(), md.template cast<complex<double> >() * vcd.asDiagonal());
+
// vd.asDiagonal() * mf; // does not even compile
// vcd.asDiagonal() * mf; // does not even compile
@@ -92,7 +147,6 @@ 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);
@@ -103,6 +157,20 @@ template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
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());
+ VERIFY_IS_APPROX(sf*mcf.adjoint()*mf.adjoint(), sf*mcf.adjoint()*mf.template cast<CF>().adjoint());
+ VERIFY_IS_APPROX(sf*mf*mcf.adjoint(), (sf*mf).template cast<CF>().eval()*mcf.adjoint());
+ VERIFY_IS_APPROX(sf*mcf*mf.adjoint(), sf*mcf*mf.template cast<CF>().adjoint());
+
VERIFY_IS_APPROX(sf*mf*vcf, (sf*mf).template cast<CF>().eval()*vcf);
VERIFY_IS_APPROX(scf*mf*vcf,(scf*mf.template cast<CF>()).eval()*vcf);
VERIFY_IS_APPROX(sf*mcf*vf, sf*mcf*vf.template cast<CF>());
@@ -122,11 +190,111 @@ 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*vcd.adjoint()*md.transpose().template triangularView<Upper>(), sd*vcd.adjoint()*md.transpose().template cast<CD>().eval().template triangularView<Upper>());
+ VERIFY_IS_APPROX(scd*vcd.adjoint()*md.transpose().template triangularView<Lower>(), scd*vcd.adjoint()*md.transpose().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>());
+ VERIFY_IS_APPROX( sd*vd.adjoint()*mcd.transpose().template triangularView<Lower>(), sd*vd.adjoint().template cast<CD>().eval()*mcd.transpose().template triangularView<Lower>());
+ VERIFY_IS_APPROX(scd*vd.adjoint()*mcd.transpose().template triangularView<Upper>(), scd*vd.adjoint().template cast<CD>().eval()*mcd.transpose().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>()));
+
+
+ VERIFY_IS_APPROX( md.array() * mcd.array(), md.template cast<CD>().eval().array() * mcd.array() );
+ VERIFY_IS_APPROX( mcd.array() * md.array(), mcd.array() * md.template cast<CD>().eval().array() );
+
+ VERIFY_IS_APPROX( md.array() + mcd.array(), md.template cast<CD>().eval().array() + mcd.array() );
+ VERIFY_IS_APPROX( mcd.array() + md.array(), mcd.array() + md.template cast<CD>().eval().array() );
+
+ VERIFY_IS_APPROX( md.array() - mcd.array(), md.template cast<CD>().eval().array() - mcd.array() );
+ VERIFY_IS_APPROX( mcd.array() - md.array(), mcd.array() - md.template cast<CD>().eval().array() );
+
+ if(mcd.array().abs().minCoeff()>epsd)
+ {
+ VERIFY_IS_APPROX( md.array() / mcd.array(), md.template cast<CD>().eval().array() / mcd.array() );
+ }
+ if(md.array().abs().minCoeff()>epsd)
+ {
+ VERIFY_IS_APPROX( mcd.array() / md.array(), mcd.array() / md.template cast<CD>().eval().array() );
+ }
+
+ if(md.array().abs().minCoeff()>epsd || mcd.array().abs().minCoeff()>epsd)
+ {
+ VERIFY_IS_APPROX( md.array().pow(mcd.array()), md.template cast<CD>().eval().array().pow(mcd.array()) );
+ VERIFY_IS_APPROX( mcd.array().pow(md.array()), mcd.array().pow(md.template cast<CD>().eval().array()) );
+
+ VERIFY_IS_APPROX( pow(md.array(),mcd.array()), md.template cast<CD>().eval().array().pow(mcd.array()) );
+ VERIFY_IS_APPROX( pow(mcd.array(),md.array()), mcd.array().pow(md.template cast<CD>().eval().array()) );
+ }
+
+ rcd = mcd;
+ VERIFY_IS_APPROX( rcd = md, md.template cast<CD>().eval() );
+ rcd = mcd;
+ VERIFY_IS_APPROX( rcd += md, mcd + md.template cast<CD>().eval() );
+ rcd = mcd;
+ VERIFY_IS_APPROX( rcd -= md, mcd - md.template cast<CD>().eval() );
+ rcd = mcd;
+ VERIFY_IS_APPROX( rcd.array() *= md.array(), mcd.array() * md.template cast<CD>().eval().array() );
+ rcd = mcd;
+ if(md.array().abs().minCoeff()>epsd)
+ {
+ VERIFY_IS_APPROX( rcd.array() /= md.array(), mcd.array() / md.template cast<CD>().eval().array() );
+ }
+
+ rcd = mcd;
+ VERIFY_IS_APPROX( rcd.noalias() += md + mcd*md, mcd + (md.template cast<CD>().eval()) + mcd*(md.template cast<CD>().eval()));
+
+ VERIFY_IS_APPROX( rcd.noalias() = md*md, ((md*md).eval().template cast<CD>()) );
+ rcd = mcd;
+ VERIFY_IS_APPROX( rcd.noalias() += md*md, mcd + ((md*md).eval().template cast<CD>()) );
+ rcd = mcd;
+ VERIFY_IS_APPROX( rcd.noalias() -= md*md, mcd - ((md*md).eval().template cast<CD>()) );
+
+ VERIFY_IS_APPROX( rcd.noalias() = mcd + md*md, mcd + ((md*md).eval().template cast<CD>()) );
+ rcd = mcd;
+ VERIFY_IS_APPROX( rcd.noalias() += mcd + md*md, mcd + mcd + ((md*md).eval().template cast<CD>()) );
+ rcd = mcd;
+ VERIFY_IS_APPROX( rcd.noalias() -= mcd + md*md, - ((md*md).eval().template cast<CD>()) );
}
void test_mixingtypes()
{
- CALL_SUBTEST_1(mixingtypes<3>());
- CALL_SUBTEST_2(mixingtypes<4>());
- CALL_SUBTEST_3(mixingtypes<Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)));
+ for(int i = 0; i < g_repeat; i++) {
+ CALL_SUBTEST_1(mixingtypes<3>());
+ CALL_SUBTEST_2(mixingtypes<4>());
+ CALL_SUBTEST_3(mixingtypes<Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)));
+
+ CALL_SUBTEST_4(mixingtypes<3>());
+ CALL_SUBTEST_5(mixingtypes<4>());
+ CALL_SUBTEST_6(mixingtypes<Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)));
+ }
}
diff --git a/test/mpl2only.cpp b/test/mpl2only.cpp
new file mode 100644
index 000000000..7d04d6bba
--- /dev/null
+++ b/test/mpl2only.cpp
@@ -0,0 +1,22 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// 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/.
+
+#define EIGEN_MPL2_ONLY
+#include <Eigen/Dense>
+#include <Eigen/SparseCore>
+#include <Eigen/SparseLU>
+#include <Eigen/SparseQR>
+#include <Eigen/Sparse>
+#include <Eigen/IterativeLinearSolvers>
+#include <Eigen/Eigen>
+
+int main()
+{
+ return 0;
+}
diff --git a/test/nesting_ops.cpp b/test/nesting_ops.cpp
index 1e8523283..a419b0e44 100644
--- a/test/nesting_ops.cpp
+++ b/test/nesting_ops.cpp
@@ -2,16 +2,37 @@
// for linear algebra.
//
// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
+// 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/.
+#define TEST_ENABLE_TEMPORARY_TRACKING
+
#include "main.h"
-template <typename MatrixType> void run_nesting_ops(const MatrixType& _m)
+template <int N, typename XprType>
+void use_n_times(const XprType &xpr)
{
- typename MatrixType::Nested m(_m);
+ typename internal::nested_eval<XprType,N>::type mat(xpr);
+ typename XprType::PlainObject res(mat.rows(), mat.cols());
+ nb_temporaries--; // remove res
+ res.setZero();
+ for(int i=0; i<N; ++i)
+ res += mat;
+}
+
+template <int N, typename ReferenceType, typename XprType>
+bool verify_eval_type(const XprType &, const ReferenceType&)
+{
+ typedef typename internal::nested_eval<XprType,N>::type EvalType;
+ return internal::is_same<typename internal::remove_all<EvalType>::type, typename internal::remove_all<ReferenceType>::type>::value;
+}
+
+template <typename MatrixType> void run_nesting_ops_1(const MatrixType& _m)
+{
+ typename internal::nested_eval<MatrixType,2>::type m(_m);
// Make really sure that we are in debug mode!
VERIFY_RAISES_ASSERT(eigen_assert(false));
@@ -24,10 +45,63 @@ template <typename MatrixType> void run_nesting_ops(const MatrixType& _m)
VERIFY_IS_APPROX( (m.transpose() * m).array().abs().sum(), (m.transpose() * m).array().abs().sum() );
}
+template <typename MatrixType> void run_nesting_ops_2(const MatrixType& _m)
+{
+ typedef typename MatrixType::Scalar Scalar;
+ 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))
+ {
+ VERIFY_EVALUATION_COUNT( use_n_times<1>(m1 + m1*m1), 1 );
+ VERIFY_EVALUATION_COUNT( use_n_times<10>(m1 + m1*m1), 1 );
+
+ VERIFY_EVALUATION_COUNT( use_n_times<1>(m1.template triangularView<Lower>().solve(m1.col(0))), 1 );
+ VERIFY_EVALUATION_COUNT( use_n_times<10>(m1.template triangularView<Lower>().solve(m1.col(0))), 1 );
+
+ VERIFY_EVALUATION_COUNT( use_n_times<1>(Scalar(2)*m1.template triangularView<Lower>().solve(m1.col(0))), 2 ); // FIXME could be one by applying the scaling in-place on the solve result
+ VERIFY_EVALUATION_COUNT( use_n_times<1>(m1.col(0)+m1.template triangularView<Lower>().solve(m1.col(0))), 2 ); // FIXME could be one by adding m1.col() inplace
+ VERIFY_EVALUATION_COUNT( use_n_times<10>(m1.col(0)+m1.template triangularView<Lower>().solve(m1.col(0))), 2 );
+ }
+
+ {
+ VERIFY( verify_eval_type<10>(m1, m1) );
+ if(!NumTraits<Scalar>::IsComplex)
+ {
+ VERIFY( verify_eval_type<3>(2*m1, 2*m1) );
+ VERIFY( verify_eval_type<4>(2*m1, m1) );
+ }
+ else
+ {
+ VERIFY( verify_eval_type<2>(2*m1, 2*m1) );
+ VERIFY( verify_eval_type<3>(2*m1, m1) );
+ }
+ 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(), 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) );
+ VERIFY( verify_eval_type<1>(m1+m1.template triangularView<Lower>().solve(m1), m1) );
+ }
+}
+
+
void test_nesting_ops()
{
- CALL_SUBTEST_1(run_nesting_ops(MatrixXf::Random(25,25)));
- CALL_SUBTEST_2(run_nesting_ops(MatrixXd::Random(25,25)));
- CALL_SUBTEST_3(run_nesting_ops(Matrix4f::Random()));
- CALL_SUBTEST_4(run_nesting_ops(Matrix4d::Random()));
+ CALL_SUBTEST_1(run_nesting_ops_1(MatrixXf::Random(25,25)));
+ CALL_SUBTEST_2(run_nesting_ops_1(MatrixXcd::Random(25,25)));
+ CALL_SUBTEST_3(run_nesting_ops_1(Matrix4f::Random()));
+ CALL_SUBTEST_4(run_nesting_ops_1(Matrix2d::Random()));
+
+ Index s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
+ CALL_SUBTEST_1( run_nesting_ops_2(MatrixXf(s,s)) );
+ CALL_SUBTEST_2( run_nesting_ops_2(MatrixXcd(s,s)) );
+ CALL_SUBTEST_3( run_nesting_ops_2(Matrix4f()) );
+ CALL_SUBTEST_4( run_nesting_ops_2(Matrix2d()) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
}
diff --git a/test/nomalloc.cpp b/test/nomalloc.cpp
index 8e0402358..50756c2fb 100644
--- a/test/nomalloc.cpp
+++ b/test/nomalloc.cpp
@@ -8,20 +8,10 @@
// 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/.
-// this hack is needed to make this file compiles with -pedantic (gcc)
-#ifdef __GNUC__
-#define throw(X)
-#endif
-
-#ifdef __INTEL_COMPILER
- // disable "warning #76: argument to macro is empty" produced by the above hack
- #pragma warning disable 76
-#endif
-
// discard stack allocation as that too bypasses malloc
#define EIGEN_STACK_ALLOCATION_LIMIT 0
-// any heap allocation will raise an assert
-#define EIGEN_NO_MALLOC
+// heap allocation will raise an assert if enabled at runtime
+#define EIGEN_RUNTIME_NO_MALLOC
#include "main.h"
#include <Eigen/Cholesky>
@@ -88,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>
@@ -171,7 +162,7 @@ void test_zerosized() {
Eigen::VectorXd v;
// explicit zero-sized:
Eigen::ArrayXXd A0(0,0);
- Eigen::ArrayXd v0(std::ptrdiff_t(0)); // FIXME ArrayXd(0) is ambiguous
+ Eigen::ArrayXd v0(0);
// assigning empty objects to each other:
A=A0;
@@ -183,9 +174,11 @@ template<typename MatrixType> void test_reference(const MatrixType& m) {
enum { Flag = MatrixType::IsRowMajor ? Eigen::RowMajor : Eigen::ColMajor};
enum { TransposeFlag = !MatrixType::IsRowMajor ? Eigen::RowMajor : Eigen::ColMajor};
typename MatrixType::Index rows = m.rows(), cols=m.cols();
+ typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Flag > MatrixX;
+ typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, TransposeFlag> MatrixXT;
// Dynamic reference:
- typedef Eigen::Ref<const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Flag > > Ref;
- typedef Eigen::Ref<const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, TransposeFlag> > RefT;
+ typedef Eigen::Ref<const MatrixX > Ref;
+ typedef Eigen::Ref<const MatrixXT > RefT;
Ref r1(m);
Ref r2(m.block(rows/3, cols/4, rows/2, cols/2));
@@ -195,10 +188,30 @@ template<typename MatrixType> void test_reference(const MatrixType& m) {
VERIFY_RAISES_ASSERT(RefT r5(m));
VERIFY_RAISES_ASSERT(Ref r6(m.transpose()));
VERIFY_RAISES_ASSERT(Ref r7(Scalar(2) * m));
+
+ // Copy constructors shall also never malloc
+ Ref r8 = r1;
+ RefT r9 = r3;
+
+ // Initializing from a compatible Ref shall also never malloc
+ Eigen::Ref<const MatrixX, Unaligned, Stride<Dynamic, Dynamic> > r10=r8, r11=m;
+
+ // Initializing from an incompatible Ref will malloc:
+ typedef Eigen::Ref<const MatrixX, Aligned> RefAligned;
+ VERIFY_RAISES_ASSERT(RefAligned r12=r10);
+ VERIFY_RAISES_ASSERT(Ref r13=r10); // r10 has more dynamic strides
+
}
void test_nomalloc()
{
+ // create some dynamic objects
+ Eigen::MatrixXd M1 = MatrixXd::Random(3,3);
+ Ref<const MatrixXd> R1 = 2.0*M1; // Ref requires temporary
+
+ // from here on prohibit malloc:
+ Eigen::internal::set_is_malloc_allowed(false);
+
// check that our operator new is indeed called:
VERIFY_RAISES_ASSERT(MatrixXd dummy(MatrixXd::Random(3,3)));
CALL_SUBTEST_1(nomalloc(Matrix<float, 1, 1>()) );
@@ -207,6 +220,10 @@ void test_nomalloc()
// Check decomposition modules with dynamic matrices that have a known compile-time max size (ctms)
CALL_SUBTEST_4(ctms_decompositions<float>());
+
CALL_SUBTEST_5(test_zerosized());
+
CALL_SUBTEST_6(test_reference(Matrix<float,32,32>()));
+ CALL_SUBTEST_7(test_reference(R1));
+ CALL_SUBTEST_8(Ref<MatrixXd> R2 = M1.topRows<2>(); test_reference(R2));
}
diff --git a/test/nullary.cpp b/test/nullary.cpp
index fbc721a1a..acd55506e 100644
--- a/test/nullary.cpp
+++ b/test/nullary.cpp
@@ -2,6 +2,7 @@
// for linear algebra.
//
// Copyright (C) 2010-2011 Jitse Niesen <jitse@maths.leeds.ac.uk>
+// Copyright (C) 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
@@ -12,7 +13,6 @@
template<typename MatrixType>
bool equalsIdentity(const MatrixType& A)
{
- typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
Scalar zero = static_cast<Scalar>(0);
@@ -30,13 +30,41 @@ bool equalsIdentity(const MatrixType& A)
bool diagOK = (A.diagonal().array() == 1).all();
return offDiagOK && diagOK;
+
+}
+
+template<typename VectorType>
+void check_extremity_accuracy(const VectorType &v, const typename VectorType::Scalar &low, const typename VectorType::Scalar &high)
+{
+ typedef typename VectorType::Scalar Scalar;
+ typedef typename VectorType::RealScalar RealScalar;
+
+ RealScalar prec = internal::is_same<RealScalar,float>::value ? NumTraits<RealScalar>::dummy_precision()*10 : NumTraits<RealScalar>::dummy_precision()/10;
+ Index size = v.size();
+
+ if(size<20)
+ return;
+
+ for (int i=0; i<size; ++i)
+ {
+ if(i<5 || i>size-6)
+ {
+ Scalar ref = (low*RealScalar(size-i-1))/RealScalar(size-1) + (high*RealScalar(i))/RealScalar(size-1);
+ if(std::abs(ref)>1)
+ {
+ if(!internal::isApprox(v(i), ref, prec))
+ std::cout << v(i) << " != " << ref << " ; relative error: " << std::abs((v(i)-ref)/ref) << " ; required precision: " << prec << " ; range: " << low << "," << high << " ; i: " << i << "\n";
+ VERIFY(internal::isApprox(v(i), (low*RealScalar(size-i-1))/RealScalar(size-1) + (high*RealScalar(i))/RealScalar(size-1), prec));
+ }
+ }
+ }
}
template<typename VectorType>
void testVectorType(const VectorType& base)
{
- typedef typename internal::traits<VectorType>::Index Index;
- typedef typename internal::traits<VectorType>::Scalar Scalar;
+ typedef typename VectorType::Scalar Scalar;
+ typedef typename VectorType::RealScalar RealScalar;
const Index size = base.size();
@@ -44,36 +72,61 @@ void testVectorType(const VectorType& base)
Scalar low = (size == 1 ? high : internal::random<Scalar>(-500,500));
if (low>high) std::swap(low,high);
+ // check low==high
+ if(internal::random<float>(0.f,1.f)<0.05f)
+ low = high;
+ // check abs(low) >> abs(high)
+ else if(size>2 && std::numeric_limits<RealScalar>::max_exponent10>0 && internal::random<float>(0.f,1.f)<0.1f)
+ low = -internal::random<Scalar>(1,2) * RealScalar(std::pow(RealScalar(10),std::numeric_limits<RealScalar>::max_exponent10/2));
+
const Scalar step = ((size == 1) ? 1 : (high-low)/(size-1));
// check whether the result yields what we expect it to do
VectorType m(base);
m.setLinSpaced(size,low,high);
- VectorType n(size);
- for (int i=0; i<size; ++i)
- n(i) = low+i*step;
+ if(!NumTraits<Scalar>::IsInteger)
+ {
+ VectorType n(size);
+ for (int i=0; i<size; ++i)
+ n(i) = low+i*step;
+ VERIFY_IS_APPROX(m,n);
- VERIFY_IS_APPROX(m,n);
+ CALL_SUBTEST( check_extremity_accuracy(m, low, high) );
+ }
- // random access version
- m = VectorType::LinSpaced(size,low,high);
- VERIFY_IS_APPROX(m,n);
+ if((!NumTraits<Scalar>::IsInteger) || ((high-low)>=size && (Index(high-low)%(size-1))==0) || (Index(high-low+1)<size && (size%Index(high-low+1))==0))
+ {
+ VectorType n(size);
+ if((!NumTraits<Scalar>::IsInteger) || (high-low>=size))
+ for (int i=0; i<size; ++i)
+ n(i) = size==1 ? low : (low + ((high-low)*Scalar(i))/(size-1));
+ else
+ for (int i=0; i<size; ++i)
+ n(i) = size==1 ? low : low + Scalar((double(high-low+1)*double(i))/double(size));
+ 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() );
+ // random access version
+ m = VectorType::LinSpaced(size,low,high);
+ VERIFY_IS_APPROX(m,n);
+ VERIFY( internal::isApprox(m(m.size()-1),high) );
+ VERIFY( size==1 || internal::isApprox(m(0),low) );
+ VERIFY_IS_EQUAL(m(m.size()-1) , high);
+ if(!NumTraits<Scalar>::IsInteger)
+ CALL_SUBTEST( check_extremity_accuracy(m, low, high) );
+ }
- // 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( m(m.size()-1) <= high );
+ VERIFY( (m.array() <= high).all() );
+ VERIFY( (m.array() >= low).all() );
- // 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( m(m.size()-1) >= low );
+ if(size>=1)
+ {
+ VERIFY( internal::isApprox(m(0),low) );
+ VERIFY_IS_EQUAL(m(0) , low);
+ }
// check whether everything works with row and col major vectors
Matrix<Scalar,Dynamic,1> row_vector(size);
@@ -95,23 +148,77 @@ void testVectorType(const VectorType& base)
VERIFY_IS_APPROX( ScalarMatrix::LinSpaced(1,low,high), ScalarMatrix::Constant(high) );
// regression test for bug 526 (linear vectorized transversal)
- if (size > 1) {
+ if (size > 1 && (!NumTraits<Scalar>::IsInteger)) {
m.tail(size-1).setLinSpaced(low, high);
VERIFY_IS_APPROX(m(size-1), high);
}
+
+ // regression test for bug 1383 (LinSpaced with empty size/range)
+ {
+ Index n0 = VectorType::SizeAtCompileTime==Dynamic ? 0 : VectorType::SizeAtCompileTime;
+ low = internal::random<Scalar>();
+ m = VectorType::LinSpaced(n0,low,low-1);
+ VERIFY(m.size()==n0);
+
+ if(VectorType::SizeAtCompileTime==Dynamic)
+ {
+ VERIFY_IS_EQUAL(VectorType::LinSpaced(n0,0,Scalar(n0-1)).sum(),Scalar(0));
+ VERIFY_IS_EQUAL(VectorType::LinSpaced(n0,low,low-1).sum(),Scalar(0));
+ }
+
+ m.setLinSpaced(n0,0,Scalar(n0-1));
+ VERIFY(m.size()==n0);
+ m.setLinSpaced(n0,low,low-1);
+ VERIFY(m.size()==n0);
+
+ // empty range only:
+ VERIFY_IS_APPROX(VectorType::LinSpaced(size,low,low),VectorType::Constant(size,low));
+ m.setLinSpaced(size,low,low);
+ VERIFY_IS_APPROX(m,VectorType::Constant(size,low));
+
+ if(NumTraits<Scalar>::IsInteger)
+ {
+ VERIFY_IS_APPROX( VectorType::LinSpaced(size,low,Scalar(low+size-1)), VectorType::LinSpaced(size,Scalar(low+size-1),low).reverse() );
+
+ if(VectorType::SizeAtCompileTime==Dynamic)
+ {
+ // Check negative multiplicator path:
+ for(Index k=1; k<5; ++k)
+ VERIFY_IS_APPROX( VectorType::LinSpaced(size,low,Scalar(low+(size-1)*k)), VectorType::LinSpaced(size,Scalar(low+(size-1)*k),low).reverse() );
+ // Check negative divisor path:
+ for(Index k=1; k<5; ++k)
+ VERIFY_IS_APPROX( VectorType::LinSpaced(size*k,low,Scalar(low+size-1)), VectorType::LinSpaced(size*k,Scalar(low+size-1),low).reverse() );
+ }
+ }
+ }
}
template<typename MatrixType>
void testMatrixType(const MatrixType& m)
{
- typedef typename MatrixType::Index Index;
+ using std::abs;
const Index rows = m.rows();
const Index cols = m.cols();
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
+
+ Scalar s1;
+ do {
+ s1 = internal::random<Scalar>();
+ } while(abs(s1)<RealScalar(1e-5) && (!NumTraits<Scalar>::IsInteger));
MatrixType A;
A.setIdentity(rows, cols);
VERIFY(equalsIdentity(A));
VERIFY(equalsIdentity(MatrixType::Identity(rows, cols)));
+
+
+ A = MatrixType::Constant(rows,cols,s1);
+ Index i = internal::random<Index>(0,rows-1);
+ Index j = internal::random<Index>(0,cols-1);
+ VERIFY_IS_APPROX( MatrixType::Constant(rows,cols,s1)(i,j), s1 );
+ VERIFY_IS_APPROX( MatrixType::Constant(rows,cols,s1).coeff(i,j), s1 );
+ VERIFY_IS_APPROX( A(i,j), s1 );
}
void test_nullary()
@@ -120,12 +227,78 @@ void test_nullary()
CALL_SUBTEST_2( testMatrixType(MatrixXcf(internal::random<int>(1,300),internal::random<int>(1,300))) );
CALL_SUBTEST_3( testMatrixType(MatrixXf(internal::random<int>(1,300),internal::random<int>(1,300))) );
- for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST_4( testVectorType(VectorXd(internal::random<int>(1,300))) );
+ for(int i = 0; i < g_repeat*10; i++) {
+ CALL_SUBTEST_4( testVectorType(VectorXd(internal::random<int>(1,30000))) );
CALL_SUBTEST_5( testVectorType(Vector4d()) ); // regression test for bug 232
CALL_SUBTEST_6( testVectorType(Vector3d()) );
- CALL_SUBTEST_7( testVectorType(VectorXf(internal::random<int>(1,300))) );
+ CALL_SUBTEST_7( testVectorType(VectorXf(internal::random<int>(1,30000))) );
CALL_SUBTEST_8( testVectorType(Vector3f()) );
+ 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,10))) );
+ CALL_SUBTEST_9( testVectorType(VectorXi(internal::random<int>(9,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
+
+#ifdef EIGEN_TEST_PART_9
+ // Check possible overflow issue
+ {
+ int n = 60000;
+ ArrayXi a1(n), a2(n);
+ a1.setLinSpaced(n, 0, n-1);
+ for(int i=0; i<n; ++i)
+ a2(i) = i;
+ VERIFY_IS_APPROX(a1,a2);
+ }
+#endif
+
+#ifdef EIGEN_TEST_PART_10
+ // check some internal logic
+ VERIFY(( internal::has_nullary_operator<internal::scalar_constant_op<double> >::value ));
+ VERIFY(( !internal::has_unary_operator<internal::scalar_constant_op<double> >::value ));
+ VERIFY(( !internal::has_binary_operator<internal::scalar_constant_op<double> >::value ));
+ VERIFY(( internal::functor_has_linear_access<internal::scalar_constant_op<double> >::ret ));
+
+ VERIFY(( !internal::has_nullary_operator<internal::scalar_identity_op<double> >::value ));
+ VERIFY(( !internal::has_unary_operator<internal::scalar_identity_op<double> >::value ));
+ VERIFY(( internal::has_binary_operator<internal::scalar_identity_op<double> >::value ));
+ VERIFY(( !internal::functor_has_linear_access<internal::scalar_identity_op<double> >::ret ));
+
+ VERIFY(( !internal::has_nullary_operator<internal::linspaced_op<float,float> >::value ));
+ VERIFY(( internal::has_unary_operator<internal::linspaced_op<float,float> >::value ));
+ VERIFY(( !internal::has_binary_operator<internal::linspaced_op<float,float> >::value ));
+ VERIFY(( internal::functor_has_linear_access<internal::linspaced_op<float,float> >::ret ));
+
+ // Regression unit test for a weird MSVC bug.
+ // Search "nullary_wrapper_workaround_msvc" in CoreEvaluators.h for the details.
+ // See also traits<Ref>::match.
+ {
+ MatrixXf A = MatrixXf::Random(3,3);
+ Ref<const MatrixXf> R = 2.0*A;
+ VERIFY_IS_APPROX(R, A+A);
+
+ Ref<const MatrixXf> R1 = MatrixXf::Random(3,3)+A;
+
+ VectorXi V = VectorXi::Random(3);
+ Ref<const VectorXi> R2 = VectorXi::LinSpaced(3,1,3)+V;
+ VERIFY_IS_APPROX(R2, V+Vector3i(1,2,3));
+
+ VERIFY(( internal::has_nullary_operator<internal::scalar_constant_op<float> >::value ));
+ VERIFY(( !internal::has_unary_operator<internal::scalar_constant_op<float> >::value ));
+ VERIFY(( !internal::has_binary_operator<internal::scalar_constant_op<float> >::value ));
+ VERIFY(( internal::functor_has_linear_access<internal::scalar_constant_op<float> >::ret ));
+
+ VERIFY(( !internal::has_nullary_operator<internal::linspaced_op<int,int> >::value ));
+ VERIFY(( internal::has_unary_operator<internal::linspaced_op<int,int> >::value ));
+ VERIFY(( !internal::has_binary_operator<internal::linspaced_op<int,int> >::value ));
+ VERIFY(( internal::functor_has_linear_access<internal::linspaced_op<int,int> >::ret ));
}
+#endif
}
diff --git a/test/packetmath.cpp b/test/packetmath.cpp
index 38aa256ce..7821a1738 100644
--- a/test/packetmath.cpp
+++ b/test/packetmath.cpp
@@ -9,16 +9,28 @@
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "main.h"
+#include "unsupported/Eigen/SpecialFunctions"
+#if defined __GNUC__ && __GNUC__>=6
+ #pragma GCC diagnostic ignored "-Wignored-attributes"
+#endif
// using namespace Eigen;
+#ifdef EIGEN_VECTORIZE_SSE
+const bool g_vectorize_sse = true;
+#else
+const bool g_vectorize_sse = false;
+#endif
+
namespace Eigen {
namespace internal {
template<typename T> T negate(const T& x) { return -x; }
}
}
-template<typename Scalar> bool isApproxAbs(const Scalar& a, const Scalar& b, const typename NumTraits<Scalar>::Real& refvalue)
+// NOTE: we disbale inlining for this function to workaround a GCC issue when using -O3 and the i387 FPU.
+template<typename Scalar> EIGEN_DONT_INLINE
+bool isApproxAbs(const Scalar& a, const Scalar& b, const typename NumTraits<Scalar>::Real& refvalue)
{
return internal::isMuchSmallerThan(a-b, refvalue);
}
@@ -29,7 +41,7 @@ template<typename Scalar> bool areApproxAbs(const Scalar* a, const Scalar* b, in
{
if (!isApproxAbs(a[i],b[i],refvalue))
{
- std::cout << "[" << Map<const Matrix<Scalar,1,Dynamic> >(a,size) << "]" << " != " << Map<const Matrix<Scalar,1,Dynamic> >(b,size) << "\n";
+ std::cout << "ref: [" << Map<const Matrix<Scalar,1,Dynamic> >(a,size) << "]" << " != vec: [" << Map<const Matrix<Scalar,1,Dynamic> >(b,size) << "]\n";
return false;
}
}
@@ -42,21 +54,13 @@ template<typename Scalar> bool areApprox(const Scalar* a, const Scalar* b, int s
{
if (a[i]!=b[i] && !internal::isApprox(a[i],b[i]))
{
- std::cout << "[" << Map<const Matrix<Scalar,1,Dynamic> >(a,size) << "]" << " != " << Map<const Matrix<Scalar,1,Dynamic> >(b,size) << "\n";
+ std::cout << "ref: [" << Map<const Matrix<Scalar,1,Dynamic> >(a,size) << "]" << " != vec: [" << Map<const Matrix<Scalar,1,Dynamic> >(b,size) << "]\n";
return false;
}
}
return true;
}
-
-#define CHECK_CWISE2(REFOP, POP) { \
- for (int i=0; i<PacketSize; ++i) \
- ref[i] = REFOP(data1[i], data1[i+PacketSize]); \
- internal::pstore(data2, POP(internal::pload<Packet>(data1), internal::pload<Packet>(data1+PacketSize))); \
- VERIFY(areApprox(ref, data2, PacketSize) && #POP); \
-}
-
#define CHECK_CWISE1(REFOP, POP) { \
for (int i=0; i<PacketSize; ++i) \
ref[i] = REFOP(data1[i]); \
@@ -92,6 +96,14 @@ struct packet_helper<false,Packet>
VERIFY(areApprox(ref, data2, PacketSize) && #POP); \
}
+#define CHECK_CWISE2_IF(COND, REFOP, POP) if(COND) { \
+ packet_helper<COND,Packet> h; \
+ for (int i=0; i<PacketSize; ++i) \
+ ref[i] = REFOP(data1[i], data1[i+PacketSize]); \
+ h.store(data2, POP(h.load(data1),h.load(data1+PacketSize))); \
+ VERIFY(areApprox(ref, data2, PacketSize) && #POP); \
+}
+
#define REF_ADD(a,b) ((a)+(b))
#define REF_SUB(a,b) ((a)-(b))
#define REF_MUL(a,b) ((a)*(b))
@@ -100,15 +112,17 @@ struct packet_helper<false,Packet>
template<typename Scalar> void packetmath()
{
using std::abs;
- typedef typename internal::packet_traits<Scalar>::type Packet;
- const int PacketSize = internal::packet_traits<Scalar>::size;
+ typedef internal::packet_traits<Scalar> PacketTraits;
+ typedef typename PacketTraits::type Packet;
+ const int PacketSize = PacketTraits::size;
typedef typename NumTraits<Scalar>::Real RealScalar;
- const int size = PacketSize*4;
- EIGEN_ALIGN16 Scalar data1[internal::packet_traits<Scalar>::size*4];
- EIGEN_ALIGN16 Scalar data2[internal::packet_traits<Scalar>::size*4];
- EIGEN_ALIGN16 Packet packets[PacketSize*2];
- EIGEN_ALIGN16 Scalar ref[internal::packet_traits<Scalar>::size*4];
+ const int max_size = PacketSize > 4 ? PacketSize : 4;
+ const int size = PacketSize*max_size;
+ EIGEN_ALIGN_MAX Scalar data1[size];
+ EIGEN_ALIGN_MAX Scalar data2[size];
+ EIGEN_ALIGN_MAX Packet packets[PacketSize*2];
+ EIGEN_ALIGN_MAX Scalar ref[size];
RealScalar refvalue = 0;
for (int i=0; i<size; ++i)
{
@@ -140,6 +154,18 @@ template<typename Scalar> void packetmath()
else if (offset==1) internal::palign<1>(packets[0], packets[1]);
else if (offset==2) internal::palign<2>(packets[0], packets[1]);
else if (offset==3) internal::palign<3>(packets[0], packets[1]);
+ else if (offset==4) internal::palign<4>(packets[0], packets[1]);
+ else if (offset==5) internal::palign<5>(packets[0], packets[1]);
+ else if (offset==6) internal::palign<6>(packets[0], packets[1]);
+ else if (offset==7) internal::palign<7>(packets[0], packets[1]);
+ else if (offset==8) internal::palign<8>(packets[0], packets[1]);
+ else if (offset==9) internal::palign<9>(packets[0], packets[1]);
+ else if (offset==10) internal::palign<10>(packets[0], packets[1]);
+ else if (offset==11) internal::palign<11>(packets[0], packets[1]);
+ else if (offset==12) internal::palign<12>(packets[0], packets[1]);
+ else if (offset==13) internal::palign<13>(packets[0], packets[1]);
+ else if (offset==14) internal::palign<14>(packets[0], packets[1]);
+ else if (offset==15) internal::palign<15>(packets[0], packets[1]);
internal::pstore(data2, packets[0]);
for (int i=0; i<PacketSize; ++i)
@@ -148,13 +174,17 @@ template<typename Scalar> void packetmath()
VERIFY(areApprox(ref, data2, PacketSize) && "internal::palign");
}
- CHECK_CWISE2(REF_ADD, internal::padd);
- CHECK_CWISE2(REF_SUB, internal::psub);
- CHECK_CWISE2(REF_MUL, internal::pmul);
- #ifndef EIGEN_VECTORIZE_ALTIVEC
- if (!internal::is_same<Scalar,int>::value)
- CHECK_CWISE2(REF_DIV, internal::pdiv);
- #endif
+ VERIFY((!PacketTraits::Vectorizable) || PacketTraits::HasAdd);
+ VERIFY((!PacketTraits::Vectorizable) || PacketTraits::HasSub);
+ VERIFY((!PacketTraits::Vectorizable) || PacketTraits::HasMul);
+ VERIFY((!PacketTraits::Vectorizable) || PacketTraits::HasNegate);
+ VERIFY((internal::is_same<Scalar,int>::value) || (!PacketTraits::Vectorizable) || PacketTraits::HasDiv);
+
+ CHECK_CWISE2_IF(PacketTraits::HasAdd, REF_ADD, internal::padd);
+ CHECK_CWISE2_IF(PacketTraits::HasSub, REF_SUB, internal::psub);
+ CHECK_CWISE2_IF(PacketTraits::HasMul, REF_MUL, internal::pmul);
+ CHECK_CWISE2_IF(PacketTraits::HasDiv, REF_DIV, internal::pdiv);
+
CHECK_CWISE1(internal::negate, internal::pnegate);
CHECK_CWISE1(numext::conj, internal::pconj);
@@ -165,9 +195,31 @@ 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];
+ Packet A0, A1, A2, A3;
+ internal::pbroadcast4<Packet>(data1, A0, A1, A2, A3);
+ internal::pstore(data2+0*PacketSize, A0);
+ internal::pstore(data2+1*PacketSize, A1);
+ internal::pstore(data2+2*PacketSize, A2);
+ internal::pstore(data2+3*PacketSize, A3);
+ VERIFY(areApprox(ref, data2, 4*PacketSize) && "internal::pbroadcast4");
+ }
+
+ {
+ for (int i=0; i<PacketSize*2; ++i)
+ ref[i] = data1[i/PacketSize];
+ Packet A0, A1;
+ internal::pbroadcast2<Packet>(data1, A0, A1);
+ internal::pstore(data2+0*PacketSize, A0);
+ 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)
@@ -179,11 +231,31 @@ template<typename Scalar> void packetmath()
}
}
+ if(PacketSize>2)
+ {
+ for(int offset=0;offset<4;++offset)
+ {
+ for(int i=0;i<PacketSize/4;++i)
+ ref[4*i+0] = ref[4*i+1] = ref[4*i+2] = ref[4*i+3] = data1[offset+i];
+ internal::pstore(data2,internal::ploadquad<Packet>(data1+offset));
+ VERIFY(areApprox(ref, data2, PacketSize) && "ploadquad");
+ }
+ }
+
ref[0] = 0;
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;
+ for (int i=0; i<PacketSize; ++i)
+ ref[i%4] += data1[i];
+ internal::pstore(data2, internal::predux_downto4(internal::pload<Packet>(data1)));
+ VERIFY(areApprox(ref, data2, PacketSize>4?PacketSize/2:PacketSize) && "internal::predux_downto4");
+ }
+
ref[0] = 1;
for (int i=0; i<PacketSize; ++i)
ref[0] *= data1[i];
@@ -203,116 +275,258 @@ template<typename Scalar> void packetmath()
ref[i] = data1[PacketSize-i-1];
internal::pstore(data2, internal::preverse(internal::pload<Packet>(data1)));
VERIFY(areApprox(ref, data2, PacketSize) && "internal::preverse");
+
+ internal::PacketBlock<Packet> kernel;
+ for (int i=0; i<PacketSize; ++i) {
+ kernel.packet[i] = internal::pload<Packet>(data1+i*PacketSize);
+ }
+ ptranspose(kernel);
+ for (int i=0; i<PacketSize; ++i) {
+ internal::pstore(data2, kernel.packet[i]);
+ for (int j = 0; j < PacketSize; ++j) {
+ VERIFY(isApproxAbs(data2[j], data1[i+j*PacketSize], refvalue) && "ptranspose");
+ }
+ }
+
+ if (PacketTraits::HasBlend) {
+ Packet thenPacket = internal::pload<Packet>(data1);
+ Packet elsePacket = internal::pload<Packet>(data2);
+ EIGEN_ALIGN_MAX internal::Selector<PacketSize> selector;
+ for (int i = 0; i < PacketSize; ++i) {
+ selector.select[i] = i;
+ }
+
+ Packet blend = internal::pblend(selector, thenPacket, elsePacket);
+ EIGEN_ALIGN_MAX Scalar result[size];
+ internal::pstore(result, blend);
+ for (int i = 0; i < PacketSize; ++i) {
+ VERIFY(isApproxAbs(result[i], (selector.select[i] ? data1[i] : data2[i]), refvalue));
+ }
+ }
+
+ if (PacketTraits::HasBlend || g_vectorize_sse) {
+ // pinsertfirst
+ for (int i=0; i<PacketSize; ++i)
+ ref[i] = data1[i];
+ Scalar s = internal::random<Scalar>();
+ ref[0] = s;
+ internal::pstore(data2, internal::pinsertfirst(internal::pload<Packet>(data1),s));
+ VERIFY(areApprox(ref, data2, PacketSize) && "internal::pinsertfirst");
+ }
+
+ if (PacketTraits::HasBlend || g_vectorize_sse) {
+ // pinsertlast
+ for (int i=0; i<PacketSize; ++i)
+ ref[i] = data1[i];
+ Scalar s = internal::random<Scalar>();
+ ref[PacketSize-1] = s;
+ internal::pstore(data2, internal::pinsertlast(internal::pload<Packet>(data1),s));
+ VERIFY(areApprox(ref, data2, PacketSize) && "internal::pinsertlast");
+ }
}
template<typename Scalar> void packetmath_real()
{
using std::abs;
- typedef typename internal::packet_traits<Scalar>::type Packet;
- const int PacketSize = internal::packet_traits<Scalar>::size;
+ typedef internal::packet_traits<Scalar> PacketTraits;
+ typedef typename PacketTraits::type Packet;
+ const int PacketSize = PacketTraits::size;
const int size = PacketSize*4;
- EIGEN_ALIGN16 Scalar data1[internal::packet_traits<Scalar>::size*4];
- EIGEN_ALIGN16 Scalar data2[internal::packet_traits<Scalar>::size*4];
- EIGEN_ALIGN16 Scalar ref[internal::packet_traits<Scalar>::size*4];
+ EIGEN_ALIGN_MAX Scalar data1[PacketTraits::size*4];
+ EIGEN_ALIGN_MAX Scalar data2[PacketTraits::size*4];
+ EIGEN_ALIGN_MAX Scalar ref[PacketTraits::size*4];
for (int i=0; i<size; ++i)
{
data1[i] = internal::random<Scalar>(-1,1) * std::pow(Scalar(10), internal::random<Scalar>(-3,3));
data2[i] = internal::random<Scalar>(-1,1) * std::pow(Scalar(10), internal::random<Scalar>(-3,3));
}
- CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasSin, std::sin, internal::psin);
- CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasCos, std::cos, internal::pcos);
- CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasTan, std::tan, internal::ptan);
-
+ CHECK_CWISE1_IF(PacketTraits::HasSin, std::sin, internal::psin);
+ CHECK_CWISE1_IF(PacketTraits::HasCos, std::cos, internal::pcos);
+ CHECK_CWISE1_IF(PacketTraits::HasTan, std::tan, internal::ptan);
+
+ CHECK_CWISE1_IF(PacketTraits::HasRound, numext::round, internal::pround);
+ CHECK_CWISE1_IF(PacketTraits::HasCeil, numext::ceil, internal::pceil);
+ CHECK_CWISE1_IF(PacketTraits::HasFloor, numext::floor, internal::pfloor);
+
for (int i=0; i<size; ++i)
{
data1[i] = internal::random<Scalar>(-1,1);
data2[i] = internal::random<Scalar>(-1,1);
}
- CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasASin, std::asin, internal::pasin);
- CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasACos, std::acos, internal::pacos);
+ CHECK_CWISE1_IF(PacketTraits::HasASin, std::asin, internal::pasin);
+ CHECK_CWISE1_IF(PacketTraits::HasACos, std::acos, internal::pacos);
for (int i=0; i<size; ++i)
{
data1[i] = internal::random<Scalar>(-87,88);
data2[i] = internal::random<Scalar>(-87,88);
}
- CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasExp, std::exp, internal::pexp);
+ 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();
+ data1[1] = std::numeric_limits<Scalar>::epsilon();
+ packet_helper<PacketTraits::HasExp,Packet> h;
+ h.store(data2, internal::pexp(h.load(data1)));
+ VERIFY((numext::isnan)(data2[0]));
+ VERIFY_IS_EQUAL(std::exp(std::numeric_limits<Scalar>::epsilon()), data2[1]);
+
+ data1[0] = -std::numeric_limits<Scalar>::epsilon();
+ 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(Scalar(0)), data2[1]);
+
+ data1[0] = (std::numeric_limits<Scalar>::min)();
+ data1[1] = -(std::numeric_limits<Scalar>::min)();
+ h.store(data2, internal::pexp(h.load(data1)));
+ VERIFY_IS_EQUAL(std::exp((std::numeric_limits<Scalar>::min)()), data2[0]);
+ VERIFY_IS_EQUAL(std::exp(-(std::numeric_limits<Scalar>::min)()), data2[1]);
+
+ data1[0] = std::numeric_limits<Scalar>::denorm_min();
+ data1[1] = -std::numeric_limits<Scalar>::denorm_min();
+ h.store(data2, internal::pexp(h.load(data1)));
+ VERIFY_IS_EQUAL(std::exp(std::numeric_limits<Scalar>::denorm_min()), data2[0]);
+ VERIFY_IS_EQUAL(std::exp(-std::numeric_limits<Scalar>::denorm_min()), data2[1]);
+ }
+
+ if (PacketTraits::HasTanh) {
+ // NOTE this test migh fail with GCC prior to 6.3, see MathFunctionsImpl.h for details.
+ data1[0] = std::numeric_limits<Scalar>::quiet_NaN();
+ packet_helper<internal::packet_traits<Scalar>::HasTanh,Packet> h;
+ h.store(data2, internal::ptanh(h.load(data1)));
+ VERIFY((numext::isnan)(data2[0]));
+ }
+
+#if 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>::HasExp,Packet> h;
- h.store(data2, internal::pexp(h.load(data1)));
- VERIFY(isNaN(data2[0]));
+ 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)
+
+ if(internal::random<float>(0,1)<0.1f)
data1[internal::random<int>(0, PacketSize)] = 0;
- CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasSqrt, std::sqrt, internal::psqrt);
- CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasLog, std::log, internal::plog);
+ CHECK_CWISE1_IF(PacketTraits::HasSqrt, std::sqrt, internal::psqrt);
+ CHECK_CWISE1_IF(PacketTraits::HasLog, std::log, internal::plog);
+#if EIGEN_HAS_C99_MATH && (__cplusplus > 199711L)
+ CHECK_CWISE1_IF(PacketTraits::HasLog1p, std::log1p, internal::plog1p);
+ 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();
- packet_helper<internal::packet_traits<Scalar>::HasLog,Packet> h;
+ data1[1] = std::numeric_limits<Scalar>::epsilon();
+ packet_helper<PacketTraits::HasLog,Packet> h;
h.store(data2, internal::plog(h.load(data1)));
- VERIFY(isNaN(data2[0]));
- data1[0] = -1.0f;
+ VERIFY((numext::isnan)(data2[0]));
+ VERIFY_IS_EQUAL(std::log(std::numeric_limits<Scalar>::epsilon()), data2[1]);
+
+ data1[0] = -std::numeric_limits<Scalar>::epsilon();
+ data1[1] = 0;
+ h.store(data2, internal::plog(h.load(data1)));
+ VERIFY((numext::isnan)(data2[0]));
+ VERIFY_IS_EQUAL(std::log(Scalar(0)), data2[1]);
+
+ data1[0] = (std::numeric_limits<Scalar>::min)();
+ data1[1] = -(std::numeric_limits<Scalar>::min)();
+ h.store(data2, internal::plog(h.load(data1)));
+ VERIFY_IS_EQUAL(std::log((std::numeric_limits<Scalar>::min)()), data2[0]);
+ VERIFY((numext::isnan)(data2[1]));
+
+ data1[0] = std::numeric_limits<Scalar>::denorm_min();
+ data1[1] = -std::numeric_limits<Scalar>::denorm_min();
+ h.store(data2, internal::plog(h.load(data1)));
+ // VERIFY_IS_EQUAL(std::log(std::numeric_limits<Scalar>::denorm_min()), data2[0]);
+ VERIFY((numext::isnan)(data2[1]));
+
+ data1[0] = Scalar(-1.0f);
h.store(data2, internal::plog(h.load(data1)));
- VERIFY(isNaN(data2[0]));
-#if !EIGEN_FAST_MATH
+ VERIFY((numext::isnan)(data2[0]));
h.store(data2, internal::psqrt(h.load(data1)));
- VERIFY(isNaN(data2[0]));
- VERIFY(isNaN(data2[1]));
-#endif
+ VERIFY((numext::isnan)(data2[0]));
+ VERIFY((numext::isnan)(data2[1]));
}
}
template<typename Scalar> void packetmath_notcomplex()
{
using std::abs;
- typedef typename internal::packet_traits<Scalar>::type Packet;
- const int PacketSize = internal::packet_traits<Scalar>::size;
+ typedef internal::packet_traits<Scalar> PacketTraits;
+ typedef typename PacketTraits::type Packet;
+ const int PacketSize = PacketTraits::size;
+
+ EIGEN_ALIGN_MAX Scalar data1[PacketTraits::size*4];
+ EIGEN_ALIGN_MAX Scalar data2[PacketTraits::size*4];
+ EIGEN_ALIGN_MAX Scalar ref[PacketTraits::size*4];
- EIGEN_ALIGN16 Scalar data1[internal::packet_traits<Scalar>::size*4];
- EIGEN_ALIGN16 Scalar data2[internal::packet_traits<Scalar>::size*4];
- EIGEN_ALIGN16 Scalar ref[internal::packet_traits<Scalar>::size*4];
-
- Array<Scalar,Dynamic,1>::Map(data1, internal::packet_traits<Scalar>::size*4).setRandom();
+ Array<Scalar,Dynamic,1>::Map(data1, PacketTraits::size*4).setRandom();
ref[0] = data1[0];
for (int i=0; i<PacketSize; ++i)
ref[0] = (std::min)(ref[0],data1[i]);
VERIFY(internal::isApprox(ref[0], internal::predux_min(internal::pload<Packet>(data1))) && "internal::predux_min");
- CHECK_CWISE2((std::min), internal::pmin);
- CHECK_CWISE2((std::max), internal::pmax);
+ VERIFY((!PacketTraits::Vectorizable) || PacketTraits::HasMin);
+ VERIFY((!PacketTraits::Vectorizable) || PacketTraits::HasMax);
+
+ CHECK_CWISE2_IF(PacketTraits::HasMin, (std::min), internal::pmin);
+ CHECK_CWISE2_IF(PacketTraits::HasMax, (std::max), internal::pmax);
CHECK_CWISE1(abs, internal::pabs);
ref[0] = data1[0];
for (int i=0; i<PacketSize; ++i)
ref[0] = (std::max)(ref[0],data1[i]);
VERIFY(internal::isApprox(ref[0], internal::predux_max(internal::pload<Packet>(data1))) && "internal::predux_max");
-
+
for (int i=0; i<PacketSize; ++i)
ref[i] = data1[0]+Scalar(i);
- internal::pstore(data2, internal::plset(data1[0]));
+ internal::pstore(data2, internal::plset<Packet>(data1[0]));
VERIFY(areApprox(ref, data2, PacketSize) && "internal::plset");
}
template<typename Scalar,bool ConjLhs,bool ConjRhs> void test_conj_helper(Scalar* data1, Scalar* data2, Scalar* ref, Scalar* pval)
{
- typedef typename internal::packet_traits<Scalar>::type Packet;
- const int PacketSize = internal::packet_traits<Scalar>::size;
-
+ typedef internal::packet_traits<Scalar> PacketTraits;
+ typedef typename PacketTraits::type Packet;
+ const int PacketSize = PacketTraits::size;
+
internal::conj_if<ConjLhs> cj0;
internal::conj_if<ConjRhs> cj1;
internal::conj_helper<Scalar,Scalar,ConjLhs,ConjRhs> cj;
internal::conj_helper<Packet,Packet,ConjLhs,ConjRhs> pcj;
-
+
for(int i=0;i<PacketSize;++i)
{
ref[i] = cj0(data1[i]) * cj1(data2[i]);
@@ -320,7 +534,7 @@ template<typename Scalar,bool ConjLhs,bool ConjRhs> void test_conj_helper(Scalar
}
internal::pstore(pval,pcj.pmul(internal::pload<Packet>(data1),internal::pload<Packet>(data2)));
VERIFY(areApprox(ref, pval, PacketSize) && "conj_helper pmul");
-
+
for(int i=0;i<PacketSize;++i)
{
Scalar tmp = ref[i];
@@ -333,34 +547,70 @@ template<typename Scalar,bool ConjLhs,bool ConjRhs> void test_conj_helper(Scalar
template<typename Scalar> void packetmath_complex()
{
- typedef typename internal::packet_traits<Scalar>::type Packet;
- const int PacketSize = internal::packet_traits<Scalar>::size;
+ typedef internal::packet_traits<Scalar> PacketTraits;
+ typedef typename PacketTraits::type Packet;
+ const int PacketSize = PacketTraits::size;
const int size = PacketSize*4;
- EIGEN_ALIGN16 Scalar data1[PacketSize*4];
- EIGEN_ALIGN16 Scalar data2[PacketSize*4];
- EIGEN_ALIGN16 Scalar ref[PacketSize*4];
- EIGEN_ALIGN16 Scalar pval[PacketSize*4];
+ EIGEN_ALIGN_MAX Scalar data1[PacketSize*4];
+ EIGEN_ALIGN_MAX Scalar data2[PacketSize*4];
+ EIGEN_ALIGN_MAX Scalar ref[PacketSize*4];
+ EIGEN_ALIGN_MAX Scalar pval[PacketSize*4];
for (int i=0; i<size; ++i)
{
data1[i] = internal::random<Scalar>() * Scalar(1e2);
data2[i] = internal::random<Scalar>() * Scalar(1e2);
}
-
+
test_conj_helper<Scalar,false,false> (data1,data2,ref,pval);
test_conj_helper<Scalar,false,true> (data1,data2,ref,pval);
test_conj_helper<Scalar,true,false> (data1,data2,ref,pval);
test_conj_helper<Scalar,true,true> (data1,data2,ref,pval);
-
+
{
for(int i=0;i<PacketSize;++i)
ref[i] = Scalar(std::imag(data1[i]),std::real(data1[i]));
internal::pstore(pval,internal::pcplxflip(internal::pload<Packet>(data1)));
VERIFY(areApprox(ref, pval, PacketSize) && "pcplxflip");
}
-
-
+}
+
+template<typename Scalar> void packetmath_scatter_gather()
+{
+ typedef internal::packet_traits<Scalar> PacketTraits;
+ typedef typename PacketTraits::type Packet;
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+ const int PacketSize = PacketTraits::size;
+ EIGEN_ALIGN_MAX Scalar data1[PacketSize];
+ RealScalar refvalue = 0;
+ for (int i=0; i<PacketSize; ++i) {
+ data1[i] = internal::random<Scalar>()/RealScalar(PacketSize);
+ }
+
+ int stride = internal::random<int>(1,20);
+
+ EIGEN_ALIGN_MAX Scalar buffer[PacketSize*20];
+ memset(buffer, 0, 20*PacketSize*sizeof(Scalar));
+ Packet packet = internal::pload<Packet>(data1);
+ internal::pscatter<Scalar, Packet>(buffer, packet, stride);
+
+ for (int i = 0; i < PacketSize*20; ++i) {
+ if ((i%stride) == 0 && i<stride*PacketSize) {
+ VERIFY(isApproxAbs(buffer[i], data1[i/stride], refvalue) && "pscatter");
+ } else {
+ VERIFY(isApproxAbs(buffer[i], Scalar(0), refvalue) && "pscatter");
+ }
+ }
+
+ for (int i=0; i<PacketSize*7; ++i) {
+ buffer[i] = internal::random<Scalar>()/RealScalar(PacketSize);
+ }
+ packet = internal::pgather<Scalar, Packet>(buffer, 7);
+ internal::pstore(data1, packet);
+ for (int i = 0; i < PacketSize; ++i) {
+ VERIFY(isApproxAbs(data1[i], buffer[i*7], refvalue) && "pgather");
+ }
}
void test_packetmath()
@@ -369,17 +619,23 @@ void test_packetmath()
CALL_SUBTEST_1( packetmath<float>() );
CALL_SUBTEST_2( packetmath<double>() );
CALL_SUBTEST_3( packetmath<int>() );
- CALL_SUBTEST_1( packetmath<std::complex<float> >() );
- CALL_SUBTEST_2( packetmath<std::complex<double> >() );
+ CALL_SUBTEST_4( packetmath<std::complex<float> >() );
+ CALL_SUBTEST_5( packetmath<std::complex<double> >() );
CALL_SUBTEST_1( packetmath_notcomplex<float>() );
CALL_SUBTEST_2( packetmath_notcomplex<double>() );
CALL_SUBTEST_3( packetmath_notcomplex<int>() );
-
+
CALL_SUBTEST_1( packetmath_real<float>() );
CALL_SUBTEST_2( packetmath_real<double>() );
- CALL_SUBTEST_1( packetmath_complex<std::complex<float> >() );
- CALL_SUBTEST_2( packetmath_complex<std::complex<double> >() );
+ CALL_SUBTEST_4( packetmath_complex<std::complex<float> >() );
+ CALL_SUBTEST_5( packetmath_complex<std::complex<double> >() );
+
+ CALL_SUBTEST_1( packetmath_scatter_gather<float>() );
+ CALL_SUBTEST_2( packetmath_scatter_gather<double>() );
+ CALL_SUBTEST_3( packetmath_scatter_gather<int>() );
+ CALL_SUBTEST_4( packetmath_scatter_gather<std::complex<float> >() );
+ CALL_SUBTEST_5( packetmath_scatter_gather<std::complex<double> >() );
}
}
diff --git a/test/pastix_support.cpp b/test/pastix_support.cpp
index 14da0944b..b62f85739 100644
--- a/test/pastix_support.cpp
+++ b/test/pastix_support.cpp
@@ -7,6 +7,8 @@
// 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/.
+
+#define EIGEN_NO_DEBUG_SMALL_PRODUCT_BLOCKS
#include "sparse_solver.h"
#include <Eigen/PaStiXSupport>
#include <unsupported/Eigen/SparseExtra>
@@ -25,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/permutationmatrices.cpp b/test/permutationmatrices.cpp
index 7b0dbc763..db1266579 100644
--- a/test/permutationmatrices.cpp
+++ b/test/permutationmatrices.cpp
@@ -7,6 +7,8 @@
// 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/.
+#define TEST_ENABLE_TEMPORARY_TRACKING
+
#include "main.h"
using namespace std;
@@ -33,7 +35,9 @@ template<typename MatrixType> void permutationmatrices(const MatrixType& m)
RightPermutationVectorType rv;
randomPermutationVector(rv, cols);
RightPermutationType rp(rv);
- MatrixType m_permuted = lp * m_original * rp;
+ MatrixType m_permuted = MatrixType::Random(rows,cols);
+
+ VERIFY_EVALUATION_COUNT(m_permuted = lp * m_original * rp, 1); // 1 temp for sub expression "lp * m_original"
for (int i=0; i<rows; i++)
for (int j=0; j<cols; j++)
@@ -43,7 +47,11 @@ template<typename MatrixType> void permutationmatrices(const MatrixType& m)
Matrix<Scalar,Cols,Cols> rm(rp);
VERIFY_IS_APPROX(m_permuted, lm*m_original*rm);
-
+
+ m_permuted = m_original;
+ VERIFY_EVALUATION_COUNT(m_permuted = lp * m_permuted * rp, 1);
+ VERIFY_IS_APPROX(m_permuted, lm*m_original*rm);
+
VERIFY_IS_APPROX(lp.inverse()*m_permuted*rp.inverse(), m_original);
VERIFY_IS_APPROX(lv.asPermutation().inverse()*m_permuted*rv.asPermutation().inverse(), m_original);
VERIFY_IS_APPROX(MapLeftPerm(lv.data(),lv.size()).inverse()*m_permuted*MapRightPerm(rv.data(),rv.size()).inverse(), m_original);
@@ -63,22 +71,22 @@ template<typename MatrixType> void permutationmatrices(const MatrixType& m)
LeftPermutationType identityp;
identityp.setIdentity(rows);
VERIFY_IS_APPROX(m_original, identityp*m_original);
-
+
// check inplace permutations
m_permuted = m_original;
- m_permuted = lp.inverse() * m_permuted;
+ VERIFY_EVALUATION_COUNT(m_permuted.noalias()= lp.inverse() * m_permuted, 1); // 1 temp to allocate the mask
VERIFY_IS_APPROX(m_permuted, lp.inverse()*m_original);
-
+
m_permuted = m_original;
- m_permuted = m_permuted * rp.inverse();
+ VERIFY_EVALUATION_COUNT(m_permuted.noalias() = m_permuted * rp.inverse(), 1); // 1 temp to allocate the mask
VERIFY_IS_APPROX(m_permuted, m_original*rp.inverse());
-
+
m_permuted = m_original;
- m_permuted = lp * m_permuted;
+ VERIFY_EVALUATION_COUNT(m_permuted.noalias() = lp * m_permuted, 1); // 1 temp to allocate the mask
VERIFY_IS_APPROX(m_permuted, lp*m_original);
-
+
m_permuted = m_original;
- m_permuted = m_permuted * rp;
+ VERIFY_EVALUATION_COUNT(m_permuted.noalias() = m_permuted * rp, 1); // 1 temp to allocate the mask
VERIFY_IS_APPROX(m_permuted, m_original*rp);
if(rows>1 && cols>1)
@@ -99,7 +107,38 @@ template<typename MatrixType> void permutationmatrices(const MatrixType& m)
rm = rp;
rm.col(i).swap(rm.col(j));
VERIFY_IS_APPROX(rm, rp2.toDenseMatrix().template cast<Scalar>());
- }
+ }
+
+ {
+ // simple compilation check
+ Matrix<Scalar, Cols, Cols> A = rp;
+ Matrix<Scalar, Cols, Cols> B = rp.transpose();
+ VERIFY_IS_APPROX(A, B.transpose());
+ }
+}
+
+template<typename T>
+void bug890()
+{
+ typedef Matrix<T, Dynamic, Dynamic> MatrixType;
+ typedef Matrix<T, Dynamic, 1> VectorType;
+ typedef Stride<Dynamic,Dynamic> S;
+ typedef Map<MatrixType, Aligned, S> MapType;
+ typedef PermutationMatrix<Dynamic> Perm;
+
+ VectorType v1(2), v2(2), op(4), rhs(2);
+ v1 << 666,667;
+ op << 1,0,0,1;
+ rhs << 42,42;
+
+ Perm P(2);
+ P.indices() << 1, 0;
+
+ MapType(v1.data(),2,1,S(1,1)) = P * MapType(rhs.data(),2,1,S(1,1));
+ VERIFY_IS_APPROX(v1, (P * rhs).eval());
+
+ MapType(v1.data(),2,1,S(1,1)) = P.inverse() * MapType(rhs.data(),2,1,S(1,1));
+ VERIFY_IS_APPROX(v1, (P.inverse() * rhs).eval());
}
void test_permutationmatrices()
@@ -113,4 +152,5 @@ void test_permutationmatrices()
CALL_SUBTEST_6( permutationmatrices(Matrix<double,Dynamic,Dynamic,RowMajor>(20, 30)) );
CALL_SUBTEST_7( permutationmatrices(MatrixXcf(15, 10)) );
}
+ CALL_SUBTEST_5( bug890<double>() );
}
diff --git a/test/prec_inverse_4x4.cpp b/test/prec_inverse_4x4.cpp
index c4ef2d4bd..eb6ad18c9 100644
--- a/test/prec_inverse_4x4.cpp
+++ b/test/prec_inverse_4x4.cpp
@@ -53,14 +53,29 @@ template<typename MatrixType> void inverse_general_4x4(int repeat)
// FIXME that 1.25 used to be 1.2 until we tested gcc 4.1 on 30 June 2010 and got 1.21.
VERIFY(error_avg < (NumTraits<Scalar>::IsComplex ? 8.0 : 1.25));
VERIFY(error_max < (NumTraits<Scalar>::IsComplex ? 64.0 : 20.0));
+
+ {
+ int s = 5;//internal::random<int>(4,10);
+ int i = 0;//internal::random<int>(0,s-4);
+ int j = 0;//internal::random<int>(0,s-4);
+ Matrix<Scalar,5,5> mat(s,s);
+ mat.setRandom();
+ MatrixType submat = mat.template block<4,4>(i,j);
+ MatrixType mat_inv = mat.template block<4,4>(i,j).inverse();
+ VERIFY_IS_APPROX(mat_inv, submat.inverse());
+ mat.template block<4,4>(i,j) = submat.inverse();
+ VERIFY_IS_APPROX(mat_inv, (mat.template block<4,4>(i,j)));
+ }
}
void test_prec_inverse_4x4()
{
CALL_SUBTEST_1((inverse_permutation_4x4<Matrix4f>()));
CALL_SUBTEST_1(( inverse_general_4x4<Matrix4f>(200000 * g_repeat) ));
+ CALL_SUBTEST_1(( inverse_general_4x4<Matrix<float,4,4,RowMajor> >(200000 * g_repeat) ));
CALL_SUBTEST_2((inverse_permutation_4x4<Matrix<double,4,4,RowMajor> >()));
+ CALL_SUBTEST_2(( inverse_general_4x4<Matrix<double,4,4,ColMajor> >(200000 * g_repeat) ));
CALL_SUBTEST_2(( inverse_general_4x4<Matrix<double,4,4,RowMajor> >(200000 * g_repeat) ));
CALL_SUBTEST_3((inverse_permutation_4x4<Matrix4cf>()));
diff --git a/test/product.h b/test/product.h
index 0b3abe402..3b6511270 100644
--- a/test/product.h
+++ b/test/product.h
@@ -22,7 +22,6 @@ template<typename MatrixType> void product(const MatrixType& m)
/* this test covers the following files:
Identity.h Product.h
*/
- typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> RowVectorType;
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> ColVectorType;
@@ -112,6 +111,23 @@ template<typename MatrixType> void product(const MatrixType& m)
vcres.noalias() -= m1.transpose() * v1;
VERIFY_IS_APPROX(vcres, vc2 - m1.transpose() * v1);
+ // test d ?= a+b*c rules
+ res.noalias() = square + m1 * m2.transpose();
+ VERIFY_IS_APPROX(res, square + m1 * m2.transpose());
+ res.noalias() += square + m1 * m2.transpose();
+ VERIFY_IS_APPROX(res, 2*(square + m1 * m2.transpose()));
+ res.noalias() -= square + m1 * m2.transpose();
+ VERIFY_IS_APPROX(res, square + m1 * m2.transpose());
+
+ // test d ?= a-b*c rules
+ res.noalias() = square - m1 * m2.transpose();
+ VERIFY_IS_APPROX(res, square - m1 * m2.transpose());
+ res.noalias() += square - m1 * m2.transpose();
+ VERIFY_IS_APPROX(res, 2*(square - m1 * m2.transpose()));
+ res.noalias() -= square - m1 * m2.transpose();
+ VERIFY_IS_APPROX(res, square - m1 * m2.transpose());
+
+
tm1 = m1;
VERIFY_IS_APPROX(tm1.transpose() * v1, m1.transpose() * v1);
VERIFY_IS_APPROX(v1.transpose() * tm1, v1.transpose() * m1);
@@ -136,15 +152,80 @@ 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));
+ }
+
+ // vector.block() (see bug 1283)
+ {
+ RowVectorType w1(rows);
+ VERIFY_IS_APPROX(square * v1.block(0,0,rows,1), square * v1);
+ VERIFY_IS_APPROX(w1.noalias() = square * v1.block(0,0,rows,1), square * v1);
+ VERIFY_IS_APPROX(w1.block(0,0,rows,1).noalias() = square * v1.block(0,0,rows,1), square * v1);
+
+ Matrix<Scalar,1,MatrixType::ColsAtCompileTime> w2(cols);
+ VERIFY_IS_APPROX(vc2.block(0,0,cols,1).transpose() * square2, vc2.transpose() * square2);
+ VERIFY_IS_APPROX(w2.noalias() = vc2.block(0,0,cols,1).transpose() * square2, vc2.transpose() * square2);
+ VERIFY_IS_APPROX(w2.block(0,0,1,cols).noalias() = vc2.block(0,0,cols,1).transpose() * square2, vc2.transpose() * square2);
+
+ vc2 = square2.block(0,0,1,cols).transpose();
+ VERIFY_IS_APPROX(square2.block(0,0,1,cols) * square2, vc2.transpose() * square2);
+ VERIFY_IS_APPROX(w2.noalias() = square2.block(0,0,1,cols) * square2, vc2.transpose() * square2);
+ VERIFY_IS_APPROX(w2.block(0,0,1,cols).noalias() = square2.block(0,0,1,cols) * square2, vc2.transpose() * square2);
+
+ vc2 = square2.block(0,0,cols,1);
+ VERIFY_IS_APPROX(square2.block(0,0,cols,1).transpose() * square2, vc2.transpose() * square2);
+ VERIFY_IS_APPROX(w2.noalias() = square2.block(0,0,cols,1).transpose() * square2, vc2.transpose() * square2);
+ VERIFY_IS_APPROX(w2.block(0,0,1,cols).noalias() = square2.block(0,0,cols,1).transpose() * square2, vc2.transpose() * 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_extra.cpp b/test/product_extra.cpp
index ea2486937..e2b855bff 100644
--- a/test/product_extra.cpp
+++ b/test/product_extra.cpp
@@ -98,6 +98,16 @@ template<typename MatrixType> void product_extra(const MatrixType& m)
// regression test
MatrixType tmp = m1 * m1.adjoint() * s1;
VERIFY_IS_APPROX(tmp, m1 * m1.adjoint() * s1);
+
+ // regression test for bug 1343, assignment to arrays
+ Array<Scalar,Dynamic,1> a1 = m1 * vc2;
+ VERIFY_IS_APPROX(a1.matrix(),m1*vc2);
+ Array<Scalar,Dynamic,1> a2 = s1 * (m1 * vc2);
+ VERIFY_IS_APPROX(a2.matrix(),s1*m1*vc2);
+ Array<Scalar,1,Dynamic> a3 = v1 * m1;
+ VERIFY_IS_APPROX(a3.matrix(),v1*m1);
+ Array<Scalar,Dynamic,Dynamic> a4 = m1 * m2.adjoint();
+ VERIFY_IS_APPROX(a4.matrix(),m1*m2.adjoint());
}
// Regression test for bug reported at http://forum.kde.org/viewtopic.php?f=74&t=96947
@@ -116,8 +126,8 @@ void zero_sized_objects(const MatrixType& m)
typedef typename MatrixType::Scalar Scalar;
const int PacketSize = internal::packet_traits<Scalar>::size;
const int PacketSize1 = PacketSize>1 ? PacketSize-1 : 1;
- DenseIndex rows = m.rows();
- DenseIndex cols = m.cols();
+ Index rows = m.rows();
+ Index cols = m.cols();
{
MatrixType res, a(rows,0), b(0,cols);
@@ -169,6 +179,7 @@ void zero_sized_objects(const MatrixType& m)
}
}
+template<int>
void bug_127()
{
// Bug 127
@@ -193,6 +204,16 @@ void bug_127()
a*b;
}
+template<int> void bug_817()
+{
+ ArrayXXf B = ArrayXXf::Random(10,10), C;
+ VectorXf x = VectorXf::Random(10);
+ C = (x.transpose()*B.matrix());
+ B = (x.transpose()*B.matrix());
+ VERIFY_IS_APPROX(B,C);
+}
+
+template<int>
void unaligned_objects()
{
// Regression test for the bug reported here:
@@ -222,6 +243,116 @@ void unaligned_objects()
}
}
+template<typename T>
+EIGEN_DONT_INLINE
+Index test_compute_block_size(Index m, Index n, Index k)
+{
+ Index mc(m), nc(n), kc(k);
+ internal::computeProductBlockingSizes<T,T>(kc, mc, nc);
+ return kc+mc+nc;
+}
+
+template<typename T>
+Index compute_block_size()
+{
+ Index ret = 0;
+ ret += test_compute_block_size<T>(0,1,1);
+ ret += test_compute_block_size<T>(1,0,1);
+ ret += test_compute_block_size<T>(1,1,0);
+ ret += test_compute_block_size<T>(0,0,1);
+ ret += test_compute_block_size<T>(0,1,0);
+ ret += test_compute_block_size<T>(1,0,0);
+ ret += test_compute_block_size<T>(0,0,0);
+ return ret;
+}
+
+template<typename>
+void aliasing_with_resize()
+{
+ Index m = internal::random<Index>(10,50);
+ Index n = internal::random<Index>(10,50);
+ MatrixXd A, B, C(m,n), D(m,m);
+ VectorXd a, b, c(n);
+ C.setRandom();
+ D.setRandom();
+ c.setRandom();
+ double s = internal::random<double>(1,10);
+
+ A = C;
+ B = A * A.transpose();
+ A = A * A.transpose();
+ VERIFY_IS_APPROX(A,B);
+
+ A = C;
+ B = (A * A.transpose())/s;
+ A = (A * A.transpose())/s;
+ VERIFY_IS_APPROX(A,B);
+
+ A = C;
+ B = (A * A.transpose()) + D;
+ A = (A * A.transpose()) + D;
+ VERIFY_IS_APPROX(A,B);
+
+ A = C;
+ B = D + (A * A.transpose());
+ A = D + (A * A.transpose());
+ VERIFY_IS_APPROX(A,B);
+
+ A = C;
+ B = s * (A * A.transpose());
+ A = s * (A * A.transpose());
+ VERIFY_IS_APPROX(A,B);
+
+ A = C;
+ a = c;
+ b = (A * a)/s;
+ a = (A * a)/s;
+ VERIFY_IS_APPROX(a,b);
+}
+
+template<int>
+void bug_1308()
+{
+ int n = 10;
+ MatrixXd r(n,n);
+ VectorXd v = VectorXd::Random(n);
+ r = v * RowVectorXd::Ones(n);
+ VERIFY_IS_APPROX(r, v.rowwise().replicate(n));
+ r = VectorXd::Ones(n) * v.transpose();
+ VERIFY_IS_APPROX(r, v.rowwise().replicate(n).transpose());
+
+ Matrix4d ones44 = Matrix4d::Ones();
+ Matrix4d m44 = Matrix4d::Ones() * Matrix4d::Ones();
+ VERIFY_IS_APPROX(m44,Matrix4d::Constant(4));
+ VERIFY_IS_APPROX(m44.noalias()=ones44*Matrix4d::Ones(), Matrix4d::Constant(4));
+ VERIFY_IS_APPROX(m44.noalias()=ones44.transpose()*Matrix4d::Ones(), Matrix4d::Constant(4));
+ VERIFY_IS_APPROX(m44.noalias()=Matrix4d::Ones()*ones44, Matrix4d::Constant(4));
+ VERIFY_IS_APPROX(m44.noalias()=Matrix4d::Ones()*ones44.transpose(), Matrix4d::Constant(4));
+
+ typedef Matrix<double,4,4,RowMajor> RMatrix4d;
+ RMatrix4d r44 = Matrix4d::Ones() * Matrix4d::Ones();
+ VERIFY_IS_APPROX(r44,Matrix4d::Constant(4));
+ VERIFY_IS_APPROX(r44.noalias()=ones44*Matrix4d::Ones(), Matrix4d::Constant(4));
+ VERIFY_IS_APPROX(r44.noalias()=ones44.transpose()*Matrix4d::Ones(), Matrix4d::Constant(4));
+ VERIFY_IS_APPROX(r44.noalias()=Matrix4d::Ones()*ones44, Matrix4d::Constant(4));
+ VERIFY_IS_APPROX(r44.noalias()=Matrix4d::Ones()*ones44.transpose(), Matrix4d::Constant(4));
+ VERIFY_IS_APPROX(r44.noalias()=ones44*RMatrix4d::Ones(), Matrix4d::Constant(4));
+ VERIFY_IS_APPROX(r44.noalias()=ones44.transpose()*RMatrix4d::Ones(), Matrix4d::Constant(4));
+ VERIFY_IS_APPROX(r44.noalias()=RMatrix4d::Ones()*ones44, Matrix4d::Constant(4));
+ VERIFY_IS_APPROX(r44.noalias()=RMatrix4d::Ones()*ones44.transpose(), Matrix4d::Constant(4));
+
+// RowVector4d r4;
+ m44.setOnes();
+ r44.setZero();
+ VERIFY_IS_APPROX(r44.noalias() += m44.row(0).transpose() * RowVector4d::Ones(), ones44);
+ r44.setZero();
+ VERIFY_IS_APPROX(r44.noalias() += m44.col(0) * RowVector4d::Ones(), ones44);
+ r44.setZero();
+ VERIFY_IS_APPROX(r44.noalias() += Vector4d::Ones() * m44.row(0), ones44);
+ r44.setZero();
+ VERIFY_IS_APPROX(r44.noalias() += Vector4d::Ones() * m44.col(0).transpose(), ones44);
+}
+
void test_product_extra()
{
for(int i = 0; i < g_repeat; i++) {
@@ -232,6 +363,13 @@ void test_product_extra()
CALL_SUBTEST_4( product_extra(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
CALL_SUBTEST_1( zero_sized_objects(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
}
- CALL_SUBTEST_5( bug_127() );
- CALL_SUBTEST_6( unaligned_objects() );
+ CALL_SUBTEST_5( bug_127<0>() );
+ CALL_SUBTEST_5( bug_817<0>() );
+ CALL_SUBTEST_5( bug_1308<0>() );
+ CALL_SUBTEST_6( unaligned_objects<0>() );
+ CALL_SUBTEST_7( compute_block_size<float>() );
+ CALL_SUBTEST_7( compute_block_size<double>() );
+ CALL_SUBTEST_7( compute_block_size<std::complex<double> >() );
+ CALL_SUBTEST_8( aliasing_with_resize<void>() );
+
}
diff --git a/test/product_large.cpp b/test/product_large.cpp
index 03d7bd8ed..845cd40ca 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
@@ -39,15 +62,16 @@ void test_product_large()
// check the functions to setup blocking sizes compile and do not segfault
// FIXME check they do what they are supposed to do !!
std::ptrdiff_t l1 = internal::random<int>(10000,20000);
- std::ptrdiff_t l2 = internal::random<int>(1000000,2000000);
- setCpuCacheSizes(l1,l2);
+ std::ptrdiff_t l2 = internal::random<int>(100000,200000);
+ std::ptrdiff_t l3 = internal::random<int>(1000000,2000000);
+ setCpuCacheSizes(l1,l2,l3);
VERIFY(l1==l1CacheSize());
VERIFY(l2==l2CacheSize());
std::ptrdiff_t k1 = internal::random<int>(10,100)*16;
std::ptrdiff_t m1 = internal::random<int>(10,100)*16;
std::ptrdiff_t n1 = internal::random<int>(10,100)*16;
// only makes sure it compiles fine
- internal::computeProductBlockingSizes<float,float>(k1,m1,n1);
+ internal::computeProductBlockingSizes<float,float,std::ptrdiff_t>(k1,m1,n1,1);
}
{
@@ -60,5 +84,24 @@ void test_product_large()
MatrixXf r2 = mat1.row(2)*mat2;
VERIFY_IS_APPROX(r2, (mat1.row(2)*mat2).eval());
}
+
+ {
+ Eigen::MatrixXd A(10,10), B, C;
+ A.setRandom();
+ C = A;
+ for(int k=0; k<79; ++k)
+ C = C * A;
+ B.noalias() = (((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A)) * ((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A)))
+ * (((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A)) * ((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A)));
+ VERIFY_IS_APPROX(B,C);
+ }
+#endif
+
+ // Regression test for bug 714:
+#if defined EIGEN_HAS_OPENMP
+ omp_set_dynamic(1);
+ for(int i = 0; i < g_repeat; i++) {
+ CALL_SUBTEST_6( product(Matrix<float,Dynamic,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+ }
#endif
}
diff --git a/test/product_mmtr.cpp b/test/product_mmtr.cpp
index aeba009f4..f6e4bb1ae 100644
--- a/test/product_mmtr.cpp
+++ b/test/product_mmtr.cpp
@@ -13,7 +13,8 @@
ref2 = ref1 = DEST; \
DEST.template triangularView<TRI>() OP; \
ref1 OP; \
- ref2.template triangularView<TRI>() = ref1; \
+ ref2.template triangularView<TRI>() \
+ = ref1.template triangularView<TRI>(); \
VERIFY_IS_APPROX(DEST,ref2); \
}
@@ -32,6 +33,8 @@ template<typename Scalar> void mmtr(int size)
MatrixColMaj osc(othersize,size); osc.setRandom();
MatrixRowMaj sor(size,othersize); sor.setRandom();
MatrixRowMaj osr(othersize,size); osr.setRandom();
+ MatrixColMaj sqc(size,size); sqc.setRandom();
+ MatrixRowMaj sqr(size,size); sqr.setRandom();
Scalar s = internal::random<Scalar>();
@@ -49,6 +52,29 @@ template<typename Scalar> void mmtr(int size)
CHECK_MMTR(matc, Upper, -= s*(osc.transpose()*osc.conjugate()));
CHECK_MMTR(matr, Lower, -= s*soc*soc.adjoint());
CHECK_MMTR(matr, Upper, -= soc*(s*soc.adjoint()));
+
+ CHECK_MMTR(matc, Lower, -= s*sqr*sqc.template triangularView<Upper>());
+ CHECK_MMTR(matc, Upper, = s*sqc*sqr.template triangularView<Upper>());
+ CHECK_MMTR(matc, Lower, += s*sqr*sqc.template triangularView<Lower>());
+ CHECK_MMTR(matc, Upper, = s*sqc*sqc.template triangularView<Lower>());
+
+ CHECK_MMTR(matc, Lower, = (s*sqr).template triangularView<Upper>()*sqc);
+ CHECK_MMTR(matc, Upper, -= (s*sqc).template triangularView<Upper>()*sqc);
+ CHECK_MMTR(matc, Lower, = (s*sqr).template triangularView<Lower>()*sqc);
+ CHECK_MMTR(matc, Upper, += (s*sqc).template triangularView<Lower>()*sqc);
+
+ // check aliasing
+ ref2 = ref1 = matc;
+ ref1 = sqc.adjoint() * matc * sqc;
+ ref2.template triangularView<Upper>() = ref1.template triangularView<Upper>();
+ matc.template triangularView<Upper>() = sqc.adjoint() * matc * sqc;
+ VERIFY_IS_APPROX(matc, ref2);
+
+ ref2 = ref1 = matc;
+ ref1 = sqc * matc * sqc.adjoint();
+ ref2.template triangularView<Lower>() = ref1.template triangularView<Lower>();
+ matc.template triangularView<Lower>() = sqc * matc * sqc.adjoint();
+ VERIFY_IS_APPROX(matc, ref2);
}
void test_product_mmtr()
diff --git a/test/product_notemporary.cpp b/test/product_notemporary.cpp
index 258d238e2..8bf71b4f2 100644
--- a/test/product_notemporary.cpp
+++ b/test/product_notemporary.cpp
@@ -7,25 +7,10 @@
// 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/.
-static int nb_temporaries;
-
-inline void on_temporary_creation(int size) {
- // here's a great place to set a breakpoint when debugging failures in this test!
- if(size!=0) nb_temporaries++;
-}
-
-
-#define EIGEN_DENSE_STORAGE_CTOR_PLUGIN { on_temporary_creation(size); }
+#define TEST_ENABLE_TEMPORARY_TRACKING
#include "main.h"
-#define VERIFY_EVALUATION_COUNT(XPR,N) {\
- nb_temporaries = 0; \
- XPR; \
- if(nb_temporaries!=N) std::cerr << "nb_temporaries == " << nb_temporaries << "\n"; \
- VERIFY( (#XPR) && nb_temporaries==N ); \
- }
-
template<typename MatrixType> void product_notemporary(const MatrixType& m)
{
/* This test checks the number of temporaries created
@@ -58,10 +43,23 @@ 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);
+ 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);
+
VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * m2.adjoint(), 0);
VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * (m1*s3+m2*s2).adjoint(), 1);
VERIFY_EVALUATION_COUNT( m3.noalias() = (s1 * m1).adjoint() * s2 * m2, 0);
@@ -77,7 +75,7 @@ template<typename MatrixType> void product_notemporary(const MatrixType& m)
VERIFY_EVALUATION_COUNT( m3.noalias() -= (s1 * m1).template triangularView<Lower>() * m2, 0);
VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<Upper>() * (m2+m2), 1);
VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpper>() * m2.adjoint(), 0);
-
+
VERIFY_EVALUATION_COUNT( m3.template triangularView<Upper>() = (m1 * m2.adjoint()), 0);
VERIFY_EVALUATION_COUNT( m3.template triangularView<Upper>() -= (m1 * m2.adjoint()), 0);
@@ -114,8 +112,7 @@ template<typename MatrixType> void product_notemporary(const MatrixType& m)
VERIFY_EVALUATION_COUNT( Scalar tmp = 0; tmp += Scalar(RealScalar(1)) / (m3.transpose() * m3).diagonal().array().abs().sum(), 0 );
// Zero temporaries for ... CoeffBasedProductMode
- // - does not work with GCC because of the <..>, we'ld need variadic macros ...
- //VERIFY_EVALUATION_COUNT( m3.col(0).head<5>() * m3.col(0).transpose() + m3.col(0).head<5>() * m3.col(0).transpose(), 0 );
+ VERIFY_EVALUATION_COUNT( m3.col(0).template head<5>() * m3.col(0).transpose() + m3.col(0).template head<5>() * m3.col(0).transpose(), 0 );
// Check matrix * vectors
VERIFY_EVALUATION_COUNT( cvres.noalias() = m1 * cv1, 0 );
@@ -123,6 +120,26 @@ template<typename MatrixType> void product_notemporary(const MatrixType& m)
VERIFY_EVALUATION_COUNT( cvres.noalias() -= m1 * m2.col(0), 0 );
VERIFY_EVALUATION_COUNT( cvres.noalias() -= m1 * rv1.adjoint(), 0 );
VERIFY_EVALUATION_COUNT( cvres.noalias() -= m1 * m2.row(0).transpose(), 0 );
+
+ VERIFY_EVALUATION_COUNT( cvres.noalias() = (m1+m1) * cv1, 0 );
+ VERIFY_EVALUATION_COUNT( cvres.noalias() = (rm3+rm3) * cv1, 0 );
+ VERIFY_EVALUATION_COUNT( cvres.noalias() = (m1+m1) * (m1*cv1), 1 );
+ VERIFY_EVALUATION_COUNT( cvres.noalias() = (rm3+rm3) * (m1*cv1), 1 );
+
+ // Check outer products
+ m3 = cv1 * rv1;
+ VERIFY_EVALUATION_COUNT( m3.noalias() = cv1 * rv1, 0 );
+ VERIFY_EVALUATION_COUNT( m3.noalias() = (cv1+cv1) * (rv1+rv1), 1 );
+ VERIFY_EVALUATION_COUNT( m3.noalias() = (m1*cv1) * (rv1), 1 );
+ VERIFY_EVALUATION_COUNT( m3.noalias() += (m1*cv1) * (rv1), 1 );
+ VERIFY_EVALUATION_COUNT( rm3.noalias() = (cv1) * (rv1 * m1), 1 );
+ VERIFY_EVALUATION_COUNT( rm3.noalias() -= (cv1) * (rv1 * m1), 1 );
+ VERIFY_EVALUATION_COUNT( rm3.noalias() = (m1*cv1) * (rv1 * m1), 2 );
+ VERIFY_EVALUATION_COUNT( rm3.noalias() += (m1*cv1) * (rv1 * m1), 2 );
+
+ // Check nested products
+ VERIFY_EVALUATION_COUNT( cvres.noalias() = m1.adjoint() * m1 * cv1, 1 );
+ VERIFY_EVALUATION_COUNT( rvres.noalias() = rv1 * (m1 * m2.adjoint()), 1 );
}
void test_product_notemporary()
@@ -131,11 +148,12 @@ void test_product_notemporary()
for(int i = 0; i < g_repeat; i++) {
s = internal::random<int>(16,EIGEN_TEST_MAX_SIZE);
CALL_SUBTEST_1( product_notemporary(MatrixXf(s, s)) );
- s = internal::random<int>(16,EIGEN_TEST_MAX_SIZE);
CALL_SUBTEST_2( product_notemporary(MatrixXd(s, s)) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
+
s = internal::random<int>(16,EIGEN_TEST_MAX_SIZE/2);
CALL_SUBTEST_3( product_notemporary(MatrixXcf(s,s)) );
- s = internal::random<int>(16,EIGEN_TEST_MAX_SIZE/2);
CALL_SUBTEST_4( product_notemporary(MatrixXcd(s,s)) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
}
}
diff --git a/test/product_selfadjoint.cpp b/test/product_selfadjoint.cpp
index 374e2393b..3d768aa7e 100644
--- a/test/product_selfadjoint.cpp
+++ b/test/product_selfadjoint.cpp
@@ -67,14 +67,21 @@ void test_product_selfadjoint()
CALL_SUBTEST_1( product_selfadjoint(Matrix<float, 1, 1>()) );
CALL_SUBTEST_2( product_selfadjoint(Matrix<float, 2, 2>()) );
CALL_SUBTEST_3( product_selfadjoint(Matrix3d()) );
+
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
CALL_SUBTEST_4( product_selfadjoint(MatrixXcf(s, s)) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
+
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
CALL_SUBTEST_5( product_selfadjoint(MatrixXcd(s,s)) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
+
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
CALL_SUBTEST_6( product_selfadjoint(MatrixXd(s,s)) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
+
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
CALL_SUBTEST_7( product_selfadjoint(Matrix<float,Dynamic,Dynamic,RowMajor>(s,s)) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
}
- TEST_SET_BUT_UNUSED_VARIABLE(s)
}
diff --git a/test/product_small.cpp b/test/product_small.cpp
index 8b132abb6..fdfdd9f6c 100644
--- a/test/product_small.cpp
+++ b/test/product_small.cpp
@@ -9,8 +9,10 @@
#define EIGEN_NO_STATIC_ASSERT
#include "product.h"
+#include <Eigen/LU>
// regression test for bug 447
+template<int>
void product1x1()
{
Matrix<float,1,3> matAstatic;
@@ -28,16 +30,237 @@ void product1x1()
matAdynamic.cwiseProduct(matBdynamic.transpose()).sum() );
}
+template<typename TC, typename TA, typename TB>
+const TC& ref_prod(TC &C, const TA &A, const TB &B)
+{
+ for(Index i=0;i<C.rows();++i)
+ for(Index j=0;j<C.cols();++j)
+ for(Index k=0;k<A.cols();++k)
+ C.coeffRef(i,j) += A.coeff(i,k) * B.coeff(k,j);
+ return C;
+}
+
+template<typename T, int Rows, int Cols, int Depth, int OC, int OA, int OB>
+typename internal::enable_if<! ( (Rows ==1&&Depth!=1&&OA==ColMajor)
+ || (Depth==1&&Rows !=1&&OA==RowMajor)
+ || (Cols ==1&&Depth!=1&&OB==RowMajor)
+ || (Depth==1&&Cols !=1&&OB==ColMajor)
+ || (Rows ==1&&Cols !=1&&OC==ColMajor)
+ || (Cols ==1&&Rows !=1&&OC==RowMajor)),void>::type
+test_lazy_single(int rows, int cols, int depth)
+{
+ Matrix<T,Rows,Depth,OA> A(rows,depth); A.setRandom();
+ Matrix<T,Depth,Cols,OB> B(depth,cols); B.setRandom();
+ Matrix<T,Rows,Cols,OC> C(rows,cols); C.setRandom();
+ Matrix<T,Rows,Cols,OC> D(C);
+ VERIFY_IS_APPROX(C+=A.lazyProduct(B), ref_prod(D,A,B));
+}
+
+template<typename T, int Rows, int Cols, int Depth, int OC, int OA, int OB>
+typename internal::enable_if< ( (Rows ==1&&Depth!=1&&OA==ColMajor)
+ || (Depth==1&&Rows !=1&&OA==RowMajor)
+ || (Cols ==1&&Depth!=1&&OB==RowMajor)
+ || (Depth==1&&Cols !=1&&OB==ColMajor)
+ || (Rows ==1&&Cols !=1&&OC==ColMajor)
+ || (Cols ==1&&Rows !=1&&OC==RowMajor)),void>::type
+test_lazy_single(int, int, int)
+{
+}
+
+template<typename T, int Rows, int Cols, int Depth>
+void test_lazy_all_layout(int rows=Rows, int cols=Cols, int depth=Depth)
+{
+ CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,ColMajor,ColMajor,ColMajor>(rows,cols,depth) ));
+ CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,RowMajor,ColMajor,ColMajor>(rows,cols,depth) ));
+ CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,ColMajor,RowMajor,ColMajor>(rows,cols,depth) ));
+ CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,RowMajor,RowMajor,ColMajor>(rows,cols,depth) ));
+ CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,ColMajor,ColMajor,RowMajor>(rows,cols,depth) ));
+ CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,RowMajor,ColMajor,RowMajor>(rows,cols,depth) ));
+ CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,ColMajor,RowMajor,RowMajor>(rows,cols,depth) ));
+ CALL_SUBTEST(( test_lazy_single<T,Rows,Cols,Depth,RowMajor,RowMajor,RowMajor>(rows,cols,depth) ));
+}
+
+template<typename T>
+void test_lazy_l1()
+{
+ int rows = internal::random<int>(1,12);
+ int cols = internal::random<int>(1,12);
+ int depth = internal::random<int>(1,12);
+
+ // Inner
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,1,1>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,1,2>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,1,3>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,1,8>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,1,9>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,1,-1>(1,1,depth) ));
+
+ // Outer
+ CALL_SUBTEST(( test_lazy_all_layout<T,2,1,1>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,2,1>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,2,2,1>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,3,3,1>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,4,4,1>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,4,8,1>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,4,-1,1>(4,cols) ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,7,-1,1>(7,cols) ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,-1,8,1>(rows) ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,-1,3,1>(rows) ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,-1,-1,1>(rows,cols) ));
+}
+
+template<typename T>
+void test_lazy_l2()
+{
+ int rows = internal::random<int>(1,12);
+ int cols = internal::random<int>(1,12);
+ int depth = internal::random<int>(1,12);
+
+ // mat-vec
+ CALL_SUBTEST(( test_lazy_all_layout<T,2,1,2>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,2,1,4>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,4,1,2>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,4,1,4>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,5,1,4>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,4,1,5>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,4,1,6>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,6,1,4>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,8,1,8>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,-1,1,4>(rows) ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,4,1,-1>(4,1,depth) ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,-1,1,-1>(rows,1,depth) ));
+
+ // vec-mat
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,2,2>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,2,4>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,4,2>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,4,4>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,5,4>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,4,5>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,4,6>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,6,4>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,8,8>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,-1, 4>(1,cols) ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,1, 4,-1>(1,4,depth) ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,1,-1,-1>(1,cols,depth) ));
+}
+
+template<typename T>
+void test_lazy_l3()
+{
+ int rows = internal::random<int>(1,12);
+ int cols = internal::random<int>(1,12);
+ int depth = internal::random<int>(1,12);
+ // mat-mat
+ CALL_SUBTEST(( test_lazy_all_layout<T,2,4,2>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,2,6,4>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,4,3,2>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,4,8,4>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,5,6,4>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,4,2,5>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,4,7,6>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,6,8,4>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,8,3,8>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,-1,6,4>(rows) ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,4,3,-1>(4,3,depth) ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,-1,6,-1>(rows,6,depth) ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,8,2,2>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,5,2,4>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,4,4,2>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,8,4,4>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,6,5,4>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,4,4,5>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,3,4,6>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,2,6,4>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,7,8,8>() ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,8,-1, 4>(8,cols) ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,3, 4,-1>(3,4,depth) ));
+ CALL_SUBTEST(( test_lazy_all_layout<T,4,-1,-1>(4,cols,depth) ));
+}
+
+template<typename T,int N,int M,int K>
+void test_linear_but_not_vectorizable()
+{
+ // Check tricky cases for which the result of the product is a vector and thus must exhibit the LinearBit flag,
+ // but is not vectorizable along the linear dimension.
+ Index n = N==Dynamic ? internal::random<Index>(1,32) : N;
+ Index m = M==Dynamic ? internal::random<Index>(1,32) : M;
+ Index k = K==Dynamic ? internal::random<Index>(1,32) : K;
+
+ {
+ Matrix<T,N,M+1> A; A.setRandom(n,m+1);
+ Matrix<T,M*2,K> B; B.setRandom(m*2,k);
+ Matrix<T,1,K> C;
+ Matrix<T,1,K> R;
+
+ C.noalias() = A.template topLeftCorner<1,M>() * (B.template topRows<M>()+B.template bottomRows<M>());
+ R.noalias() = A.template topLeftCorner<1,M>() * (B.template topRows<M>()+B.template bottomRows<M>()).eval();
+ VERIFY_IS_APPROX(C,R);
+ }
+
+ {
+ Matrix<T,M+1,N,RowMajor> A; A.setRandom(m+1,n);
+ Matrix<T,K,M*2,RowMajor> B; B.setRandom(k,m*2);
+ Matrix<T,K,1> C;
+ Matrix<T,K,1> R;
+
+ C.noalias() = (B.template leftCols<M>()+B.template rightCols<M>()) * A.template topLeftCorner<M,1>();
+ R.noalias() = (B.template leftCols<M>()+B.template rightCols<M>()).eval() * A.template topLeftCorner<M,1>();
+ VERIFY_IS_APPROX(C,R);
+ }
+}
+
+template<int Rows>
+void bug_1311()
+{
+ Matrix< double, Rows, 2 > A; A.setRandom();
+ Vector2d b = Vector2d::Random() ;
+ Matrix<double,Rows,1> res;
+ res.noalias() = 1. * (A * b);
+ VERIFY_IS_APPROX(res, A*b);
+ res.noalias() = 1.*A * b;
+ VERIFY_IS_APPROX(res, A*b);
+ res.noalias() = (1.*A).lazyProduct(b);
+ VERIFY_IS_APPROX(res, A*b);
+ res.noalias() = (1.*A).lazyProduct(1.*b);
+ VERIFY_IS_APPROX(res, A*b);
+ res.noalias() = (A).lazyProduct(1.*b);
+ VERIFY_IS_APPROX(res, A*b);
+}
void test_product_small()
{
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_1( product(Matrix<float, 3, 2>()) );
- CALL_SUBTEST_2( product(Matrix<int, 3, 5>()) );
+ CALL_SUBTEST_2( product(Matrix<int, 3, 17>()) );
+ CALL_SUBTEST_8( product(Matrix<double, 3, 17>()) );
CALL_SUBTEST_3( product(Matrix3d()) );
CALL_SUBTEST_4( product(Matrix4d()) );
CALL_SUBTEST_5( product(Matrix4f()) );
- CALL_SUBTEST_6( product1x1() );
+ CALL_SUBTEST_6( product1x1<0>() );
+
+ CALL_SUBTEST_11( test_lazy_l1<float>() );
+ CALL_SUBTEST_12( test_lazy_l2<float>() );
+ CALL_SUBTEST_13( test_lazy_l3<float>() );
+
+ CALL_SUBTEST_21( test_lazy_l1<double>() );
+ CALL_SUBTEST_22( test_lazy_l2<double>() );
+ CALL_SUBTEST_23( test_lazy_l3<double>() );
+
+ CALL_SUBTEST_31( test_lazy_l1<std::complex<float> >() );
+ CALL_SUBTEST_32( test_lazy_l2<std::complex<float> >() );
+ CALL_SUBTEST_33( test_lazy_l3<std::complex<float> >() );
+
+ CALL_SUBTEST_41( test_lazy_l1<std::complex<double> >() );
+ CALL_SUBTEST_42( test_lazy_l2<std::complex<double> >() );
+ CALL_SUBTEST_43( test_lazy_l3<std::complex<double> >() );
+
+ CALL_SUBTEST_7(( test_linear_but_not_vectorizable<float,2,1,Dynamic>() ));
+ CALL_SUBTEST_7(( test_linear_but_not_vectorizable<float,3,1,Dynamic>() ));
+ CALL_SUBTEST_7(( test_linear_but_not_vectorizable<float,2,1,16>() ));
+
+ CALL_SUBTEST_6( bug_1311<3>() );
+ CALL_SUBTEST_6( bug_1311<5>() );
}
#ifdef EIGEN_TEST_PART_6
@@ -46,5 +269,25 @@ void test_product_small()
Vector3f v = Vector3f::Random();
VERIFY_IS_APPROX( (v * v.transpose()) * v, (v * v.transpose()).eval() * v);
}
+
+ {
+ // regression test for pull-request #93
+ Eigen::Matrix<double, 1, 1> A; A.setRandom();
+ Eigen::Matrix<double, 18, 1> B; B.setRandom();
+ Eigen::Matrix<double, 1, 18> C; C.setRandom();
+ VERIFY_IS_APPROX(B * A.inverse(), B * A.inverse()[0]);
+ VERIFY_IS_APPROX(A.inverse() * C, A.inverse()[0] * C);
+ }
+
+ {
+ Eigen::Matrix<double, 10, 10> A, B, C;
+ A.setRandom();
+ C = A;
+ for(int k=0; k<79; ++k)
+ C = C * A;
+ B.noalias() = (((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A)) * ((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A)))
+ * (((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A)) * ((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A))*((A*A)*(A*A)));
+ VERIFY_IS_APPROX(B,C);
+ }
#endif
}
diff --git a/test/product_symm.cpp b/test/product_symm.cpp
index 74d7329b1..8c44383f9 100644
--- a/test/product_symm.cpp
+++ b/test/product_symm.cpp
@@ -39,6 +39,24 @@ template<typename Scalar, int Size, int OtherSize> void symm(int size = Size, in
VERIFY_IS_APPROX(rhs12 = (s1*m2).template selfadjointView<Lower>() * (s2*rhs1),
rhs13 = (s1*m1) * (s2*rhs1));
+ VERIFY_IS_APPROX(rhs12 = (s1*m2).transpose().template selfadjointView<Upper>() * (s2*rhs1),
+ rhs13 = (s1*m1.transpose()) * (s2*rhs1));
+
+ VERIFY_IS_APPROX(rhs12 = (s1*m2).template selfadjointView<Lower>().transpose() * (s2*rhs1),
+ rhs13 = (s1*m1.transpose()) * (s2*rhs1));
+
+ VERIFY_IS_APPROX(rhs12 = (s1*m2).conjugate().template selfadjointView<Lower>() * (s2*rhs1),
+ rhs13 = (s1*m1).conjugate() * (s2*rhs1));
+
+ VERIFY_IS_APPROX(rhs12 = (s1*m2).template selfadjointView<Lower>().conjugate() * (s2*rhs1),
+ rhs13 = (s1*m1).conjugate() * (s2*rhs1));
+
+ VERIFY_IS_APPROX(rhs12 = (s1*m2).adjoint().template selfadjointView<Upper>() * (s2*rhs1),
+ rhs13 = (s1*m1).adjoint() * (s2*rhs1));
+
+ VERIFY_IS_APPROX(rhs12 = (s1*m2).template selfadjointView<Lower>().adjoint() * (s2*rhs1),
+ rhs13 = (s1*m1).adjoint() * (s2*rhs1));
+
m2 = m1.template triangularView<Upper>(); rhs12.setRandom(); rhs13 = rhs12;
m3 = m2.template selfadjointView<Upper>();
VERIFY_IS_EQUAL(m1, m3);
diff --git a/test/product_syrk.cpp b/test/product_syrk.cpp
index 73c95000c..e10f0f2f2 100644
--- a/test/product_syrk.cpp
+++ b/test/product_syrk.cpp
@@ -125,11 +125,12 @@ void test_product_syrk()
int s;
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
CALL_SUBTEST_1( syrk(MatrixXf(s, s)) );
- s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
CALL_SUBTEST_2( syrk(MatrixXd(s, s)) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
+
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
CALL_SUBTEST_3( syrk(MatrixXcf(s, s)) );
- s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
CALL_SUBTEST_4( syrk(MatrixXcd(s, s)) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
}
}
diff --git a/test/product_trmm.cpp b/test/product_trmm.cpp
index d715b9a36..12e554410 100644
--- a/test/product_trmm.cpp
+++ b/test/product_trmm.cpp
@@ -9,10 +9,18 @@
#include "main.h"
+template<typename T>
+int get_random_size()
+{
+ const int factor = NumTraits<T>::ReadCost;
+ const int max_test_size = EIGEN_TEST_MAX_SIZE>2*factor ? EIGEN_TEST_MAX_SIZE/factor : EIGEN_TEST_MAX_SIZE;
+ return internal::random<int>(1,max_test_size);
+}
+
template<typename Scalar, int Mode, int TriOrder, int OtherOrder, int ResOrder, int OtherCols>
-void trmm(int rows=internal::random<int>(1,EIGEN_TEST_MAX_SIZE),
- int cols=internal::random<int>(1,EIGEN_TEST_MAX_SIZE),
- int otherCols = OtherCols==Dynamic?internal::random<int>(1,EIGEN_TEST_MAX_SIZE):OtherCols)
+void trmm(int rows=get_random_size<Scalar>(),
+ int cols=get_random_size<Scalar>(),
+ int otherCols = OtherCols==Dynamic?get_random_size<Scalar>():OtherCols)
{
typedef Matrix<Scalar,Dynamic,Dynamic,TriOrder> TriMatrix;
typedef Matrix<Scalar,Dynamic,OtherCols,OtherCols==1?ColMajor:OtherOrder> OnTheRight;
@@ -42,13 +50,13 @@ void trmm(int rows=internal::random<int>(1,EIGEN_TEST_MAX_SIZE),
VERIFY_IS_APPROX( ge_xs.noalias() = mat.template triangularView<Mode>() * ge_right, tri * ge_right);
VERIFY_IS_APPROX( ge_sx.noalias() = ge_left * mat.template triangularView<Mode>(), ge_left * tri);
-
+
VERIFY_IS_APPROX( ge_xs.noalias() = (s1*mat.adjoint()).template triangularView<Mode>() * (s2*ge_left.transpose()), s1*triTr.conjugate() * (s2*ge_left.transpose()));
VERIFY_IS_APPROX( ge_sx.noalias() = ge_right.transpose() * mat.adjoint().template triangularView<Mode>(), ge_right.transpose() * triTr.conjugate());
VERIFY_IS_APPROX( ge_xs.noalias() = (s1*mat.adjoint()).template triangularView<Mode>() * (s2*ge_left.adjoint()), s1*triTr.conjugate() * (s2*ge_left.adjoint()));
VERIFY_IS_APPROX( ge_sx.noalias() = ge_right.adjoint() * mat.adjoint().template triangularView<Mode>(), ge_right.adjoint() * triTr.conjugate());
-
+
ge_xs_save = ge_xs;
VERIFY_IS_APPROX( (ge_xs_save + s1*triTr.conjugate() * (s2*ge_left.adjoint())).eval(), ge_xs.noalias() += (s1*mat.adjoint()).template triangularView<Mode>() * (s2*ge_left.adjoint()) );
ge_sx.setRandom();
@@ -61,13 +69,13 @@ void trmm(int rows=internal::random<int>(1,EIGEN_TEST_MAX_SIZE),
}
template<typename Scalar, int Mode, int TriOrder>
-void trmv(int rows=internal::random<int>(1,EIGEN_TEST_MAX_SIZE), int cols=internal::random<int>(1,EIGEN_TEST_MAX_SIZE))
+void trmv(int rows=get_random_size<Scalar>(), int cols=get_random_size<Scalar>())
{
trmm<Scalar,Mode,TriOrder,ColMajor,ColMajor,1>(rows,cols,1);
}
template<typename Scalar, int Mode, int TriOrder, int OtherOrder, int ResOrder>
-void trmm(int rows=internal::random<int>(1,EIGEN_TEST_MAX_SIZE), int cols=internal::random<int>(1,EIGEN_TEST_MAX_SIZE), int otherCols = internal::random<int>(1,EIGEN_TEST_MAX_SIZE))
+void trmm(int rows=get_random_size<Scalar>(), int cols=get_random_size<Scalar>(), int otherCols = get_random_size<Scalar>())
{
trmm<Scalar,Mode,TriOrder,OtherOrder,ResOrder,Dynamic>(rows,cols,otherCols);
}
diff --git a/test/product_trmv.cpp b/test/product_trmv.cpp
index 4c3c435c2..57a202afc 100644
--- a/test/product_trmv.cpp
+++ b/test/product_trmv.cpp
@@ -78,12 +78,14 @@ void test_product_trmv()
CALL_SUBTEST_1( trmv(Matrix<float, 1, 1>()) );
CALL_SUBTEST_2( trmv(Matrix<float, 2, 2>()) );
CALL_SUBTEST_3( trmv(Matrix3d()) );
+
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
CALL_SUBTEST_4( trmv(MatrixXcf(s,s)) );
- s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
CALL_SUBTEST_5( trmv(MatrixXcd(s,s)) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
+
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
CALL_SUBTEST_6( trmv(Matrix<float,Dynamic,Dynamic,RowMajor>(s, s)) );
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
}
- TEST_SET_BUT_UNUSED_VARIABLE(s);
}
diff --git a/test/product_trsolve.cpp b/test/product_trsolve.cpp
index 69892b3a8..4b97fa9d6 100644
--- a/test/product_trsolve.cpp
+++ b/test/product_trsolve.cpp
@@ -84,10 +84,18 @@ void test_product_trsolve()
CALL_SUBTEST_4((trsolve<std::complex<double>,Dynamic,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2),internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))));
// vectors
- CALL_SUBTEST_1((trsolve<float,Dynamic,1>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))));
- CALL_SUBTEST_5((trsolve<std::complex<double>,Dynamic,1>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))));
- CALL_SUBTEST_6((trsolve<float,1,1>()));
- CALL_SUBTEST_7((trsolve<float,1,2>()));
- CALL_SUBTEST_8((trsolve<std::complex<float>,4,1>()));
+ CALL_SUBTEST_5((trsolve<float,Dynamic,1>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))));
+ CALL_SUBTEST_6((trsolve<double,Dynamic,1>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))));
+ CALL_SUBTEST_7((trsolve<std::complex<float>,Dynamic,1>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))));
+ CALL_SUBTEST_8((trsolve<std::complex<double>,Dynamic,1>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))));
+
+ // meta-unrollers
+ CALL_SUBTEST_9((trsolve<float,4,1>()));
+ CALL_SUBTEST_10((trsolve<double,4,1>()));
+ CALL_SUBTEST_11((trsolve<std::complex<float>,4,1>()));
+ CALL_SUBTEST_12((trsolve<float,1,1>()));
+ CALL_SUBTEST_13((trsolve<float,1,2>()));
+ CALL_SUBTEST_14((trsolve<float,3,1>()));
+
}
}
diff --git a/test/qr.cpp b/test/qr.cpp
index a79e0dd34..dfcc1e8f9 100644
--- a/test/qr.cpp
+++ b/test/qr.cpp
@@ -54,6 +54,8 @@ template<typename MatrixType> void qr_invertible()
{
using std::log;
using std::abs;
+ using std::pow;
+ using std::max;
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
typedef typename MatrixType::Scalar Scalar;
@@ -65,7 +67,7 @@ template<typename MatrixType> void qr_invertible()
if (internal::is_same<RealScalar,float>::value)
{
// let's build a matrix more stable to inverse
- MatrixType a = MatrixType::Random(size,size*2);
+ MatrixType a = MatrixType::Random(size,size*4);
m1 += a * a.adjoint();
}
@@ -81,8 +83,11 @@ template<typename MatrixType> void qr_invertible()
m3 = qr.householderQ(); // get a unitary
m1 = m3 * m1 * m3;
qr.compute(m1);
- VERIFY_IS_APPROX(absdet, qr.absDeterminant());
VERIFY_IS_APPROX(log(absdet), qr.logAbsDeterminant());
+ // This test is tricky if the determinant becomes too small.
+ // Since we generate random numbers with magnitude rrange [0,1], the average determinant is 0.5^size
+ VERIFY_IS_MUCH_SMALLER_THAN( abs(absdet-qr.absDeterminant()), numext::maxi(RealScalar(pow(0.5,size)),numext::maxi<RealScalar>(abs(absdet),abs(qr.absDeterminant()))) );
+
}
template<typename MatrixType> void qr_verify_assert()
diff --git a/test/qr_colpivoting.cpp b/test/qr_colpivoting.cpp
index eb3feac01..26ed27f5c 100644
--- a/test/qr_colpivoting.cpp
+++ b/test/qr_colpivoting.cpp
@@ -10,21 +10,103 @@
#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()
{
+ using std::sqrt;
typedef typename MatrixType::Index Index;
Index rows = internal::random<Index>(2,EIGEN_TEST_MAX_SIZE), cols = internal::random<Index>(2,EIGEN_TEST_MAX_SIZE), 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 typename MatrixType::RealScalar RealScalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType;
MatrixType m1;
createRandomPIMatrixOfRank(rank,rows,cols,m1);
ColPivHouseholderQR<MatrixType> qr(m1);
- VERIFY(rank == qr.rank());
- VERIFY(cols - qr.rank() == qr.dimensionOfKernel());
+ VERIFY_IS_EQUAL(rank, qr.rank());
+ VERIFY_IS_EQUAL(cols - qr.rank(), qr.dimensionOfKernel());
VERIFY(!qr.isInjective());
VERIFY(!qr.isInvertible());
VERIFY(!qr.isSurjective());
@@ -36,26 +118,59 @@ 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 =
+ sqrt(RealScalar(rows)) * numext::abs(r(0, 0)) * NumTraits<Scalar>::epsilon();
+ for (Index i = 0; i < (std::min)(rows, cols) - 1; ++i) {
+ RealScalar x = numext::abs(r(i, i));
+ RealScalar y = numext::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| = " << numext::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);
m2 = qr.solve(m3);
VERIFY_IS_APPROX(m3, m1*m2);
+
+ {
+ Index size = rows;
+ do {
+ m1 = MatrixType::Random(size,size);
+ qr.compute(m1);
+ } while(!qr.isInvertible());
+ MatrixType m1_inv = qr.inverse();
+ m3 = m1 * MatrixType::Random(size,cols2);
+ m2 = qr.solve(m3);
+ VERIFY_IS_APPROX(m2, m1_inv*m3);
+ }
}
template<typename MatrixType, int Cols2> void qr_fixedsize()
{
+ using std::sqrt;
+ using std::abs;
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);
ColPivHouseholderQR<Matrix<Scalar,Rows,Cols> > qr(m1);
- VERIFY(rank == qr.rank());
- VERIFY(Cols - qr.rank() == qr.dimensionOfKernel());
- VERIFY(qr.isInjective() == (rank == Rows));
- VERIFY(qr.isSurjective() == (rank == Cols));
- VERIFY(qr.isInvertible() == (qr.isInjective() && qr.isSurjective()));
+ VERIFY_IS_EQUAL(rank, qr.rank());
+ VERIFY_IS_EQUAL(Cols - qr.rank(), qr.dimensionOfKernel());
+ VERIFY_IS_EQUAL(qr.isInjective(), (rank == Rows));
+ VERIFY_IS_EQUAL(qr.isSurjective(), (rank == Cols));
+ VERIFY_IS_EQUAL(qr.isInvertible(), (qr.isInjective() && qr.isSurjective()));
Matrix<Scalar,Rows,Cols> r = qr.matrixQR().template triangularView<Upper>();
Matrix<Scalar,Rows,Cols> c = qr.householderQ() * r * qr.colsPermutation().inverse();
@@ -66,6 +181,71 @@ 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 =
+ 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 = numext::abs(r(i, i));
+ RealScalar y = numext::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| = " << numext::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()
+{
+ using std::sqrt;
+ using std::abs;
+ 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);
+ RealScalar pow_s_i(1.0); // pow(s,i)
+ 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);
+ pow_s_i *= s;
+ }
+ m1 = (m1 + m1.transpose()).eval();
+ ColPivHouseholderQR<MatrixType> qr(m1);
+ MatrixType r = qr.matrixQR().template triangularView<Upper>();
+
+ RealScalar threshold =
+ std::sqrt(RealScalar(rows)) * numext::abs(r(0, 0)) * NumTraits<Scalar>::epsilon();
+ for (Index i = 0; i < (std::min)(rows, cols) - 1; ++i) {
+ RealScalar x = numext::abs(r(i, i));
+ RealScalar y = numext::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| = " << numext::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 +312,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 +336,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/qr_fullpivoting.cpp b/test/qr_fullpivoting.cpp
index 511f2473f..70e89c198 100644
--- a/test/qr_fullpivoting.cpp
+++ b/test/qr_fullpivoting.cpp
@@ -15,16 +15,20 @@ template<typename MatrixType> void qr()
{
typedef typename MatrixType::Index Index;
- Index rows = internal::random<Index>(20,200), cols = internal::random<int>(20,200), cols2 = internal::random<int>(20,200);
- Index rank = internal::random<Index>(1, (std::min)(rows, cols)-1);
+ Index max_size = EIGEN_TEST_MAX_SIZE;
+ Index min_size = numext::maxi(1,EIGEN_TEST_MAX_SIZE/10);
+ Index rows = internal::random<Index>(min_size,max_size),
+ cols = internal::random<Index>(min_size,max_size),
+ cols2 = internal::random<Index>(min_size,max_size),
+ rank = internal::random<Index>(1, (std::min)(rows, cols)-1);
typedef typename MatrixType::Scalar Scalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType;
MatrixType m1;
createRandomPIMatrixOfRank(rank,rows,cols,m1);
FullPivHouseholderQR<MatrixType> qr(m1);
- VERIFY(rank == qr.rank());
- VERIFY(cols - qr.rank() == qr.dimensionOfKernel());
+ VERIFY_IS_EQUAL(rank, qr.rank());
+ VERIFY_IS_EQUAL(cols - qr.rank(), qr.dimensionOfKernel());
VERIFY(!qr.isInjective());
VERIFY(!qr.isInvertible());
VERIFY(!qr.isSurjective());
@@ -40,12 +44,28 @@ template<typename MatrixType> void qr()
MatrixType c = qr.matrixQ() * r * qr.colsPermutation().inverse();
VERIFY_IS_APPROX(m1, c);
-
+
+ // stress the ReturnByValue mechanism
+ MatrixType tmp;
+ VERIFY_IS_APPROX(tmp.noalias() = qr.matrixQ() * r, (qr.matrixQ() * r).eval());
+
MatrixType m2 = MatrixType::Random(cols,cols2);
MatrixType m3 = m1*m2;
m2 = MatrixType::Random(cols,cols2);
m2 = qr.solve(m3);
VERIFY_IS_APPROX(m3, m1*m2);
+
+ {
+ Index size = rows;
+ do {
+ m1 = MatrixType::Random(size,size);
+ qr.compute(m1);
+ } while(!qr.isInvertible());
+ MatrixType m1_inv = qr.inverse();
+ m3 = m1 * MatrixType::Random(size,cols2);
+ m2 = qr.solve(m3);
+ VERIFY_IS_APPROX(m2, m1_inv*m3);
+ }
}
template<typename MatrixType> void qr_invertible()
@@ -55,7 +75,9 @@ template<typename MatrixType> void qr_invertible()
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
typedef typename MatrixType::Scalar Scalar;
- int size = internal::random<int>(10,50);
+ Index max_size = numext::mini(50,EIGEN_TEST_MAX_SIZE);
+ Index min_size = numext::maxi(1,EIGEN_TEST_MAX_SIZE/10);
+ Index size = internal::random<Index>(min_size,max_size);
MatrixType m1(size, size), m2(size, size), m3(size, size);
m1 = MatrixType::Random(size,size);
diff --git a/test/rand.cpp b/test/rand.cpp
new file mode 100644
index 000000000..51cf01773
--- /dev/null
+++ b/test/rand.cpp
@@ -0,0 +1,118 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// 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/.
+
+#include "main.h"
+
+typedef long long int64;
+
+template<typename Scalar> Scalar check_in_range(Scalar x, Scalar y)
+{
+ Scalar r = internal::random<Scalar>(x,y);
+ VERIFY(r>=x);
+ if(y>=x)
+ {
+ VERIFY(r<=y);
+ }
+ return r;
+}
+
+template<typename Scalar> void check_all_in_range(Scalar x, Scalar y)
+{
+ Array<int,1,Dynamic> mask(y-x+1);
+ mask.fill(0);
+ long n = (y-x+1)*32;
+ for(long k=0; k<n; ++k)
+ {
+ mask( check_in_range(x,y)-x )++;
+ }
+ for(Index i=0; i<mask.size(); ++i)
+ if(mask(i)==0)
+ std::cout << "WARNING: value " << x+i << " not reached." << std::endl;
+ VERIFY( (mask>0).all() );
+}
+
+template<typename Scalar> void check_histogram(Scalar x, Scalar y, int bins)
+{
+ Array<int,1,Dynamic> hist(bins);
+ hist.fill(0);
+ int f = 100000;
+ int n = bins*f;
+ int64 range = int64(y)-int64(x);
+ int divisor = int((range+1)/bins);
+ assert(((range+1)%bins)==0);
+ for(int k=0; k<n; ++k)
+ {
+ Scalar r = check_in_range(x,y);
+ hist( int((int64(r)-int64(x))/divisor) )++;
+ }
+ VERIFY( (((hist.cast<double>()/double(f))-1.0).abs()<0.02).all() );
+}
+
+void test_rand()
+{
+ long long_ref = NumTraits<long>::highest()/10;
+ signed char char_offset = (std::min)(g_repeat,64);
+ signed char short_offset = (std::min)(g_repeat,16000);
+
+ for(int i = 0; i < g_repeat*10000; i++) {
+ CALL_SUBTEST(check_in_range<float>(10,11));
+ CALL_SUBTEST(check_in_range<float>(1.24234523,1.24234523));
+ CALL_SUBTEST(check_in_range<float>(-1,1));
+ CALL_SUBTEST(check_in_range<float>(-1432.2352,-1432.2352));
+
+ CALL_SUBTEST(check_in_range<double>(10,11));
+ CALL_SUBTEST(check_in_range<double>(1.24234523,1.24234523));
+ CALL_SUBTEST(check_in_range<double>(-1,1));
+ CALL_SUBTEST(check_in_range<double>(-1432.2352,-1432.2352));
+
+ CALL_SUBTEST(check_in_range<int>(0,-1));
+ CALL_SUBTEST(check_in_range<short>(0,-1));
+ CALL_SUBTEST(check_in_range<long>(0,-1));
+ CALL_SUBTEST(check_in_range<int>(-673456,673456));
+ CALL_SUBTEST(check_in_range<int>(-RAND_MAX+10,RAND_MAX-10));
+ CALL_SUBTEST(check_in_range<short>(-24345,24345));
+ CALL_SUBTEST(check_in_range<long>(-long_ref,long_ref));
+ }
+
+ CALL_SUBTEST(check_all_in_range<signed char>(11,11));
+ CALL_SUBTEST(check_all_in_range<signed char>(11,11+char_offset));
+ CALL_SUBTEST(check_all_in_range<signed char>(-5,5));
+ CALL_SUBTEST(check_all_in_range<signed char>(-11-char_offset,-11));
+ CALL_SUBTEST(check_all_in_range<signed char>(-126,-126+char_offset));
+ CALL_SUBTEST(check_all_in_range<signed char>(126-char_offset,126));
+ CALL_SUBTEST(check_all_in_range<signed char>(-126,126));
+
+ CALL_SUBTEST(check_all_in_range<short>(11,11));
+ CALL_SUBTEST(check_all_in_range<short>(11,11+short_offset));
+ CALL_SUBTEST(check_all_in_range<short>(-5,5));
+ CALL_SUBTEST(check_all_in_range<short>(-11-short_offset,-11));
+ CALL_SUBTEST(check_all_in_range<short>(-24345,-24345+short_offset));
+ CALL_SUBTEST(check_all_in_range<short>(24345,24345+short_offset));
+
+ CALL_SUBTEST(check_all_in_range<int>(11,11));
+ CALL_SUBTEST(check_all_in_range<int>(11,11+g_repeat));
+ CALL_SUBTEST(check_all_in_range<int>(-5,5));
+ CALL_SUBTEST(check_all_in_range<int>(-11-g_repeat,-11));
+ CALL_SUBTEST(check_all_in_range<int>(-673456,-673456+g_repeat));
+ CALL_SUBTEST(check_all_in_range<int>(673456,673456+g_repeat));
+
+ CALL_SUBTEST(check_all_in_range<long>(11,11));
+ CALL_SUBTEST(check_all_in_range<long>(11,11+g_repeat));
+ CALL_SUBTEST(check_all_in_range<long>(-5,5));
+ CALL_SUBTEST(check_all_in_range<long>(-11-g_repeat,-11));
+ CALL_SUBTEST(check_all_in_range<long>(-long_ref,-long_ref+g_repeat));
+ CALL_SUBTEST(check_all_in_range<long>( long_ref, long_ref+g_repeat));
+
+ CALL_SUBTEST(check_histogram<int>(-5,5,11));
+ int bins = 100;
+ CALL_SUBTEST(check_histogram<int>(-3333,-3333+bins*(3333/bins)-1,bins));
+ bins = 1000;
+ CALL_SUBTEST(check_histogram<int>(-RAND_MAX+10,-RAND_MAX+10+bins*(RAND_MAX/bins)-1,bins));
+ CALL_SUBTEST(check_histogram<int>(-RAND_MAX+10,-int64(RAND_MAX)+10+bins*(2*int64(RAND_MAX)/bins)-1,bins));
+}
diff --git a/test/real_qz.cpp b/test/real_qz.cpp
index a1766c6d9..99ac31235 100644
--- a/test/real_qz.cpp
+++ b/test/real_qz.cpp
@@ -7,6 +7,7 @@
// 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/.
+#define EIGEN_RUNTIME_NO_MALLOC
#include "main.h"
#include <limits>
#include <Eigen/Eigenvalues>
@@ -41,7 +42,11 @@ template<typename MatrixType> void real_qz(const MatrixType& m)
break;
}
- RealQZ<MatrixType> qz(A,B);
+ RealQZ<MatrixType> qz(dim);
+ // TODO enable full-prealocation of required memory, this probably requires an in-place mode for HessenbergDecomposition
+ //Eigen::internal::set_is_malloc_allowed(false);
+ qz.compute(A,B);
+ //Eigen::internal::set_is_malloc_allowed(true);
VERIFY_IS_EQUAL(qz.info(), Success);
// check for zeros
@@ -49,11 +54,20 @@ template<typename MatrixType> void real_qz(const MatrixType& m)
for (Index i=0; i<A.cols(); i++)
for (Index j=0; j<i; j++) {
if (abs(qz.matrixT()(i,j))!=Scalar(0.0))
+ {
+ std::cerr << "Error: T(" << i << "," << j << ") = " << qz.matrixT()(i,j) << std::endl;
all_zeros = false;
+ }
if (j<i-1 && abs(qz.matrixS()(i,j))!=Scalar(0.0))
+ {
+ std::cerr << "Error: S(" << i << "," << j << ") = " << qz.matrixS()(i,j) << std::endl;
all_zeros = false;
+ }
if (j==i-1 && j>0 && abs(qz.matrixS()(i,j))!=Scalar(0.0) && abs(qz.matrixS()(i-1,j-1))!=Scalar(0.0))
+ {
+ std::cerr << "Error: S(" << i << "," << j << ") = " << qz.matrixS()(i,j) << " && S(" << i-1 << "," << j-1 << ") = " << qz.matrixS()(i-1,j-1) << std::endl;
all_zeros = false;
+ }
}
VERIFY_IS_EQUAL(all_zeros, true);
VERIFY_IS_APPROX(qz.matrixQ()*qz.matrixS()*qz.matrixZ(), A);
diff --git a/test/redux.cpp b/test/redux.cpp
index 0d176e500..989e1057b 100644
--- a/test/redux.cpp
+++ b/test/redux.cpp
@@ -2,11 +2,14 @@
// for linear algebra.
//
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// 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/.
+#define TEST_ENABLE_TEMPORARY_TRACKING
+
#include "main.h"
template<typename MatrixType> void matrixRedux(const MatrixType& m)
@@ -21,7 +24,7 @@ template<typename MatrixType> void matrixRedux(const MatrixType& m)
MatrixType m1 = MatrixType::Random(rows, cols);
// The entries of m1 are uniformly distributed in [0,1], so m1.prod() is very small. This may lead to test
- // failures if we underflow into denormals. Thus, we scale so that entires are close to 1.
+ // failures if we underflow into denormals. Thus, we scale so that entries are close to 1.
MatrixType m1_for_prod = MatrixType::Ones(rows, cols) + RealScalar(0.2) * m1;
VERIFY_IS_MUCH_SMALLER_THAN(MatrixType::Zero(rows, cols).sum(), Scalar(1));
@@ -53,10 +56,24 @@ template<typename MatrixType> void matrixRedux(const MatrixType& m)
VERIFY_IS_APPROX(m1_for_prod.block(r0,c0,r1,c1).prod(), m1_for_prod.block(r0,c0,r1,c1).eval().prod());
VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).real().minCoeff(), m1.block(r0,c0,r1,c1).real().eval().minCoeff());
VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).real().maxCoeff(), m1.block(r0,c0,r1,c1).real().eval().maxCoeff());
+
+ // regression for bug 1090
+ const int R1 = MatrixType::RowsAtCompileTime>=2 ? MatrixType::RowsAtCompileTime/2 : 6;
+ const int C1 = MatrixType::ColsAtCompileTime>=2 ? MatrixType::ColsAtCompileTime/2 : 6;
+ if(R1<=rows-r0 && C1<=cols-c0)
+ {
+ VERIFY_IS_APPROX( (m1.template block<R1,C1>(r0,c0).sum()), m1.block(r0,c0,R1,C1).sum() );
+ }
// test empty objects
VERIFY_IS_APPROX(m1.block(r0,c0,0,0).sum(), Scalar(0));
VERIFY_IS_APPROX(m1.block(r0,c0,0,0).prod(), Scalar(1));
+
+ // test nesting complex expression
+ VERIFY_EVALUATION_COUNT( (m1.matrix()*m1.matrix().transpose()).sum(), (MatrixType::IsVectorAtCompileTime && MatrixType::SizeAtCompileTime!=1 ? 0 : 1) );
+ Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> m2(rows,rows);
+ m2.setRandom();
+ VERIFY_EVALUATION_COUNT( ((m1.matrix()*m1.matrix().transpose())+m2).sum(),(MatrixType::IsVectorAtCompileTime && MatrixType::SizeAtCompileTime!=1 ? 0 : 1));
}
template<typename VectorType> void vectorRedux(const VectorType& w)
@@ -139,8 +156,10 @@ void test_redux()
CALL_SUBTEST_1( matrixRedux(Array<float, 1, 1>()) );
CALL_SUBTEST_2( matrixRedux(Matrix2f()) );
CALL_SUBTEST_2( matrixRedux(Array2f()) );
+ CALL_SUBTEST_2( matrixRedux(Array22f()) );
CALL_SUBTEST_3( matrixRedux(Matrix4d()) );
CALL_SUBTEST_3( matrixRedux(Array4d()) );
+ CALL_SUBTEST_3( matrixRedux(Array44d()) );
CALL_SUBTEST_4( matrixRedux(MatrixXcf(internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
CALL_SUBTEST_4( matrixRedux(ArrayXXcf(internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
CALL_SUBTEST_5( matrixRedux(MatrixXd (internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
diff --git a/test/ref.cpp b/test/ref.cpp
index 44bbd3bf1..769db0414 100644
--- a/test/ref.cpp
+++ b/test/ref.cpp
@@ -12,27 +12,23 @@
#undef EIGEN_DEFAULT_TO_ROW_MAJOR
#endif
-static int nb_temporaries;
-
-inline void on_temporary_creation(int) {
- // here's a great place to set a breakpoint when debugging failures in this test!
- nb_temporaries++;
-}
-
-
-#define EIGEN_DENSE_STORAGE_CTOR_PLUGIN { on_temporary_creation(size); }
+#define TEST_ENABLE_TEMPORARY_TRACKING
#include "main.h"
-#define VERIFY_EVALUATION_COUNT(XPR,N) {\
- nb_temporaries = 0; \
- XPR; \
- if(nb_temporaries!=N) std::cerr << "nb_temporaries == " << nb_temporaries << "\n"; \
- VERIFY( (#XPR) && nb_temporaries==N ); \
- }
+// test Ref.h
+// Deal with i387 extended precision
+#if EIGEN_ARCH_i386 && !(EIGEN_ARCH_x86_64)
-// test Ref.h
+#if EIGEN_COMP_GNUC_STRICT && EIGEN_GNUC_AT_LEAST(4,4)
+#pragma GCC optimize ("-ffloat-store")
+#else
+#undef VERIFY_IS_EQUAL
+#define VERIFY_IS_EQUAL(X,Y) VERIFY_IS_APPROX(X,Y)
+#endif
+
+#endif
template<typename MatrixType> void ref_matrix(const MatrixType& m)
{
@@ -71,7 +67,6 @@ template<typename MatrixType> void ref_matrix(const MatrixType& m)
rm2 = m2.block(i,j,brows,bcols);
VERIFY_IS_EQUAL(m1, m2);
-
ConstRefDynMat rm3 = m1.block(i,j,brows,bcols);
m1.block(i,j,brows,bcols) *= 2;
m2.block(i,j,brows,bcols) *= 2;
@@ -237,6 +232,12 @@ int test_ref_overload_fun1(Ref<MatrixXf> ) { return 3; }
int test_ref_overload_fun2(Ref<const MatrixXd> ) { return 4; }
int test_ref_overload_fun2(Ref<const MatrixXf> ) { return 5; }
+void test_ref_ambiguous(const Ref<const ArrayXd> &A, Ref<ArrayXd> B)
+{
+ B = A;
+ B = A - A;
+}
+
// See also bug 969
void test_ref_overloads()
{
@@ -249,6 +250,9 @@ void test_ref_overloads()
VERIFY( test_ref_overload_fun2(Ad)==4 );
VERIFY( test_ref_overload_fun2(Ad+Bd)==4 );
VERIFY( test_ref_overload_fun2(Af+Bf)==5 );
+
+ ArrayXd A, B;
+ test_ref_ambiguous(A, B);
}
void test_ref()
diff --git a/test/runtest.sh b/test/runtest.sh
deleted file mode 100755
index 2be250819..000000000
--- a/test/runtest.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-black='\E[30m'
-red='\E[31m'
-green='\E[32m'
-yellow='\E[33m'
-blue='\E[34m'
-magenta='\E[35m'
-cyan='\E[36m'
-white='\E[37m'
-
-if ! ./$1 > /dev/null 2> .runtest.log ; then
- echo -e $red Test $1 failed: $black
- echo -e $blue
- cat .runtest.log
- echo -e $black
- exit 1
-else
-echo -e $green Test $1 passed$black
-fi
diff --git a/test/rvalue_types.cpp b/test/rvalue_types.cpp
new file mode 100644
index 000000000..8887f1b1b
--- /dev/null
+++ b/test/rvalue_types.cpp
@@ -0,0 +1,64 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2013 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/Core>
+
+using internal::UIntPtr;
+
+#if EIGEN_HAS_RVALUE_REFERENCES
+template <typename MatrixType>
+void rvalue_copyassign(const MatrixType& m)
+{
+
+ typedef typename internal::traits<MatrixType>::Scalar Scalar;
+
+ // create a temporary which we are about to destroy by moving
+ MatrixType tmp = m;
+ UIntPtr src_address = reinterpret_cast<UIntPtr>(tmp.data());
+
+ // move the temporary to n
+ MatrixType n = std::move(tmp);
+ UIntPtr dst_address = reinterpret_cast<UIntPtr>(n.data());
+
+ if (MatrixType::RowsAtCompileTime==Dynamic|| MatrixType::ColsAtCompileTime==Dynamic)
+ {
+ // verify that we actually moved the guts
+ VERIFY_IS_EQUAL(src_address, dst_address);
+ }
+
+ // verify that the content did not change
+ Scalar abs_diff = (m-n).array().abs().sum();
+ VERIFY_IS_EQUAL(abs_diff, Scalar(0));
+}
+#else
+template <typename MatrixType>
+void rvalue_copyassign(const MatrixType&) {}
+#endif
+
+void test_rvalue_types()
+{
+ CALL_SUBTEST_1(rvalue_copyassign( MatrixXf::Random(50,50).eval() ));
+ CALL_SUBTEST_1(rvalue_copyassign( ArrayXXf::Random(50,50).eval() ));
+
+ CALL_SUBTEST_1(rvalue_copyassign( Matrix<float,1,Dynamic>::Random(50).eval() ));
+ CALL_SUBTEST_1(rvalue_copyassign( Array<float,1,Dynamic>::Random(50).eval() ));
+
+ CALL_SUBTEST_1(rvalue_copyassign( Matrix<float,Dynamic,1>::Random(50).eval() ));
+ CALL_SUBTEST_1(rvalue_copyassign( Array<float,Dynamic,1>::Random(50).eval() ));
+
+ CALL_SUBTEST_2(rvalue_copyassign( Array<float,2,1>::Random().eval() ));
+ CALL_SUBTEST_2(rvalue_copyassign( Array<float,3,1>::Random().eval() ));
+ CALL_SUBTEST_2(rvalue_copyassign( Array<float,4,1>::Random().eval() ));
+
+ CALL_SUBTEST_2(rvalue_copyassign( Array<float,2,2>::Random().eval() ));
+ CALL_SUBTEST_2(rvalue_copyassign( Array<float,3,3>::Random().eval() ));
+ CALL_SUBTEST_2(rvalue_copyassign( Array<float,4,4>::Random().eval() ));
+}
diff --git a/test/schur_complex.cpp b/test/schur_complex.cpp
index 5e869790f..deb78e44e 100644
--- a/test/schur_complex.cpp
+++ b/test/schur_complex.cpp
@@ -25,7 +25,7 @@ template<typename MatrixType> void schur(int size = MatrixType::ColsAtCompileTim
ComplexMatrixType T = schurOfA.matrixT();
for(int row = 1; row < size; ++row) {
for(int col = 0; col < row; ++col) {
- VERIFY(T(row,col) == (typename MatrixType::Scalar)0);
+ VERIFY(T(row,col) == (typename MatrixType::Scalar)0);
}
}
VERIFY_IS_APPROX(A.template cast<ComplexScalar>(), U * T * U.adjoint());
@@ -70,7 +70,7 @@ template<typename MatrixType> void schur(int size = MatrixType::ColsAtCompileTim
VERIFY_IS_EQUAL(cs1.matrixT(), csOnlyT.matrixT());
VERIFY_RAISES_ASSERT(csOnlyT.matrixU());
- if (size > 1)
+ if (size > 1 && size < 20)
{
// Test matrix with NaN
A(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
diff --git a/test/schur_real.cpp b/test/schur_real.cpp
index 36b9c24d1..4aede87df 100644
--- a/test/schur_real.cpp
+++ b/test/schur_real.cpp
@@ -82,7 +82,7 @@ template<typename MatrixType> void schur(int size = MatrixType::ColsAtCompileTim
Atriangular.template triangularView<StrictlyLower>().setZero();
rs3.setMaxIterations(1).compute(Atriangular); // triangular matrices do not need any iterations
VERIFY_IS_EQUAL(rs3.info(), Success);
- VERIFY_IS_EQUAL(rs3.matrixT(), Atriangular);
+ VERIFY_IS_APPROX(rs3.matrixT(), Atriangular); // approx because of scaling...
VERIFY_IS_EQUAL(rs3.matrixU(), MatrixType::Identity(size, size));
// Test computation of only T, not U
@@ -91,7 +91,7 @@ template<typename MatrixType> void schur(int size = MatrixType::ColsAtCompileTim
VERIFY_IS_EQUAL(rs1.matrixT(), rsOnlyT.matrixT());
VERIFY_RAISES_ASSERT(rsOnlyT.matrixU());
- if (size > 2)
+ if (size > 2 && size < 20)
{
// Test matrix with NaN
A(0,0) = std::numeric_limits<typename MatrixType::Scalar>::quiet_NaN();
diff --git a/test/selfadjoint.cpp b/test/selfadjoint.cpp
index 76dab6d64..92401e506 100644
--- a/test/selfadjoint.cpp
+++ b/test/selfadjoint.cpp
@@ -21,7 +21,9 @@ template<typename MatrixType> void selfadjoint(const MatrixType& m)
Index cols = m.cols();
MatrixType m1 = MatrixType::Random(rows, cols),
- m3(rows, cols);
+ m2 = MatrixType::Random(rows, cols),
+ m3(rows, cols),
+ m4(rows, cols);
m1.diagonal() = m1.diagonal().real().template cast<Scalar>();
@@ -30,10 +32,19 @@ template<typename MatrixType> void selfadjoint(const MatrixType& m)
VERIFY_IS_APPROX(MatrixType(m3.template triangularView<Upper>()), MatrixType(m1.template triangularView<Upper>()));
VERIFY_IS_APPROX(m3, m3.adjoint());
-
m3 = m1.template selfadjointView<Lower>();
VERIFY_IS_APPROX(MatrixType(m3.template triangularView<Lower>()), MatrixType(m1.template triangularView<Lower>()));
VERIFY_IS_APPROX(m3, m3.adjoint());
+
+ m3 = m1.template selfadjointView<Upper>();
+ m4 = m2;
+ m4 += m1.template selfadjointView<Upper>();
+ VERIFY_IS_APPROX(m4, m2+m3);
+
+ m3 = m1.template selfadjointView<Lower>();
+ m4 = m2;
+ m4 -= m1.template selfadjointView<Lower>();
+ VERIFY_IS_APPROX(m4, m2-m3);
}
void bug_159()
diff --git a/test/simplicial_cholesky.cpp b/test/simplicial_cholesky.cpp
index 786468421..649c817b4 100644
--- a/test/simplicial_cholesky.cpp
+++ b/test/simplicial_cholesky.cpp
@@ -9,16 +9,17 @@
#include "sparse_solver.h"
-template<typename T> void test_simplicial_cholesky_T()
+template<typename T, typename I> void test_simplicial_cholesky_T()
{
- SimplicialCholesky<SparseMatrix<T>, Lower> chol_colmajor_lower_amd;
- SimplicialCholesky<SparseMatrix<T>, Upper> chol_colmajor_upper_amd;
- SimplicialLLT<SparseMatrix<T>, Lower> llt_colmajor_lower_amd;
- SimplicialLLT<SparseMatrix<T>, Upper> llt_colmajor_upper_amd;
- SimplicialLDLT<SparseMatrix<T>, Lower> ldlt_colmajor_lower_amd;
- SimplicialLDLT<SparseMatrix<T>, Upper> ldlt_colmajor_upper_amd;
- SimplicialLDLT<SparseMatrix<T>, Lower, NaturalOrdering<int> > ldlt_colmajor_lower_nat;
- SimplicialLDLT<SparseMatrix<T>, Upper, NaturalOrdering<int> > ldlt_colmajor_upper_nat;
+ typedef SparseMatrix<T,0,I> SparseMatrixType;
+ SimplicialCholesky<SparseMatrixType, Lower> chol_colmajor_lower_amd;
+ SimplicialCholesky<SparseMatrixType, Upper> chol_colmajor_upper_amd;
+ SimplicialLLT< SparseMatrixType, Lower> llt_colmajor_lower_amd;
+ SimplicialLLT< SparseMatrixType, Upper> llt_colmajor_upper_amd;
+ SimplicialLDLT< SparseMatrixType, Lower> ldlt_colmajor_lower_amd;
+ SimplicialLDLT< SparseMatrixType, Upper> ldlt_colmajor_upper_amd;
+ SimplicialLDLT< SparseMatrixType, Lower, NaturalOrdering<I> > ldlt_colmajor_lower_nat;
+ SimplicialLDLT< SparseMatrixType, Upper, NaturalOrdering<I> > ldlt_colmajor_upper_nat;
check_sparse_spd_solving(chol_colmajor_lower_amd);
check_sparse_spd_solving(chol_colmajor_upper_amd);
@@ -34,12 +35,13 @@ template<typename T> void test_simplicial_cholesky_T()
check_sparse_spd_determinant(ldlt_colmajor_lower_amd);
check_sparse_spd_determinant(ldlt_colmajor_upper_amd);
- check_sparse_spd_solving(ldlt_colmajor_lower_nat);
- check_sparse_spd_solving(ldlt_colmajor_upper_nat);
+ check_sparse_spd_solving(ldlt_colmajor_lower_nat, 300, 1000);
+ check_sparse_spd_solving(ldlt_colmajor_upper_nat, 300, 1000);
}
void test_simplicial_cholesky()
{
- CALL_SUBTEST_1(test_simplicial_cholesky_T<double>());
- CALL_SUBTEST_2(test_simplicial_cholesky_T<std::complex<double> >());
+ CALL_SUBTEST_1(( test_simplicial_cholesky_T<double,int>() ));
+ CALL_SUBTEST_2(( test_simplicial_cholesky_T<std::complex<double>, int>() ));
+ CALL_SUBTEST_3(( test_simplicial_cholesky_T<double,long int>() ));
}
diff --git a/test/sizeof.cpp b/test/sizeof.cpp
index d9ad35620..03ad20453 100644
--- a/test/sizeof.cpp
+++ b/test/sizeof.cpp
@@ -13,14 +13,27 @@ template<typename MatrixType> void verifySizeOf(const MatrixType&)
{
typedef typename MatrixType::Scalar Scalar;
if (MatrixType::RowsAtCompileTime!=Dynamic && MatrixType::ColsAtCompileTime!=Dynamic)
- VERIFY(std::ptrdiff_t(sizeof(MatrixType))==std::ptrdiff_t(sizeof(Scalar))*std::ptrdiff_t(MatrixType::SizeAtCompileTime));
+ VERIFY_IS_EQUAL(std::ptrdiff_t(sizeof(MatrixType)),std::ptrdiff_t(sizeof(Scalar))*std::ptrdiff_t(MatrixType::SizeAtCompileTime));
else
- VERIFY(sizeof(MatrixType)==sizeof(Scalar*) + 2 * sizeof(typename MatrixType::Index));
+ VERIFY_IS_EQUAL(sizeof(MatrixType),sizeof(Scalar*) + 2 * sizeof(typename MatrixType::Index));
}
void test_sizeof()
{
CALL_SUBTEST(verifySizeOf(Matrix<float, 1, 1>()) );
+ CALL_SUBTEST(verifySizeOf(Array<float, 2, 1>()) );
+ CALL_SUBTEST(verifySizeOf(Array<float, 3, 1>()) );
+ CALL_SUBTEST(verifySizeOf(Array<float, 4, 1>()) );
+ CALL_SUBTEST(verifySizeOf(Array<float, 5, 1>()) );
+ CALL_SUBTEST(verifySizeOf(Array<float, 6, 1>()) );
+ CALL_SUBTEST(verifySizeOf(Array<float, 7, 1>()) );
+ CALL_SUBTEST(verifySizeOf(Array<float, 8, 1>()) );
+ CALL_SUBTEST(verifySizeOf(Array<float, 9, 1>()) );
+ CALL_SUBTEST(verifySizeOf(Array<float, 10, 1>()) );
+ CALL_SUBTEST(verifySizeOf(Array<float, 11, 1>()) );
+ CALL_SUBTEST(verifySizeOf(Array<float, 12, 1>()) );
+ CALL_SUBTEST(verifySizeOf(Vector2d()) );
+ CALL_SUBTEST(verifySizeOf(Vector4f()) );
CALL_SUBTEST(verifySizeOf(Matrix4d()) );
CALL_SUBTEST(verifySizeOf(Matrix<double, 4, 2>()) );
CALL_SUBTEST(verifySizeOf(Matrix<bool, 7, 5>()) );
diff --git a/test/sizeoverflow.cpp b/test/sizeoverflow.cpp
index 16d6f8d04..240d22294 100644
--- a/test/sizeoverflow.cpp
+++ b/test/sizeoverflow.cpp
@@ -18,8 +18,6 @@
VERIFY(threw && "should have thrown bad_alloc: " #a); \
}
-typedef DenseIndex Index;
-
template<typename MatrixType>
void triggerMatrixBadAlloc(Index rows, Index cols)
{
diff --git a/test/sparse.h b/test/sparse.h
index e19a76316..9912e1e24 100644
--- a/test/sparse.h
+++ b/test/sparse.h
@@ -53,15 +53,15 @@ enum {
* \param zeroCoords and nonzeroCoords allows to get the coordinate lists of the non zero,
* and zero coefficients respectively.
*/
-template<typename Scalar,int Opt1,int Opt2,typename Index> void
+template<typename Scalar,int Opt1,int Opt2,typename StorageIndex> void
initSparse(double density,
Matrix<Scalar,Dynamic,Dynamic,Opt1>& refMat,
- SparseMatrix<Scalar,Opt2,Index>& sparseMat,
+ SparseMatrix<Scalar,Opt2,StorageIndex>& sparseMat,
int flags = 0,
- std::vector<Matrix<Index,2,1> >* zeroCoords = 0,
- std::vector<Matrix<Index,2,1> >* nonzeroCoords = 0)
+ std::vector<Matrix<StorageIndex,2,1> >* zeroCoords = 0,
+ std::vector<Matrix<StorageIndex,2,1> >* nonzeroCoords = 0)
{
- enum { IsRowMajor = SparseMatrix<Scalar,Opt2,Index>::IsRowMajor };
+ enum { IsRowMajor = SparseMatrix<Scalar,Opt2,StorageIndex>::IsRowMajor };
sparseMat.setZero();
//sparseMat.reserve(int(refMat.rows()*refMat.cols()*density));
sparseMat.reserve(VectorXi::Constant(IsRowMajor ? refMat.rows() : refMat.cols(), int((1.5*density)*(IsRowMajor?refMat.cols():refMat.rows()))));
@@ -71,14 +71,17 @@ initSparse(double density,
//sparseMat.startVec(j);
for(Index i=0; i<sparseMat.innerSize(); i++)
{
- int ai(i), aj(j);
+ Index ai(i), aj(j);
if(IsRowMajor)
std::swap(ai,aj);
Scalar v = (internal::random<double>(0,1) < density) ? internal::random<Scalar>() : Scalar(0);
if ((flags&ForceNonZeroDiag) && (i==j))
{
+ // FIXME: the following is too conservative
v = internal::random<Scalar>()*Scalar(3.);
- v = v*v + Scalar(5.);
+ v = v*v;
+ if(numext::real(v)>0) v += Scalar(5);
+ else v -= Scalar(5);
}
if ((flags & MakeLowerTriangular) && aj>ai)
v = Scalar(0);
@@ -93,11 +96,11 @@ initSparse(double density,
//sparseMat.insertBackByOuterInner(j,i) = v;
sparseMat.insertByOuterInner(j,i) = v;
if (nonzeroCoords)
- nonzeroCoords->push_back(Matrix<Index,2,1> (ai,aj));
+ nonzeroCoords->push_back(Matrix<StorageIndex,2,1> (ai,aj));
}
else if (zeroCoords)
{
- zeroCoords->push_back(Matrix<Index,2,1> (ai,aj));
+ zeroCoords->push_back(Matrix<StorageIndex,2,1> (ai,aj));
}
refMat(ai,aj) = v;
}
@@ -163,7 +166,7 @@ initSparse(double density,
{
sparseVec.reserve(int(refVec.size()*density));
sparseVec.setZero();
- for(Index i=0; i<refVec.size(); i++)
+ for(int i=0; i<refVec.size(); i++)
{
Scalar v = (internal::random<double>(0,1) < density) ? internal::random<Scalar>() : Scalar(0);
if (v!=Scalar(0))
diff --git a/test/sparse_basic.cpp b/test/sparse_basic.cpp
index ce41d713c..384985028 100644
--- a/test/sparse_basic.cpp
+++ b/test/sparse_basic.cpp
@@ -9,22 +9,28 @@
// 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/.
+static long g_realloc_count = 0;
+#define EIGEN_SPARSE_COMPRESSED_STORAGE_REALLOCATE_PLUGIN g_realloc_count++;
+
#include "sparse.h"
template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& ref)
{
- typedef typename SparseMatrixType::Index Index;
- typedef Matrix<Index,2,1> Vector2;
+ typedef typename SparseMatrixType::StorageIndex StorageIndex;
+ typedef Matrix<StorageIndex,2,1> Vector2;
const Index rows = ref.rows();
const Index cols = ref.cols();
+ //const Index inner = ref.innerSize();
+ //const Index outer = ref.outerSize();
+
typedef typename SparseMatrixType::Scalar Scalar;
+ typedef typename SparseMatrixType::RealScalar RealScalar;
enum { Flags = SparseMatrixType::Flags };
double density = (std::max)(8./(rows*cols), 0.01);
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
typedef Matrix<Scalar,Dynamic,1> DenseVector;
- typedef Matrix<Scalar,1,Dynamic> RowDenseVector;
Scalar eps = 1e-6;
Scalar s1 = internal::random<Scalar>();
@@ -37,94 +43,22 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
std::vector<Vector2> nonzeroCoords;
initSparse<Scalar>(density, refMat, m, 0, &zeroCoords, &nonzeroCoords);
- if (zeroCoords.size()==0 || nonzeroCoords.size()==0)
- return;
-
// test coeff and coeffRef
- for (int i=0; i<(int)zeroCoords.size(); ++i)
+ for (std::size_t i=0; i<zeroCoords.size(); ++i)
{
VERIFY_IS_MUCH_SMALLER_THAN( m.coeff(zeroCoords[i].x(),zeroCoords[i].y()), eps );
if(internal::is_same<SparseMatrixType,SparseMatrix<Scalar,Flags> >::value)
- VERIFY_RAISES_ASSERT( m.coeffRef(zeroCoords[0].x(),zeroCoords[0].y()) = 5 );
+ VERIFY_RAISES_ASSERT( m.coeffRef(zeroCoords[i].x(),zeroCoords[i].y()) = 5 );
}
VERIFY_IS_APPROX(m, refMat);
- m.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
- refMat.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
+ if(!nonzeroCoords.empty()) {
+ m.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
+ refMat.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
+ }
VERIFY_IS_APPROX(m, refMat);
-
- // test InnerIterators and Block expressions
- for (int t=0; t<10; ++t)
- {
- int j = internal::random<int>(0,cols-1);
- int i = internal::random<int>(0,rows-1);
- int w = internal::random<int>(1,cols-j-1);
- int h = internal::random<int>(1,rows-i-1);
- VERIFY_IS_APPROX(m.block(i,j,h,w), refMat.block(i,j,h,w));
- for(int c=0; c<w; c++)
- {
- VERIFY_IS_APPROX(m.block(i,j,h,w).col(c), refMat.block(i,j,h,w).col(c));
- for(int r=0; r<h; r++)
- {
- VERIFY_IS_APPROX(m.block(i,j,h,w).col(c).coeff(r), refMat.block(i,j,h,w).col(c).coeff(r));
- VERIFY_IS_APPROX(m.block(i,j,h,w).coeff(r,c), refMat.block(i,j,h,w).coeff(r,c));
- }
- }
- for(int r=0; r<h; r++)
- {
- VERIFY_IS_APPROX(m.block(i,j,h,w).row(r), refMat.block(i,j,h,w).row(r));
- for(int c=0; c<w; c++)
- {
- VERIFY_IS_APPROX(m.block(i,j,h,w).row(r).coeff(c), refMat.block(i,j,h,w).row(r).coeff(c));
- VERIFY_IS_APPROX(m.block(i,j,h,w).coeff(r,c), refMat.block(i,j,h,w).coeff(r,c));
- }
- }
-
- VERIFY_IS_APPROX(m.middleCols(j,w), refMat.middleCols(j,w));
- VERIFY_IS_APPROX(m.middleRows(i,h), refMat.middleRows(i,h));
- for(int r=0; r<h; r++)
- {
- VERIFY_IS_APPROX(m.middleCols(j,w).row(r), refMat.middleCols(j,w).row(r));
- VERIFY_IS_APPROX(m.middleRows(i,h).row(r), refMat.middleRows(i,h).row(r));
- for(int c=0; c<w; c++)
- {
- VERIFY_IS_APPROX(m.col(c).coeff(r), refMat.col(c).coeff(r));
- VERIFY_IS_APPROX(m.row(r).coeff(c), refMat.row(r).coeff(c));
-
- VERIFY_IS_APPROX(m.middleCols(j,w).coeff(r,c), refMat.middleCols(j,w).coeff(r,c));
- VERIFY_IS_APPROX(m.middleRows(i,h).coeff(r,c), refMat.middleRows(i,h).coeff(r,c));
- if(m.middleCols(j,w).coeff(r,c) != Scalar(0))
- {
- VERIFY_IS_APPROX(m.middleCols(j,w).coeffRef(r,c), refMat.middleCols(j,w).coeff(r,c));
- }
- if(m.middleRows(i,h).coeff(r,c) != Scalar(0))
- {
- VERIFY_IS_APPROX(m.middleRows(i,h).coeff(r,c), refMat.middleRows(i,h).coeff(r,c));
- }
- }
- }
- for(int c=0; c<w; c++)
- {
- VERIFY_IS_APPROX(m.middleCols(j,w).col(c), refMat.middleCols(j,w).col(c));
- VERIFY_IS_APPROX(m.middleRows(i,h).col(c), refMat.middleRows(i,h).col(c));
- }
- }
-
- for(int c=0; c<cols; c++)
- {
- VERIFY_IS_APPROX(m.col(c) + m.col(c), (m + m).col(c));
- VERIFY_IS_APPROX(m.col(c) + m.col(c), refMat.col(c) + refMat.col(c));
- }
-
- for(int r=0; r<rows; r++)
- {
- VERIFY_IS_APPROX(m.row(r) + m.row(r), (m + m).row(r));
- VERIFY_IS_APPROX(m.row(r) + m.row(r), refMat.row(r) + refMat.row(r));
- }
-
-
// test assertion
VERIFY_RAISES_ASSERT( m.coeffRef(-1,1) = 0 );
VERIFY_RAISES_ASSERT( m.coeffRef(0,m.cols()) = 0 );
@@ -135,17 +69,31 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
DenseMatrix m1(rows,cols);
m1.setZero();
SparseMatrixType m2(rows,cols);
- if(internal::random<int>()%2)
- m2.reserve(VectorXi::Constant(m2.outerSize(), 2));
+ bool call_reserve = internal::random<int>()%2;
+ Index nnz = internal::random<int>(1,int(rows)/2);
+ if(call_reserve)
+ {
+ if(internal::random<int>()%2)
+ m2.reserve(VectorXi::Constant(m2.outerSize(), int(nnz)));
+ else
+ m2.reserve(m2.outerSize() * nnz);
+ }
+ g_realloc_count = 0;
for (Index j=0; j<cols; ++j)
{
- for (Index k=0; k<rows/2; ++k)
+ for (Index k=0; k<nnz; ++k)
{
Index i = internal::random<Index>(0,rows-1);
if (m1.coeff(i,j)==Scalar(0))
m2.insert(i,j) = m1(i,j) = internal::random<Scalar>();
}
}
+
+ if(call_reserve && !SparseMatrixType::IsRowMajor)
+ {
+ VERIFY(g_realloc_count==0);
+ }
+
m2.finalize();
VERIFY_IS_APPROX(m2,m1);
}
@@ -179,9 +127,9 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
DenseMatrix m1(rows,cols);
m1.setZero();
SparseMatrixType m2(rows,cols);
- VectorXi r(VectorXi::Constant(m2.outerSize(), ((mode%2)==0) ? m2.innerSize() : std::max<int>(1,m2.innerSize()/8)));
+ VectorXi r(VectorXi::Constant(m2.outerSize(), ((mode%2)==0) ? int(m2.innerSize()) : std::max<int>(1,int(m2.innerSize())/8)));
m2.reserve(r);
- for (int k=0; k<rows*cols; ++k)
+ for (Index k=0; k<rows*cols; ++k)
{
Index i = internal::random<Index>(0,rows-1);
Index j = internal::random<Index>(0,cols-1);
@@ -195,110 +143,46 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
VERIFY_IS_APPROX(m2,m1);
}
- // test innerVector()
- {
- DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
- SparseMatrixType m2(rows, rows);
- initSparse<Scalar>(density, refMat2, m2);
- Index j0 = internal::random<Index>(0,rows-1);
- Index j1 = internal::random<Index>(0,rows-1);
- if(SparseMatrixType::IsRowMajor)
- VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.row(j0));
- else
- VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.col(j0));
-
- if(SparseMatrixType::IsRowMajor)
- VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.row(j0)+refMat2.row(j1));
- else
- VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.col(j0)+refMat2.col(j1));
-
- SparseMatrixType m3(rows,rows);
- m3.reserve(VectorXi::Constant(rows,rows/2));
- for(Index j=0; j<rows; ++j)
- for(Index k=0; k<j; ++k)
- m3.insertByOuterInner(j,k) = k+1;
- for(Index j=0; j<rows; ++j)
- {
- VERIFY(j==numext::real(m3.innerVector(j).nonZeros()));
- if(j>0)
- VERIFY(j==numext::real(m3.innerVector(j).lastCoeff()));
- }
- m3.makeCompressed();
- for(Index j=0; j<rows; ++j)
- {
- VERIFY(j==numext::real(m3.innerVector(j).nonZeros()));
- if(j>0)
- VERIFY(j==numext::real(m3.innerVector(j).lastCoeff()));
- }
-
- //m2.innerVector(j0) = 2*m2.innerVector(j1);
- //refMat2.col(j0) = 2*refMat2.col(j1);
- //VERIFY_IS_APPROX(m2, refMat2);
- }
-
- // test innerVectors()
- {
- DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
- SparseMatrixType m2(rows, rows);
- initSparse<Scalar>(density, refMat2, m2);
- if(internal::random<float>(0,1)>0.5) m2.makeCompressed();
-
- Index j0 = internal::random<Index>(0,rows-2);
- Index j1 = internal::random<Index>(0,rows-2);
- Index n0 = internal::random<Index>(1,rows-(std::max)(j0,j1));
- if(SparseMatrixType::IsRowMajor)
- VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(j0,0,n0,cols));
- else
- VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(0,j0,rows,n0));
- if(SparseMatrixType::IsRowMajor)
- VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0),
- refMat2.middleRows(j0,n0)+refMat2.middleRows(j1,n0));
- else
- VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0),
- refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0));
-
- VERIFY_IS_APPROX(m2, refMat2);
-
- m2.innerVectors(j0,n0) = m2.innerVectors(j0,n0) + m2.innerVectors(j1,n0);
- if(SparseMatrixType::IsRowMajor)
- refMat2.middleRows(j0,n0) = (refMat2.middleRows(j0,n0) + refMat2.middleRows(j1,n0)).eval();
- else
- refMat2.middleCols(j0,n0) = (refMat2.middleCols(j0,n0) + refMat2.middleCols(j1,n0)).eval();
-
- VERIFY_IS_APPROX(m2, refMat2);
-
- }
-
// test basic computations
{
- DenseMatrix refM1 = DenseMatrix::Zero(rows, rows);
- DenseMatrix refM2 = DenseMatrix::Zero(rows, rows);
- DenseMatrix refM3 = DenseMatrix::Zero(rows, rows);
- DenseMatrix refM4 = DenseMatrix::Zero(rows, rows);
- SparseMatrixType m1(rows, rows);
- SparseMatrixType m2(rows, rows);
- SparseMatrixType m3(rows, rows);
- SparseMatrixType m4(rows, rows);
+ DenseMatrix refM1 = DenseMatrix::Zero(rows, cols);
+ DenseMatrix refM2 = DenseMatrix::Zero(rows, cols);
+ DenseMatrix refM3 = DenseMatrix::Zero(rows, cols);
+ DenseMatrix refM4 = DenseMatrix::Zero(rows, cols);
+ SparseMatrixType m1(rows, cols);
+ SparseMatrixType m2(rows, cols);
+ SparseMatrixType m3(rows, cols);
+ SparseMatrixType m4(rows, cols);
initSparse<Scalar>(density, refM1, m1);
initSparse<Scalar>(density, refM2, m2);
initSparse<Scalar>(density, refM3, m3);
initSparse<Scalar>(density, refM4, m4);
+ if(internal::random<bool>())
+ m1.makeCompressed();
+
+ Index m1_nnz = m1.nonZeros();
+
+ VERIFY_IS_APPROX(m1*s1, refM1*s1);
VERIFY_IS_APPROX(m1+m2, refM1+refM2);
VERIFY_IS_APPROX(m1+m2+m3, refM1+refM2+refM3);
VERIFY_IS_APPROX(m3.cwiseProduct(m1+m2), refM3.cwiseProduct(refM1+refM2));
VERIFY_IS_APPROX(m1*s1-m2, refM1*s1-refM2);
-
- VERIFY_IS_APPROX(m1*=s1, refM1*=s1);
- VERIFY_IS_APPROX(m1/=s1, refM1/=s1);
-
- VERIFY_IS_APPROX(m1+=m2, refM1+=refM2);
- VERIFY_IS_APPROX(m1-=m2, refM1-=refM2);
+ VERIFY_IS_APPROX(m4=m1/s1, refM1/s1);
+ VERIFY_IS_EQUAL(m4.nonZeros(), m1_nnz);
if(SparseMatrixType::IsRowMajor)
VERIFY_IS_APPROX(m1.innerVector(0).dot(refM2.row(0)), refM1.row(0).dot(refM2.row(0)));
else
- VERIFY_IS_APPROX(m1.innerVector(0).dot(refM2.row(0)), refM1.col(0).dot(refM2.row(0)));
+ VERIFY_IS_APPROX(m1.innerVector(0).dot(refM2.col(0)), refM1.col(0).dot(refM2.col(0)));
+
+ DenseVector rv = DenseVector::Random(m1.cols());
+ DenseVector cv = DenseVector::Random(m1.rows());
+ Index r = internal::random<Index>(0,m1.rows()-2);
+ Index c = internal::random<Index>(0,m1.cols()-1);
+ VERIFY_IS_APPROX(( m1.template block<1,Dynamic>(r,0,1,m1.cols()).dot(rv)) , refM1.row(r).dot(rv));
+ VERIFY_IS_APPROX(m1.row(r).dot(rv), refM1.row(r).dot(rv));
+ VERIFY_IS_APPROX(m1.col(c).dot(cv), refM1.col(c).dot(cv));
VERIFY_IS_APPROX(m1.conjugate(), refM1.conjugate());
VERIFY_IS_APPROX(m1.real(), refM1.real());
@@ -306,105 +190,167 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
refM4.setRandom();
// sparse cwise* dense
VERIFY_IS_APPROX(m3.cwiseProduct(refM4), refM3.cwiseProduct(refM4));
+ // dense cwise* sparse
+ 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);
+ VERIFY_IS_APPROX((RealScalar(0.5)*refM4 + RealScalar(0.5)*m3).eval(), RealScalar(0.5)*refM4 + RealScalar(0.5)*refM3);
+ VERIFY_IS_APPROX((RealScalar(0.5)*refM4 + m3*RealScalar(0.5)).eval(), RealScalar(0.5)*refM4 + RealScalar(0.5)*refM3);
+ VERIFY_IS_APPROX((RealScalar(0.5)*refM4 + m3.cwiseProduct(m3)).eval(), RealScalar(0.5)*refM4 + refM3.cwiseProduct(refM3));
+
+ VERIFY_IS_APPROX((RealScalar(0.5)*refM4 + RealScalar(0.5)*m3).eval(), RealScalar(0.5)*refM4 + RealScalar(0.5)*refM3);
+ VERIFY_IS_APPROX((RealScalar(0.5)*refM4 + m3*RealScalar(0.5)).eval(), RealScalar(0.5)*refM4 + RealScalar(0.5)*refM3);
+ VERIFY_IS_APPROX((RealScalar(0.5)*refM4 + (m3+m3)).eval(), RealScalar(0.5)*refM4 + (refM3+refM3));
+ VERIFY_IS_APPROX(((refM3+m3)+RealScalar(0.5)*m3).eval(), RealScalar(0.5)*refM3 + (refM3+refM3));
+ VERIFY_IS_APPROX((RealScalar(0.5)*refM4 + (refM3+m3)).eval(), RealScalar(0.5)*refM4 + (refM3+refM3));
+ VERIFY_IS_APPROX((RealScalar(0.5)*refM4 + (m3+refM3)).eval(), RealScalar(0.5)*refM4 + (refM3+refM3));
+
+
+ VERIFY_IS_APPROX(m1.sum(), refM1.sum());
+
+ m4 = m1; refM4 = m4;
+
+ VERIFY_IS_APPROX(m1*=s1, refM1*=s1);
+ VERIFY_IS_EQUAL(m1.nonZeros(), m1_nnz);
+ VERIFY_IS_APPROX(m1/=s1, refM1/=s1);
+ VERIFY_IS_EQUAL(m1.nonZeros(), m1_nnz);
+
+ VERIFY_IS_APPROX(m1+=m2, refM1+=refM2);
+ VERIFY_IS_APPROX(m1-=m2, refM1-=refM2);
+
+ if (rows>=2 && cols>=2)
+ {
+ VERIFY_RAISES_ASSERT( m1 += m1.innerVector(0) );
+ VERIFY_RAISES_ASSERT( m1 -= m1.innerVector(0) );
+ VERIFY_RAISES_ASSERT( refM1 -= m1.innerVector(0) );
+ VERIFY_RAISES_ASSERT( refM1 += m1.innerVector(0) );
+ m1 = m4; refM1 = refM4;
+ }
+
// test aliasing
VERIFY_IS_APPROX((m1 = -m1), (refM1 = -refM1));
+ VERIFY_IS_EQUAL(m1.nonZeros(), m1_nnz);
+ m1 = m4; refM1 = refM4;
VERIFY_IS_APPROX((m1 = m1.transpose()), (refM1 = refM1.transpose().eval()));
+ VERIFY_IS_EQUAL(m1.nonZeros(), m1_nnz);
+ m1 = m4; refM1 = refM4;
VERIFY_IS_APPROX((m1 = -m1.transpose()), (refM1 = -refM1.transpose().eval()));
+ VERIFY_IS_EQUAL(m1.nonZeros(), m1_nnz);
+ m1 = m4; refM1 = refM4;
VERIFY_IS_APPROX((m1 += -m1), (refM1 += -refM1));
+ VERIFY_IS_EQUAL(m1.nonZeros(), m1_nnz);
+ m1 = m4; refM1 = refM4;
+
+ if(m1.isCompressed())
+ {
+ VERIFY_IS_APPROX(m1.coeffs().sum(), m1.sum());
+ m1.coeffs() += s1;
+ for(Index j = 0; j<m1.outerSize(); ++j)
+ for(typename SparseMatrixType::InnerIterator it(m1,j); it; ++it)
+ refM1(it.row(), it.col()) += s1;
+ VERIFY_IS_APPROX(m1, refM1);
+ }
+
+ // and/or
+ {
+ typedef SparseMatrix<bool, SparseMatrixType::Options, typename SparseMatrixType::StorageIndex> SpBool;
+ SpBool mb1 = m1.real().template cast<bool>();
+ SpBool mb2 = m2.real().template cast<bool>();
+ VERIFY_IS_EQUAL(mb1.template cast<int>().sum(), refM1.real().template cast<bool>().count());
+ VERIFY_IS_EQUAL((mb1 && mb2).template cast<int>().sum(), (refM1.real().template cast<bool>() && refM2.real().template cast<bool>()).count());
+ VERIFY_IS_EQUAL((mb1 || mb2).template cast<int>().sum(), (refM1.real().template cast<bool>() || refM2.real().template cast<bool>()).count());
+ SpBool mb3 = mb1 && mb2;
+ if(mb1.coeffs().all() && mb2.coeffs().all())
+ {
+ VERIFY_IS_EQUAL(mb3.nonZeros(), (refM1.real().template cast<bool>() && refM2.real().template cast<bool>()).count());
+ }
+ }
}
- // test transpose
+ // test reverse iterators
{
- DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
- SparseMatrixType m2(rows, rows);
+ DenseMatrix refMat2 = DenseMatrix::Zero(rows, cols);
+ SparseMatrixType m2(rows, cols);
initSparse<Scalar>(density, refMat2, m2);
- VERIFY_IS_APPROX(m2.transpose().eval(), refMat2.transpose().eval());
- VERIFY_IS_APPROX(m2.transpose(), refMat2.transpose());
+ std::vector<Scalar> ref_value(m2.innerSize());
+ std::vector<Index> ref_index(m2.innerSize());
+ if(internal::random<bool>())
+ m2.makeCompressed();
+ for(Index j = 0; j<m2.outerSize(); ++j)
+ {
+ Index count_forward = 0;
- VERIFY_IS_APPROX(SparseMatrixType(m2.adjoint()), refMat2.adjoint());
+ for(typename SparseMatrixType::InnerIterator it(m2,j); it; ++it)
+ {
+ ref_value[ref_value.size()-1-count_forward] = it.value();
+ ref_index[ref_index.size()-1-count_forward] = it.index();
+ count_forward++;
+ }
+ Index count_reverse = 0;
+ for(typename SparseMatrixType::ReverseInnerIterator it(m2,j); it; --it)
+ {
+ VERIFY_IS_APPROX( std::abs(ref_value[ref_value.size()-count_forward+count_reverse])+1, std::abs(it.value())+1);
+ VERIFY_IS_EQUAL( ref_index[ref_index.size()-count_forward+count_reverse] , it.index());
+ count_reverse++;
+ }
+ VERIFY_IS_EQUAL(count_forward, count_reverse);
+ }
}
-
-
- // test generic blocks
+ // test transpose
{
- DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
- SparseMatrixType m2(rows, rows);
+ DenseMatrix refMat2 = DenseMatrix::Zero(rows, cols);
+ SparseMatrixType m2(rows, cols);
initSparse<Scalar>(density, refMat2, m2);
- Index j0 = internal::random<Index>(0,rows-2);
- Index j1 = internal::random<Index>(0,rows-2);
- Index n0 = internal::random<Index>(1,rows-(std::max)(j0,j1));
- if(SparseMatrixType::IsRowMajor)
- VERIFY_IS_APPROX(m2.block(j0,0,n0,cols), refMat2.block(j0,0,n0,cols));
- else
- VERIFY_IS_APPROX(m2.block(0,j0,rows,n0), refMat2.block(0,j0,rows,n0));
-
- if(SparseMatrixType::IsRowMajor)
- VERIFY_IS_APPROX(m2.block(j0,0,n0,cols)+m2.block(j1,0,n0,cols),
- refMat2.block(j0,0,n0,cols)+refMat2.block(j1,0,n0,cols));
- else
- VERIFY_IS_APPROX(m2.block(0,j0,rows,n0)+m2.block(0,j1,rows,n0),
- refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0));
-
- Index i = internal::random<Index>(0,m2.outerSize()-1);
- if(SparseMatrixType::IsRowMajor) {
- m2.innerVector(i) = m2.innerVector(i) * s1;
- refMat2.row(i) = refMat2.row(i) * s1;
- VERIFY_IS_APPROX(m2,refMat2);
- } else {
- m2.innerVector(i) = m2.innerVector(i) * s1;
- refMat2.col(i) = refMat2.col(i) * s1;
- VERIFY_IS_APPROX(m2,refMat2);
- }
-
- VERIFY_IS_APPROX(DenseVector(m2.col(j0)), refMat2.col(j0));
- VERIFY_IS_APPROX(m2.col(j0), refMat2.col(j0));
-
- VERIFY_IS_APPROX(RowDenseVector(m2.row(j0)), refMat2.row(j0));
- VERIFY_IS_APPROX(m2.row(j0), refMat2.row(j0));
+ VERIFY_IS_APPROX(m2.transpose().eval(), refMat2.transpose().eval());
+ VERIFY_IS_APPROX(m2.transpose(), refMat2.transpose());
+
+ VERIFY_IS_APPROX(SparseMatrixType(m2.adjoint()), refMat2.adjoint());
- VERIFY_IS_APPROX(m2.block(j0,j1,n0,n0), refMat2.block(j0,j1,n0,n0));
- VERIFY_IS_APPROX((2*m2).block(j0,j1,n0,n0), (2*refMat2).block(j0,j1,n0,n0));
+ // check isApprox handles opposite storage order
+ typename Transpose<SparseMatrixType>::PlainObject m3(m2);
+ VERIFY(m2.isApprox(m3));
}
// test prune
{
- SparseMatrixType m2(rows, rows);
- DenseMatrix refM2(rows, rows);
+ SparseMatrixType m2(rows, cols);
+ DenseMatrix refM2(rows, cols);
refM2.setZero();
int countFalseNonZero = 0;
int countTrueNonZero = 0;
- for (Index j=0; j<m2.outerSize(); ++j)
+ m2.reserve(VectorXi::Constant(m2.outerSize(), int(m2.innerSize())));
+ for (Index j=0; j<m2.cols(); ++j)
{
- m2.startVec(j);
- for (Index i=0; i<m2.innerSize(); ++i)
+ for (Index i=0; i<m2.rows(); ++i)
{
float x = internal::random<float>(0,1);
- if (x<0.1)
+ if (x<0.1f)
{
// do nothing
}
- else if (x<0.5)
+ else if (x<0.5f)
{
countFalseNonZero++;
- m2.insertBackByOuterInner(j,i) = Scalar(0);
+ m2.insert(i,j) = Scalar(0);
}
else
{
countTrueNonZero++;
- m2.insertBackByOuterInner(j,i) = Scalar(1);
- if(SparseMatrixType::IsRowMajor)
- refM2(j,i) = Scalar(1);
- else
- refM2(i,j) = Scalar(1);
+ m2.insert(i,j) = Scalar(1);
+ refM2(i,j) = Scalar(1);
}
}
}
- m2.finalize();
+ if(internal::random<bool>())
+ m2.makeCompressed();
VERIFY(countFalseNonZero+countTrueNonZero == m2.nonZeros());
- VERIFY_IS_APPROX(m2, refM2);
+ if(countTrueNonZero>0)
+ VERIFY_IS_APPROX(m2, refM2);
m2.prune(Scalar(1));
VERIFY(countTrueNonZero==m2.nonZeros());
VERIFY_IS_APPROX(m2, refM2);
@@ -412,29 +358,74 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
// test setFromTriplets
{
- typedef Triplet<Scalar,Index> TripletType;
+ typedef Triplet<Scalar,StorageIndex> TripletType;
std::vector<TripletType> triplets;
- int ntriplets = rows*cols;
+ Index ntriplets = rows*cols;
triplets.reserve(ntriplets);
- DenseMatrix refMat(rows,cols);
- refMat.setZero();
- for(int i=0;i<ntriplets;++i)
+ DenseMatrix refMat_sum = DenseMatrix::Zero(rows,cols);
+ DenseMatrix refMat_prod = DenseMatrix::Zero(rows,cols);
+ DenseMatrix refMat_last = DenseMatrix::Zero(rows,cols);
+
+ for(Index i=0;i<ntriplets;++i)
{
- Index r = internal::random<Index>(0,rows-1);
- Index c = internal::random<Index>(0,cols-1);
+ StorageIndex r = internal::random<StorageIndex>(0,StorageIndex(rows-1));
+ StorageIndex c = internal::random<StorageIndex>(0,StorageIndex(cols-1));
Scalar v = internal::random<Scalar>();
triplets.push_back(TripletType(r,c,v));
- refMat(r,c) += v;
+ refMat_sum(r,c) += v;
+ if(std::abs(refMat_prod(r,c))==0)
+ refMat_prod(r,c) = v;
+ else
+ refMat_prod(r,c) *= v;
+ refMat_last(r,c) = v;
}
SparseMatrixType m(rows,cols);
m.setFromTriplets(triplets.begin(), triplets.end());
- VERIFY_IS_APPROX(m, refMat);
+ VERIFY_IS_APPROX(m, refMat_sum);
+
+ m.setFromTriplets(triplets.begin(), triplets.end(), std::multiplies<Scalar>());
+ VERIFY_IS_APPROX(m, refMat_prod);
+#if (defined(__cplusplus) && __cplusplus >= 201103L)
+ m.setFromTriplets(triplets.begin(), triplets.end(), [] (Scalar,Scalar b) { return b; });
+ VERIFY_IS_APPROX(m, refMat_last);
+#endif
+ }
+
+ // test Map
+ {
+ DenseMatrix refMat2(rows, cols), refMat3(rows, cols);
+ SparseMatrixType m2(rows, cols), m3(rows, cols);
+ initSparse<Scalar>(density, refMat2, m2);
+ initSparse<Scalar>(density, refMat3, m3);
+ {
+ Map<SparseMatrixType> mapMat2(m2.rows(), m2.cols(), m2.nonZeros(), m2.outerIndexPtr(), m2.innerIndexPtr(), m2.valuePtr(), m2.innerNonZeroPtr());
+ Map<SparseMatrixType> mapMat3(m3.rows(), m3.cols(), m3.nonZeros(), m3.outerIndexPtr(), m3.innerIndexPtr(), m3.valuePtr(), m3.innerNonZeroPtr());
+ VERIFY_IS_APPROX(mapMat2+mapMat3, refMat2+refMat3);
+ VERIFY_IS_APPROX(mapMat2+mapMat3, refMat2+refMat3);
+ }
+ {
+ MappedSparseMatrix<Scalar,SparseMatrixType::Options,StorageIndex> mapMat2(m2.rows(), m2.cols(), m2.nonZeros(), m2.outerIndexPtr(), m2.innerIndexPtr(), m2.valuePtr(), m2.innerNonZeroPtr());
+ MappedSparseMatrix<Scalar,SparseMatrixType::Options,StorageIndex> mapMat3(m3.rows(), m3.cols(), m3.nonZeros(), m3.outerIndexPtr(), m3.innerIndexPtr(), m3.valuePtr(), m3.innerNonZeroPtr());
+ VERIFY_IS_APPROX(mapMat2+mapMat3, refMat2+refMat3);
+ VERIFY_IS_APPROX(mapMat2+mapMat3, refMat2+refMat3);
+ }
+
+ Index i = internal::random<Index>(0,rows-1);
+ Index j = internal::random<Index>(0,cols-1);
+ m2.coeffRef(i,j) = 123;
+ if(internal::random<bool>())
+ m2.makeCompressed();
+ Map<SparseMatrixType> mapMat2(rows, cols, m2.nonZeros(), m2.outerIndexPtr(), m2.innerIndexPtr(), m2.valuePtr(), m2.innerNonZeroPtr());
+ VERIFY_IS_EQUAL(m2.coeff(i,j),Scalar(123));
+ VERIFY_IS_EQUAL(mapMat2.coeff(i,j),Scalar(123));
+ mapMat2.coeffRef(i,j) = -123;
+ VERIFY_IS_EQUAL(m2.coeff(i,j),Scalar(-123));
}
// test triangularView
{
- DenseMatrix refMat2(rows, rows), refMat3(rows, rows);
- SparseMatrixType m2(rows, rows), m3(rows, rows);
+ DenseMatrix refMat2(rows, cols), refMat3(rows, cols);
+ SparseMatrixType m2(rows, cols), m3(rows, cols);
initSparse<Scalar>(density, refMat2, m2);
refMat3 = refMat2.template triangularView<Lower>();
m3 = m2.template triangularView<Lower>();
@@ -444,13 +435,15 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
m3 = m2.template triangularView<Upper>();
VERIFY_IS_APPROX(m3, refMat3);
- refMat3 = refMat2.template triangularView<UnitUpper>();
- m3 = m2.template triangularView<UnitUpper>();
- VERIFY_IS_APPROX(m3, refMat3);
+ {
+ refMat3 = refMat2.template triangularView<UnitUpper>();
+ m3 = m2.template triangularView<UnitUpper>();
+ VERIFY_IS_APPROX(m3, refMat3);
- refMat3 = refMat2.template triangularView<UnitLower>();
- m3 = m2.template triangularView<UnitLower>();
- VERIFY_IS_APPROX(m3, refMat3);
+ refMat3 = refMat2.template triangularView<UnitLower>();
+ m3 = m2.template triangularView<UnitLower>();
+ VERIFY_IS_APPROX(m3, refMat3);
+ }
refMat3 = refMat2.template triangularView<StrictlyUpper>();
m3 = m2.template triangularView<StrictlyUpper>();
@@ -459,6 +452,10 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
refMat3 = refMat2.template triangularView<StrictlyLower>();
m3 = m2.template triangularView<StrictlyLower>();
VERIFY_IS_APPROX(m3, refMat3);
+
+ // check sparse-triangular to dense
+ refMat3 = m2.template triangularView<StrictlyUpper>();
+ VERIFY_IS_APPROX(refMat3, DenseMatrix(refMat2.template triangularView<StrictlyUpper>()));
}
// test selfadjointView
@@ -470,6 +467,19 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
refMat3 = refMat2.template selfadjointView<Lower>();
m3 = m2.template selfadjointView<Lower>();
VERIFY_IS_APPROX(m3, refMat3);
+
+ refMat3 += refMat2.template selfadjointView<Lower>();
+ m3 += m2.template selfadjointView<Lower>();
+ VERIFY_IS_APPROX(m3, refMat3);
+
+ refMat3 -= refMat2.template selfadjointView<Lower>();
+ m3 -= m2.template selfadjointView<Lower>();
+ VERIFY_IS_APPROX(m3, refMat3);
+
+ // selfadjointView only works for square matrices:
+ SparseMatrixType m4(rows, rows+1);
+ VERIFY_RAISES_ASSERT(m4.template selfadjointView<Lower>());
+ VERIFY_RAISES_ASSERT(m4.template selfadjointView<Upper>());
}
// test sparseView
@@ -478,28 +488,59 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
SparseMatrixType m2(rows, rows);
initSparse<Scalar>(density, refMat2, m2);
VERIFY_IS_APPROX(m2.eval(), refMat2.sparseView().eval());
+
+ // sparse view on expressions:
+ VERIFY_IS_APPROX((s1*m2).eval(), (s1*refMat2).sparseView().eval());
+ VERIFY_IS_APPROX((m2+m2).eval(), (refMat2+refMat2).sparseView().eval());
+ VERIFY_IS_APPROX((m2*m2).eval(), (refMat2.lazyProduct(refMat2)).sparseView().eval());
+ VERIFY_IS_APPROX((m2*m2).eval(), (refMat2*refMat2).sparseView().eval());
}
// test diagonal
{
- DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
- SparseMatrixType m2(rows, rows);
+ DenseMatrix refMat2 = DenseMatrix::Zero(rows, cols);
+ SparseMatrixType m2(rows, cols);
initSparse<Scalar>(density, refMat2, m2);
VERIFY_IS_APPROX(m2.diagonal(), refMat2.diagonal().eval());
+ DenseVector d = m2.diagonal();
+ VERIFY_IS_APPROX(d, refMat2.diagonal().eval());
+ d = m2.diagonal().array();
+ VERIFY_IS_APPROX(d, refMat2.diagonal().eval());
+ VERIFY_IS_APPROX(const_cast<const SparseMatrixType&>(m2).diagonal(), refMat2.diagonal().eval());
+
+ initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag);
+ m2.diagonal() += refMat2.diagonal();
+ refMat2.diagonal() += refMat2.diagonal();
+ VERIFY_IS_APPROX(m2, refMat2);
+ }
+
+ // test diagonal to sparse
+ {
+ DenseVector d = DenseVector::Random(rows);
+ DenseMatrix refMat2 = d.asDiagonal();
+ SparseMatrixType m2(rows, rows);
+ m2 = d.asDiagonal();
+ VERIFY_IS_APPROX(m2, refMat2);
+ SparseMatrixType m3(d.asDiagonal());
+ VERIFY_IS_APPROX(m3, refMat2);
+ refMat2 += d.asDiagonal();
+ m2 += d.asDiagonal();
+ VERIFY_IS_APPROX(m2, refMat2);
}
// test conservative resize
{
- std::vector< std::pair<Index,Index> > inc;
- inc.push_back(std::pair<Index,Index>(-3,-2));
- inc.push_back(std::pair<Index,Index>(0,0));
- inc.push_back(std::pair<Index,Index>(3,2));
- inc.push_back(std::pair<Index,Index>(3,0));
- inc.push_back(std::pair<Index,Index>(0,3));
+ std::vector< std::pair<StorageIndex,StorageIndex> > inc;
+ if(rows > 3 && cols > 2)
+ inc.push_back(std::pair<StorageIndex,StorageIndex>(-3,-2));
+ inc.push_back(std::pair<StorageIndex,StorageIndex>(0,0));
+ inc.push_back(std::pair<StorageIndex,StorageIndex>(3,2));
+ inc.push_back(std::pair<StorageIndex,StorageIndex>(3,0));
+ inc.push_back(std::pair<StorageIndex,StorageIndex>(0,3));
for(size_t i = 0; i< inc.size(); i++) {
- Index incRows = inc[i].first;
- Index incCols = inc[i].second;
+ StorageIndex incRows = inc[i].first;
+ StorageIndex incCols = inc[i].second;
SparseMatrixType m1(rows, cols);
DenseMatrix refMat1 = DenseMatrix::Zero(rows, cols);
initSparse<Scalar>(density, refMat1, m1);
@@ -529,22 +570,119 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
SparseMatrixType m1(rows, rows);
m1.setIdentity();
VERIFY_IS_APPROX(m1, refMat1);
+ for(int k=0; k<rows*rows/4; ++k)
+ {
+ Index i = internal::random<Index>(0,rows-1);
+ Index j = internal::random<Index>(0,rows-1);
+ Scalar v = internal::random<Scalar>();
+ m1.coeffRef(i,j) = v;
+ refMat1.coeffRef(i,j) = v;
+ VERIFY_IS_APPROX(m1, refMat1);
+ if(internal::random<Index>(0,10)<2)
+ m1.makeCompressed();
+ }
+ m1.setIdentity();
+ 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);
+ }
+}
+
+
+template<typename SparseMatrixType>
+void big_sparse_triplet(Index rows, Index cols, double density) {
+ typedef typename SparseMatrixType::StorageIndex StorageIndex;
+ typedef typename SparseMatrixType::Scalar Scalar;
+ typedef Triplet<Scalar,Index> TripletType;
+ std::vector<TripletType> triplets;
+ double nelements = density * rows*cols;
+ VERIFY(nelements>=0 && nelements < NumTraits<StorageIndex>::highest());
+ Index ntriplets = Index(nelements);
+ triplets.reserve(ntriplets);
+ Scalar sum = Scalar(0);
+ for(Index i=0;i<ntriplets;++i)
+ {
+ Index r = internal::random<Index>(0,rows-1);
+ Index c = internal::random<Index>(0,cols-1);
+ Scalar v = internal::random<Scalar>();
+ triplets.push_back(TripletType(r,c,v));
+ sum += v;
+ }
+ SparseMatrixType m(rows,cols);
+ m.setFromTriplets(triplets.begin(), triplets.end());
+ VERIFY(m.nonZeros() <= ntriplets);
+ VERIFY_IS_APPROX(sum, m.sum());
}
+
void test_sparse_basic()
{
for(int i = 0; i < g_repeat; i++) {
- int s = Eigen::internal::random<int>(1,50);
- EIGEN_UNUSED_VARIABLE(s);
+ int r = Eigen::internal::random<int>(1,200), c = Eigen::internal::random<int>(1,200);
+ 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_basic(SparseMatrix<double>(1, 1)) ));
CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double>(8, 8)) ));
- CALL_SUBTEST_2(( sparse_basic(SparseMatrix<std::complex<double>, ColMajor>(s, s)) ));
- CALL_SUBTEST_2(( sparse_basic(SparseMatrix<std::complex<double>, RowMajor>(s, s)) ));
- CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double>(s, s)) ));
- CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double,ColMajor,long int>(s, s)) ));
- CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double,RowMajor,long int>(s, s)) ));
+ CALL_SUBTEST_2(( sparse_basic(SparseMatrix<std::complex<double>, ColMajor>(r, c)) ));
+ CALL_SUBTEST_2(( sparse_basic(SparseMatrix<std::complex<double>, RowMajor>(r, c)) ));
+ CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double>(r, c)) ));
+ CALL_SUBTEST_5(( sparse_basic(SparseMatrix<double,ColMajor,long int>(r, c)) ));
+ CALL_SUBTEST_5(( sparse_basic(SparseMatrix<double,RowMajor,long int>(r, c)) ));
- CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double,ColMajor,short int>(short(s), short(s))) ));
- CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double,RowMajor,short int>(short(s), short(s))) ));
+ r = Eigen::internal::random<int>(1,100);
+ c = Eigen::internal::random<int>(1,100);
+ if(Eigen::internal::random<int>(0,4) == 0) {
+ r = c; // check square matrices in 25% of tries
+ }
+
+ CALL_SUBTEST_6(( sparse_basic(SparseMatrix<double,ColMajor,short int>(short(r), short(c))) ));
+ CALL_SUBTEST_6(( sparse_basic(SparseMatrix<double,RowMajor,short int>(short(r), short(c))) ));
+ }
+
+ // Regression test for bug 900: (manually insert higher values here, if you have enough RAM):
+ CALL_SUBTEST_3((big_sparse_triplet<SparseMatrix<float, RowMajor, int> >(10000, 10000, 0.125)));
+ CALL_SUBTEST_4((big_sparse_triplet<SparseMatrix<double, ColMajor, long int> >(10000, 10000, 0.125)));
+
+ // Regression test for bug 1105
+#ifdef EIGEN_TEST_PART_7
+ {
+ int n = Eigen::internal::random<int>(200,600);
+ SparseMatrix<std::complex<double>,0, long> mat(n, n);
+ std::complex<double> val;
+
+ for(int i=0; i<n; ++i)
+ {
+ mat.coeffRef(i, i%(n/10)) = val;
+ VERIFY(mat.data().allocatedSize()<20*n);
+ }
}
+#endif
}
diff --git a/test/sparse_block.cpp b/test/sparse_block.cpp
new file mode 100644
index 000000000..2a0b3b617
--- /dev/null
+++ b/test/sparse_block.cpp
@@ -0,0 +1,317 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-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/.
+
+#include "sparse.h"
+
+template<typename T>
+typename Eigen::internal::enable_if<(T::Flags&RowMajorBit)==RowMajorBit, typename T::RowXpr>::type
+innervec(T& A, Index i)
+{
+ return A.row(i);
+}
+
+template<typename T>
+typename Eigen::internal::enable_if<(T::Flags&RowMajorBit)==0, typename T::ColXpr>::type
+innervec(T& A, Index i)
+{
+ return A.col(i);
+}
+
+template<typename SparseMatrixType> void sparse_block(const SparseMatrixType& ref)
+{
+ const Index rows = ref.rows();
+ const Index cols = ref.cols();
+ const Index inner = ref.innerSize();
+ const Index outer = ref.outerSize();
+
+ typedef typename SparseMatrixType::Scalar Scalar;
+ typedef typename SparseMatrixType::StorageIndex StorageIndex;
+
+ double density = (std::max)(8./(rows*cols), 0.01);
+ typedef Matrix<Scalar,Dynamic,Dynamic,SparseMatrixType::IsRowMajor?RowMajor:ColMajor> DenseMatrix;
+ typedef Matrix<Scalar,Dynamic,1> DenseVector;
+ typedef Matrix<Scalar,1,Dynamic> RowDenseVector;
+ typedef SparseVector<Scalar> SparseVectorType;
+
+ Scalar s1 = internal::random<Scalar>();
+ {
+ SparseMatrixType m(rows, cols);
+ DenseMatrix refMat = DenseMatrix::Zero(rows, cols);
+ initSparse<Scalar>(density, refMat, m);
+
+ VERIFY_IS_APPROX(m, refMat);
+
+ // test InnerIterators and Block expressions
+ for (int t=0; t<10; ++t)
+ {
+ Index j = internal::random<Index>(0,cols-2);
+ Index i = internal::random<Index>(0,rows-2);
+ Index w = internal::random<Index>(1,cols-j);
+ Index h = internal::random<Index>(1,rows-i);
+
+ VERIFY_IS_APPROX(m.block(i,j,h,w), refMat.block(i,j,h,w));
+ for(Index c=0; c<w; c++)
+ {
+ VERIFY_IS_APPROX(m.block(i,j,h,w).col(c), refMat.block(i,j,h,w).col(c));
+ for(Index r=0; r<h; r++)
+ {
+ VERIFY_IS_APPROX(m.block(i,j,h,w).col(c).coeff(r), refMat.block(i,j,h,w).col(c).coeff(r));
+ VERIFY_IS_APPROX(m.block(i,j,h,w).coeff(r,c), refMat.block(i,j,h,w).coeff(r,c));
+ }
+ }
+ for(Index r=0; r<h; r++)
+ {
+ VERIFY_IS_APPROX(m.block(i,j,h,w).row(r), refMat.block(i,j,h,w).row(r));
+ for(Index c=0; c<w; c++)
+ {
+ VERIFY_IS_APPROX(m.block(i,j,h,w).row(r).coeff(c), refMat.block(i,j,h,w).row(r).coeff(c));
+ VERIFY_IS_APPROX(m.block(i,j,h,w).coeff(r,c), refMat.block(i,j,h,w).coeff(r,c));
+ }
+ }
+
+ VERIFY_IS_APPROX(m.middleCols(j,w), refMat.middleCols(j,w));
+ VERIFY_IS_APPROX(m.middleRows(i,h), refMat.middleRows(i,h));
+ for(Index r=0; r<h; r++)
+ {
+ VERIFY_IS_APPROX(m.middleCols(j,w).row(r), refMat.middleCols(j,w).row(r));
+ VERIFY_IS_APPROX(m.middleRows(i,h).row(r), refMat.middleRows(i,h).row(r));
+ for(Index c=0; c<w; c++)
+ {
+ VERIFY_IS_APPROX(m.col(c).coeff(r), refMat.col(c).coeff(r));
+ VERIFY_IS_APPROX(m.row(r).coeff(c), refMat.row(r).coeff(c));
+
+ VERIFY_IS_APPROX(m.middleCols(j,w).coeff(r,c), refMat.middleCols(j,w).coeff(r,c));
+ VERIFY_IS_APPROX(m.middleRows(i,h).coeff(r,c), refMat.middleRows(i,h).coeff(r,c));
+ if(m.middleCols(j,w).coeff(r,c) != Scalar(0))
+ {
+ VERIFY_IS_APPROX(m.middleCols(j,w).coeffRef(r,c), refMat.middleCols(j,w).coeff(r,c));
+ }
+ if(m.middleRows(i,h).coeff(r,c) != Scalar(0))
+ {
+ VERIFY_IS_APPROX(m.middleRows(i,h).coeff(r,c), refMat.middleRows(i,h).coeff(r,c));
+ }
+ }
+ }
+ for(Index c=0; c<w; c++)
+ {
+ VERIFY_IS_APPROX(m.middleCols(j,w).col(c), refMat.middleCols(j,w).col(c));
+ VERIFY_IS_APPROX(m.middleRows(i,h).col(c), refMat.middleRows(i,h).col(c));
+ }
+ }
+
+ for(Index c=0; c<cols; c++)
+ {
+ VERIFY_IS_APPROX(m.col(c) + m.col(c), (m + m).col(c));
+ VERIFY_IS_APPROX(m.col(c) + m.col(c), refMat.col(c) + refMat.col(c));
+ }
+
+ for(Index r=0; r<rows; r++)
+ {
+ VERIFY_IS_APPROX(m.row(r) + m.row(r), (m + m).row(r));
+ VERIFY_IS_APPROX(m.row(r) + m.row(r), refMat.row(r) + refMat.row(r));
+ }
+ }
+
+ // test innerVector()
+ {
+ DenseMatrix refMat2 = DenseMatrix::Zero(rows, cols);
+ SparseMatrixType m2(rows, cols);
+ initSparse<Scalar>(density, refMat2, m2);
+ Index j0 = internal::random<Index>(0,outer-1);
+ Index j1 = internal::random<Index>(0,outer-1);
+ Index r0 = internal::random<Index>(0,rows-1);
+ Index c0 = internal::random<Index>(0,cols-1);
+
+ VERIFY_IS_APPROX(m2.innerVector(j0), innervec(refMat2,j0));
+ VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), innervec(refMat2,j0)+innervec(refMat2,j1));
+
+ m2.innerVector(j0) *= Scalar(2);
+ innervec(refMat2,j0) *= Scalar(2);
+ VERIFY_IS_APPROX(m2, refMat2);
+
+ m2.row(r0) *= Scalar(3);
+ refMat2.row(r0) *= Scalar(3);
+ VERIFY_IS_APPROX(m2, refMat2);
+
+ m2.col(c0) *= Scalar(4);
+ refMat2.col(c0) *= Scalar(4);
+ VERIFY_IS_APPROX(m2, refMat2);
+
+ m2.row(r0) /= Scalar(3);
+ refMat2.row(r0) /= Scalar(3);
+ VERIFY_IS_APPROX(m2, refMat2);
+
+ m2.col(c0) /= Scalar(4);
+ refMat2.col(c0) /= Scalar(4);
+ VERIFY_IS_APPROX(m2, refMat2);
+
+ SparseVectorType v1;
+ VERIFY_IS_APPROX(v1 = m2.col(c0) * 4, refMat2.col(c0)*4);
+ VERIFY_IS_APPROX(v1 = m2.row(r0) * 4, refMat2.row(r0).transpose()*4);
+
+ SparseMatrixType m3(rows,cols);
+ m3.reserve(VectorXi::Constant(outer,int(inner/2)));
+ for(Index j=0; j<outer; ++j)
+ for(Index k=0; k<(std::min)(j,inner); ++k)
+ m3.insertByOuterInner(j,k) = internal::convert_index<StorageIndex>(k+1);
+ for(Index j=0; j<(std::min)(outer, inner); ++j)
+ {
+ VERIFY(j==numext::real(m3.innerVector(j).nonZeros()));
+ if(j>0)
+ VERIFY(j==numext::real(m3.innerVector(j).lastCoeff()));
+ }
+ m3.makeCompressed();
+ for(Index j=0; j<(std::min)(outer, inner); ++j)
+ {
+ VERIFY(j==numext::real(m3.innerVector(j).nonZeros()));
+ if(j>0)
+ VERIFY(j==numext::real(m3.innerVector(j).lastCoeff()));
+ }
+
+ VERIFY(m3.innerVector(j0).nonZeros() == m3.transpose().innerVector(j0).nonZeros());
+
+// m2.innerVector(j0) = 2*m2.innerVector(j1);
+// refMat2.col(j0) = 2*refMat2.col(j1);
+// VERIFY_IS_APPROX(m2, refMat2);
+ }
+
+ // test innerVectors()
+ {
+ DenseMatrix refMat2 = DenseMatrix::Zero(rows, cols);
+ SparseMatrixType m2(rows, cols);
+ initSparse<Scalar>(density, refMat2, m2);
+ if(internal::random<float>(0,1)>0.5f) m2.makeCompressed();
+ Index j0 = internal::random<Index>(0,outer-2);
+ Index j1 = internal::random<Index>(0,outer-2);
+ Index n0 = internal::random<Index>(1,outer-(std::max)(j0,j1));
+ if(SparseMatrixType::IsRowMajor)
+ VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(j0,0,n0,cols));
+ else
+ VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(0,j0,rows,n0));
+ if(SparseMatrixType::IsRowMajor)
+ VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0),
+ refMat2.middleRows(j0,n0)+refMat2.middleRows(j1,n0));
+ else
+ VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0),
+ refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0));
+
+ VERIFY_IS_APPROX(m2, refMat2);
+
+ VERIFY(m2.innerVectors(j0,n0).nonZeros() == m2.transpose().innerVectors(j0,n0).nonZeros());
+
+ m2.innerVectors(j0,n0) = m2.innerVectors(j0,n0) + m2.innerVectors(j1,n0);
+ if(SparseMatrixType::IsRowMajor)
+ refMat2.middleRows(j0,n0) = (refMat2.middleRows(j0,n0) + refMat2.middleRows(j1,n0)).eval();
+ else
+ refMat2.middleCols(j0,n0) = (refMat2.middleCols(j0,n0) + refMat2.middleCols(j1,n0)).eval();
+
+ VERIFY_IS_APPROX(m2, refMat2);
+ }
+
+ // test generic blocks
+ {
+ DenseMatrix refMat2 = DenseMatrix::Zero(rows, cols);
+ SparseMatrixType m2(rows, cols);
+ initSparse<Scalar>(density, refMat2, m2);
+ Index j0 = internal::random<Index>(0,outer-2);
+ Index j1 = internal::random<Index>(0,outer-2);
+ Index n0 = internal::random<Index>(1,outer-(std::max)(j0,j1));
+ if(SparseMatrixType::IsRowMajor)
+ VERIFY_IS_APPROX(m2.block(j0,0,n0,cols), refMat2.block(j0,0,n0,cols));
+ else
+ VERIFY_IS_APPROX(m2.block(0,j0,rows,n0), refMat2.block(0,j0,rows,n0));
+
+ if(SparseMatrixType::IsRowMajor)
+ VERIFY_IS_APPROX(m2.block(j0,0,n0,cols)+m2.block(j1,0,n0,cols),
+ refMat2.block(j0,0,n0,cols)+refMat2.block(j1,0,n0,cols));
+ else
+ VERIFY_IS_APPROX(m2.block(0,j0,rows,n0)+m2.block(0,j1,rows,n0),
+ refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0));
+
+ Index i = internal::random<Index>(0,m2.outerSize()-1);
+ if(SparseMatrixType::IsRowMajor) {
+ m2.innerVector(i) = m2.innerVector(i) * s1;
+ refMat2.row(i) = refMat2.row(i) * s1;
+ VERIFY_IS_APPROX(m2,refMat2);
+ } else {
+ m2.innerVector(i) = m2.innerVector(i) * s1;
+ refMat2.col(i) = refMat2.col(i) * s1;
+ VERIFY_IS_APPROX(m2,refMat2);
+ }
+
+ Index r0 = internal::random<Index>(0,rows-2);
+ Index c0 = internal::random<Index>(0,cols-2);
+ Index r1 = internal::random<Index>(1,rows-r0);
+ Index c1 = internal::random<Index>(1,cols-c0);
+
+ VERIFY_IS_APPROX(DenseVector(m2.col(c0)), refMat2.col(c0));
+ VERIFY_IS_APPROX(m2.col(c0), refMat2.col(c0));
+
+ VERIFY_IS_APPROX(RowDenseVector(m2.row(r0)), refMat2.row(r0));
+ VERIFY_IS_APPROX(m2.row(r0), refMat2.row(r0));
+
+ VERIFY_IS_APPROX(m2.block(r0,c0,r1,c1), refMat2.block(r0,c0,r1,c1));
+ VERIFY_IS_APPROX((2*m2).block(r0,c0,r1,c1), (2*refMat2).block(r0,c0,r1,c1));
+
+ if(m2.nonZeros()>0)
+ {
+ VERIFY_IS_APPROX(m2, refMat2);
+ SparseMatrixType m3(rows, cols);
+ DenseMatrix refMat3(rows, cols); refMat3.setZero();
+ Index n = internal::random<Index>(1,10);
+ for(Index k=0; k<n; ++k)
+ {
+ Index o1 = internal::random<Index>(0,outer-1);
+ Index o2 = internal::random<Index>(0,outer-1);
+ if(SparseMatrixType::IsRowMajor)
+ {
+ m3.innerVector(o1) = m2.row(o2);
+ refMat3.row(o1) = refMat2.row(o2);
+ }
+ else
+ {
+ m3.innerVector(o1) = m2.col(o2);
+ refMat3.col(o1) = refMat2.col(o2);
+ }
+ if(internal::random<bool>())
+ m3.makeCompressed();
+ }
+ if(m3.nonZeros()>0)
+ VERIFY_IS_APPROX(m3, refMat3);
+ }
+ }
+}
+
+void test_sparse_block()
+{
+ for(int i = 0; i < g_repeat; i++) {
+ int r = Eigen::internal::random<int>(1,200), c = Eigen::internal::random<int>(1,200);
+ 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_block(SparseMatrix<double>(1, 1)) ));
+ CALL_SUBTEST_1(( sparse_block(SparseMatrix<double>(8, 8)) ));
+ CALL_SUBTEST_1(( sparse_block(SparseMatrix<double>(r, c)) ));
+ CALL_SUBTEST_2(( sparse_block(SparseMatrix<std::complex<double>, ColMajor>(r, c)) ));
+ CALL_SUBTEST_2(( sparse_block(SparseMatrix<std::complex<double>, RowMajor>(r, c)) ));
+
+ CALL_SUBTEST_3(( sparse_block(SparseMatrix<double,ColMajor,long int>(r, c)) ));
+ CALL_SUBTEST_3(( sparse_block(SparseMatrix<double,RowMajor,long int>(r, c)) ));
+
+ r = Eigen::internal::random<int>(1,100);
+ c = Eigen::internal::random<int>(1,100);
+ if(Eigen::internal::random<int>(0,4) == 0) {
+ r = c; // check square matrices in 25% of tries
+ }
+
+ CALL_SUBTEST_4(( sparse_block(SparseMatrix<double,ColMajor,short int>(short(r), short(c))) ));
+ CALL_SUBTEST_4(( sparse_block(SparseMatrix<double,RowMajor,short int>(short(r), short(c))) ));
+ }
+}
diff --git a/test/sparse_permutations.cpp b/test/sparse_permutations.cpp
index e4ce1d679..b82cceff8 100644
--- a/test/sparse_permutations.cpp
+++ b/test/sparse_permutations.cpp
@@ -1,25 +1,57 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
-// Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2011-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/.
+
+static long int nb_transposed_copies;
+#define EIGEN_SPARSE_TRANSPOSED_COPY_PLUGIN {nb_transposed_copies++;}
+#define VERIFY_TRANSPOSITION_COUNT(XPR,N) {\
+ nb_transposed_copies = 0; \
+ XPR; \
+ if(nb_transposed_copies!=N) std::cerr << "nb_transposed_copies == " << nb_transposed_copies << "\n"; \
+ VERIFY( (#XPR) && nb_transposed_copies==N ); \
+ }
+
#include "sparse.h"
-template<int OtherStorage, typename SparseMatrixType> void sparse_permutations(const SparseMatrixType& ref)
+template<typename T>
+bool is_sorted(const T& mat) {
+ for(Index k = 0; k<mat.outerSize(); ++k)
+ {
+ Index prev = -1;
+ for(typename T::InnerIterator it(mat,k); it; ++it)
+ {
+ if(prev>=it.index())
+ return false;
+ prev = it.index();
+ }
+ }
+ return true;
+}
+
+template<typename T>
+typename internal::nested_eval<T,1>::type eval(const T &xpr)
{
- typedef typename SparseMatrixType::Index Index;
+ VERIFY( int(internal::nested_eval<T,1>::type::Flags&RowMajorBit) == int(internal::evaluator<T>::Flags&RowMajorBit) );
+ return xpr;
+}
+template<int OtherStorage, typename SparseMatrixType> void sparse_permutations(const SparseMatrixType& ref)
+{
const Index rows = ref.rows();
const Index cols = ref.cols();
typedef typename SparseMatrixType::Scalar Scalar;
- typedef typename SparseMatrixType::Index Index;
- typedef SparseMatrix<Scalar, OtherStorage, Index> OtherSparseMatrixType;
+ typedef typename SparseMatrixType::StorageIndex StorageIndex;
+ typedef SparseMatrix<Scalar, OtherStorage, StorageIndex> OtherSparseMatrixType;
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
- typedef Matrix<Index,Dynamic,1> VectorI;
+ typedef Matrix<StorageIndex,Dynamic,1> VectorI;
+// bool IsRowMajor1 = SparseMatrixType::IsRowMajor;
+// bool IsRowMajor2 = OtherSparseMatrixType::IsRowMajor;
double density = (std::max)(8./(rows*cols), 0.01);
@@ -44,58 +76,69 @@ template<int OtherStorage, typename SparseMatrixType> void sparse_permutations(c
randomPermutationVector(pi, cols);
p.indices() = pi;
- res = mat*p;
+ VERIFY( is_sorted( ::eval(mat*p) ));
+ VERIFY( is_sorted( res = mat*p ));
+ VERIFY_TRANSPOSITION_COUNT( ::eval(mat*p), 0);
+ //VERIFY_TRANSPOSITION_COUNT( res = mat*p, IsRowMajor ? 1 : 0 );
res_d = mat_d*p;
VERIFY(res.isApprox(res_d) && "mat*p");
- res = p*mat;
+ VERIFY( is_sorted( ::eval(p*mat) ));
+ VERIFY( is_sorted( res = p*mat ));
+ VERIFY_TRANSPOSITION_COUNT( ::eval(p*mat), 0);
res_d = p*mat_d;
VERIFY(res.isApprox(res_d) && "p*mat");
- res = mat*p.inverse();
+ VERIFY( is_sorted( (mat*p).eval() ));
+ VERIFY( is_sorted( res = mat*p.inverse() ));
+ VERIFY_TRANSPOSITION_COUNT( ::eval(mat*p.inverse()), 0);
res_d = mat*p.inverse();
VERIFY(res.isApprox(res_d) && "mat*inv(p)");
- res = p.inverse()*mat;
+ VERIFY( is_sorted( (p*mat+p*mat).eval() ));
+ VERIFY( is_sorted( res = p.inverse()*mat ));
+ VERIFY_TRANSPOSITION_COUNT( ::eval(p.inverse()*mat), 0);
res_d = p.inverse()*mat_d;
VERIFY(res.isApprox(res_d) && "inv(p)*mat");
- res = mat.twistedBy(p);
+ VERIFY( is_sorted( (p * mat * p.inverse()).eval() ));
+ VERIFY( is_sorted( res = mat.twistedBy(p) ));
+ VERIFY_TRANSPOSITION_COUNT( ::eval(p * mat * p.inverse()), 0);
res_d = (p * mat_d) * p.inverse();
VERIFY(res.isApprox(res_d) && "p*mat*inv(p)");
- res = mat.template selfadjointView<Upper>().twistedBy(p_null);
+ VERIFY( is_sorted( res = mat.template selfadjointView<Upper>().twistedBy(p_null) ));
res_d = up_sym_d;
VERIFY(res.isApprox(res_d) && "full selfadjoint upper to full");
- res = mat.template selfadjointView<Lower>().twistedBy(p_null);
+ VERIFY( is_sorted( res = mat.template selfadjointView<Lower>().twistedBy(p_null) ));
res_d = lo_sym_d;
VERIFY(res.isApprox(res_d) && "full selfadjoint lower to full");
- res = up.template selfadjointView<Upper>().twistedBy(p_null);
+ VERIFY( is_sorted( res = up.template selfadjointView<Upper>().twistedBy(p_null) ));
res_d = up_sym_d;
VERIFY(res.isApprox(res_d) && "upper selfadjoint to full");
- res = lo.template selfadjointView<Lower>().twistedBy(p_null);
+ VERIFY( is_sorted( res = lo.template selfadjointView<Lower>().twistedBy(p_null) ));
res_d = lo_sym_d;
VERIFY(res.isApprox(res_d) && "lower selfadjoint full");
- res = mat.template selfadjointView<Upper>();
+ VERIFY( is_sorted( res = mat.template selfadjointView<Upper>() ));
res_d = up_sym_d;
VERIFY(res.isApprox(res_d) && "full selfadjoint upper to full");
- res = mat.template selfadjointView<Lower>();
+ VERIFY( is_sorted( res = mat.template selfadjointView<Lower>() ));
res_d = lo_sym_d;
VERIFY(res.isApprox(res_d) && "full selfadjoint lower to full");
- res = up.template selfadjointView<Upper>();
+ VERIFY( is_sorted( res = up.template selfadjointView<Upper>() ));
res_d = up_sym_d;
VERIFY(res.isApprox(res_d) && "upper selfadjoint to full");
- res = lo.template selfadjointView<Lower>();
+ VERIFY( is_sorted( res = lo.template selfadjointView<Lower>() ));
res_d = lo_sym_d;
VERIFY(res.isApprox(res_d) && "lower selfadjoint full");
@@ -152,19 +195,19 @@ template<int OtherStorage, typename SparseMatrixType> void sparse_permutations(c
VERIFY(res.isApprox(res_d) && "upper selfadjoint twisted to lower");
- res = mat.template selfadjointView<Upper>().twistedBy(p);
+ VERIFY( is_sorted( res = mat.template selfadjointView<Upper>().twistedBy(p) ));
res_d = (p * up_sym_d) * p.inverse();
VERIFY(res.isApprox(res_d) && "full selfadjoint upper twisted to full");
- res = mat.template selfadjointView<Lower>().twistedBy(p);
+ VERIFY( is_sorted( res = mat.template selfadjointView<Lower>().twistedBy(p) ));
res_d = (p * lo_sym_d) * p.inverse();
VERIFY(res.isApprox(res_d) && "full selfadjoint lower twisted to full");
- res = up.template selfadjointView<Upper>().twistedBy(p);
+ VERIFY( is_sorted( res = up.template selfadjointView<Upper>().twistedBy(p) ));
res_d = (p * up_sym_d) * p.inverse();
VERIFY(res.isApprox(res_d) && "upper selfadjoint twisted to full");
- res = lo.template selfadjointView<Lower>().twistedBy(p);
+ VERIFY( is_sorted( res = lo.template selfadjointView<Lower>().twistedBy(p) ));
res_d = (p * lo_sym_d) * p.inverse();
VERIFY(res.isApprox(res_d) && "lower selfadjoint twisted to full");
}
@@ -184,4 +227,10 @@ void test_sparse_permutations()
CALL_SUBTEST_1(( sparse_permutations_all<double>(s) ));
CALL_SUBTEST_2(( sparse_permutations_all<std::complex<double> >(s) ));
}
+
+ VERIFY((internal::is_same<internal::permutation_matrix_product<SparseMatrix<double>,OnTheRight,false,SparseShape>::ReturnType,
+ internal::nested_eval<Product<SparseMatrix<double>,PermutationMatrix<Dynamic,Dynamic>,AliasFreeProduct>,1>::type>::value));
+
+ VERIFY((internal::is_same<internal::permutation_matrix_product<SparseMatrix<double>,OnTheLeft,false,SparseShape>::ReturnType,
+ internal::nested_eval<Product<PermutationMatrix<Dynamic,Dynamic>,SparseMatrix<double>,AliasFreeProduct>,1>::type>::value));
}
diff --git a/test/sparse_product.cpp b/test/sparse_product.cpp
index a2ea9d5b7..c1edd26e3 100644
--- a/test/sparse_product.cpp
+++ b/test/sparse_product.cpp
@@ -7,37 +7,29 @@
// 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 "sparse.h"
+static long int nb_temporaries;
-template<typename SparseMatrixType, typename DenseMatrix, bool IsRowMajor=SparseMatrixType::IsRowMajor> struct test_outer;
+inline void on_temporary_creation() {
+ // here's a great place to set a breakpoint when debugging failures in this test!
+ nb_temporaries++;
+}
-template<typename SparseMatrixType, typename DenseMatrix> struct test_outer<SparseMatrixType,DenseMatrix,false> {
- static void run(SparseMatrixType& m2, SparseMatrixType& m4, DenseMatrix& refMat2, DenseMatrix& refMat4) {
- typedef typename SparseMatrixType::Index Index;
- Index c = internal::random<Index>(0,m2.cols()-1);
- Index c1 = internal::random<Index>(0,m2.cols()-1);
- VERIFY_IS_APPROX(m4=m2.col(c)*refMat2.col(c1).transpose(), refMat4=refMat2.col(c)*refMat2.col(c1).transpose());
- VERIFY_IS_APPROX(m4=refMat2.col(c1)*m2.col(c).transpose(), refMat4=refMat2.col(c1)*refMat2.col(c).transpose());
- }
-};
-
-template<typename SparseMatrixType, typename DenseMatrix> struct test_outer<SparseMatrixType,DenseMatrix,true> {
- static void run(SparseMatrixType& m2, SparseMatrixType& m4, DenseMatrix& refMat2, DenseMatrix& refMat4) {
- typedef typename SparseMatrixType::Index Index;
- Index r = internal::random<Index>(0,m2.rows()-1);
- Index c1 = internal::random<Index>(0,m2.cols()-1);
- VERIFY_IS_APPROX(m4=m2.row(r).transpose()*refMat2.col(c1).transpose(), refMat4=refMat2.row(r).transpose()*refMat2.col(c1).transpose());
- VERIFY_IS_APPROX(m4=refMat2.col(c1)*m2.row(r), refMat4=refMat2.col(c1)*refMat2.row(r));
+#define EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN { on_temporary_creation(); }
+
+#include "sparse.h"
+
+#define VERIFY_EVALUATION_COUNT(XPR,N) {\
+ nb_temporaries = 0; \
+ CALL_SUBTEST( XPR ); \
+ if(nb_temporaries!=N) std::cerr << "nb_temporaries == " << nb_temporaries << "\n"; \
+ VERIFY( (#XPR) && nb_temporaries==N ); \
}
-};
-// (m2,m4,refMat2,refMat4,dv1);
-// VERIFY_IS_APPROX(m4=m2.innerVector(c)*dv1.transpose(), refMat4=refMat2.colVector(c)*dv1.transpose());
-// VERIFY_IS_APPROX(m4=dv1*mcm.col(c).transpose(), refMat4=dv1*refMat2.col(c).transpose());
+
template<typename SparseMatrixType> void sparse_product()
{
- typedef typename SparseMatrixType::Index Index;
+ typedef typename SparseMatrixType::StorageIndex StorageIndex;
Index n = 100;
const Index rows = internal::random<Index>(1,n);
const Index cols = internal::random<Index>(1,n);
@@ -45,12 +37,12 @@ template<typename SparseMatrixType> void sparse_product()
typedef typename SparseMatrixType::Scalar Scalar;
enum { Flags = SparseMatrixType::Flags };
- double density = (std::max)(8./(rows*cols), 0.1);
+ double density = (std::max)(8./(rows*cols), 0.2);
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
typedef Matrix<Scalar,Dynamic,1> DenseVector;
typedef Matrix<Scalar,1,Dynamic> RowDenseVector;
- typedef SparseVector<Scalar,0,Index> ColSpVector;
- typedef SparseVector<Scalar,RowMajor,Index> RowSpVector;
+ typedef SparseVector<Scalar,0,StorageIndex> ColSpVector;
+ typedef SparseVector<Scalar,RowMajor,StorageIndex> RowSpVector;
Scalar s1 = internal::random<Scalar>();
Scalar s2 = internal::random<Scalar>();
@@ -93,33 +85,124 @@ template<typename SparseMatrixType> void sparse_product()
VERIFY_IS_APPROX(m4 = m2*m3/s1, refMat4 = refMat2*refMat3/s1);
VERIFY_IS_APPROX(m4 = m2*m3*s1, refMat4 = refMat2*refMat3*s1);
VERIFY_IS_APPROX(m4 = s2*m2*m3*s1, refMat4 = s2*refMat2*refMat3*s1);
+ VERIFY_IS_APPROX(m4 = (m2+m2)*m3, refMat4 = (refMat2+refMat2)*refMat3);
+ VERIFY_IS_APPROX(m4 = m2*m3.leftCols(cols/2), refMat4 = refMat2*refMat3.leftCols(cols/2));
+ VERIFY_IS_APPROX(m4 = m2*(m3+m3).leftCols(cols/2), refMat4 = refMat2*(refMat3+refMat3).leftCols(cols/2));
VERIFY_IS_APPROX(m4=(m2*m3).pruned(0), refMat4=refMat2*refMat3);
VERIFY_IS_APPROX(m4=(m2t.transpose()*m3).pruned(0), refMat4=refMat2t.transpose()*refMat3);
VERIFY_IS_APPROX(m4=(m2t.transpose()*m3t.transpose()).pruned(0), refMat4=refMat2t.transpose()*refMat3t.transpose());
VERIFY_IS_APPROX(m4=(m2*m3t.transpose()).pruned(0), refMat4=refMat2*refMat3t.transpose());
+ // make sure the right product implementation is called:
+ if((!SparseMatrixType::IsRowMajor) && m2.rows()<=m3.cols())
+ {
+ VERIFY_EVALUATION_COUNT(m4 = m2*m3, 3); // 1 temp for the result + 2 for transposing and get a sorted result.
+ VERIFY_EVALUATION_COUNT(m4 = (m2*m3).pruned(0), 1);
+ VERIFY_EVALUATION_COUNT(m4 = (m2*m3).eval().pruned(0), 4);
+ }
+
+ // and that pruning is effective:
+ {
+ DenseMatrix Ad(2,2);
+ Ad << -1, 1, 1, 1;
+ SparseMatrixType As(Ad.sparseView()), B(2,2);
+ VERIFY_IS_EQUAL( (As*As.transpose()).eval().nonZeros(), 4);
+ VERIFY_IS_EQUAL( (Ad*Ad.transpose()).eval().sparseView().eval().nonZeros(), 2);
+ VERIFY_IS_EQUAL( (As*As.transpose()).pruned(1e-6).eval().nonZeros(), 2);
+ }
+
+ // dense ?= sparse * sparse
+ VERIFY_IS_APPROX(dm4 =m2*m3, refMat4 =refMat2*refMat3);
+ VERIFY_IS_APPROX(dm4+=m2*m3, refMat4+=refMat2*refMat3);
+ VERIFY_IS_APPROX(dm4-=m2*m3, refMat4-=refMat2*refMat3);
+ VERIFY_IS_APPROX(dm4 =m2t.transpose()*m3, refMat4 =refMat2t.transpose()*refMat3);
+ VERIFY_IS_APPROX(dm4+=m2t.transpose()*m3, refMat4+=refMat2t.transpose()*refMat3);
+ VERIFY_IS_APPROX(dm4-=m2t.transpose()*m3, refMat4-=refMat2t.transpose()*refMat3);
+ VERIFY_IS_APPROX(dm4 =m2t.transpose()*m3t.transpose(), refMat4 =refMat2t.transpose()*refMat3t.transpose());
+ VERIFY_IS_APPROX(dm4+=m2t.transpose()*m3t.transpose(), refMat4+=refMat2t.transpose()*refMat3t.transpose());
+ VERIFY_IS_APPROX(dm4-=m2t.transpose()*m3t.transpose(), refMat4-=refMat2t.transpose()*refMat3t.transpose());
+ VERIFY_IS_APPROX(dm4 =m2*m3t.transpose(), refMat4 =refMat2*refMat3t.transpose());
+ VERIFY_IS_APPROX(dm4+=m2*m3t.transpose(), refMat4+=refMat2*refMat3t.transpose());
+ VERIFY_IS_APPROX(dm4-=m2*m3t.transpose(), refMat4-=refMat2*refMat3t.transpose());
+ VERIFY_IS_APPROX(dm4 = m2*m3*s1, refMat4 = refMat2*refMat3*s1);
+
// test aliasing
m4 = m2; refMat4 = refMat2;
VERIFY_IS_APPROX(m4=m4*m3, refMat4=refMat4*refMat3);
- // sparse * dense
+ // sparse * dense matrix
VERIFY_IS_APPROX(dm4=m2*refMat3, refMat4=refMat2*refMat3);
VERIFY_IS_APPROX(dm4=m2*refMat3t.transpose(), refMat4=refMat2*refMat3t.transpose());
VERIFY_IS_APPROX(dm4=m2t.transpose()*refMat3, refMat4=refMat2t.transpose()*refMat3);
VERIFY_IS_APPROX(dm4=m2t.transpose()*refMat3t.transpose(), refMat4=refMat2t.transpose()*refMat3t.transpose());
+ VERIFY_IS_APPROX(dm4=m2*refMat3, refMat4=refMat2*refMat3);
+ VERIFY_IS_APPROX(dm4=dm4+m2*refMat3, refMat4=refMat4+refMat2*refMat3);
+ VERIFY_IS_APPROX(dm4+=m2*refMat3, refMat4+=refMat2*refMat3);
+ VERIFY_IS_APPROX(dm4-=m2*refMat3, refMat4-=refMat2*refMat3);
+ VERIFY_IS_APPROX(dm4.noalias()+=m2*refMat3, refMat4+=refMat2*refMat3);
+ VERIFY_IS_APPROX(dm4.noalias()-=m2*refMat3, refMat4-=refMat2*refMat3);
VERIFY_IS_APPROX(dm4=m2*(refMat3+refMat3), refMat4=refMat2*(refMat3+refMat3));
VERIFY_IS_APPROX(dm4=m2t.transpose()*(refMat3+refMat5)*0.5, refMat4=refMat2t.transpose()*(refMat3+refMat5)*0.5);
+
+ // sparse * dense vector
+ VERIFY_IS_APPROX(dm4.col(0)=m2*refMat3.col(0), refMat4.col(0)=refMat2*refMat3.col(0));
+ VERIFY_IS_APPROX(dm4.col(0)=m2*refMat3t.transpose().col(0), refMat4.col(0)=refMat2*refMat3t.transpose().col(0));
+ VERIFY_IS_APPROX(dm4.col(0)=m2t.transpose()*refMat3.col(0), refMat4.col(0)=refMat2t.transpose()*refMat3.col(0));
+ VERIFY_IS_APPROX(dm4.col(0)=m2t.transpose()*refMat3t.transpose().col(0), refMat4.col(0)=refMat2t.transpose()*refMat3t.transpose().col(0));
// dense * sparse
VERIFY_IS_APPROX(dm4=refMat2*m3, refMat4=refMat2*refMat3);
+ VERIFY_IS_APPROX(dm4=dm4+refMat2*m3, refMat4=refMat4+refMat2*refMat3);
+ VERIFY_IS_APPROX(dm4+=refMat2*m3, refMat4+=refMat2*refMat3);
+ VERIFY_IS_APPROX(dm4-=refMat2*m3, refMat4-=refMat2*refMat3);
+ VERIFY_IS_APPROX(dm4.noalias()+=refMat2*m3, refMat4+=refMat2*refMat3);
+ VERIFY_IS_APPROX(dm4.noalias()-=refMat2*m3, refMat4-=refMat2*refMat3);
VERIFY_IS_APPROX(dm4=refMat2*m3t.transpose(), refMat4=refMat2*refMat3t.transpose());
VERIFY_IS_APPROX(dm4=refMat2t.transpose()*m3, refMat4=refMat2t.transpose()*refMat3);
VERIFY_IS_APPROX(dm4=refMat2t.transpose()*m3t.transpose(), refMat4=refMat2t.transpose()*refMat3t.transpose());
// sparse * dense and dense * sparse outer product
- test_outer<SparseMatrixType,DenseMatrix>::run(m2,m4,refMat2,refMat4);
+ {
+ Index c = internal::random<Index>(0,depth-1);
+ Index r = internal::random<Index>(0,rows-1);
+ Index c1 = internal::random<Index>(0,cols-1);
+ Index r1 = internal::random<Index>(0,depth-1);
+ DenseMatrix dm5 = DenseMatrix::Random(depth, cols);
+
+ VERIFY_IS_APPROX( m4=m2.col(c)*dm5.col(c1).transpose(), refMat4=refMat2.col(c)*dm5.col(c1).transpose());
+ VERIFY_IS_EQUAL(m4.nonZeros(), (refMat4.array()!=0).count());
+ VERIFY_IS_APPROX( m4=m2.middleCols(c,1)*dm5.col(c1).transpose(), refMat4=refMat2.col(c)*dm5.col(c1).transpose());
+ VERIFY_IS_EQUAL(m4.nonZeros(), (refMat4.array()!=0).count());
+ VERIFY_IS_APPROX(dm4=m2.col(c)*dm5.col(c1).transpose(), refMat4=refMat2.col(c)*dm5.col(c1).transpose());
+
+ VERIFY_IS_APPROX(m4=dm5.col(c1)*m2.col(c).transpose(), refMat4=dm5.col(c1)*refMat2.col(c).transpose());
+ VERIFY_IS_EQUAL(m4.nonZeros(), (refMat4.array()!=0).count());
+ VERIFY_IS_APPROX(m4=dm5.col(c1)*m2.middleCols(c,1).transpose(), refMat4=dm5.col(c1)*refMat2.col(c).transpose());
+ VERIFY_IS_EQUAL(m4.nonZeros(), (refMat4.array()!=0).count());
+ VERIFY_IS_APPROX(dm4=dm5.col(c1)*m2.col(c).transpose(), refMat4=dm5.col(c1)*refMat2.col(c).transpose());
+
+ VERIFY_IS_APPROX( m4=dm5.row(r1).transpose()*m2.col(c).transpose(), refMat4=dm5.row(r1).transpose()*refMat2.col(c).transpose());
+ VERIFY_IS_EQUAL(m4.nonZeros(), (refMat4.array()!=0).count());
+ VERIFY_IS_APPROX(dm4=dm5.row(r1).transpose()*m2.col(c).transpose(), refMat4=dm5.row(r1).transpose()*refMat2.col(c).transpose());
+
+ VERIFY_IS_APPROX( m4=m2.row(r).transpose()*dm5.col(c1).transpose(), refMat4=refMat2.row(r).transpose()*dm5.col(c1).transpose());
+ VERIFY_IS_EQUAL(m4.nonZeros(), (refMat4.array()!=0).count());
+ VERIFY_IS_APPROX( m4=m2.middleRows(r,1).transpose()*dm5.col(c1).transpose(), refMat4=refMat2.row(r).transpose()*dm5.col(c1).transpose());
+ VERIFY_IS_EQUAL(m4.nonZeros(), (refMat4.array()!=0).count());
+ VERIFY_IS_APPROX(dm4=m2.row(r).transpose()*dm5.col(c1).transpose(), refMat4=refMat2.row(r).transpose()*dm5.col(c1).transpose());
+
+ VERIFY_IS_APPROX( m4=dm5.col(c1)*m2.row(r), refMat4=dm5.col(c1)*refMat2.row(r));
+ VERIFY_IS_EQUAL(m4.nonZeros(), (refMat4.array()!=0).count());
+ VERIFY_IS_APPROX( m4=dm5.col(c1)*m2.middleRows(r,1), refMat4=dm5.col(c1)*refMat2.row(r));
+ VERIFY_IS_EQUAL(m4.nonZeros(), (refMat4.array()!=0).count());
+ VERIFY_IS_APPROX(dm4=dm5.col(c1)*m2.row(r), refMat4=dm5.col(c1)*refMat2.row(r));
+
+ VERIFY_IS_APPROX( m4=dm5.row(r1).transpose()*m2.row(r), refMat4=dm5.row(r1).transpose()*refMat2.row(r));
+ VERIFY_IS_EQUAL(m4.nonZeros(), (refMat4.array()!=0).count());
+ VERIFY_IS_APPROX(dm4=dm5.row(r1).transpose()*m2.row(r), refMat4=dm5.row(r1).transpose()*refMat2.row(r));
+ }
VERIFY_IS_APPROX(m6=m6*m6, refMat6=refMat6*refMat6);
@@ -131,11 +214,11 @@ template<typename SparseMatrixType> void sparse_product()
RowSpVector rv0(depth), rv1;
RowDenseVector drv0(depth), drv1(rv1);
initSparse(2*density,drv0, rv0);
-
- VERIFY_IS_APPROX(cv1=rv0*m3, dcv1=drv0*refMat3);
+
+ VERIFY_IS_APPROX(cv1=m3*cv0, dcv1=refMat3*dcv0);
VERIFY_IS_APPROX(rv1=rv0*m3, drv1=drv0*refMat3);
- VERIFY_IS_APPROX(cv1=m3*cv0, dcv1=refMat3*dcv0);
VERIFY_IS_APPROX(cv1=m3t.adjoint()*cv0, dcv1=refMat3t.adjoint()*dcv0);
+ VERIFY_IS_APPROX(cv1=rv0*m3, dcv1=drv0*refMat3);
VERIFY_IS_APPROX(rv1=m3*cv0, drv1=refMat3*dcv0);
}
@@ -158,12 +241,16 @@ template<typename SparseMatrixType> void sparse_product()
// also check with a SparseWrapper:
DenseVector v1 = DenseVector::Random(cols);
DenseVector v2 = DenseVector::Random(rows);
+ DenseVector v3 = DenseVector::Random(rows);
VERIFY_IS_APPROX(m3=m2*v1.asDiagonal(), refM3=refM2*v1.asDiagonal());
VERIFY_IS_APPROX(m3=m2.transpose()*v2.asDiagonal(), refM3=refM2.transpose()*v2.asDiagonal());
VERIFY_IS_APPROX(m3=v2.asDiagonal()*m2, refM3=v2.asDiagonal()*refM2);
VERIFY_IS_APPROX(m3=v1.asDiagonal()*m2.transpose(), refM3=v1.asDiagonal()*refM2.transpose());
VERIFY_IS_APPROX(m3=v2.asDiagonal()*m2*v1.asDiagonal(), refM3=v2.asDiagonal()*refM2*v1.asDiagonal());
+
+ VERIFY_IS_APPROX(v2=m2*v1.asDiagonal()*v1, refM2*v1.asDiagonal()*v1);
+ VERIFY_IS_APPROX(v3=v2.asDiagonal()*m2*v1, v2.asDiagonal()*refM2*v1);
// evaluate to a dense matrix to check the .row() and .col() iterator functions
VERIFY_IS_APPROX(d3=m2*d1, refM3=refM2*d1);
@@ -172,7 +259,7 @@ template<typename SparseMatrixType> void sparse_product()
VERIFY_IS_APPROX(d3=d1*m2.transpose(), refM3=d1*refM2.transpose());
}
- // test self adjoint products
+ // test self-adjoint and triangular-view products
{
DenseMatrix b = DenseMatrix::Random(rows, rows);
DenseMatrix x = DenseMatrix::Random(rows, rows);
@@ -180,9 +267,12 @@ template<typename SparseMatrixType> void sparse_product()
DenseMatrix refUp = DenseMatrix::Zero(rows, rows);
DenseMatrix refLo = DenseMatrix::Zero(rows, rows);
DenseMatrix refS = DenseMatrix::Zero(rows, rows);
+ DenseMatrix refA = DenseMatrix::Zero(rows, rows);
SparseMatrixType mUp(rows, rows);
SparseMatrixType mLo(rows, rows);
SparseMatrixType mS(rows, rows);
+ SparseMatrixType mA(rows, rows);
+ initSparse<Scalar>(density, refA, mA);
do {
initSparse<Scalar>(density, refUp, mUp, ForceRealDiag|/*ForceNonZeroDiag|*/MakeUpperTriangular);
} while (refUp.isZero());
@@ -195,26 +285,41 @@ template<typename SparseMatrixType> void sparse_product()
for (int k=0; k<mS.outerSize(); ++k)
for (typename SparseMatrixType::InnerIterator it(mS,k); it; ++it)
if (it.index() == k)
- it.valueRef() *= 0.5;
+ it.valueRef() *= Scalar(0.5);
VERIFY_IS_APPROX(refS.adjoint(), refS);
VERIFY_IS_APPROX(mS.adjoint(), mS);
VERIFY_IS_APPROX(mS, refS);
VERIFY_IS_APPROX(x=mS*b, refX=refS*b);
+ // sparse selfadjointView with dense matrices
VERIFY_IS_APPROX(x=mUp.template selfadjointView<Upper>()*b, refX=refS*b);
VERIFY_IS_APPROX(x=mLo.template selfadjointView<Lower>()*b, refX=refS*b);
VERIFY_IS_APPROX(x=mS.template selfadjointView<Upper|Lower>()*b, refX=refS*b);
+
+ VERIFY_IS_APPROX(x.noalias()+=mUp.template selfadjointView<Upper>()*b, refX+=refS*b);
+ VERIFY_IS_APPROX(x.noalias()-=mLo.template selfadjointView<Lower>()*b, refX-=refS*b);
+ VERIFY_IS_APPROX(x.noalias()+=mS.template selfadjointView<Upper|Lower>()*b, refX+=refS*b);
- // sparse selfadjointView * sparse
+ // sparse selfadjointView with sparse matrices
SparseMatrixType mSres(rows,rows);
VERIFY_IS_APPROX(mSres = mLo.template selfadjointView<Lower>()*mS,
refX = refLo.template selfadjointView<Lower>()*refS);
- // sparse * sparse selfadjointview
VERIFY_IS_APPROX(mSres = mS * mLo.template selfadjointView<Lower>(),
refX = refS * refLo.template selfadjointView<Lower>());
+
+ // sparse triangularView with dense matrices
+ VERIFY_IS_APPROX(x=mA.template triangularView<Upper>()*b, refX=refA.template triangularView<Upper>()*b);
+ VERIFY_IS_APPROX(x=mA.template triangularView<Lower>()*b, refX=refA.template triangularView<Lower>()*b);
+ VERIFY_IS_APPROX(x=b*mA.template triangularView<Upper>(), refX=b*refA.template triangularView<Upper>());
+ VERIFY_IS_APPROX(x=b*mA.template triangularView<Lower>(), refX=b*refA.template triangularView<Lower>());
+
+ // sparse triangularView with sparse matrices
+ VERIFY_IS_APPROX(mSres = mA.template triangularView<Lower>()*mS, refX = refA.template triangularView<Lower>()*refS);
+ VERIFY_IS_APPROX(mSres = mS * mA.template triangularView<Lower>(), refX = refS * refA.template triangularView<Lower>());
+ VERIFY_IS_APPROX(mSres = mA.template triangularView<Upper>()*mS, refX = refA.template triangularView<Upper>()*refS);
+ VERIFY_IS_APPROX(mSres = mS * mA.template triangularView<Upper>(), refX = refS * refA.template triangularView<Upper>());
}
-
}
// New test for Bug in SparseTimeDenseProduct
@@ -239,11 +344,35 @@ template<typename SparseMatrixType, typename DenseMatrixType> void sparse_produc
VERIFY_IS_APPROX( m4(0,0), 0.0 );
}
+template<typename Scalar>
+void bug_942()
+{
+ typedef Matrix<Scalar, Dynamic, 1> Vector;
+ typedef SparseMatrix<Scalar, ColMajor> ColSpMat;
+ typedef SparseMatrix<Scalar, RowMajor> RowSpMat;
+ ColSpMat cmA(1,1);
+ cmA.insert(0,0) = 1;
+
+ RowSpMat rmA(1,1);
+ rmA.insert(0,0) = 1;
+
+ Vector d(1);
+ d[0] = 2;
+
+ double res = 2;
+
+ VERIFY_IS_APPROX( ( cmA*d.asDiagonal() ).eval().coeff(0,0), res );
+ VERIFY_IS_APPROX( ( d.asDiagonal()*rmA ).eval().coeff(0,0), res );
+ VERIFY_IS_APPROX( ( rmA*d.asDiagonal() ).eval().coeff(0,0), res );
+ VERIFY_IS_APPROX( ( d.asDiagonal()*cmA ).eval().coeff(0,0), res );
+}
+
void test_sparse_product()
{
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_1( (sparse_product<SparseMatrix<double,ColMajor> >()) );
CALL_SUBTEST_1( (sparse_product<SparseMatrix<double,RowMajor> >()) );
+ CALL_SUBTEST_1( (bug_942<double>()) );
CALL_SUBTEST_2( (sparse_product<SparseMatrix<std::complex<double>, ColMajor > >()) );
CALL_SUBTEST_2( (sparse_product<SparseMatrix<std::complex<double>, RowMajor > >()) );
CALL_SUBTEST_3( (sparse_product<SparseMatrix<float,ColMajor,long int> >()) );
diff --git a/test/sparse_ref.cpp b/test/sparse_ref.cpp
new file mode 100644
index 000000000..5e9607234
--- /dev/null
+++ b/test/sparse_ref.cpp
@@ -0,0 +1,139 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 20015 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/.
+
+// This unit test cannot be easily written to work with EIGEN_DEFAULT_TO_ROW_MAJOR
+#ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
+#undef EIGEN_DEFAULT_TO_ROW_MAJOR
+#endif
+
+static long int nb_temporaries;
+
+inline void on_temporary_creation() {
+ // here's a great place to set a breakpoint when debugging failures in this test!
+ nb_temporaries++;
+}
+
+#define EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN { on_temporary_creation(); }
+
+#include "main.h"
+#include <Eigen/SparseCore>
+
+#define VERIFY_EVALUATION_COUNT(XPR,N) {\
+ nb_temporaries = 0; \
+ CALL_SUBTEST( XPR ); \
+ if(nb_temporaries!=N) std::cerr << "nb_temporaries == " << nb_temporaries << "\n"; \
+ VERIFY( (#XPR) && nb_temporaries==N ); \
+ }
+
+template<typename PlainObjectType> void check_const_correctness(const PlainObjectType&)
+{
+ // verify that ref-to-const don't have LvalueBit
+ typedef typename internal::add_const<PlainObjectType>::type ConstPlainObjectType;
+ VERIFY( !(internal::traits<Ref<ConstPlainObjectType> >::Flags & LvalueBit) );
+ VERIFY( !(internal::traits<Ref<ConstPlainObjectType, Aligned> >::Flags & LvalueBit) );
+ VERIFY( !(Ref<ConstPlainObjectType>::Flags & LvalueBit) );
+ VERIFY( !(Ref<ConstPlainObjectType, Aligned>::Flags & LvalueBit) );
+}
+
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_1(Ref<SparseMatrix<float> > a, const B &b) { VERIFY_IS_EQUAL(a.toDense(),b.toDense()); }
+
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_2(const Ref<const SparseMatrix<float> >& a, const B &b) { VERIFY_IS_EQUAL(a.toDense(),b.toDense()); }
+
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_3(const Ref<const SparseMatrix<float>, StandardCompressedFormat>& a, const B &b) {
+ VERIFY(a.isCompressed());
+ VERIFY_IS_EQUAL(a.toDense(),b.toDense());
+}
+
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_4(Ref<SparseVector<float> > a, const B &b) { VERIFY_IS_EQUAL(a.toDense(),b.toDense()); }
+
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_5(const Ref<const SparseVector<float> >& a, const B &b) { VERIFY_IS_EQUAL(a.toDense(),b.toDense()); }
+
+void call_ref()
+{
+ SparseMatrix<float> A = MatrixXf::Random(10,10).sparseView(0.5,1);
+ SparseMatrix<float,RowMajor> B = MatrixXf::Random(10,10).sparseView(0.5,1);
+ SparseMatrix<float> C = MatrixXf::Random(10,10).sparseView(0.5,1);
+ C.reserve(VectorXi::Constant(C.outerSize(), 2));
+ const SparseMatrix<float>& Ac(A);
+ Block<SparseMatrix<float> > Ab(A,0,1, 3,3);
+ const Block<SparseMatrix<float> > Abc(A,0,1,3,3);
+ SparseVector<float> vc = VectorXf::Random(10).sparseView(0.5,1);
+ SparseVector<float,RowMajor> vr = VectorXf::Random(10).sparseView(0.5,1);
+ SparseMatrix<float> AA = A*A;
+
+
+ VERIFY_EVALUATION_COUNT( call_ref_1(A, A), 0);
+// VERIFY_EVALUATION_COUNT( call_ref_1(Ac, Ac), 0); // does not compile on purpose
+ VERIFY_EVALUATION_COUNT( call_ref_2(A, A), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_3(A, A), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_2(A.transpose(), A.transpose()), 1);
+ VERIFY_EVALUATION_COUNT( call_ref_3(A.transpose(), A.transpose()), 1);
+ VERIFY_EVALUATION_COUNT( call_ref_2(Ac,Ac), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_3(Ac,Ac), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_2(A+A,2*Ac), 1);
+ VERIFY_EVALUATION_COUNT( call_ref_3(A+A,2*Ac), 1);
+ VERIFY_EVALUATION_COUNT( call_ref_2(B, B), 1);
+ VERIFY_EVALUATION_COUNT( call_ref_3(B, B), 1);
+ VERIFY_EVALUATION_COUNT( call_ref_2(B.transpose(), B.transpose()), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_3(B.transpose(), B.transpose()), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_2(A*A, AA), 3);
+ VERIFY_EVALUATION_COUNT( call_ref_3(A*A, AA), 3);
+
+ VERIFY(!C.isCompressed());
+ VERIFY_EVALUATION_COUNT( call_ref_3(C, C), 1);
+
+ Ref<SparseMatrix<float> > Ar(A);
+ VERIFY_IS_APPROX(Ar+Ar, A+A);
+ VERIFY_EVALUATION_COUNT( call_ref_1(Ar, A), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_2(Ar, A), 0);
+
+ Ref<SparseMatrix<float,RowMajor> > Br(B);
+ VERIFY_EVALUATION_COUNT( call_ref_1(Br.transpose(), Br.transpose()), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_2(Br, Br), 1);
+ VERIFY_EVALUATION_COUNT( call_ref_2(Br.transpose(), Br.transpose()), 0);
+
+ Ref<const SparseMatrix<float> > Arc(A);
+// VERIFY_EVALUATION_COUNT( call_ref_1(Arc, Arc), 0); // does not compile on purpose
+ VERIFY_EVALUATION_COUNT( call_ref_2(Arc, Arc), 0);
+
+ VERIFY_EVALUATION_COUNT( call_ref_2(A.middleCols(1,3), A.middleCols(1,3)), 0);
+
+ VERIFY_EVALUATION_COUNT( call_ref_2(A.col(2), A.col(2)), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_2(vc, vc), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_2(vr.transpose(), vr.transpose()), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_2(vr, vr.transpose()), 0);
+
+ VERIFY_EVALUATION_COUNT( call_ref_2(A.block(1,1,3,3), A.block(1,1,3,3)), 1); // should be 0 (allocate starts/nnz only)
+
+ VERIFY_EVALUATION_COUNT( call_ref_4(vc, vc), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_4(vr, vr.transpose()), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_5(vc, vc), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_5(vr, vr.transpose()), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_4(A.col(2), A.col(2)), 0);
+ VERIFY_EVALUATION_COUNT( call_ref_5(A.col(2), A.col(2)), 0);
+ // VERIFY_EVALUATION_COUNT( call_ref_4(A.row(2), A.row(2).transpose()), 1); // does not compile on purpose
+ VERIFY_EVALUATION_COUNT( call_ref_5(A.row(2), A.row(2).transpose()), 1);
+}
+
+void test_sparse_ref()
+{
+ for(int i = 0; i < g_repeat; i++) {
+ CALL_SUBTEST_1( check_const_correctness(SparseMatrix<float>()) );
+ CALL_SUBTEST_1( check_const_correctness(SparseMatrix<double,RowMajor>()) );
+ CALL_SUBTEST_2( call_ref() );
+
+ CALL_SUBTEST_3( check_const_correctness(SparseVector<float>()) );
+ CALL_SUBTEST_3( check_const_correctness(SparseVector<double,RowMajor>()) );
+ }
+}
diff --git a/test/sparse_solver.h b/test/sparse_solver.h
index 59d77daa2..5145bc3eb 100644
--- a/test/sparse_solver.h
+++ b/test/sparse_solver.h
@@ -9,102 +9,167 @@
#include "sparse.h"
#include <Eigen/SparseCore>
+#include <sstream>
+
+template<typename Solver, typename Rhs, typename Guess,typename Result>
+void solve_with_guess(IterativeSolverBase<Solver>& solver, const MatrixBase<Rhs>& b, const Guess& g, Result &x) {
+ if(internal::random<bool>())
+ {
+ // With a temporary through evaluator<SolveWithGuess>
+ x = solver.derived().solveWithGuess(b,g) + Result::Zero(x.rows(), x.cols());
+ }
+ else
+ {
+ // direct evaluation within x through Assignment<Result,SolveWithGuess>
+ x = solver.derived().solveWithGuess(b.derived(),g);
+ }
+}
+
+template<typename Solver, typename Rhs, typename Guess,typename Result>
+void solve_with_guess(SparseSolverBase<Solver>& solver, const MatrixBase<Rhs>& b, const Guess& , Result& x) {
+ if(internal::random<bool>())
+ x = solver.derived().solve(b) + Result::Zero(x.rows(), x.cols());
+ else
+ x = solver.derived().solve(b);
+}
+
+template<typename Solver, typename Rhs, typename Guess,typename Result>
+void solve_with_guess(SparseSolverBase<Solver>& solver, const SparseMatrixBase<Rhs>& b, const Guess& , Result& x) {
+ x = solver.derived().solve(b);
+}
template<typename Solver, typename Rhs, typename DenseMat, typename DenseRhs>
void check_sparse_solving(Solver& solver, const typename Solver::MatrixType& A, const Rhs& b, const DenseMat& dA, const DenseRhs& db)
{
typedef typename Solver::MatrixType Mat;
typedef typename Mat::Scalar Scalar;
+ typedef typename Mat::StorageIndex StorageIndex;
- DenseRhs refX = dA.lu().solve(db);
+ DenseRhs refX = dA.householderQr().solve(db);
{
- Rhs x(b.rows(), b.cols());
+ Rhs x(A.cols(), b.cols());
Rhs oldb = b;
solver.compute(A);
if (solver.info() != Success)
{
- std::cerr << "sparse solver testing: factorization failed (check_sparse_solving)\n";
- exit(0);
- return;
+ std::cerr << "ERROR | sparse solver testing, factorization failed (" << typeid(Solver).name() << ")\n";
+ VERIFY(solver.info() == Success);
}
x = solver.solve(b);
if (solver.info() != Success)
{
- std::cerr << "sparse solver testing: solving failed\n";
+ std::cerr << "WARNING | sparse solver testing: solving failed (" << typeid(Solver).name() << ")\n";
return;
}
VERIFY(oldb.isApprox(b) && "sparse solver testing: the rhs should not be modified!");
+ VERIFY(x.isApprox(refX,test_precision<Scalar>()));
+ x.setZero();
+ solve_with_guess(solver, b, x, x);
+ VERIFY(solver.info() == Success && "solving failed when using analyzePattern/factorize API");
+ VERIFY(oldb.isApprox(b) && "sparse solver testing: the rhs should not be modified!");
VERIFY(x.isApprox(refX,test_precision<Scalar>()));
+
x.setZero();
// test the analyze/factorize API
solver.analyzePattern(A);
solver.factorize(A);
- if (solver.info() != Success)
- {
- std::cerr << "sparse solver testing: factorization failed (check_sparse_solving)\n";
- exit(0);
- return;
- }
+ VERIFY(solver.info() == Success && "factorization failed when using analyzePattern/factorize API");
x = solver.solve(b);
- if (solver.info() != Success)
- {
- std::cerr << "sparse solver testing: solving failed\n";
- return;
- }
+ VERIFY(solver.info() == Success && "solving failed when using analyzePattern/factorize API");
VERIFY(oldb.isApprox(b) && "sparse solver testing: the rhs should not be modified!");
-
VERIFY(x.isApprox(refX,test_precision<Scalar>()));
+
+ x.setZero();
+ // test with Map
+ MappedSparseMatrix<Scalar,Mat::Options,StorageIndex> Am(A.rows(), A.cols(), A.nonZeros(), const_cast<StorageIndex*>(A.outerIndexPtr()), const_cast<StorageIndex*>(A.innerIndexPtr()), const_cast<Scalar*>(A.valuePtr()));
+ solver.compute(Am);
+ VERIFY(solver.info() == Success && "factorization failed when using Map");
+ DenseRhs dx(refX);
+ dx.setZero();
+ Map<DenseRhs> xm(dx.data(), dx.rows(), dx.cols());
+ Map<const DenseRhs> bm(db.data(), db.rows(), db.cols());
+ xm = solver.solve(bm);
+ VERIFY(solver.info() == Success && "solving failed when using Map");
+ VERIFY(oldb.isApprox(bm) && "sparse solver testing: the rhs should not be modified!");
+ VERIFY(xm.isApprox(refX,test_precision<Scalar>()));
}
- // test dense Block as the result and rhs:
+ // if not too large, do some extra check:
+ if(A.rows()<2000)
{
- DenseRhs x(db.rows(), db.cols());
- DenseRhs oldb(db);
- x.setZero();
- x.block(0,0,x.rows(),x.cols()) = solver.solve(db.block(0,0,db.rows(),db.cols()));
- VERIFY(oldb.isApprox(db) && "sparse solver testing: the rhs should not be modified!");
- VERIFY(x.isApprox(refX,test_precision<Scalar>()));
+ // test initialization ctor
+ {
+ Rhs x(b.rows(), b.cols());
+ Solver solver2(A);
+ VERIFY(solver2.info() == Success);
+ x = solver2.solve(b);
+ VERIFY(x.isApprox(refX,test_precision<Scalar>()));
+ }
+
+ // test dense Block as the result and rhs:
+ {
+ DenseRhs x(refX.rows(), refX.cols());
+ DenseRhs oldb(db);
+ x.setZero();
+ x.block(0,0,x.rows(),x.cols()) = solver.solve(db.block(0,0,db.rows(),db.cols()));
+ VERIFY(oldb.isApprox(db) && "sparse solver testing: the rhs should not be modified!");
+ VERIFY(x.isApprox(refX,test_precision<Scalar>()));
+ }
+
+ // test uncompressed inputs
+ {
+ Mat A2 = A;
+ A2.reserve((ArrayXf::Random(A.outerSize())+2).template cast<typename Mat::StorageIndex>().eval());
+ solver.compute(A2);
+ Rhs x = solver.solve(b);
+ VERIFY(x.isApprox(refX,test_precision<Scalar>()));
+ }
+
+ // test expression as input
+ {
+ solver.compute(0.5*(A+A));
+ Rhs x = solver.solve(b);
+ VERIFY(x.isApprox(refX,test_precision<Scalar>()));
+
+ Solver solver2(0.5*(A+A));
+ Rhs x2 = solver2.solve(b);
+ VERIFY(x2.isApprox(refX,test_precision<Scalar>()));
+ }
}
}
template<typename Solver, typename Rhs>
-void check_sparse_solving_real_cases(Solver& solver, const typename Solver::MatrixType& A, const Rhs& b, const Rhs& refX)
+void check_sparse_solving_real_cases(Solver& solver, const typename Solver::MatrixType& A, const Rhs& b, const typename Solver::MatrixType& fullA, const Rhs& refX)
{
typedef typename Solver::MatrixType Mat;
typedef typename Mat::Scalar Scalar;
typedef typename Mat::RealScalar RealScalar;
- Rhs x(b.rows(), b.cols());
-
+ Rhs x(A.cols(), b.cols());
+
solver.compute(A);
if (solver.info() != Success)
{
- std::cerr << "sparse solver testing: factorization failed (check_sparse_solving_real_cases)\n";
- exit(0);
- return;
+ std::cerr << "ERROR | sparse solver testing, factorization failed (" << typeid(Solver).name() << ")\n";
+ VERIFY(solver.info() == Success);
}
x = solver.solve(b);
+
if (solver.info() != Success)
{
- std::cerr << "sparse solver testing: solving failed\n";
+ std::cerr << "WARNING | sparse solver testing, solving failed (" << typeid(Solver).name() << ")\n";
return;
}
- RealScalar res_error;
- // Compute the norm of the relative error
- if(refX.size() != 0)
- res_error = (refX - x).norm()/refX.norm();
- else
- {
- // Compute the relative residual norm
- res_error = (b - A * x).norm()/b.norm();
- }
- if (res_error > test_precision<Scalar>() ){
- std::cerr << "Test " << g_test_stack.back() << " failed in "EI_PP_MAKE_STRING(__FILE__)
- << " (" << EI_PP_MAKE_STRING(__LINE__) << ")" << std::endl << std::endl;
- abort();
+ RealScalar res_error = (fullA*x-b).norm()/b.norm();
+ VERIFY( (res_error <= test_precision<Scalar>() ) && "sparse solver failed without noticing it");
+
+
+ if(refX.size() != 0 && (refX - x).norm()/refX.norm() > test_precision<Scalar>())
+ {
+ std::cerr << "WARNING | found solution is different from the provided reference one\n";
}
}
@@ -117,7 +182,7 @@ void check_sparse_determinant(Solver& solver, const typename Solver::MatrixType&
solver.compute(A);
if (solver.info() != Success)
{
- std::cerr << "sparse solver testing: factorization failed (check_sparse_determinant)\n";
+ std::cerr << "WARNING | sparse solver testing: factorization failed (check_sparse_determinant)\n";
return;
}
@@ -134,7 +199,7 @@ void check_sparse_abs_determinant(Solver& solver, const typename Solver::MatrixT
solver.compute(A);
if (solver.info() != Success)
{
- std::cerr << "sparse solver testing: factorization failed (check_sparse_abs_determinant)\n";
+ std::cerr << "WARNING | sparse solver testing: factorization failed (check_sparse_abs_determinant)\n";
return;
}
@@ -181,13 +246,33 @@ inline std::string get_matrixfolder()
mat_folder = mat_folder + static_cast<std::string>("/real/");
return mat_folder;
}
+std::string sym_to_string(int sym)
+{
+ if(sym==Symmetric) return "Symmetric ";
+ if(sym==SPD) return "SPD ";
+ return "";
+}
+template<typename Derived>
+std::string solver_stats(const IterativeSolverBase<Derived> &solver)
+{
+ std::stringstream ss;
+ ss << solver.iterations() << " iters, error: " << solver.error();
+ return ss.str();
+}
+template<typename Derived>
+std::string solver_stats(const SparseSolverBase<Derived> &/*solver*/)
+{
+ return "";
+}
#endif
-template<typename Solver> void check_sparse_spd_solving(Solver& solver)
+template<typename Solver> void check_sparse_spd_solving(Solver& solver, int maxSize = 300, int maxRealWorldSize = 100000)
{
typedef typename Solver::MatrixType Mat;
typedef typename Mat::Scalar Scalar;
- typedef SparseMatrix<Scalar,ColMajor> SpMat;
+ typedef typename Mat::StorageIndex StorageIndex;
+ typedef SparseMatrix<Scalar,ColMajor, StorageIndex> SpMat;
+ typedef SparseVector<Scalar, 0, StorageIndex> SpVec;
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
typedef Matrix<Scalar,Dynamic,1> DenseVector;
@@ -195,7 +280,7 @@ template<typename Solver> void check_sparse_spd_solving(Solver& solver)
Mat A, halfA;
DenseMatrix dA;
for (int i = 0; i < g_repeat; i++) {
- int size = generate_sparse_spd_problem(solver, A, halfA, dA);
+ int size = generate_sparse_spd_problem(solver, A, halfA, dA, maxSize);
// generate the right hand sides
int rhsCols = internal::random<int>(1,16);
@@ -204,13 +289,17 @@ template<typename Solver> void check_sparse_spd_solving(Solver& solver)
DenseVector b = DenseVector::Random(size);
DenseMatrix dB(size,rhsCols);
initSparse<Scalar>(density, dB, B, ForceNonZeroDiag);
+ SpVec c = B.col(0);
+ DenseVector dc = dB.col(0);
- check_sparse_solving(solver, A, b, dA, b);
- check_sparse_solving(solver, halfA, b, dA, b);
- check_sparse_solving(solver, A, dB, dA, dB);
- check_sparse_solving(solver, halfA, dB, dA, dB);
- check_sparse_solving(solver, A, B, dA, dB);
- check_sparse_solving(solver, halfA, B, dA, dB);
+ CALL_SUBTEST( check_sparse_solving(solver, A, b, dA, b) );
+ CALL_SUBTEST( check_sparse_solving(solver, halfA, b, dA, b) );
+ CALL_SUBTEST( check_sparse_solving(solver, A, dB, dA, dB) );
+ CALL_SUBTEST( check_sparse_solving(solver, halfA, dB, dA, dB) );
+ CALL_SUBTEST( check_sparse_solving(solver, A, B, dA, dB) );
+ CALL_SUBTEST( check_sparse_solving(solver, halfA, B, dA, dB) );
+ CALL_SUBTEST( check_sparse_solving(solver, A, c, dA, dc) );
+ CALL_SUBTEST( check_sparse_solving(solver, halfA, c, dA, dc) );
// check only once
if(i==0)
@@ -221,25 +310,44 @@ template<typename Solver> void check_sparse_spd_solving(Solver& solver)
}
// First, get the folder
-#ifdef TEST_REAL_CASES
- if (internal::is_same<Scalar, float>::value
- || internal::is_same<Scalar, std::complex<float> >::value)
- return ;
-
- std::string mat_folder = get_matrixfolder<Scalar>();
- MatrixMarketIterator<Scalar> it(mat_folder);
- for (; it; ++it)
+#ifdef TEST_REAL_CASES
+ // Test real problems with double precision only
+ if (internal::is_same<typename NumTraits<Scalar>::Real, double>::value)
{
- if (it.sym() == SPD){
- Mat halfA;
- PermutationMatrix<Dynamic, Dynamic, Index> pnull;
- halfA.template selfadjointView<Solver::UpLo>() = it.matrix().template triangularView<Eigen::Lower>().twistedBy(pnull);
-
- std::cout<< " ==== SOLVING WITH MATRIX " << it.matname() << " ==== \n";
- check_sparse_solving_real_cases(solver, it.matrix(), it.rhs(), it.refX());
- check_sparse_solving_real_cases(solver, halfA, it.rhs(), it.refX());
+ std::string mat_folder = get_matrixfolder<Scalar>();
+ MatrixMarketIterator<Scalar> it(mat_folder);
+ for (; it; ++it)
+ {
+ if (it.sym() == SPD){
+ A = it.matrix();
+ if(A.diagonal().size() <= maxRealWorldSize)
+ {
+ DenseVector b = it.rhs();
+ DenseVector refX = it.refX();
+ PermutationMatrix<Dynamic, Dynamic, StorageIndex> pnull;
+ halfA.resize(A.rows(), A.cols());
+ if(Solver::UpLo == (Lower|Upper))
+ halfA = A;
+ else
+ halfA.template selfadjointView<Solver::UpLo>() = A.template triangularView<Eigen::Lower>().twistedBy(pnull);
+
+ std::cout << "INFO | Testing " << sym_to_string(it.sym()) << "sparse problem " << it.matname()
+ << " (" << A.rows() << "x" << A.cols() << ") using " << typeid(Solver).name() << "..." << std::endl;
+ CALL_SUBTEST( check_sparse_solving_real_cases(solver, A, b, A, refX) );
+ std::string stats = solver_stats(solver);
+ if(stats.size()>0)
+ std::cout << "INFO | " << stats << std::endl;
+ CALL_SUBTEST( check_sparse_solving_real_cases(solver, halfA, b, A, refX) );
+ }
+ else
+ {
+ std::cout << "INFO | Skip sparse problem \"" << it.matname() << "\" (too large)" << std::endl;
+ }
+ }
}
}
+#else
+ EIGEN_UNUSED_VARIABLE(maxRealWorldSize);
#endif
}
@@ -261,27 +369,39 @@ template<typename Solver> void check_sparse_spd_determinant(Solver& solver)
}
template<typename Solver, typename DenseMat>
-int generate_sparse_square_problem(Solver&, typename Solver::MatrixType& A, DenseMat& dA, int maxSize = 300)
+Index generate_sparse_square_problem(Solver&, typename Solver::MatrixType& A, DenseMat& dA, int maxSize = 300, int options = ForceNonZeroDiag)
{
typedef typename Solver::MatrixType Mat;
typedef typename Mat::Scalar Scalar;
- int size = internal::random<int>(1,maxSize);
+ Index size = internal::random<int>(1,maxSize);
double density = (std::max)(8./(size*size), 0.01);
A.resize(size,size);
dA.resize(size,size);
- initSparse<Scalar>(density, dA, A, ForceNonZeroDiag);
+ initSparse<Scalar>(density, dA, A, options);
return size;
}
-template<typename Solver> void check_sparse_square_solving(Solver& solver)
+
+struct prune_column {
+ Index m_col;
+ prune_column(Index col) : m_col(col) {}
+ template<class Scalar>
+ bool operator()(Index, Index col, const Scalar&) const {
+ return col != m_col;
+ }
+};
+
+
+template<typename Solver> void check_sparse_square_solving(Solver& solver, int maxSize = 300, int maxRealWorldSize = 100000, bool checkDeficient = false)
{
typedef typename Solver::MatrixType Mat;
typedef typename Mat::Scalar Scalar;
- typedef SparseMatrix<Scalar,ColMajor> SpMat;
+ typedef SparseMatrix<Scalar,ColMajor, typename Mat::StorageIndex> SpMat;
+ typedef SparseVector<Scalar, 0, typename Mat::StorageIndex> SpVec;
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
typedef Matrix<Scalar,Dynamic,1> DenseVector;
@@ -290,7 +410,7 @@ template<typename Solver> void check_sparse_square_solving(Solver& solver)
Mat A;
DenseMatrix dA;
for (int i = 0; i < g_repeat; i++) {
- int size = generate_sparse_square_problem(solver, A, dA);
+ Index size = generate_sparse_square_problem(solver, A, dA, maxSize);
A.makeCompressed();
DenseVector b = DenseVector::Random(size);
@@ -299,9 +419,12 @@ template<typename Solver> void check_sparse_square_solving(Solver& solver)
double density = (std::max)(8./(size*rhsCols), 0.1);
initSparse<Scalar>(density, dB, B, ForceNonZeroDiag);
B.makeCompressed();
- check_sparse_solving(solver, A, b, dA, b);
- check_sparse_solving(solver, A, dB, dA, dB);
- check_sparse_solving(solver, A, B, dA, dB);
+ SpVec c = B.col(0);
+ DenseVector dc = dB.col(0);
+ CALL_SUBTEST(check_sparse_solving(solver, A, b, dA, b));
+ CALL_SUBTEST(check_sparse_solving(solver, A, dB, dA, dB));
+ CALL_SUBTEST(check_sparse_solving(solver, A, B, dA, dB));
+ CALL_SUBTEST(check_sparse_solving(solver, A, c, dA, dc));
// check only once
if(i==0)
@@ -309,21 +432,44 @@ template<typename Solver> void check_sparse_square_solving(Solver& solver)
b = DenseVector::Zero(size);
check_sparse_solving(solver, A, b, dA, b);
}
+ // regression test for Bug 792 (structurally rank deficient matrices):
+ if(checkDeficient && size>1) {
+ Index col = internal::random<int>(0,int(size-1));
+ A.prune(prune_column(col));
+ solver.compute(A);
+ VERIFY_IS_EQUAL(solver.info(), NumericalIssue);
+ }
}
// First, get the folder
#ifdef TEST_REAL_CASES
- if (internal::is_same<Scalar, float>::value
- || internal::is_same<Scalar, std::complex<float> >::value)
- return ;
-
- std::string mat_folder = get_matrixfolder<Scalar>();
- MatrixMarketIterator<Scalar> it(mat_folder);
- for (; it; ++it)
+ // Test real problems with double precision only
+ if (internal::is_same<typename NumTraits<Scalar>::Real, double>::value)
{
- std::cout<< " ==== SOLVING WITH MATRIX " << it.matname() << " ==== \n";
- check_sparse_solving_real_cases(solver, it.matrix(), it.rhs(), it.refX());
+ std::string mat_folder = get_matrixfolder<Scalar>();
+ MatrixMarketIterator<Scalar> it(mat_folder);
+ for (; it; ++it)
+ {
+ A = it.matrix();
+ if(A.diagonal().size() <= maxRealWorldSize)
+ {
+ DenseVector b = it.rhs();
+ DenseVector refX = it.refX();
+ std::cout << "INFO | Testing " << sym_to_string(it.sym()) << "sparse problem " << it.matname()
+ << " (" << A.rows() << "x" << A.cols() << ") using " << typeid(Solver).name() << "..." << std::endl;
+ CALL_SUBTEST(check_sparse_solving_real_cases(solver, A, b, A, refX));
+ std::string stats = solver_stats(solver);
+ if(stats.size()>0)
+ std::cout << "INFO | " << stats << std::endl;
+ }
+ else
+ {
+ std::cout << "INFO | SKIP sparse problem \"" << it.matname() << "\" (too large)" << std::endl;
+ }
+ }
}
+#else
+ EIGEN_UNUSED_VARIABLE(maxRealWorldSize);
#endif
}
@@ -333,13 +479,20 @@ template<typename Solver> void check_sparse_square_determinant(Solver& solver)
typedef typename Solver::MatrixType Mat;
typedef typename Mat::Scalar Scalar;
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
-
- // generate the problem
- Mat A;
- DenseMatrix dA;
- generate_sparse_square_problem(solver, A, dA, 30);
- A.makeCompressed();
+
for (int i = 0; i < g_repeat; i++) {
+ // generate the problem
+ Mat A;
+ DenseMatrix dA;
+
+ int size = internal::random<int>(1,30);
+ dA.setRandom(size,size);
+
+ dA = (dA.array().abs()<0.3).select(0,dA);
+ dA.diagonal() = (dA.diagonal().array()==0).select(1,dA.diagonal());
+ A = dA.sparseView();
+ A.makeCompressed();
+
check_sparse_determinant(solver, A, dA);
}
}
@@ -350,13 +503,63 @@ template<typename Solver> void check_sparse_square_abs_determinant(Solver& solve
typedef typename Mat::Scalar Scalar;
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
- // generate the problem
- Mat A;
- DenseMatrix dA;
- generate_sparse_square_problem(solver, A, dA, 30);
- A.makeCompressed();
for (int i = 0; i < g_repeat; i++) {
+ // generate the problem
+ Mat A;
+ DenseMatrix dA;
+ generate_sparse_square_problem(solver, A, dA, 30);
+ A.makeCompressed();
check_sparse_abs_determinant(solver, A, dA);
}
}
+template<typename Solver, typename DenseMat>
+void generate_sparse_leastsquare_problem(Solver&, typename Solver::MatrixType& A, DenseMat& dA, int maxSize = 300, int options = ForceNonZeroDiag)
+{
+ typedef typename Solver::MatrixType Mat;
+ typedef typename Mat::Scalar Scalar;
+
+ int rows = internal::random<int>(1,maxSize);
+ int cols = internal::random<int>(1,rows);
+ double density = (std::max)(8./(rows*cols), 0.01);
+
+ A.resize(rows,cols);
+ dA.resize(rows,cols);
+
+ initSparse<Scalar>(density, dA, A, options);
+}
+
+template<typename Solver> void check_sparse_leastsquare_solving(Solver& solver)
+{
+ typedef typename Solver::MatrixType Mat;
+ typedef typename Mat::Scalar Scalar;
+ typedef SparseMatrix<Scalar,ColMajor, typename Mat::StorageIndex> SpMat;
+ typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+ typedef Matrix<Scalar,Dynamic,1> DenseVector;
+
+ int rhsCols = internal::random<int>(1,16);
+
+ Mat A;
+ DenseMatrix dA;
+ for (int i = 0; i < g_repeat; i++) {
+ generate_sparse_leastsquare_problem(solver, A, dA);
+
+ A.makeCompressed();
+ DenseVector b = DenseVector::Random(A.rows());
+ DenseMatrix dB(A.rows(),rhsCols);
+ SpMat B(A.rows(),rhsCols);
+ double density = (std::max)(8./(A.rows()*rhsCols), 0.1);
+ initSparse<Scalar>(density, dB, B, ForceNonZeroDiag);
+ B.makeCompressed();
+ check_sparse_solving(solver, A, b, dA, b);
+ check_sparse_solving(solver, A, dB, dA, dB);
+ check_sparse_solving(solver, A, B, dA, dB);
+
+ // check only once
+ if(i==0)
+ {
+ b = DenseVector::Zero(A.rows());
+ check_sparse_solving(solver, A, b, dA, b);
+ }
+ }
+}
diff --git a/test/sparse_vector.cpp b/test/sparse_vector.cpp
index 0c9476803..b3e1dda25 100644
--- a/test/sparse_vector.cpp
+++ b/test/sparse_vector.cpp
@@ -9,22 +9,22 @@
#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);
+ double densityVec = (std::max)(8./(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);
SparseVectorType v1(rows), v2(rows), v3(rows);
DenseMatrix refM1 = DenseMatrix::Zero(rows, rows);
DenseVector refV1 = DenseVector::Random(rows),
- refV2 = DenseVector::Random(rows),
- refV3 = DenseVector::Random(rows);
+ refV2 = DenseVector::Random(rows),
+ refV3 = DenseVector::Random(rows);
std::vector<int> zerocoords, nonzerocoords;
initSparse<Scalar>(densityVec, refV1, v1, &zerocoords, &nonzerocoords);
@@ -52,6 +52,20 @@ template<typename Scalar,typename Index> void sparse_vector(int rows, int cols)
}
}
VERIFY_IS_APPROX(v1, refV1);
+
+ // test coeffRef with reallocation
+ {
+ SparseVectorType v4(rows);
+ DenseVector v5 = DenseVector::Zero(rows);
+ for(int k=0; k<rows; ++k)
+ {
+ int i = internal::random<int>(0,rows-1);
+ Scalar v = internal::random<Scalar>();
+ v4.coeffRef(i) += v;
+ v5.coeffRef(i) += v;
+ }
+ VERIFY_IS_APPROX(v4,v5);
+ }
v1.coeffRef(nonzerocoords[0]) = Scalar(5);
refV1.coeffRef(nonzerocoords[0]) = Scalar(5);
@@ -71,9 +85,12 @@ template<typename Scalar,typename Index> void sparse_vector(int rows, int cols)
VERIFY_IS_APPROX(v1.dot(v2), refV1.dot(refV2));
VERIFY_IS_APPROX(v1.dot(refV2), refV1.dot(refV2));
+ 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());
@@ -96,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/sparselu.cpp b/test/sparselu.cpp
index 37eb069a9..bd000baf1 100644
--- a/test/sparselu.cpp
+++ b/test/sparselu.cpp
@@ -3,25 +3,9 @@
//
// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
//
-// 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/>.
-
+// 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/.
// SparseLU solve does not accept column major matrices for the destination.
// However, as expected, the generic check_sparse_square_solving routines produces row-major
@@ -41,9 +25,9 @@ template<typename T> void test_sparselu_T()
SparseLU<SparseMatrix<T, ColMajor>, AMDOrdering<int> > sparselu_amd;
SparseLU<SparseMatrix<T, ColMajor, long int>, NaturalOrdering<long int> > sparselu_natural;
- check_sparse_square_solving(sparselu_colamd);
- check_sparse_square_solving(sparselu_amd);
- check_sparse_square_solving(sparselu_natural);
+ check_sparse_square_solving(sparselu_colamd, 300, 100000, true);
+ check_sparse_square_solving(sparselu_amd, 300, 10000, true);
+ check_sparse_square_solving(sparselu_natural, 300, 2000, true);
check_sparse_square_abs_determinant(sparselu_colamd);
check_sparse_square_abs_determinant(sparselu_amd);
diff --git a/test/sparseqr.cpp b/test/sparseqr.cpp
index 451c0e7f8..e8605fd21 100644
--- a/test/sparseqr.cpp
+++ b/test/sparseqr.cpp
@@ -10,11 +10,12 @@
#include <Eigen/SparseQR>
template<typename MatrixType,typename DenseMat>
-int generate_sparse_rectangular_problem(MatrixType& A, DenseMat& dA, int maxRows = 300)
+int generate_sparse_rectangular_problem(MatrixType& A, DenseMat& dA, int maxRows = 300, int maxCols = 150)
{
+ eigen_assert(maxRows >= maxCols);
typedef typename MatrixType::Scalar Scalar;
int rows = internal::random<int>(1,maxRows);
- int cols = internal::random<int>(1,rows);
+ int cols = internal::random<int>(1,maxCols);
double density = (std::max)(8./(rows*cols), 0.01);
A.resize(rows,cols);
@@ -53,7 +54,7 @@ template<typename Scalar> void test_sparseqr_scalar()
b = dA * DenseVector::Random(A.cols());
solver.compute(A);
- if(internal::random<float>(0,1)>0.5)
+ if(internal::random<float>(0,1)>0.5f)
solver.factorize(A); // this checks that calling analyzePattern is not needed if the pattern do not change.
if (solver.info() != Success)
{
@@ -88,6 +89,11 @@ template<typename Scalar> void test_sparseqr_scalar()
QtQ = Q * Q.adjoint();
idM.resize(Q.rows(), Q.rows()); idM.setIdentity();
VERIFY(idM.isApprox(QtQ));
+
+ // Q to dense
+ DenseMat dQ;
+ dQ = solver.matrixQ();
+ VERIFY_IS_APPROX(Q, dQ);
}
void test_sparseqr()
{
diff --git a/test/spqr_support.cpp b/test/spqr_support.cpp
index b8980e081..81e63b6a5 100644
--- a/test/spqr_support.cpp
+++ b/test/spqr_support.cpp
@@ -5,6 +5,8 @@
//
// 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
+
+#define EIGEN_NO_DEBUG_SMALL_PRODUCT_BLOCKS
#include "sparse.h"
#include <Eigen/SPQRSupport>
@@ -18,8 +20,8 @@ int generate_sparse_rectangular_problem(MatrixType& A, DenseMat& dA, int maxRows
int cols = internal::random<int>(1,rows);
double density = (std::max)(8./(rows*cols), 0.01);
- A.resize(rows,rows);
- dA.resize(rows,rows);
+ A.resize(rows,cols);
+ dA.resize(rows,cols);
initSparse<Scalar>(density, dA, A,ForceNonZeroDiag);
A.makeCompressed();
return rows;
@@ -35,7 +37,7 @@ template<typename Scalar> void test_spqr_scalar()
SPQR<MatrixType> solver;
generate_sparse_rectangular_problem(A,dA);
- int m = A.rows();
+ Index m = A.rows();
b = DenseVector::Random(m);
solver.compute(A);
if (solver.info() != Success)
diff --git a/test/stable_norm.cpp b/test/stable_norm.cpp
index 231dd9189..c3eb5ff31 100644
--- a/test/stable_norm.cpp
+++ b/test/stable_norm.cpp
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2009-2014 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
@@ -9,14 +9,6 @@
#include "main.h"
-// workaround aggressive optimization in ICC
-template<typename T> EIGEN_DONT_INLINE T sub(T a, T b) { return a - b; }
-
-template<typename T> bool isFinite(const T& x)
-{
- return isNotNaN(sub(x,x));
-}
-
template<typename T> EIGEN_DONT_INLINE T copy(const T& x)
{
return x;
@@ -32,6 +24,8 @@ template<typename MatrixType> void stable_norm(const MatrixType& m)
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
+
+ bool complex_real_product_ok = true;
// Check the basic machine-dependent constants.
{
@@ -44,6 +38,16 @@ template<typename MatrixType> void stable_norm(const MatrixType& m)
VERIFY( (!(iemin > 1 - 2*it || 1+it>iemax || (it==2 && ibeta<5) || (it<=4 && ibeta <= 3 ) || it<2))
&& "the stable norm algorithm cannot be guaranteed on this computer");
+
+ Scalar inf = std::numeric_limits<RealScalar>::infinity();
+ if(NumTraits<Scalar>::IsComplex && (numext::isnan)(inf*RealScalar(1)) )
+ {
+ complex_real_product_ok = false;
+ static bool first = true;
+ if(first)
+ std::cerr << "WARNING: compiler mess up complex*real product, " << inf << " * " << 1.0 << " = " << inf*RealScalar(1) << std::endl;
+ first = false;
+ }
}
@@ -76,19 +80,19 @@ template<typename MatrixType> void stable_norm(const MatrixType& m)
RealScalar size = static_cast<RealScalar>(m.size());
- // test isFinite
- VERIFY(!isFinite( std::numeric_limits<RealScalar>::infinity()));
- VERIFY(!isFinite(sqrt(-abs(big))));
+ // test numext::isfinite
+ VERIFY(!(numext::isfinite)( std::numeric_limits<RealScalar>::infinity()));
+ VERIFY(!(numext::isfinite)(sqrt(-abs(big))));
// test overflow
- VERIFY(isFinite(sqrt(size)*abs(big)));
+ VERIFY((numext::isfinite)(sqrt(size)*abs(big)));
VERIFY_IS_NOT_APPROX(sqrt(copy(vbig.squaredNorm())), abs(sqrt(size)*big)); // here the default norm must fail
VERIFY_IS_APPROX(vbig.stableNorm(), sqrt(size)*abs(big));
VERIFY_IS_APPROX(vbig.blueNorm(), sqrt(size)*abs(big));
VERIFY_IS_APPROX(vbig.hypotNorm(), sqrt(size)*abs(big));
// test underflow
- VERIFY(isFinite(sqrt(size)*abs(small)));
+ VERIFY((numext::isfinite)(sqrt(size)*abs(small)));
VERIFY_IS_NOT_APPROX(sqrt(copy(vsmall.squaredNorm())), abs(sqrt(size)*small)); // here the default norm must fail
VERIFY_IS_APPROX(vsmall.stableNorm(), sqrt(size)*abs(small));
VERIFY_IS_APPROX(vsmall.blueNorm(), sqrt(size)*abs(small));
@@ -101,6 +105,79 @@ template<typename MatrixType> void stable_norm(const MatrixType& m)
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());
+
+ // test NaN, +inf, -inf
+ MatrixType v;
+ Index i = internal::random<Index>(0,rows-1);
+ Index j = internal::random<Index>(0,cols-1);
+
+ // NaN
+ {
+ v = vrand;
+ v(i,j) = std::numeric_limits<RealScalar>::quiet_NaN();
+ VERIFY(!(numext::isfinite)(v.squaredNorm())); VERIFY((numext::isnan)(v.squaredNorm()));
+ VERIFY(!(numext::isfinite)(v.norm())); VERIFY((numext::isnan)(v.norm()));
+ VERIFY(!(numext::isfinite)(v.stableNorm())); VERIFY((numext::isnan)(v.stableNorm()));
+ VERIFY(!(numext::isfinite)(v.blueNorm())); VERIFY((numext::isnan)(v.blueNorm()));
+ VERIFY(!(numext::isfinite)(v.hypotNorm())); VERIFY((numext::isnan)(v.hypotNorm()));
+ }
+
+ // +inf
+ {
+ v = vrand;
+ v(i,j) = std::numeric_limits<RealScalar>::infinity();
+ VERIFY(!(numext::isfinite)(v.squaredNorm())); VERIFY(isPlusInf(v.squaredNorm()));
+ VERIFY(!(numext::isfinite)(v.norm())); VERIFY(isPlusInf(v.norm()));
+ VERIFY(!(numext::isfinite)(v.stableNorm()));
+ if(complex_real_product_ok){
+ VERIFY(isPlusInf(v.stableNorm()));
+ }
+ VERIFY(!(numext::isfinite)(v.blueNorm())); VERIFY(isPlusInf(v.blueNorm()));
+ VERIFY(!(numext::isfinite)(v.hypotNorm())); VERIFY(isPlusInf(v.hypotNorm()));
+ }
+
+ // -inf
+ {
+ v = vrand;
+ v(i,j) = -std::numeric_limits<RealScalar>::infinity();
+ VERIFY(!(numext::isfinite)(v.squaredNorm())); VERIFY(isPlusInf(v.squaredNorm()));
+ VERIFY(!(numext::isfinite)(v.norm())); VERIFY(isPlusInf(v.norm()));
+ VERIFY(!(numext::isfinite)(v.stableNorm()));
+ if(complex_real_product_ok) {
+ VERIFY(isPlusInf(v.stableNorm()));
+ }
+ VERIFY(!(numext::isfinite)(v.blueNorm())); VERIFY(isPlusInf(v.blueNorm()));
+ VERIFY(!(numext::isfinite)(v.hypotNorm())); VERIFY(isPlusInf(v.hypotNorm()));
+ }
+
+ // mix
+ {
+ Index i2 = internal::random<Index>(0,rows-1);
+ Index j2 = internal::random<Index>(0,cols-1);
+ v = vrand;
+ v(i,j) = -std::numeric_limits<RealScalar>::infinity();
+ v(i2,j2) = std::numeric_limits<RealScalar>::quiet_NaN();
+ VERIFY(!(numext::isfinite)(v.squaredNorm())); VERIFY((numext::isnan)(v.squaredNorm()));
+ VERIFY(!(numext::isfinite)(v.norm())); VERIFY((numext::isnan)(v.norm()));
+ VERIFY(!(numext::isfinite)(v.stableNorm())); VERIFY((numext::isnan)(v.stableNorm()));
+ 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/eigen2/eigen2_newstdvector.cpp b/test/stddeque_overload.cpp
index 5f9009901..4da618bbf 100644
--- a/test/eigen2/eigen2_newstdvector.cpp
+++ b/test/stddeque_overload.cpp
@@ -2,23 +2,36 @@
// 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/.
-#define EIGEN_USE_NEW_STDVECTOR
#include "main.h"
-#include <Eigen/StdVector>
+
+#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_stdvector_matrix(const MatrixType& m)
+void check_stddeque_matrix(const MatrixType& m)
{
- int rows = m.rows();
- int cols = m.cols();
+ typename MatrixType::Index rows = m.rows();
+ typename MatrixType::Index cols = m.cols();
MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
- std::vector<MatrixType,Eigen::aligned_allocator<MatrixType> > v(10, MatrixType(rows,cols)), w(20, y);
+ 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]);
@@ -35,9 +48,8 @@ void check_stdvector_matrix(const MatrixType& m)
VERIFY_IS_APPROX(v[21], y);
v.push_back(x);
VERIFY_IS_APPROX(v[22], x);
- VERIFY((std::size_t)&(v[22]) == (std::size_t)&(v[21]) + sizeof(MatrixType));
- // do a lot of push_back such that the vector gets internally resized
+ // 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)
@@ -49,11 +61,11 @@ void check_stdvector_matrix(const MatrixType& m)
}
template<typename TransformType>
-void check_stdvector_transform(const TransformType&)
+void check_stddeque_transform(const TransformType&)
{
typedef typename TransformType::MatrixType MatrixType;
TransformType x(MatrixType::Random()), y(MatrixType::Random());
- std::vector<TransformType,Eigen::aligned_allocator<TransformType> > v(10), w(20, y);
+ std::deque<TransformType> v(10), w(20, y);
v[5] = x;
w[6] = v[5];
VERIFY_IS_APPROX(w[6], v[5]);
@@ -70,9 +82,8 @@ void check_stdvector_transform(const TransformType&)
VERIFY_IS_APPROX(v[21], y);
v.push_back(x);
VERIFY_IS_APPROX(v[22], x);
- VERIFY((std::size_t)&(v[22]) == (std::size_t)&(v[21]) + sizeof(TransformType));
- // do a lot of push_back such that the vector gets internally resized
+ // 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)
@@ -84,11 +95,11 @@ void check_stdvector_transform(const TransformType&)
}
template<typename QuaternionType>
-void check_stdvector_quaternion(const QuaternionType&)
+void check_stddeque_quaternion(const QuaternionType&)
{
typedef typename QuaternionType::Coefficients Coefficients;
QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
- std::vector<QuaternionType,Eigen::aligned_allocator<QuaternionType> > v(10), w(20, y);
+ std::deque<QuaternionType> v(10), w(20, y);
v[5] = x;
w[6] = v[5];
VERIFY_IS_APPROX(w[6], v[5]);
@@ -105,9 +116,8 @@ void check_stdvector_quaternion(const QuaternionType&)
VERIFY_IS_APPROX(v[21], y);
v.push_back(x);
VERIFY_IS_APPROX(v[22], x);
- VERIFY((std::size_t)&(v[22]) == (std::size_t)&(v[21]) + sizeof(QuaternionType));
- // do a lot of push_back such that the vector gets internally resized
+ // 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)
@@ -118,32 +128,31 @@ void check_stdvector_quaternion(const QuaternionType&)
}
}
-void test_eigen2_newstdvector()
+void test_stddeque_overload()
{
// some non vectorizable fixed sizes
- CALL_SUBTEST_1(check_stdvector_matrix(Vector2f()));
- CALL_SUBTEST_1(check_stdvector_matrix(Matrix3f()));
- CALL_SUBTEST_1(check_stdvector_matrix(Matrix3d()));
+ 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_2(check_stdvector_matrix(Matrix2f()));
- CALL_SUBTEST_2(check_stdvector_matrix(Vector4f()));
- CALL_SUBTEST_2(check_stdvector_matrix(Matrix4f()));
- CALL_SUBTEST_2(check_stdvector_matrix(Matrix4d()));
+ 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_stdvector_matrix(MatrixXd(1,1)));
- CALL_SUBTEST_3(check_stdvector_matrix(VectorXd(20)));
- CALL_SUBTEST_3(check_stdvector_matrix(RowVectorXf(20)));
- CALL_SUBTEST_3(check_stdvector_matrix(MatrixXcf(10,10)));
+ 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_stdvector_transform(Transform2f()));
- CALL_SUBTEST_4(check_stdvector_transform(Transform3f()));
- CALL_SUBTEST_4(check_stdvector_transform(Transform3d()));
- //CALL_SUBTEST(check_stdvector_transform(Transform4d()));
+ 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_stdvector_quaternion(Quaternionf()));
- CALL_SUBTEST_5(check_stdvector_quaternion(Quaterniond()));
+ 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/stdvector.cpp b/test/stdvector.cpp
index 6e173c678..50cb3341d 100644
--- a/test/stdvector.cpp
+++ b/test/stdvector.cpp
@@ -34,7 +34,7 @@ void check_stdvector_matrix(const MatrixType& m)
VERIFY_IS_APPROX(v[21], y);
v.push_back(x);
VERIFY_IS_APPROX(v[22], x);
- VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(MatrixType));
+ VERIFY((internal::UIntPtr)&(v[22]) == (internal::UIntPtr)&(v[21]) + sizeof(MatrixType));
// do a lot of push_back such that the vector gets internally resized
// (with memory reallocation)
@@ -69,7 +69,7 @@ void check_stdvector_transform(const TransformType&)
VERIFY_IS_APPROX(v[21], y);
v.push_back(x);
VERIFY_IS_APPROX(v[22], x);
- VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(TransformType));
+ VERIFY((internal::UIntPtr)&(v[22]) == (internal::UIntPtr)&(v[21]) + sizeof(TransformType));
// do a lot of push_back such that the vector gets internally resized
// (with memory reallocation)
@@ -104,7 +104,7 @@ void check_stdvector_quaternion(const QuaternionType&)
VERIFY_IS_APPROX(v[21], y);
v.push_back(x);
VERIFY_IS_APPROX(v[22], x);
- VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(QuaternionType));
+ VERIFY((internal::UIntPtr)&(v[22]) == (internal::UIntPtr)&(v[21]) + sizeof(QuaternionType));
// do a lot of push_back such that the vector gets internally resized
// (with memory reallocation)
diff --git a/test/stdvector_overload.cpp b/test/stdvector_overload.cpp
index 736ff0ee7..959665954 100644
--- a/test/stdvector_overload.cpp
+++ b/test/stdvector_overload.cpp
@@ -48,7 +48,7 @@ void check_stdvector_matrix(const MatrixType& m)
VERIFY_IS_APPROX(v[21], y);
v.push_back(x);
VERIFY_IS_APPROX(v[22], x);
- VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(MatrixType));
+ VERIFY((internal::UIntPtr)&(v[22]) == (internal::UIntPtr)&(v[21]) + sizeof(MatrixType));
// do a lot of push_back such that the vector gets internally resized
// (with memory reallocation)
@@ -83,7 +83,7 @@ void check_stdvector_transform(const TransformType&)
VERIFY_IS_APPROX(v[21], y);
v.push_back(x);
VERIFY_IS_APPROX(v[22], x);
- VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(TransformType));
+ VERIFY((internal::UIntPtr)&(v[22]) == (internal::UIntPtr)&(v[21]) + sizeof(TransformType));
// do a lot of push_back such that the vector gets internally resized
// (with memory reallocation)
@@ -118,7 +118,7 @@ void check_stdvector_quaternion(const QuaternionType&)
VERIFY_IS_APPROX(v[21], y);
v.push_back(x);
VERIFY_IS_APPROX(v[22], x);
- VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(QuaternionType));
+ VERIFY((internal::UIntPtr)&(v[22]) == (internal::UIntPtr)&(v[21]) + sizeof(QuaternionType));
// do a lot of push_back such that the vector gets internally resized
// (with memory reallocation)
diff --git a/test/superlu_support.cpp b/test/superlu_support.cpp
index 3b16135bc..98a7bc5c8 100644
--- a/test/superlu_support.cpp
+++ b/test/superlu_support.cpp
@@ -7,6 +7,7 @@
// 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/.
+#define EIGEN_NO_DEBUG_SMALL_PRODUCT_BLOCKS
#include "sparse_solver.h"
#include <Eigen/SuperLUSupport>
diff --git a/test/svd_common.h b/test/svd_common.h
new file mode 100644
index 000000000..605d5dfef
--- /dev/null
+++ b/test/svd_common.h
@@ -0,0 +1,483 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@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/.
+
+#ifndef SVD_DEFAULT
+#error a macro SVD_DEFAULT(MatrixType) must be defined prior to including svd_common.h
+#endif
+
+#ifndef SVD_FOR_MIN_NORM
+#error a macro SVD_FOR_MIN_NORM(MatrixType) must be defined prior to including svd_common.h
+#endif
+
+#include "svd_fill.h"
+
+// Check that the matrix m is properly reconstructed and that the U and V factors are unitary
+// The SVD must have already been computed.
+template<typename SvdType, typename MatrixType>
+void svd_check_full(const MatrixType& m, const SvdType& svd)
+{
+ typedef typename MatrixType::Index Index;
+ Index rows = m.rows();
+ Index cols = m.cols();
+
+ enum {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime
+ };
+
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime> MatrixUType;
+ typedef Matrix<Scalar, ColsAtCompileTime, ColsAtCompileTime> MatrixVType;
+
+ MatrixType sigma = MatrixType::Zero(rows,cols);
+ sigma.diagonal() = svd.singularValues().template cast<Scalar>();
+ MatrixUType u = svd.matrixU();
+ MatrixVType v = svd.matrixV();
+ RealScalar scaling = m.cwiseAbs().maxCoeff();
+ if(scaling<(std::numeric_limits<RealScalar>::min)())
+ {
+ VERIFY(sigma.cwiseAbs().maxCoeff() <= (std::numeric_limits<RealScalar>::min)());
+ }
+ else
+ {
+ VERIFY_IS_APPROX(m/scaling, u * (sigma/scaling) * v.adjoint());
+ }
+ VERIFY_IS_UNITARY(u);
+ VERIFY_IS_UNITARY(v);
+}
+
+// Compare partial SVD defined by computationOptions to a full SVD referenceSvd
+template<typename SvdType, typename MatrixType>
+void svd_compare_to_full(const MatrixType& m,
+ unsigned int computationOptions,
+ const SvdType& referenceSvd)
+{
+ typedef typename MatrixType::RealScalar RealScalar;
+ Index rows = m.rows();
+ Index cols = m.cols();
+ Index diagSize = (std::min)(rows, cols);
+ RealScalar prec = test_precision<RealScalar>();
+
+ SvdType svd(m, computationOptions);
+
+ VERIFY_IS_APPROX(svd.singularValues(), referenceSvd.singularValues());
+
+ if(computationOptions & (ComputeFullV|ComputeThinV))
+ {
+ VERIFY( (svd.matrixV().adjoint()*svd.matrixV()).isIdentity(prec) );
+ VERIFY_IS_APPROX( svd.matrixV().leftCols(diagSize) * svd.singularValues().asDiagonal() * svd.matrixV().leftCols(diagSize).adjoint(),
+ referenceSvd.matrixV().leftCols(diagSize) * referenceSvd.singularValues().asDiagonal() * referenceSvd.matrixV().leftCols(diagSize).adjoint());
+ }
+
+ if(computationOptions & (ComputeFullU|ComputeThinU))
+ {
+ VERIFY( (svd.matrixU().adjoint()*svd.matrixU()).isIdentity(prec) );
+ VERIFY_IS_APPROX( svd.matrixU().leftCols(diagSize) * svd.singularValues().cwiseAbs2().asDiagonal() * svd.matrixU().leftCols(diagSize).adjoint(),
+ referenceSvd.matrixU().leftCols(diagSize) * referenceSvd.singularValues().cwiseAbs2().asDiagonal() * referenceSvd.matrixU().leftCols(diagSize).adjoint());
+ }
+
+ // The following checks are not critical.
+ // For instance, with Dived&Conquer SVD, if only the factor 'V' is computedt then different matrix-matrix product implementation will be used
+ // and the resulting 'V' factor might be significantly different when the SVD decomposition is not unique, especially with single precision float.
+ ++g_test_level;
+ if(computationOptions & ComputeFullU) VERIFY_IS_APPROX(svd.matrixU(), referenceSvd.matrixU());
+ if(computationOptions & ComputeThinU) VERIFY_IS_APPROX(svd.matrixU(), referenceSvd.matrixU().leftCols(diagSize));
+ if(computationOptions & ComputeFullV) VERIFY_IS_APPROX(svd.matrixV().cwiseAbs(), referenceSvd.matrixV().cwiseAbs());
+ if(computationOptions & ComputeThinV) VERIFY_IS_APPROX(svd.matrixV(), referenceSvd.matrixV().leftCols(diagSize));
+ --g_test_level;
+}
+
+//
+template<typename SvdType, typename MatrixType>
+void svd_least_square(const MatrixType& m, unsigned int computationOptions)
+{
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef typename MatrixType::Index Index;
+ Index rows = m.rows();
+ Index cols = m.cols();
+
+ enum {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime
+ };
+
+ typedef Matrix<Scalar, RowsAtCompileTime, Dynamic> RhsType;
+ typedef Matrix<Scalar, ColsAtCompileTime, Dynamic> SolutionType;
+
+ RhsType rhs = RhsType::Random(rows, internal::random<Index>(1, cols));
+ SvdType svd(m, computationOptions);
+
+ if(internal::is_same<RealScalar,double>::value) svd.setThreshold(1e-8);
+ else if(internal::is_same<RealScalar,float>::value) svd.setThreshold(2e-4);
+
+ SolutionType x = svd.solve(rhs);
+
+ RealScalar residual = (m*x-rhs).norm();
+ RealScalar rhs_norm = rhs.norm();
+ if(!test_isMuchSmallerThan(residual,rhs.norm()))
+ {
+ // ^^^ If the residual is very small, then we have an exact solution, so we are already good.
+
+ // evaluate normal equation which works also for least-squares solutions
+ if(internal::is_same<RealScalar,double>::value || svd.rank()==m.diagonal().size())
+ {
+ using std::sqrt;
+ // This test is not stable with single precision.
+ // This is probably because squaring m signicantly affects the precision.
+ if(internal::is_same<RealScalar,float>::value) ++g_test_level;
+
+ VERIFY_IS_APPROX(m.adjoint()*(m*x),m.adjoint()*rhs);
+
+ if(internal::is_same<RealScalar,float>::value) --g_test_level;
+ }
+
+ // Check that there is no significantly better solution in the neighborhood of x
+ for(Index k=0;k<x.rows();++k)
+ {
+ using std::abs;
+
+ SolutionType y(x);
+ y.row(k) = (RealScalar(1)+2*NumTraits<RealScalar>::epsilon())*x.row(k);
+ RealScalar residual_y = (m*y-rhs).norm();
+ VERIFY( test_isMuchSmallerThan(abs(residual_y-residual), rhs_norm) || residual < residual_y );
+ if(internal::is_same<RealScalar,float>::value) ++g_test_level;
+ VERIFY( test_isApprox(residual_y,residual) || residual < residual_y );
+ if(internal::is_same<RealScalar,float>::value) --g_test_level;
+
+ y.row(k) = (RealScalar(1)-2*NumTraits<RealScalar>::epsilon())*x.row(k);
+ residual_y = (m*y-rhs).norm();
+ VERIFY( test_isMuchSmallerThan(abs(residual_y-residual), rhs_norm) || residual < residual_y );
+ if(internal::is_same<RealScalar,float>::value) ++g_test_level;
+ VERIFY( test_isApprox(residual_y,residual) || residual < residual_y );
+ if(internal::is_same<RealScalar,float>::value) --g_test_level;
+ }
+ }
+}
+
+// check minimal norm solutions, the inoput matrix m is only used to recover problem size
+template<typename MatrixType>
+void svd_min_norm(const MatrixType& m, unsigned int computationOptions)
+{
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::Index Index;
+ Index cols = m.cols();
+
+ enum {
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime
+ };
+
+ typedef Matrix<Scalar, ColsAtCompileTime, Dynamic> SolutionType;
+
+ // generate a full-rank m x n problem with m<n
+ enum {
+ RankAtCompileTime2 = ColsAtCompileTime==Dynamic ? Dynamic : (ColsAtCompileTime)/2+1,
+ RowsAtCompileTime3 = ColsAtCompileTime==Dynamic ? Dynamic : ColsAtCompileTime+1
+ };
+ typedef Matrix<Scalar, RankAtCompileTime2, ColsAtCompileTime> MatrixType2;
+ typedef Matrix<Scalar, RankAtCompileTime2, 1> RhsType2;
+ typedef Matrix<Scalar, ColsAtCompileTime, RankAtCompileTime2> MatrixType2T;
+ Index rank = RankAtCompileTime2==Dynamic ? internal::random<Index>(1,cols) : Index(RankAtCompileTime2);
+ MatrixType2 m2(rank,cols);
+ int guard = 0;
+ do {
+ m2.setRandom();
+ } while(SVD_FOR_MIN_NORM(MatrixType2)(m2).setThreshold(test_precision<Scalar>()).rank()!=rank && (++guard)<10);
+ VERIFY(guard<10);
+
+ RhsType2 rhs2 = RhsType2::Random(rank);
+ // use QR to find a reference minimal norm solution
+ HouseholderQR<MatrixType2T> qr(m2.adjoint());
+ Matrix<Scalar,Dynamic,1> tmp = qr.matrixQR().topLeftCorner(rank,rank).template triangularView<Upper>().adjoint().solve(rhs2);
+ tmp.conservativeResize(cols);
+ tmp.tail(cols-rank).setZero();
+ SolutionType x21 = qr.householderQ() * tmp;
+ // now check with SVD
+ SVD_FOR_MIN_NORM(MatrixType2) svd2(m2, computationOptions);
+ SolutionType x22 = svd2.solve(rhs2);
+ VERIFY_IS_APPROX(m2*x21, rhs2);
+ VERIFY_IS_APPROX(m2*x22, rhs2);
+ VERIFY_IS_APPROX(x21, x22);
+
+ // Now check with a rank deficient matrix
+ typedef Matrix<Scalar, RowsAtCompileTime3, ColsAtCompileTime> MatrixType3;
+ typedef Matrix<Scalar, RowsAtCompileTime3, 1> RhsType3;
+ Index rows3 = RowsAtCompileTime3==Dynamic ? internal::random<Index>(rank+1,2*cols) : Index(RowsAtCompileTime3);
+ Matrix<Scalar,RowsAtCompileTime3,Dynamic> C = Matrix<Scalar,RowsAtCompileTime3,Dynamic>::Random(rows3,rank);
+ MatrixType3 m3 = C * m2;
+ RhsType3 rhs3 = C * rhs2;
+ SVD_FOR_MIN_NORM(MatrixType3) svd3(m3, computationOptions);
+ SolutionType x3 = svd3.solve(rhs3);
+ VERIFY_IS_APPROX(m3*x3, rhs3);
+ VERIFY_IS_APPROX(m3*x21, rhs3);
+ VERIFY_IS_APPROX(m2*x3, rhs2);
+ VERIFY_IS_APPROX(x21, x3);
+}
+
+// Check full, compare_to_full, least_square, and min_norm for all possible compute-options
+template<typename SvdType, typename MatrixType>
+void svd_test_all_computation_options(const MatrixType& m, bool full_only)
+{
+// if (QRPreconditioner == NoQRPreconditioner && m.rows() != m.cols())
+// return;
+ SvdType fullSvd(m, ComputeFullU|ComputeFullV);
+ CALL_SUBTEST(( svd_check_full(m, fullSvd) ));
+ CALL_SUBTEST(( svd_least_square<SvdType>(m, ComputeFullU | ComputeFullV) ));
+ CALL_SUBTEST(( svd_min_norm(m, ComputeFullU | ComputeFullV) ));
+
+ #if defined __INTEL_COMPILER
+ // remark #111: statement is unreachable
+ #pragma warning disable 111
+ #endif
+ if(full_only)
+ return;
+
+ CALL_SUBTEST(( svd_compare_to_full(m, ComputeFullU, fullSvd) ));
+ CALL_SUBTEST(( svd_compare_to_full(m, ComputeFullV, fullSvd) ));
+ CALL_SUBTEST(( svd_compare_to_full(m, 0, fullSvd) ));
+
+ if (MatrixType::ColsAtCompileTime == Dynamic) {
+ // thin U/V are only available with dynamic number of columns
+ CALL_SUBTEST(( svd_compare_to_full(m, ComputeFullU|ComputeThinV, fullSvd) ));
+ CALL_SUBTEST(( svd_compare_to_full(m, ComputeThinV, fullSvd) ));
+ CALL_SUBTEST(( svd_compare_to_full(m, ComputeThinU|ComputeFullV, fullSvd) ));
+ CALL_SUBTEST(( svd_compare_to_full(m, ComputeThinU , fullSvd) ));
+ CALL_SUBTEST(( svd_compare_to_full(m, ComputeThinU|ComputeThinV, fullSvd) ));
+
+ CALL_SUBTEST(( svd_least_square<SvdType>(m, ComputeFullU | ComputeThinV) ));
+ CALL_SUBTEST(( svd_least_square<SvdType>(m, ComputeThinU | ComputeFullV) ));
+ CALL_SUBTEST(( svd_least_square<SvdType>(m, ComputeThinU | ComputeThinV) ));
+
+ CALL_SUBTEST(( svd_min_norm(m, ComputeFullU | ComputeThinV) ));
+ CALL_SUBTEST(( svd_min_norm(m, ComputeThinU | ComputeFullV) ));
+ CALL_SUBTEST(( svd_min_norm(m, ComputeThinU | ComputeThinV) ));
+
+ // test reconstruction
+ typedef typename MatrixType::Index Index;
+ Index diagSize = (std::min)(m.rows(), m.cols());
+ SvdType svd(m, ComputeThinU | ComputeThinV);
+ VERIFY_IS_APPROX(m, svd.matrixU().leftCols(diagSize) * svd.singularValues().asDiagonal() * svd.matrixV().leftCols(diagSize).adjoint());
+ }
+}
+
+
+// work around stupid msvc error when constructing at compile time an expression that involves
+// a division by zero, even if the numeric type has floating point
+template<typename Scalar>
+EIGEN_DONT_INLINE Scalar zero() { return Scalar(0); }
+
+// workaround aggressive optimization in ICC
+template<typename T> EIGEN_DONT_INLINE T sub(T a, T b) { return a - b; }
+
+// all this function does is verify we don't iterate infinitely on nan/inf values
+template<typename SvdType, typename MatrixType>
+void svd_inf_nan()
+{
+ SvdType svd;
+ typedef typename MatrixType::Scalar Scalar;
+ Scalar some_inf = Scalar(1) / zero<Scalar>();
+ VERIFY(sub(some_inf, some_inf) != sub(some_inf, some_inf));
+ svd.compute(MatrixType::Constant(10,10,some_inf), ComputeFullU | ComputeFullV);
+
+ Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
+ VERIFY(nan != nan);
+ svd.compute(MatrixType::Constant(10,10,nan), ComputeFullU | ComputeFullV);
+
+ MatrixType m = MatrixType::Zero(10,10);
+ m(internal::random<int>(0,9), internal::random<int>(0,9)) = some_inf;
+ svd.compute(m, ComputeFullU | ComputeFullV);
+
+ m = MatrixType::Zero(10,10);
+ m(internal::random<int>(0,9), internal::random<int>(0,9)) = nan;
+ svd.compute(m, ComputeFullU | ComputeFullV);
+
+ // regression test for bug 791
+ m.resize(3,3);
+ m << 0, 2*NumTraits<Scalar>::epsilon(), 0.5,
+ 0, -0.5, 0,
+ nan, 0, 0;
+ svd.compute(m, ComputeFullU | ComputeFullV);
+
+ m.resize(4,4);
+ m << 1, 0, 0, 0,
+ 0, 3, 1, 2e-308,
+ 1, 0, 1, nan,
+ 0, nan, nan, 0;
+ svd.compute(m, ComputeFullU | ComputeFullV);
+}
+
+// Regression test for bug 286: JacobiSVD loops indefinitely with some
+// matrices containing denormal numbers.
+template<typename>
+void svd_underoverflow()
+{
+#if defined __INTEL_COMPILER
+// shut up warning #239: floating point underflow
+#pragma warning push
+#pragma warning disable 239
+#endif
+ Matrix2d M;
+ M << -7.90884e-313, -4.94e-324,
+ 0, 5.60844e-313;
+ SVD_DEFAULT(Matrix2d) svd;
+ svd.compute(M,ComputeFullU|ComputeFullV);
+ CALL_SUBTEST( svd_check_full(M,svd) );
+
+ // Check all 2x2 matrices made with the following coefficients:
+ VectorXd value_set(9);
+ value_set << 0, 1, -1, 5.60844e-313, -5.60844e-313, 4.94e-324, -4.94e-324, -4.94e-223, 4.94e-223;
+ Array4i id(0,0,0,0);
+ int k = 0;
+ do
+ {
+ M << value_set(id(0)), value_set(id(1)), value_set(id(2)), value_set(id(3));
+ svd.compute(M,ComputeFullU|ComputeFullV);
+ CALL_SUBTEST( svd_check_full(M,svd) );
+
+ id(k)++;
+ if(id(k)>=value_set.size())
+ {
+ while(k<3 && id(k)>=value_set.size()) id(++k)++;
+ id.head(k).setZero();
+ k=0;
+ }
+
+ } while((id<int(value_set.size())).all());
+
+#if defined __INTEL_COMPILER
+#pragma warning pop
+#endif
+
+ // Check for overflow:
+ Matrix3d M3;
+ M3 << 4.4331978442502944e+307, -5.8585363752028680e+307, 6.4527017443412964e+307,
+ 3.7841695601406358e+307, 2.4331702789740617e+306, -3.5235707140272905e+307,
+ -8.7190887618028355e+307, -7.3453213709232193e+307, -2.4367363684472105e+307;
+
+ SVD_DEFAULT(Matrix3d) svd3;
+ svd3.compute(M3,ComputeFullU|ComputeFullV); // just check we don't loop indefinitely
+ CALL_SUBTEST( svd_check_full(M3,svd3) );
+}
+
+// void jacobisvd(const MatrixType& a = MatrixType(), bool pickrandom = true)
+
+template<typename MatrixType>
+void svd_all_trivial_2x2( void (*cb)(const MatrixType&,bool) )
+{
+ MatrixType M;
+ VectorXd value_set(3);
+ value_set << 0, 1, -1;
+ Array4i id(0,0,0,0);
+ int k = 0;
+ do
+ {
+ M << value_set(id(0)), value_set(id(1)), value_set(id(2)), value_set(id(3));
+
+ cb(M,false);
+
+ id(k)++;
+ if(id(k)>=value_set.size())
+ {
+ while(k<3 && id(k)>=value_set.size()) id(++k)++;
+ id.head(k).setZero();
+ k=0;
+ }
+
+ } while((id<int(value_set.size())).all());
+}
+
+template<typename>
+void svd_preallocate()
+{
+ Vector3f v(3.f, 2.f, 1.f);
+ MatrixXf m = v.asDiagonal();
+
+ internal::set_is_malloc_allowed(false);
+ VERIFY_RAISES_ASSERT(VectorXf tmp(10);)
+ SVD_DEFAULT(MatrixXf) svd;
+ internal::set_is_malloc_allowed(true);
+ svd.compute(m);
+ VERIFY_IS_APPROX(svd.singularValues(), v);
+
+ SVD_DEFAULT(MatrixXf) svd2(3,3);
+ internal::set_is_malloc_allowed(false);
+ svd2.compute(m);
+ internal::set_is_malloc_allowed(true);
+ VERIFY_IS_APPROX(svd2.singularValues(), v);
+ VERIFY_RAISES_ASSERT(svd2.matrixU());
+ VERIFY_RAISES_ASSERT(svd2.matrixV());
+ svd2.compute(m, ComputeFullU | ComputeFullV);
+ VERIFY_IS_APPROX(svd2.matrixU(), Matrix3f::Identity());
+ VERIFY_IS_APPROX(svd2.matrixV(), Matrix3f::Identity());
+ internal::set_is_malloc_allowed(false);
+ svd2.compute(m);
+ internal::set_is_malloc_allowed(true);
+
+ SVD_DEFAULT(MatrixXf) svd3(3,3,ComputeFullU|ComputeFullV);
+ internal::set_is_malloc_allowed(false);
+ svd2.compute(m);
+ internal::set_is_malloc_allowed(true);
+ VERIFY_IS_APPROX(svd2.singularValues(), v);
+ VERIFY_IS_APPROX(svd2.matrixU(), Matrix3f::Identity());
+ VERIFY_IS_APPROX(svd2.matrixV(), Matrix3f::Identity());
+ internal::set_is_malloc_allowed(false);
+ svd2.compute(m, ComputeFullU|ComputeFullV);
+ internal::set_is_malloc_allowed(true);
+}
+
+template<typename SvdType,typename MatrixType>
+void svd_verify_assert(const MatrixType& m)
+{
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::Index Index;
+ Index rows = m.rows();
+ Index cols = m.cols();
+
+ enum {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime
+ };
+
+ typedef Matrix<Scalar, RowsAtCompileTime, 1> RhsType;
+ RhsType rhs(rows);
+ SvdType svd;
+ VERIFY_RAISES_ASSERT(svd.matrixU())
+ VERIFY_RAISES_ASSERT(svd.singularValues())
+ VERIFY_RAISES_ASSERT(svd.matrixV())
+ VERIFY_RAISES_ASSERT(svd.solve(rhs))
+ MatrixType a = MatrixType::Zero(rows, cols);
+ a.setZero();
+ svd.compute(a, 0);
+ VERIFY_RAISES_ASSERT(svd.matrixU())
+ VERIFY_RAISES_ASSERT(svd.matrixV())
+ svd.singularValues();
+ VERIFY_RAISES_ASSERT(svd.solve(rhs))
+
+ if (ColsAtCompileTime == Dynamic)
+ {
+ svd.compute(a, ComputeThinU);
+ svd.matrixU();
+ VERIFY_RAISES_ASSERT(svd.matrixV())
+ VERIFY_RAISES_ASSERT(svd.solve(rhs))
+ svd.compute(a, ComputeThinV);
+ svd.matrixV();
+ VERIFY_RAISES_ASSERT(svd.matrixU())
+ VERIFY_RAISES_ASSERT(svd.solve(rhs))
+ }
+ else
+ {
+ VERIFY_RAISES_ASSERT(svd.compute(a, ComputeThinU))
+ VERIFY_RAISES_ASSERT(svd.compute(a, ComputeThinV))
+ }
+}
+
+#undef SVD_DEFAULT
+#undef SVD_FOR_MIN_NORM
diff --git a/test/svd_fill.h b/test/svd_fill.h
new file mode 100644
index 000000000..3877c0c7e
--- /dev/null
+++ b/test/svd_fill.h
@@ -0,0 +1,119 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2014-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/.
+
+template<typename T>
+Array<T,4,1> four_denorms();
+
+template<>
+Array4f four_denorms() { return Array4f(5.60844e-39f, -5.60844e-39f, 4.94e-44f, -4.94e-44f); }
+template<>
+Array4d four_denorms() { return Array4d(5.60844e-313, -5.60844e-313, 4.94e-324, -4.94e-324); }
+template<typename T>
+Array<T,4,1> four_denorms() { return four_denorms<double>().cast<T>(); }
+
+template<typename MatrixType>
+void svd_fill_random(MatrixType &m, int Option = 0)
+{
+ using std::pow;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef typename MatrixType::Index Index;
+ Index diagSize = (std::min)(m.rows(), m.cols());
+ RealScalar s = std::numeric_limits<RealScalar>::max_exponent10/4;
+ s = internal::random<RealScalar>(1,s);
+ Matrix<RealScalar,Dynamic,1> d = Matrix<RealScalar,Dynamic,1>::Random(diagSize);
+ for(Index k=0; k<diagSize; ++k)
+ d(k) = d(k)*pow(RealScalar(10),internal::random<RealScalar>(-s,s));
+
+ bool dup = internal::random<int>(0,10) < 3;
+ bool unit_uv = internal::random<int>(0,10) < (dup?7:3); // if we duplicate some diagonal entries, then increase the chance to preserve them using unitary U and V factors
+
+ // duplicate some singular values
+ if(dup)
+ {
+ Index n = internal::random<Index>(0,d.size()-1);
+ for(Index i=0; i<n; ++i)
+ d(internal::random<Index>(0,d.size()-1)) = d(internal::random<Index>(0,d.size()-1));
+ }
+
+ Matrix<Scalar,Dynamic,Dynamic> U(m.rows(),diagSize);
+ Matrix<Scalar,Dynamic,Dynamic> VT(diagSize,m.cols());
+ if(unit_uv)
+ {
+ // in very rare cases let's try with a pure diagonal matrix
+ if(internal::random<int>(0,10) < 1)
+ {
+ U.setIdentity();
+ VT.setIdentity();
+ }
+ else
+ {
+ createRandomPIMatrixOfRank(diagSize,U.rows(), U.cols(), U);
+ createRandomPIMatrixOfRank(diagSize,VT.rows(), VT.cols(), VT);
+ }
+ }
+ else
+ {
+ U.setRandom();
+ VT.setRandom();
+ }
+
+ Matrix<Scalar,Dynamic,1> samples(9);
+ samples << 0, four_denorms<RealScalar>(),
+ -RealScalar(1)/NumTraits<RealScalar>::highest(), RealScalar(1)/NumTraits<RealScalar>::highest(), (std::numeric_limits<RealScalar>::min)(), pow((std::numeric_limits<RealScalar>::min)(),0.8);
+
+ if(Option==Symmetric)
+ {
+ m = U * d.asDiagonal() * U.transpose();
+
+ // randomly nullify some rows/columns
+ {
+ Index count = internal::random<Index>(-diagSize,diagSize);
+ for(Index k=0; k<count; ++k)
+ {
+ Index i = internal::random<Index>(0,diagSize-1);
+ m.row(i).setZero();
+ m.col(i).setZero();
+ }
+ if(count<0)
+ // (partly) cancel some coeffs
+ if(!(dup && unit_uv))
+ {
+
+ Index n = internal::random<Index>(0,m.size()-1);
+ for(Index k=0; k<n; ++k)
+ {
+ Index i = internal::random<Index>(0,m.rows()-1);
+ Index j = internal::random<Index>(0,m.cols()-1);
+ m(j,i) = m(i,j) = samples(internal::random<Index>(0,samples.size()-1));
+ if(NumTraits<Scalar>::IsComplex)
+ *(&numext::real_ref(m(j,i))+1) = *(&numext::real_ref(m(i,j))+1) = samples.real()(internal::random<Index>(0,samples.size()-1));
+ }
+ }
+ }
+ }
+ else
+ {
+ m = U * d.asDiagonal() * VT;
+ // (partly) cancel some coeffs
+ if(!(dup && unit_uv))
+ {
+ Index n = internal::random<Index>(0,m.size()-1);
+ for(Index k=0; k<n; ++k)
+ {
+ Index i = internal::random<Index>(0,m.rows()-1);
+ Index j = internal::random<Index>(0,m.cols()-1);
+ m(i,j) = samples(internal::random<Index>(0,samples.size()-1));
+ if(NumTraits<Scalar>::IsComplex)
+ *(&numext::real_ref(m(i,j))+1) = samples.real()(internal::random<Index>(0,samples.size()-1));
+ }
+ }
+ }
+}
+
diff --git a/test/swap.cpp b/test/swap.cpp
index 36b353148..f76e3624d 100644
--- a/test/swap.cpp
+++ b/test/swap.cpp
@@ -41,9 +41,15 @@ template<typename MatrixType> void swap(const MatrixType& m)
OtherMatrixType m3_copy = m3;
// test swapping 2 matrices of same type
+ Scalar *d1=m1.data(), *d2=m2.data();
m1.swap(m2);
VERIFY_IS_APPROX(m1,m2_copy);
VERIFY_IS_APPROX(m2,m1_copy);
+ if(MatrixType::SizeAtCompileTime==Dynamic)
+ {
+ VERIFY(m1.data()==d2);
+ VERIFY(m2.data()==d1);
+ }
m1 = m1_copy;
m2 = m2_copy;
@@ -68,16 +74,21 @@ template<typename MatrixType> void swap(const MatrixType& m)
m1 = m1_copy;
m3 = m3_copy;
- // test assertion on mismatching size -- matrix case
- VERIFY_RAISES_ASSERT(m1.swap(m1.row(0)));
- // test assertion on mismatching size -- xpr case
- VERIFY_RAISES_ASSERT(m1.row(0).swap(m1));
+ if(m1.rows()>1)
+ {
+ // test assertion on mismatching size -- matrix case
+ VERIFY_RAISES_ASSERT(m1.swap(m1.row(0)));
+ // test assertion on mismatching size -- xpr case
+ VERIFY_RAISES_ASSERT(m1.row(0).swap(m1));
+ }
}
void test_swap()
{
+ int s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
CALL_SUBTEST_1( swap(Matrix3f()) ); // fixed size, no vectorization
CALL_SUBTEST_2( swap(Matrix4d()) ); // fixed size, possible vectorization
- CALL_SUBTEST_3( swap(MatrixXd(3,3)) ); // dyn size, no vectorization
- CALL_SUBTEST_4( swap(MatrixXf(30,30)) ); // dyn size, possible vectorization
+ CALL_SUBTEST_3( swap(MatrixXd(s,s)) ); // dyn size, no vectorization
+ CALL_SUBTEST_4( swap(MatrixXf(s,s)) ); // dyn size, possible vectorization
+ TEST_SET_BUT_UNUSED_VARIABLE(s)
}
diff --git a/test/testsuite.cmake b/test/testsuite.cmake
deleted file mode 100644
index 3bec56b3f..000000000
--- a/test/testsuite.cmake
+++ /dev/null
@@ -1,229 +0,0 @@
-
-####################################################################
-#
-# Usage:
-# - create a new folder, let's call it cdash
-# - in that folder, do:
-# ctest -S path/to/eigen/test/testsuite.cmake[,option1=value1[,option2=value2]]
-#
-# Options:
-# - EIGEN_CXX: compiler, eg.: g++-4.2
-# default: default c++ compiler
-# - EIGEN_SITE: eg, INRIA-Bdx_pc-gael, or the name of the contributor, etc.
-# default: hostname
-# - EIGEN_BUILD_STRING: a string which identify the system/compiler. It should be formed like that:
-# <OS_name>-<OS_version>-<arch>-<compiler-version>
-# with:
-# <OS_name> = opensuse, debian, osx, windows, cygwin, freebsd, solaris, etc.
-# <OS_version> = 11.1, XP, vista, leopard, etc.
-# <arch> = i386, x86_64, ia64, powerpc, etc.
-# <compiler-version> = gcc-4.3.2, icc-11.0, MSVC-2008, etc.
-# - EIGEN_EXPLICIT_VECTORIZATION: novec, SSE2, Altivec
-# default: SSE2 for x86_64 systems, novec otherwise
-# Its value is automatically appended to EIGEN_BUILD_STRING
-# - EIGEN_CMAKE_DIR: path to cmake executable
-# - EIGEN_MODE: dashboard model, can be Experimental, Nightly, or Continuous
-# default: Nightly
-# - EIGEN_WORK_DIR: directory used to download the source files and make the builds
-# default: folder which contains this script
-# - EIGEN_CMAKE_ARGS: additional arguments passed to cmake
-# - EIGEN_GENERATOR_TYPE: allows to overwrite the generator type
-# default: nmake (windows
-# See http://www.cmake.org/cmake/help/cmake2.6docs.html#section_Generators for a complete
-# list of supported generators.
-# - EIGEN_NO_UPDATE: allows to submit dash boards from local repositories
-# This might be interesting in case you want to submit dashboards
-# including local changes.
-# - CTEST_SOURCE_DIRECTORY: path to eigen's src (use a new and empty folder, not the one you are working on)
-# default: <EIGEN_WORK_DIR>/src
-# - CTEST_BINARY_DIRECTORY: build directory
-# default: <EIGEN_WORK_DIR>/nightly-<EIGEN_CXX>
-#
-# Here is an example running several compilers on a linux system:
-# #!/bin/bash
-# ARCH=`uname -m`
-# SITE=`hostname`
-# VERSION=opensuse-11.1
-# WORK_DIR=/home/gael/Coding/eigen/cdash
-# # get the last version of the script
-# 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
-# $COMMON-gcc-4.3.2,EIGEN_CXX=g++-4.3,EIGEN_EXPLICIT_VECTORIZATION=novec
-# $COMMON-gcc-4.3.2,EIGEN_CXX=g++-4.3,EIGEN_EXPLICIT_VECTORIZATION=SSE2
-# $COMMON-icc-11.0,EIGEN_CXX=icpc
-#
-####################################################################
-
-# process the arguments
-
-set(ARGLIST ${CTEST_SCRIPT_ARG})
-while(${ARGLIST} MATCHES ".+.*")
-
- # pick first
- string(REGEX MATCH "([^,]*)(,.*)?" DUMMY ${ARGLIST})
- SET(TOP ${CMAKE_MATCH_1})
-
- # remove first
- string(REGEX MATCHALL "[^,]*,(.*)" DUMMY ${ARGLIST})
- SET(ARGLIST ${CMAKE_MATCH_1})
-
- # decompose as a pair key=value
- string(REGEX MATCH "([^=]*)(=.*)?" DUMMY ${TOP})
- SET(KEY ${CMAKE_MATCH_1})
-
- string(REGEX MATCH "[^=]*=(.*)" DUMMY ${TOP})
- SET(VALUE ${CMAKE_MATCH_1})
-
- # set the variable to the specified value
- if(VALUE)
- SET(${KEY} ${VALUE})
- else(VALUE)
- SET(${KEY} ON)
- endif(VALUE)
-
-endwhile(${ARGLIST} MATCHES ".+.*")
-
-####################################################################
-# Automatically set some user variables if they have not been defined manually
-####################################################################
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
-
-if(NOT EIGEN_SITE)
- site_name(EIGEN_SITE)
-endif(NOT EIGEN_SITE)
-
-if(NOT EIGEN_CMAKE_DIR)
- SET(EIGEN_CMAKE_DIR "")
-endif(NOT EIGEN_CMAKE_DIR)
-
-if(NOT EIGEN_BUILD_STRING)
-
- # let's try to find all information we need to make the build string ourself
-
- # OS
- build_name(EIGEN_OS_VERSION)
-
- # arch
- set(EIGEN_ARCH ${CMAKE_SYSTEM_PROCESSOR})
- if(WIN32)
- set(EIGEN_ARCH $ENV{PROCESSOR_ARCHITECTURE})
- else(WIN32)
- execute_process(COMMAND uname -m OUTPUT_VARIABLE EIGEN_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
- endif(WIN32)
-
- set(EIGEN_BUILD_STRING ${EIGEN_OS_VERSION}${EIGEN_ARCH}-${EIGEN_CXX})
-
-endif(NOT EIGEN_BUILD_STRING)
-
-if(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
- set(EIGEN_BUILD_STRING ${EIGEN_BUILD_STRING}-${EIGEN_EXPLICIT_VECTORIZATION})
-endif(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
-
-if(NOT EIGEN_WORK_DIR)
- set(EIGEN_WORK_DIR ${CTEST_SCRIPT_DIRECTORY})
-endif(NOT EIGEN_WORK_DIR)
-
-if(NOT CTEST_SOURCE_DIRECTORY)
- SET (CTEST_SOURCE_DIRECTORY "${EIGEN_WORK_DIR}/src")
-endif(NOT CTEST_SOURCE_DIRECTORY)
-
-if(NOT CTEST_BINARY_DIRECTORY)
- SET (CTEST_BINARY_DIRECTORY "${EIGEN_WORK_DIR}/nightly_${EIGEN_CXX}")
-endif(NOT CTEST_BINARY_DIRECTORY)
-
-if(NOT EIGEN_MODE)
- set(EIGEN_MODE Nightly)
-endif(NOT EIGEN_MODE)
-
-## mandatory variables (the default should be ok in most cases):
-
-if(NOT EIGEN_NO_UPDATE)
- SET (CTEST_CVS_COMMAND "hg")
- 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)
-
-# which ctest command to use for running the dashboard
-SET (CTEST_COMMAND "${EIGEN_CMAKE_DIR}ctest -D ${EIGEN_MODE} --no-compress-output")
-if($ENV{EIGEN_CTEST_ARGS})
-SET (CTEST_COMMAND "${CTEST_COMMAND} $ENV{EIGEN_CTEST_ARGS}")
-endif($ENV{EIGEN_CTEST_ARGS})
-# what cmake command to use for configuring this dashboard
-SET (CTEST_CMAKE_COMMAND "${EIGEN_CMAKE_DIR}cmake -DEIGEN_LEAVE_TEST_IN_ALL_TARGET=ON")
-
-####################################################################
-# The values in this section are optional you can either
-# have them or leave them commented out
-####################################################################
-
-# this make sure we get consistent outputs
-SET($ENV{LC_MESSAGES} "en_EN")
-
-# should ctest wipe the binary tree before running
-SET(CTEST_START_WITH_EMPTY_BINARY_DIRECTORY TRUE)
-
-# raise the warning/error limit
-set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS "33331")
-set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS "33331")
-
-# this is the initial cache to use for the binary tree, be careful to escape
-# any quotes inside of this string if you use it
-if(WIN32 AND NOT UNIX)
- #message(SEND_ERROR "win32")
- if(EIGEN_GENERATOR_TYPE)
- set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -G \"${EIGEN_GENERATOR_TYPE}\"")
- SET (CTEST_INITIAL_CACHE "
- CMAKE_BUILD_TYPE:STRING=Release
- BUILDNAME:STRING=${EIGEN_BUILD_STRING}
- SITE:STRING=${EIGEN_SITE}
- ")
- else(EIGEN_GENERATOR_TYPE)
- set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -G \"NMake Makefiles\" -DCMAKE_MAKE_PROGRAM=nmake")
- SET (CTEST_INITIAL_CACHE "
- MAKECOMMAND:STRING=nmake /i
- CMAKE_MAKE_PROGRAM:FILEPATH=nmake
- CMAKE_GENERATOR:INTERNAL=NMake Makefiles
- CMAKE_BUILD_TYPE:STRING=Release
- BUILDNAME:STRING=${EIGEN_BUILD_STRING}
- SITE:STRING=${EIGEN_SITE}
- ")
- endif(EIGEN_GENERATOR_TYPE)
-else(WIN32 AND NOT UNIX)
- SET (CTEST_INITIAL_CACHE "
- BUILDNAME:STRING=${EIGEN_BUILD_STRING}
- SITE:STRING=${EIGEN_SITE}
- ")
-endif(WIN32 AND NOT UNIX)
-
-# set any extra environment variables to use during the execution of the script here:
-# setting this variable on windows machines causes trouble ...
-
-if(EIGEN_CXX AND NOT WIN32)
- set(CTEST_ENVIRONMENT "CXX=${EIGEN_CXX}")
-endif(EIGEN_CXX AND NOT WIN32)
-
-if(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
- if(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE2)
- set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_SSE2=ON")
- elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE3)
- set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_SSE2=ON -DEIGEN_TEST_SSE3=ON")
- elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSSE3)
- set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_SSE2=ON -DEIGEN_TEST_SSE3=ON -DEIGEN_TEST_SSSE3=ON")
- elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE4_1)
- set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_SSE2=ON -DEIGEN_TEST_SSE3=ON -DEIGEN_TEST_SSSE3=ON -DEIGEN_TEST_SSE4_1=ON")
- elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE4_2)
- set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_SSE2=ON -DEIGEN_TEST_SSE3=ON -DEIGEN_TEST_SSSE3=ON -DEIGEN_TEST_SSE4_1=ON -DEIGEN_TEST_SSE4_2=ON")
- elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES Altivec)
- set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_ALTIVEC=ON")
- elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES novec)
- set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_NO_EXPLICIT_VECTORIZATION=ON")
- else(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE2)
- message(FATAL_ERROR "Invalid value for EIGEN_EXPLICIT_VECTORIZATION (${EIGEN_EXPLICIT_VECTORIZATION}), must be: novec, SSE2, SSE3, Altivec")
- endif(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE2)
-endif(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
-
-if(DEFINED EIGEN_CMAKE_ARGS)
- set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} ${EIGEN_CMAKE_ARGS}")
-endif(DEFINED EIGEN_CMAKE_ARGS)
diff --git a/test/triangular.cpp b/test/triangular.cpp
index 54320390b..b96856486 100644
--- a/test/triangular.cpp
+++ b/test/triangular.cpp
@@ -65,7 +65,7 @@ template<typename MatrixType> void triangular_square(const MatrixType& m)
m1 = MatrixType::Random(rows, cols);
for (int i=0; i<rows; ++i)
- while (numext::abs2(m1(i,i))<1e-1) m1(i,i) = internal::random<Scalar>();
+ while (numext::abs2(m1(i,i))<RealScalar(1e-1)) m1(i,i) = internal::random<Scalar>();
Transpose<MatrixType> trm4(m4);
// test back and forward subsitution with a vector as the rhs
@@ -78,7 +78,7 @@ template<typename MatrixType> void triangular_square(const MatrixType& m)
m3 = m1.template triangularView<Lower>();
VERIFY(v2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<Lower>().solve(v2)), largerEps));
- // test back and forward subsitution with a matrix as the rhs
+ // test back and forward substitution with a matrix as the rhs
m3 = m1.template triangularView<Upper>();
VERIFY(m2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<Lower>().solve(m2)), largerEps));
m3 = m1.template triangularView<Lower>();
@@ -113,6 +113,21 @@ template<typename MatrixType> void triangular_square(const MatrixType& m)
m3.setZero();
m3.template triangularView<Upper>().setOnes();
VERIFY_IS_APPROX(m2,m3);
+
+ m1.setRandom();
+ m3 = m1.template triangularView<Upper>();
+ Matrix<Scalar, MatrixType::ColsAtCompileTime, Dynamic> m5(cols, internal::random<int>(1,20)); m5.setRandom();
+ Matrix<Scalar, Dynamic, MatrixType::RowsAtCompileTime> m6(internal::random<int>(1,20), rows); m6.setRandom();
+ VERIFY_IS_APPROX(m1.template triangularView<Upper>() * m5, m3*m5);
+ VERIFY_IS_APPROX(m6*m1.template triangularView<Upper>(), m6*m3);
+
+ m1up = m1.template triangularView<Upper>();
+ VERIFY_IS_APPROX(m1.template selfadjointView<Upper>().template triangularView<Upper>().toDenseMatrix(), m1up);
+ VERIFY_IS_APPROX(m1up.template selfadjointView<Upper>().template triangularView<Upper>().toDenseMatrix(), m1up);
+ VERIFY_IS_APPROX(m1.template selfadjointView<Upper>().template triangularView<Lower>().toDenseMatrix(), m1up.adjoint());
+ VERIFY_IS_APPROX(m1up.template selfadjointView<Upper>().template triangularView<Lower>().toDenseMatrix(), m1up.adjoint());
+
+ VERIFY_IS_APPROX(m1.template selfadjointView<Upper>().diagonal(), m1.diagonal());
}
diff --git a/test/umfpack_support.cpp b/test/umfpack_support.cpp
index 9eb84c14b..37ab11f0b 100644
--- a/test/umfpack_support.cpp
+++ b/test/umfpack_support.cpp
@@ -7,6 +7,7 @@
// 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/.
+#define EIGEN_NO_DEBUG_SMALL_PRODUCT_BLOCKS
#include "sparse_solver.h"
#include <Eigen/UmfPackSupport>
diff --git a/test/unalignedassert.cpp b/test/unalignedassert.cpp
index 601dbf214..731a08977 100644
--- a/test/unalignedassert.cpp
+++ b/test/unalignedassert.cpp
@@ -2,13 +2,39 @@
// for linear algebra.
//
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// 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/.
+#if defined(EIGEN_TEST_PART_1)
+ // default
+#elif defined(EIGEN_TEST_PART_2)
+ #define EIGEN_MAX_STATIC_ALIGN_BYTES 16
+ #define EIGEN_MAX_ALIGN_BYTES 16
+#elif defined(EIGEN_TEST_PART_3)
+ #define EIGEN_MAX_STATIC_ALIGN_BYTES 32
+ #define EIGEN_MAX_ALIGN_BYTES 32
+#elif defined(EIGEN_TEST_PART_4)
+ #define EIGEN_MAX_STATIC_ALIGN_BYTES 64
+ #define EIGEN_MAX_ALIGN_BYTES 64
+#endif
+
#include "main.h"
+typedef Matrix<float, 6,1> Vector6f;
+typedef Matrix<float, 8,1> Vector8f;
+typedef Matrix<float, 12,1> Vector12f;
+
+typedef Matrix<double, 5,1> Vector5d;
+typedef Matrix<double, 6,1> Vector6d;
+typedef Matrix<double, 7,1> Vector7d;
+typedef Matrix<double, 8,1> Vector8d;
+typedef Matrix<double, 9,1> Vector9d;
+typedef Matrix<double,10,1> Vector10d;
+typedef Matrix<double,12,1> Vector12d;
+
struct TestNew1
{
MatrixXd m; // good: m will allocate its own array, taking care of alignment.
@@ -36,7 +62,7 @@ struct TestNew4
struct TestNew5
{
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
- float f; // try the f at first -- the EIGEN_ALIGN16 attribute of m should make that still work
+ float f; // try the f at first -- the EIGEN_ALIGN_MAX attribute of m should make that still work
Matrix4f m;
};
@@ -63,13 +89,13 @@ void check_unalignedassert_good()
delete[] y;
}
-#if EIGEN_ALIGN_STATICALLY
+#if EIGEN_MAX_STATIC_ALIGN_BYTES>0
template<typename T>
void construct_at_boundary(int boundary)
{
char buf[sizeof(T)+256];
- size_t _buf = reinterpret_cast<size_t>(buf);
- _buf += (16 - (_buf % 16)); // make 16-byte aligned
+ size_t _buf = reinterpret_cast<internal::UIntPtr>(buf);
+ _buf += (EIGEN_MAX_ALIGN_BYTES - (_buf % EIGEN_MAX_ALIGN_BYTES)); // make 16/32/...-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
@@ -79,26 +105,36 @@ void construct_at_boundary(int boundary)
void unalignedassert()
{
- #if EIGEN_ALIGN_STATICALLY
+#if EIGEN_MAX_STATIC_ALIGN_BYTES>0
construct_at_boundary<Vector2f>(4);
construct_at_boundary<Vector3f>(4);
construct_at_boundary<Vector4f>(16);
+ construct_at_boundary<Vector6f>(4);
+ construct_at_boundary<Vector8f>(EIGEN_MAX_ALIGN_BYTES);
+ construct_at_boundary<Vector12f>(16);
construct_at_boundary<Matrix2f>(16);
construct_at_boundary<Matrix3f>(4);
- construct_at_boundary<Matrix4f>(16);
+ construct_at_boundary<Matrix4f>(EIGEN_MAX_ALIGN_BYTES);
construct_at_boundary<Vector2d>(16);
construct_at_boundary<Vector3d>(4);
- construct_at_boundary<Vector4d>(16);
- construct_at_boundary<Matrix2d>(16);
+ construct_at_boundary<Vector4d>(EIGEN_MAX_ALIGN_BYTES);
+ construct_at_boundary<Vector5d>(4);
+ construct_at_boundary<Vector6d>(16);
+ construct_at_boundary<Vector7d>(4);
+ construct_at_boundary<Vector8d>(EIGEN_MAX_ALIGN_BYTES);
+ construct_at_boundary<Vector9d>(4);
+ construct_at_boundary<Vector10d>(16);
+ construct_at_boundary<Vector12d>(EIGEN_MAX_ALIGN_BYTES);
+ construct_at_boundary<Matrix2d>(EIGEN_MAX_ALIGN_BYTES);
construct_at_boundary<Matrix3d>(4);
- construct_at_boundary<Matrix4d>(16);
+ construct_at_boundary<Matrix4d>(EIGEN_MAX_ALIGN_BYTES);
construct_at_boundary<Vector2cf>(16);
construct_at_boundary<Vector3cf>(4);
- construct_at_boundary<Vector2cd>(16);
+ construct_at_boundary<Vector2cd>(EIGEN_MAX_ALIGN_BYTES);
construct_at_boundary<Vector3cd>(16);
- #endif
+#endif
check_unalignedassert_good<TestNew1>();
check_unalignedassert_good<TestNew2>();
@@ -109,15 +145,32 @@ void unalignedassert()
check_unalignedassert_good<TestNew6>();
check_unalignedassert_good<Depends<true> >();
-#if EIGEN_ALIGN_STATICALLY
- VERIFY_RAISES_ASSERT(construct_at_boundary<Vector4f>(8));
- VERIFY_RAISES_ASSERT(construct_at_boundary<Matrix4f>(8));
- VERIFY_RAISES_ASSERT(construct_at_boundary<Vector2d>(8));
- VERIFY_RAISES_ASSERT(construct_at_boundary<Vector4d>(8));
- VERIFY_RAISES_ASSERT(construct_at_boundary<Matrix2d>(8));
- VERIFY_RAISES_ASSERT(construct_at_boundary<Matrix4d>(8));
- VERIFY_RAISES_ASSERT(construct_at_boundary<Vector2cf>(8));
- VERIFY_RAISES_ASSERT(construct_at_boundary<Vector2cd>(8));
+#if EIGEN_MAX_STATIC_ALIGN_BYTES>0
+ if(EIGEN_MAX_ALIGN_BYTES>=16)
+ {
+ VERIFY_RAISES_ASSERT(construct_at_boundary<Vector4f>(8));
+ VERIFY_RAISES_ASSERT(construct_at_boundary<Vector8f>(8));
+ VERIFY_RAISES_ASSERT(construct_at_boundary<Vector12f>(8));
+ VERIFY_RAISES_ASSERT(construct_at_boundary<Vector2d>(8));
+ VERIFY_RAISES_ASSERT(construct_at_boundary<Vector4d>(8));
+ VERIFY_RAISES_ASSERT(construct_at_boundary<Vector6d>(8));
+ VERIFY_RAISES_ASSERT(construct_at_boundary<Vector8d>(8));
+ VERIFY_RAISES_ASSERT(construct_at_boundary<Vector10d>(8));
+ VERIFY_RAISES_ASSERT(construct_at_boundary<Vector12d>(8));
+ // Complexes are disabled because the compiler might aggressively vectorize
+ // the initialization of complex coeffs to 0 before we can check for alignedness
+ //VERIFY_RAISES_ASSERT(construct_at_boundary<Vector2cf>(8));
+ VERIFY_RAISES_ASSERT(construct_at_boundary<Vector4i>(8));
+ }
+ for(int b=8; b<EIGEN_MAX_ALIGN_BYTES; b+=8)
+ {
+ if(b<32) VERIFY_RAISES_ASSERT(construct_at_boundary<Vector8f>(b));
+ if(b<64) VERIFY_RAISES_ASSERT(construct_at_boundary<Matrix4f>(b));
+ if(b<32) VERIFY_RAISES_ASSERT(construct_at_boundary<Vector4d>(b));
+ if(b<32) VERIFY_RAISES_ASSERT(construct_at_boundary<Matrix2d>(b));
+ if(b<128) VERIFY_RAISES_ASSERT(construct_at_boundary<Matrix4d>(b));
+ //if(b<32) VERIFY_RAISES_ASSERT(construct_at_boundary<Vector2cd>(b));
+ }
#endif
}
diff --git a/test/unalignedcount.cpp b/test/unalignedcount.cpp
index ca7e159f3..d6ffeafdf 100644
--- a/test/unalignedcount.cpp
+++ b/test/unalignedcount.cpp
@@ -30,7 +30,14 @@ static int nb_storeu;
void test_unalignedcount()
{
- #ifdef EIGEN_VECTORIZE_SSE
+ #if defined(EIGEN_VECTORIZE_AVX)
+ VectorXf a(40), b(40);
+ VERIFY_ALIGNED_UNALIGNED_COUNT(a += b, 10, 0, 5, 0);
+ VERIFY_ALIGNED_UNALIGNED_COUNT(a.segment(0,40) += b.segment(0,40), 5, 5, 5, 0);
+ VERIFY_ALIGNED_UNALIGNED_COUNT(a.segment(0,40) -= b.segment(0,40), 5, 5, 5, 0);
+ VERIFY_ALIGNED_UNALIGNED_COUNT(a.segment(0,40) *= 3.5, 5, 0, 5, 0);
+ VERIFY_ALIGNED_UNALIGNED_COUNT(a.segment(0,40) /= 3.5, 5, 0, 5, 0);
+ #elif defined(EIGEN_VECTORIZE_SSE)
VectorXf a(40), b(40);
VERIFY_ALIGNED_UNALIGNED_COUNT(a += b, 20, 0, 10, 0);
VERIFY_ALIGNED_UNALIGNED_COUNT(a.segment(0,40) += b.segment(0,40), 10, 10, 10, 0);
diff --git a/test/upperbidiagonalization.cpp b/test/upperbidiagonalization.cpp
index d15bf588b..847b34b55 100644
--- a/test/upperbidiagonalization.cpp
+++ b/test/upperbidiagonalization.cpp
@@ -35,7 +35,7 @@ void test_upperbidiagonalization()
CALL_SUBTEST_1( upperbidiag(MatrixXf(3,3)) );
CALL_SUBTEST_2( upperbidiag(MatrixXd(17,12)) );
CALL_SUBTEST_3( upperbidiag(MatrixXcf(20,20)) );
- CALL_SUBTEST_4( upperbidiag(MatrixXcd(16,15)) );
+ CALL_SUBTEST_4( upperbidiag(Matrix<std::complex<double>,Dynamic,Dynamic,RowMajor>(16,15)) );
CALL_SUBTEST_5( upperbidiag(Matrix<float,6,4>()) );
CALL_SUBTEST_6( upperbidiag(Matrix<float,5,5>()) );
CALL_SUBTEST_7( upperbidiag(Matrix<double,4,3>()) );
diff --git a/test/vectorization_logic.cpp b/test/vectorization_logic.cpp
index aee68a87f..83c1439ad 100644
--- a/test/vectorization_logic.cpp
+++ b/test/vectorization_logic.cpp
@@ -1,45 +1,51 @@
// 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_TEST_PART_1
+#define EIGEN_UNALIGNED_VECTORIZE 1
+#endif
+
+#ifdef EIGEN_TEST_PART_2
+#define EIGEN_UNALIGNED_VECTORIZE 0
+#endif
+
+#ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
+#undef EIGEN_DEFAULT_TO_ROW_MAJOR
+#endif
#define EIGEN_DEBUG_ASSIGN
#include "main.h"
#include <typeinfo>
-std::string demangle_traversal(int t)
-{
- if(t==DefaultTraversal) return "DefaultTraversal";
- if(t==LinearTraversal) return "LinearTraversal";
- if(t==InnerVectorizedTraversal) return "InnerVectorizedTraversal";
- if(t==LinearVectorizedTraversal) return "LinearVectorizedTraversal";
- if(t==SliceVectorizedTraversal) return "SliceVectorizedTraversal";
- return "?";
-}
-std::string demangle_unrolling(int t)
-{
- if(t==NoUnrolling) return "NoUnrolling";
- if(t==InnerUnrolling) return "InnerUnrolling";
- if(t==CompleteUnrolling) return "CompleteUnrolling";
- return "?";
-}
+using internal::demangle_flags;
+using internal::demangle_traversal;
+using internal::demangle_unrolling;
template<typename Dst, typename Src>
bool test_assign(const Dst&, const Src&, int traversal, int unrolling)
{
- internal::assign_traits<Dst,Src>::debug();
- bool res = internal::assign_traits<Dst,Src>::Traversal==traversal
- && internal::assign_traits<Dst,Src>::Unrolling==unrolling;
+ typedef internal::copy_using_evaluator_traits<internal::evaluator<Dst>,internal::evaluator<Src>, internal::assign_op<typename Dst::Scalar,typename Src::Scalar> > traits;
+ bool res = traits::Traversal==traversal;
+ if(unrolling==InnerUnrolling+CompleteUnrolling)
+ res = res && (int(traits::Unrolling)==InnerUnrolling || int(traits::Unrolling)==CompleteUnrolling);
+ else
+ res = res && int(traits::Unrolling)==unrolling;
if(!res)
{
+ std::cerr << "Src: " << demangle_flags(Src::Flags) << std::endl;
+ std::cerr << " " << demangle_flags(internal::evaluator<Src>::Flags) << std::endl;
+ std::cerr << "Dst: " << demangle_flags(Dst::Flags) << std::endl;
+ std::cerr << " " << demangle_flags(internal::evaluator<Dst>::Flags) << std::endl;
+ traits::debug();
std::cerr << " Expected Traversal == " << demangle_traversal(traversal)
- << " got " << demangle_traversal(internal::assign_traits<Dst,Src>::Traversal) << "\n";
+ << " got " << demangle_traversal(traits::Traversal) << "\n";
std::cerr << " Expected Unrolling == " << demangle_unrolling(unrolling)
- << " got " << demangle_unrolling(internal::assign_traits<Dst,Src>::Unrolling) << "\n";
+ << " got " << demangle_unrolling(traits::Unrolling) << "\n";
}
return res;
}
@@ -47,15 +53,19 @@ bool test_assign(const Dst&, const Src&, int traversal, int unrolling)
template<typename Dst, typename Src>
bool test_assign(int traversal, int unrolling)
{
- internal::assign_traits<Dst,Src>::debug();
- bool res = internal::assign_traits<Dst,Src>::Traversal==traversal
- && internal::assign_traits<Dst,Src>::Unrolling==unrolling;
+ typedef internal::copy_using_evaluator_traits<internal::evaluator<Dst>,internal::evaluator<Src>, internal::assign_op<typename Dst::Scalar,typename Src::Scalar> > traits;
+ bool res = traits::Traversal==traversal && traits::Unrolling==unrolling;
if(!res)
{
+ std::cerr << "Src: " << demangle_flags(Src::Flags) << std::endl;
+ std::cerr << " " << demangle_flags(internal::evaluator<Src>::Flags) << std::endl;
+ std::cerr << "Dst: " << demangle_flags(Dst::Flags) << std::endl;
+ std::cerr << " " << demangle_flags(internal::evaluator<Dst>::Flags) << std::endl;
+ traits::debug();
std::cerr << " Expected Traversal == " << demangle_traversal(traversal)
- << " got " << demangle_traversal(internal::assign_traits<Dst,Src>::Traversal) << "\n";
+ << " got " << demangle_traversal(traits::Traversal) << "\n";
std::cerr << " Expected Unrolling == " << demangle_unrolling(unrolling)
- << " got " << demangle_unrolling(internal::assign_traits<Dst,Src>::Unrolling) << "\n";
+ << " got " << demangle_unrolling(traits::Unrolling) << "\n";
}
return res;
}
@@ -63,10 +73,16 @@ bool test_assign(int traversal, int unrolling)
template<typename Xpr>
bool test_redux(const Xpr&, int traversal, int unrolling)
{
- typedef internal::redux_traits<internal::scalar_sum_op<typename Xpr::Scalar>,Xpr> traits;
+ typedef typename Xpr::Scalar Scalar;
+ typedef internal::redux_traits<internal::scalar_sum_op<Scalar,Scalar>,internal::redux_evaluator<Xpr> > traits;
+
bool res = traits::Traversal==traversal && traits::Unrolling==unrolling;
if(!res)
{
+ std::cerr << demangle_flags(Xpr::Flags) << std::endl;
+ std::cerr << demangle_flags(internal::evaluator<Xpr>::Flags) << std::endl;
+ traits::debug();
+
std::cerr << " Expected Traversal == " << demangle_traversal(traversal)
<< " got " << demangle_traversal(traits::Traversal) << "\n";
std::cerr << " Expected Unrolling == " << demangle_unrolling(unrolling)
@@ -75,10 +91,16 @@ bool test_redux(const Xpr&, int traversal, int unrolling)
return res;
}
-template<typename Scalar, bool Enable = internal::packet_traits<Scalar>::Vectorizable> struct vectorization_logic
+template<typename Scalar, bool Enable = internal::packet_traits<Scalar>::Vectorizable>
+struct vectorization_logic
{
+ typedef internal::packet_traits<Scalar> PacketTraits;
+
+ typedef typename internal::packet_traits<Scalar>::type PacketType;
+ typedef typename internal::unpacket_traits<PacketType>::half HalfPacketType;
enum {
- PacketSize = internal::packet_traits<Scalar>::size
+ PacketSize = internal::unpacket_traits<PacketType>::size,
+ HalfPacketSize = internal::unpacket_traits<HalfPacketType>::size
};
static void run()
{
@@ -90,8 +112,8 @@ template<typename Scalar, bool Enable = internal::packet_traits<Scalar>::Vectori
typedef Matrix<Scalar,2*PacketSize,2*PacketSize> Matrix22;
typedef Matrix<Scalar,(Matrix11::Flags&RowMajorBit)?16:4*PacketSize,(Matrix11::Flags&RowMajorBit)?4*PacketSize:16> Matrix44;
typedef Matrix<Scalar,(Matrix11::Flags&RowMajorBit)?16:4*PacketSize,(Matrix11::Flags&RowMajorBit)?4*PacketSize:16,DontAlign|EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION> Matrix44u;
- typedef Matrix<Scalar,4*PacketSize,16,ColMajor> Matrix44c;
- typedef Matrix<Scalar,4*PacketSize,16,RowMajor> Matrix44r;
+ typedef Matrix<Scalar,4*PacketSize,4*PacketSize,ColMajor> Matrix44c;
+ typedef Matrix<Scalar,4*PacketSize,4*PacketSize,RowMajor> Matrix44r;
typedef Matrix<Scalar,
(PacketSize==8 ? 4 : PacketSize==4 ? 2 : PacketSize==2 ? 1 : /*PacketSize==1 ?*/ 1),
@@ -131,35 +153,63 @@ template<typename Scalar, bool Enable = internal::packet_traits<Scalar>::Vectori
InnerVectorizedTraversal,InnerUnrolling));
VERIFY(test_assign(Matrix44u(),Matrix44()+Matrix44(),
- LinearTraversal,NoUnrolling));
+ EIGEN_UNALIGNED_VECTORIZE ? InnerVectorizedTraversal : LinearTraversal,
+ EIGEN_UNALIGNED_VECTORIZE ? InnerUnrolling : NoUnrolling));
+
+ VERIFY(test_assign(Matrix1(),Matrix1()+Matrix1(),
+ (Matrix1::InnerSizeAtCompileTime % PacketSize)==0 ? InnerVectorizedTraversal : LinearVectorizedTraversal,
+ CompleteUnrolling));
VERIFY(test_assign(Matrix1u(),Matrix1()+Matrix1(),
- LinearTraversal,CompleteUnrolling));
+ EIGEN_UNALIGNED_VECTORIZE ? ((Matrix1::InnerSizeAtCompileTime % PacketSize)==0 ? InnerVectorizedTraversal : LinearVectorizedTraversal)
+ : LinearTraversal, CompleteUnrolling));
VERIFY(test_assign(Matrix44c().col(1),Matrix44c().col(2)+Matrix44c().col(3),
InnerVectorizedTraversal,CompleteUnrolling));
-
+
VERIFY(test_assign(Matrix44r().row(2),Matrix44r().row(1)+Matrix44r().row(1),
InnerVectorizedTraversal,CompleteUnrolling));
-
+
if(PacketSize>1)
{
typedef Matrix<Scalar,3,3,ColMajor> Matrix33c;
+ typedef Matrix<Scalar,3,1,ColMajor> Vector3;
VERIFY(test_assign(Matrix33c().row(2),Matrix33c().row(1)+Matrix33c().row(1),
LinearTraversal,CompleteUnrolling));
+ VERIFY(test_assign(Vector3(),Vector3()+Vector3(),
+ EIGEN_UNALIGNED_VECTORIZE ? (HalfPacketSize==1 ? InnerVectorizedTraversal : LinearVectorizedTraversal) : (HalfPacketSize==1 ? InnerVectorizedTraversal : LinearTraversal), CompleteUnrolling));
VERIFY(test_assign(Matrix33c().col(0),Matrix33c().col(1)+Matrix33c().col(1),
- LinearTraversal,CompleteUnrolling));
-
- VERIFY(test_assign(Matrix3(),Matrix3().cwiseQuotient(Matrix3()),
+ EIGEN_UNALIGNED_VECTORIZE ? (HalfPacketSize==1 ? InnerVectorizedTraversal : LinearVectorizedTraversal) : (HalfPacketSize==1 ? SliceVectorizedTraversal : LinearTraversal),
+ ((!EIGEN_UNALIGNED_VECTORIZE) && HalfPacketSize==1) ? NoUnrolling : CompleteUnrolling));
+
+ VERIFY(test_assign(Matrix3(),Matrix3().cwiseProduct(Matrix3()),
LinearVectorizedTraversal,CompleteUnrolling));
VERIFY(test_assign(Matrix<Scalar,17,17>(),Matrix<Scalar,17,17>()+Matrix<Scalar,17,17>(),
- LinearTraversal,NoUnrolling));
+ HalfPacketSize==1 ? InnerVectorizedTraversal :
+ EIGEN_UNALIGNED_VECTORIZE ? LinearVectorizedTraversal :
+ LinearTraversal,
+ NoUnrolling));
- VERIFY(test_assign(Matrix11(),Matrix<Scalar,17,17>().template block<PacketSize,PacketSize>(2,3)+Matrix<Scalar,17,17>().template block<PacketSize,PacketSize>(10,4),
- DefaultTraversal,CompleteUnrolling));
+ VERIFY(test_assign(Matrix11(), Matrix11()+Matrix11(),InnerVectorizedTraversal,CompleteUnrolling));
+
+
+ VERIFY(test_assign(Matrix11(),Matrix<Scalar,17,17>().template block<PacketSize,PacketSize>(2,3)+Matrix<Scalar,17,17>().template block<PacketSize,PacketSize>(8,4),
+ (EIGEN_UNALIGNED_VECTORIZE) ? InnerVectorizedTraversal : DefaultTraversal, CompleteUnrolling|InnerUnrolling));
+
+ VERIFY(test_assign(Vector1(),Matrix11()*Vector1(),
+ InnerVectorizedTraversal,CompleteUnrolling));
+
+ VERIFY(test_assign(Matrix11(),Matrix11().lazyProduct(Matrix11()),
+ InnerVectorizedTraversal,InnerUnrolling+CompleteUnrolling));
}
-
+
+ VERIFY(test_redux(Vector1(),
+ LinearVectorizedTraversal,CompleteUnrolling));
+
+ VERIFY(test_redux(Matrix<Scalar,PacketSize,3>(),
+ LinearVectorizedTraversal,CompleteUnrolling));
+
VERIFY(test_redux(Matrix3(),
LinearVectorizedTraversal,CompleteUnrolling));
@@ -174,18 +224,19 @@ template<typename Scalar, bool Enable = internal::packet_traits<Scalar>::Vectori
VERIFY(test_redux(Matrix44r().template block<1,2*PacketSize>(2,1),
LinearVectorizedTraversal,CompleteUnrolling));
-
+
VERIFY((test_assign<
- Map<Matrix22, Aligned, OuterStride<3*PacketSize> >,
+ Map<Matrix22, AlignedMax, OuterStride<3*PacketSize> >,
Matrix22
>(InnerVectorizedTraversal,CompleteUnrolling)));
VERIFY((test_assign<
- Map<Matrix22, Aligned, InnerStride<3*PacketSize> >,
- Matrix22
- >(DefaultTraversal,CompleteUnrolling)));
+ Map<Matrix<Scalar,EIGEN_PLAIN_ENUM_MAX(2,PacketSize),EIGEN_PLAIN_ENUM_MAX(2,PacketSize)>, AlignedMax, InnerStride<3*PacketSize> >,
+ Matrix<Scalar,EIGEN_PLAIN_ENUM_MAX(2,PacketSize),EIGEN_PLAIN_ENUM_MAX(2,PacketSize)>
+ >(DefaultTraversal,PacketSize>=8?InnerUnrolling:CompleteUnrolling)));
- VERIFY((test_assign(Matrix11(), Matrix11()*Matrix11(), InnerVectorizedTraversal, CompleteUnrolling)));
+ VERIFY((test_assign(Matrix11(), Matrix<Scalar,PacketSize,EIGEN_PLAIN_ENUM_MIN(2,PacketSize)>()*Matrix<Scalar,EIGEN_PLAIN_ENUM_MIN(2,PacketSize),PacketSize>(),
+ InnerVectorizedTraversal, CompleteUnrolling)));
#endif
VERIFY(test_assign(MatrixXX(10,10),MatrixXX(20,20).block(10,10,2,3),
@@ -193,12 +244,138 @@ template<typename Scalar, bool Enable = internal::packet_traits<Scalar>::Vectori
VERIFY(test_redux(VectorX(10),
LinearVectorizedTraversal,NoUnrolling));
+ }
+};
+
+template<typename Scalar> struct vectorization_logic<Scalar,false>
+{
+ static void run() {}
+};
+
+template<typename Scalar, bool Enable = !internal::is_same<typename internal::unpacket_traits<typename internal::packet_traits<Scalar>::type>::half,
+ typename internal::packet_traits<Scalar>::type>::value >
+struct vectorization_logic_half
+{
+ typedef internal::packet_traits<Scalar> PacketTraits;
+ typedef typename internal::unpacket_traits<typename internal::packet_traits<Scalar>::type>::half PacketType;
+ enum {
+ PacketSize = internal::unpacket_traits<PacketType>::size
+ };
+ static void run()
+ {
+
+ typedef Matrix<Scalar,PacketSize,1> Vector1;
+ typedef Matrix<Scalar,PacketSize,PacketSize> Matrix11;
+ typedef Matrix<Scalar,5*PacketSize,7,ColMajor> Matrix57;
+ typedef Matrix<Scalar,3*PacketSize,5,ColMajor> Matrix35;
+ typedef Matrix<Scalar,5*PacketSize,7,DontAlign|ColMajor> Matrix57u;
+// typedef Matrix<Scalar,(Matrix11::Flags&RowMajorBit)?16:4*PacketSize,(Matrix11::Flags&RowMajorBit)?4*PacketSize:16> Matrix44;
+// typedef Matrix<Scalar,(Matrix11::Flags&RowMajorBit)?16:4*PacketSize,(Matrix11::Flags&RowMajorBit)?4*PacketSize:16,DontAlign|EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION> Matrix44u;
+// typedef Matrix<Scalar,4*PacketSize,4*PacketSize,ColMajor> Matrix44c;
+// typedef Matrix<Scalar,4*PacketSize,4*PacketSize,RowMajor> Matrix44r;
+
+ typedef Matrix<Scalar,
+ (PacketSize==8 ? 4 : PacketSize==4 ? 2 : PacketSize==2 ? 1 : /*PacketSize==1 ?*/ 1),
+ (PacketSize==8 ? 2 : PacketSize==4 ? 2 : PacketSize==2 ? 2 : /*PacketSize==1 ?*/ 1)
+ > Matrix1;
+
+ typedef Matrix<Scalar,
+ (PacketSize==8 ? 4 : PacketSize==4 ? 2 : PacketSize==2 ? 1 : /*PacketSize==1 ?*/ 1),
+ (PacketSize==8 ? 2 : PacketSize==4 ? 2 : PacketSize==2 ? 2 : /*PacketSize==1 ?*/ 1),
+ DontAlign|((Matrix1::Flags&RowMajorBit)?RowMajor:ColMajor)> Matrix1u;
+ // this type is made such that it can only be vectorized when viewed as a linear 1D vector
+ typedef Matrix<Scalar,
+ (PacketSize==8 ? 4 : PacketSize==4 ? 6 : PacketSize==2 ? ((Matrix11::Flags&RowMajorBit)?2:3) : /*PacketSize==1 ?*/ 1),
+ (PacketSize==8 ? 6 : PacketSize==4 ? 2 : PacketSize==2 ? ((Matrix11::Flags&RowMajorBit)?3:2) : /*PacketSize==1 ?*/ 3)
+ > Matrix3;
+ #if !EIGEN_GCC_AND_ARCH_DOESNT_WANT_STACK_ALIGNMENT
+ VERIFY(test_assign(Vector1(),Vector1(),
+ InnerVectorizedTraversal,CompleteUnrolling));
+ VERIFY(test_assign(Vector1(),Vector1()+Vector1(),
+ InnerVectorizedTraversal,CompleteUnrolling));
+ VERIFY(test_assign(Vector1(),Vector1().template segment<PacketSize>(0).derived(),
+ EIGEN_UNALIGNED_VECTORIZE ? InnerVectorizedTraversal : LinearVectorizedTraversal,CompleteUnrolling));
+ VERIFY(test_assign(Vector1(),Scalar(2.1)*Vector1()-Vector1(),
+ InnerVectorizedTraversal,CompleteUnrolling));
+ VERIFY(test_assign(Vector1(),(Scalar(2.1)*Vector1().template segment<PacketSize>(0)-Vector1().template segment<PacketSize>(0)).derived(),
+ EIGEN_UNALIGNED_VECTORIZE ? InnerVectorizedTraversal : LinearVectorizedTraversal,CompleteUnrolling));
+ VERIFY(test_assign(Vector1(),Vector1().cwiseProduct(Vector1()),
+ InnerVectorizedTraversal,CompleteUnrolling));
+ VERIFY(test_assign(Vector1(),Vector1().template cast<Scalar>(),
+ InnerVectorizedTraversal,CompleteUnrolling));
+
+
+ VERIFY(test_assign(Vector1(),Vector1(),
+ InnerVectorizedTraversal,CompleteUnrolling));
+ VERIFY(test_assign(Vector1(),Vector1()+Vector1(),
+ InnerVectorizedTraversal,CompleteUnrolling));
+ VERIFY(test_assign(Vector1(),Vector1().cwiseProduct(Vector1()),
+ InnerVectorizedTraversal,CompleteUnrolling));
+
+ VERIFY(test_assign(Matrix57(),Matrix57()+Matrix57(),
+ InnerVectorizedTraversal,InnerUnrolling));
+
+ VERIFY(test_assign(Matrix57u(),Matrix57()+Matrix57(),
+ EIGEN_UNALIGNED_VECTORIZE ? InnerVectorizedTraversal : LinearTraversal,
+ EIGEN_UNALIGNED_VECTORIZE ? InnerUnrolling : NoUnrolling));
+
+ VERIFY(test_assign(Matrix1u(),Matrix1()+Matrix1(),
+ EIGEN_UNALIGNED_VECTORIZE ? ((Matrix1::InnerSizeAtCompileTime % PacketSize)==0 ? InnerVectorizedTraversal : LinearVectorizedTraversal) : LinearTraversal,CompleteUnrolling));
+
+ if(PacketSize>1)
+ {
+ typedef Matrix<Scalar,3,3,ColMajor> Matrix33c;
+ VERIFY(test_assign(Matrix33c().row(2),Matrix33c().row(1)+Matrix33c().row(1),
+ LinearTraversal,CompleteUnrolling));
+ VERIFY(test_assign(Matrix33c().col(0),Matrix33c().col(1)+Matrix33c().col(1),
+ EIGEN_UNALIGNED_VECTORIZE ? (PacketSize==1 ? InnerVectorizedTraversal : LinearVectorizedTraversal) : LinearTraversal,CompleteUnrolling));
+
+ VERIFY(test_assign(Matrix3(),Matrix3().cwiseQuotient(Matrix3()),
+ PacketTraits::HasDiv ? LinearVectorizedTraversal : LinearTraversal,CompleteUnrolling));
+
+ VERIFY(test_assign(Matrix<Scalar,17,17>(),Matrix<Scalar,17,17>()+Matrix<Scalar,17,17>(),
+ EIGEN_UNALIGNED_VECTORIZE ? (PacketSize==1 ? InnerVectorizedTraversal : LinearVectorizedTraversal) : LinearTraversal,
+ NoUnrolling));
+
+ VERIFY(test_assign(Matrix11(),Matrix<Scalar,17,17>().template block<PacketSize,PacketSize>(2,3)+Matrix<Scalar,17,17>().template block<PacketSize,PacketSize>(8,4),
+ EIGEN_UNALIGNED_VECTORIZE ? InnerVectorizedTraversal : DefaultTraversal,PacketSize>4?InnerUnrolling:CompleteUnrolling));
+
+ VERIFY(test_assign(Vector1(),Matrix11()*Vector1(),
+ InnerVectorizedTraversal,CompleteUnrolling));
+
+ VERIFY(test_assign(Matrix11(),Matrix11().lazyProduct(Matrix11()),
+ InnerVectorizedTraversal,InnerUnrolling+CompleteUnrolling));
+ }
+
+ VERIFY(test_redux(Vector1(),
+ LinearVectorizedTraversal,CompleteUnrolling));
+
+ VERIFY(test_redux(Matrix<Scalar,PacketSize,3>(),
+ LinearVectorizedTraversal,CompleteUnrolling));
+
+ VERIFY(test_redux(Matrix3(),
+ LinearVectorizedTraversal,CompleteUnrolling));
+
+ VERIFY(test_redux(Matrix35(),
+ LinearVectorizedTraversal,CompleteUnrolling));
+
+ VERIFY(test_redux(Matrix57().template block<PacketSize,3>(1,0),
+ DefaultTraversal,CompleteUnrolling));
+
+ VERIFY((test_assign<
+ Map<Matrix<Scalar,EIGEN_PLAIN_ENUM_MAX(2,PacketSize),EIGEN_PLAIN_ENUM_MAX(2,PacketSize)>, AlignedMax, InnerStride<3*PacketSize> >,
+ Matrix<Scalar,EIGEN_PLAIN_ENUM_MAX(2,PacketSize),EIGEN_PLAIN_ENUM_MAX(2,PacketSize)>
+ >(DefaultTraversal,CompleteUnrolling)));
+
+ VERIFY((test_assign(Matrix57(), Matrix<Scalar,5*PacketSize,3>()*Matrix<Scalar,3,7>(),
+ InnerVectorizedTraversal, InnerUnrolling|CompleteUnrolling)));
+ #endif
}
};
-template<typename Scalar> struct vectorization_logic<Scalar,false>
+template<typename Scalar> struct vectorization_logic_half<Scalar,false>
{
static void run() {}
};
@@ -208,27 +385,34 @@ void test_vectorization_logic()
#ifdef EIGEN_VECTORIZE
+ CALL_SUBTEST( vectorization_logic<int>::run() );
CALL_SUBTEST( vectorization_logic<float>::run() );
CALL_SUBTEST( vectorization_logic<double>::run() );
CALL_SUBTEST( vectorization_logic<std::complex<float> >::run() );
CALL_SUBTEST( vectorization_logic<std::complex<double> >::run() );
+ CALL_SUBTEST( vectorization_logic_half<int>::run() );
+ CALL_SUBTEST( vectorization_logic_half<float>::run() );
+ CALL_SUBTEST( vectorization_logic_half<double>::run() );
+ CALL_SUBTEST( vectorization_logic_half<std::complex<float> >::run() );
+ CALL_SUBTEST( vectorization_logic_half<std::complex<double> >::run() );
+
if(internal::packet_traits<float>::Vectorizable)
{
VERIFY(test_assign(Matrix<float,3,3>(),Matrix<float,3,3>()+Matrix<float,3,3>(),
- LinearTraversal,CompleteUnrolling));
+ EIGEN_UNALIGNED_VECTORIZE ? LinearVectorizedTraversal : LinearTraversal,CompleteUnrolling));
VERIFY(test_redux(Matrix<float,5,2>(),
- DefaultTraversal,CompleteUnrolling));
+ EIGEN_UNALIGNED_VECTORIZE ? LinearVectorizedTraversal : DefaultTraversal,CompleteUnrolling));
}
if(internal::packet_traits<double>::Vectorizable)
{
VERIFY(test_assign(Matrix<double,3,3>(),Matrix<double,3,3>()+Matrix<double,3,3>(),
- LinearTraversal,CompleteUnrolling));
+ EIGEN_UNALIGNED_VECTORIZE ? LinearVectorizedTraversal : LinearTraversal,CompleteUnrolling));
VERIFY(test_redux(Matrix<double,7,3>(),
- DefaultTraversal,CompleteUnrolling));
+ EIGEN_UNALIGNED_VECTORIZE ? LinearVectorizedTraversal : DefaultTraversal,CompleteUnrolling));
}
#endif // EIGEN_VECTORIZE
diff --git a/test/vectorwiseop.cpp b/test/vectorwiseop.cpp
index 6cd1acdda..f3ab561ee 100644
--- a/test/vectorwiseop.cpp
+++ b/test/vectorwiseop.cpp
@@ -2,11 +2,13 @@
// for linear algebra.
//
// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
+// 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/.
+#define TEST_ENABLE_TEMPORARY_TRACKING
#define EIGEN_NO_STATIC_ASSERT
#include "main.h"
@@ -101,16 +103,28 @@ template<typename ArrayType> void vectorwiseop_array(const ArrayType& m)
VERIFY_RAISES_ASSERT(m2.rowwise() /= rowvec.transpose());
VERIFY_RAISES_ASSERT(m1.rowwise() / rowvec.transpose());
-
+
m2 = m1;
// yes, there might be an aliasing issue there but ".rowwise() /="
- // is suppposed to evaluate " m2.colwise().sum()" into to temporary to avoid
- // evaluating the reducions multiple times
+ // is supposed to evaluate " m2.colwise().sum()" into a temporary to avoid
+ // evaluating the reduction multiple times
if(ArrayType::RowsAtCompileTime>2 || ArrayType::RowsAtCompileTime==Dynamic)
{
m2.rowwise() /= m2.colwise().sum();
VERIFY_IS_APPROX(m2, m1.rowwise() / m1.colwise().sum());
}
+
+ // all/any
+ Array<bool,Dynamic,Dynamic> mb(rows,cols);
+ mb = (m1.real()<=0.7).colwise().all();
+ VERIFY( (mb.col(c) == (m1.real().col(c)<=0.7).all()).all() );
+ mb = (m1.real()<=0.7).rowwise().all();
+ VERIFY( (mb.row(r) == (m1.real().row(r)<=0.7).all()).all() );
+
+ mb = (m1.real()>=0.7).colwise().any();
+ VERIFY( (mb.col(c) == (m1.real().col(c)>=0.7).any()).all() );
+ mb = (m1.real()>=0.7).rowwise().any();
+ VERIFY( (mb.row(r) == (m1.real().row(r)>=0.7).any()).all() );
}
template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m)
@@ -144,16 +158,22 @@ template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m)
VERIFY_IS_APPROX(m2, m1.colwise() + colvec);
VERIFY_IS_APPROX(m2.col(c), m1.col(c) + colvec);
- VERIFY_RAISES_ASSERT(m2.colwise() += colvec.transpose());
- VERIFY_RAISES_ASSERT(m1.colwise() + colvec.transpose());
+ if(rows>1)
+ {
+ VERIFY_RAISES_ASSERT(m2.colwise() += colvec.transpose());
+ VERIFY_RAISES_ASSERT(m1.colwise() + colvec.transpose());
+ }
m2 = m1;
m2.rowwise() += rowvec;
VERIFY_IS_APPROX(m2, m1.rowwise() + rowvec);
VERIFY_IS_APPROX(m2.row(r), m1.row(r) + rowvec);
- VERIFY_RAISES_ASSERT(m2.rowwise() += rowvec.transpose());
- VERIFY_RAISES_ASSERT(m1.rowwise() + rowvec.transpose());
+ if(cols>1)
+ {
+ VERIFY_RAISES_ASSERT(m2.rowwise() += rowvec.transpose());
+ VERIFY_RAISES_ASSERT(m1.rowwise() + rowvec.transpose());
+ }
// test substraction
@@ -162,29 +182,43 @@ template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m)
VERIFY_IS_APPROX(m2, m1.colwise() - colvec);
VERIFY_IS_APPROX(m2.col(c), m1.col(c) - colvec);
- VERIFY_RAISES_ASSERT(m2.colwise() -= colvec.transpose());
- VERIFY_RAISES_ASSERT(m1.colwise() - colvec.transpose());
+ if(rows>1)
+ {
+ VERIFY_RAISES_ASSERT(m2.colwise() -= colvec.transpose());
+ VERIFY_RAISES_ASSERT(m1.colwise() - colvec.transpose());
+ }
m2 = m1;
m2.rowwise() -= rowvec;
VERIFY_IS_APPROX(m2, m1.rowwise() - rowvec);
VERIFY_IS_APPROX(m2.row(r), m1.row(r) - rowvec);
- VERIFY_RAISES_ASSERT(m2.rowwise() -= rowvec.transpose());
- VERIFY_RAISES_ASSERT(m1.rowwise() - rowvec.transpose());
-
+ if(cols>1)
+ {
+ VERIFY_RAISES_ASSERT(m2.rowwise() -= rowvec.transpose());
+ VERIFY_RAISES_ASSERT(m1.rowwise() - rowvec.transpose());
+ }
+
// test norm
rrres = m1.colwise().norm();
VERIFY_IS_APPROX(rrres(c), m1.col(c).norm());
rcres = m1.rowwise().norm();
VERIFY_IS_APPROX(rcres(r), m1.row(r).norm());
-
+
+ VERIFY_IS_APPROX(m1.cwiseAbs().colwise().sum(), m1.colwise().template lpNorm<1>());
+ VERIFY_IS_APPROX(m1.cwiseAbs().rowwise().sum(), m1.rowwise().template lpNorm<1>());
+ 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());
m2 = m1.rowwise().normalized();
VERIFY_IS_APPROX(m2.row(r), m1.row(r).normalized());
-
+
// test normalize
m2 = m1;
m2.colwise().normalize();
@@ -192,14 +226,27 @@ template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m)
m2 = m1;
m2.rowwise().normalize();
VERIFY_IS_APPROX(m2.row(r), m1.row(r).normalized());
+
+ // test with partial reduction of products
+ Matrix<Scalar,MatrixType::RowsAtCompileTime,MatrixType::RowsAtCompileTime> m1m1 = m1 * m1.transpose();
+ VERIFY_IS_APPROX( (m1 * m1.transpose()).colwise().sum(), m1m1.colwise().sum());
+ Matrix<Scalar,1,MatrixType::RowsAtCompileTime> tmp(rows);
+ VERIFY_EVALUATION_COUNT( tmp = (m1 * m1.transpose()).colwise().sum(), 1);
+
+ m2 = m1.rowwise() - (m1.colwise().sum()/RealScalar(m1.rows())).eval();
+ m1 = m1.rowwise() - (m1.colwise().sum()/RealScalar(m1.rows()));
+ VERIFY_IS_APPROX( m1, m2 );
+ VERIFY_EVALUATION_COUNT( m2 = (m1.rowwise() - m1.colwise().sum()/RealScalar(m1.rows())), (MatrixType::RowsAtCompileTime!=1 ? 1 : 0) );
}
void test_vectorwiseop()
{
- CALL_SUBTEST_1(vectorwiseop_array(Array22cd()));
- CALL_SUBTEST_2(vectorwiseop_array(Array<double, 3, 2>()));
- CALL_SUBTEST_3(vectorwiseop_array(ArrayXXf(3, 4)));
- CALL_SUBTEST_4(vectorwiseop_matrix(Matrix4cf()));
- CALL_SUBTEST_5(vectorwiseop_matrix(Matrix<float,4,5>()));
- CALL_SUBTEST_6(vectorwiseop_matrix(MatrixXd(7,2)));
+ CALL_SUBTEST_1( vectorwiseop_array(Array22cd()) );
+ CALL_SUBTEST_2( vectorwiseop_array(Array<double, 3, 2>()) );
+ CALL_SUBTEST_3( vectorwiseop_array(ArrayXXf(3, 4)) );
+ CALL_SUBTEST_4( vectorwiseop_matrix(Matrix4cf()) );
+ CALL_SUBTEST_5( vectorwiseop_matrix(Matrix<float,4,5>()) );
+ CALL_SUBTEST_6( vectorwiseop_matrix(MatrixXd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+ CALL_SUBTEST_7( vectorwiseop_matrix(VectorXd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+ CALL_SUBTEST_7( vectorwiseop_matrix(RowVectorXd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
}
diff --git a/test/visitor.cpp b/test/visitor.cpp
index 39a5d6b5f..844170ec6 100644
--- a/test/visitor.cpp
+++ b/test/visitor.cpp
@@ -55,6 +55,11 @@ template<typename MatrixType> void matrixVisitor(const MatrixType& p)
VERIFY_IS_APPROX(maxc, eigen_maxc);
VERIFY_IS_APPROX(minc, m.minCoeff());
VERIFY_IS_APPROX(maxc, m.maxCoeff());
+
+ eigen_maxc = (m.adjoint()*m).maxCoeff(&eigen_maxrow,&eigen_maxcol);
+ eigen_maxc = (m.adjoint()*m).eval().maxCoeff(&maxrow,&maxcol);
+ VERIFY(maxrow == eigen_maxrow);
+ VERIFY(maxcol == eigen_maxcol);
}
template<typename VectorType> void vectorVisitor(const VectorType& w)
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()